1
0
Fork 0
mirror of synced 2024-05-29 16:50:00 +12:00

Helm Release: 2.6.16

This commit is contained in:
Budibase Helm Bot 2023-05-16 18:09:51 +00:00
parent 787885f616
commit 523f5badc8
33 changed files with 1999 additions and 1 deletions

BIN
docs/budibase-2.6.16.tgz Normal file

Binary file not shown.

View file

@ -1,6 +1,33 @@
apiVersion: v1
entries:
budibase:
- apiVersion: v2
appVersion: 2.6.16
created: "2023-05-16T18:09:51.233723553Z"
dependencies:
- condition: services.couchdb.enabled
name: couchdb
repository: https://apache.github.io/couchdb-helm
version: 3.3.4
- condition: ingress.nginx
name: ingress-nginx
repository: https://kubernetes.github.io/ingress-nginx
version: 4.0.13
description: Budibase is an open source low-code platform, helping thousands of
teams build apps for their workplace in minutes.
digest: 5f2d0360a18b3674d6bb4380b3cbba5f8cba9dee6dd3bbbfb334969972d15a9c
keywords:
- low-code
- database
- cluster
name: budibase
sources:
- https://github.com/Budibase/budibase
- https://budibase.com
type: application
urls:
- budibase-2.6.16.tgz
version: 2.6.16
- apiVersion: v2
appVersion: 2.6.11
created: "2023-05-12T15:17:09.315658496Z"
@ -1295,4 +1322,4 @@ entries:
urls:
- budibase-0.0.0-develop.tgz
version: 0.0.0-develop
generated: "2023-05-16T15:16:06.55576779Z"
generated: "2023-05-16T18:09:51.224174746Z"

67
packages/cli/dist/package.json vendored Normal file
View file

@ -0,0 +1,67 @@
{
"name": "@budibase/cli",
"version": "2.6.16",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "dist/index.js",
"bin": {
"budi": "dist/src/index.js"
},
"author": "Budibase",
"license": "GPL-3.0",
"scripts": {
"prebuild": "rm -rf prebuilds 2> /dev/null && cp -r ../../node_modules/leveldown/prebuilds prebuilds",
"rename": "renamer --find .node --replace .fake 'prebuilds/**'",
"tsc": "tsc -p tsconfig.build.json",
"pkg": "pkg . --out-path build --no-bytecode --public --public-packages \"*\" -C GZip",
"build": "yarn prebuild && yarn rename && yarn tsc && yarn pkg && yarn postbuild",
"postbuild": "rm -rf prebuilds 2> /dev/null"
},
"pkg": {
"targets": [
"node16-linux",
"node16-win",
"node16-macos"
],
"assets": [
"node_modules/@budibase/backend-core/dist/**/*",
"prebuilds/**/*"
],
"outputPath": "build"
},
"dependencies": {
"@budibase/backend-core": "^2.6.16",
"@budibase/string-templates": "^2.6.16",
"@budibase/types": "^2.6.16",
"axios": "0.21.2",
"chalk": "4.1.0",
"cli-progress": "3.11.2",
"commander": "7.1.0",
"docker-compose": "0.24.0",
"dotenv": "16.0.1",
"download": "8.0.0",
"find-free-port": "^2.0.0",
"inquirer": "8.0.0",
"joi": "17.6.0",
"lookpath": "1.1.0",
"node-fetch": "2.6.7",
"pkg": "5.8.0",
"posthog-node": "1.0.7",
"pouchdb": "7.3.0",
"pouchdb-replication-stream": "1.2.9",
"randomstring": "1.1.5",
"tar": "6.1.11",
"yaml": "^2.1.1"
},
"devDependencies": {
"@swc/core": "^1.3.25",
"@swc/jest": "^0.2.24",
"@types/jest": "^29.4.0",
"@types/node-fetch": "2.6.1",
"@types/pouchdb": "^6.4.0",
"copyfiles": "^2.4.1",
"eslint": "^7.20.0",
"renamer": "^4.0.0",
"ts-node": "^10.9.1",
"typescript": "4.7.3"
}
}

View file

@ -0,0 +1,32 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AnalyticsClient = void 0;
const posthog_node_1 = __importDefault(require("posthog-node"));
const constants_1 = require("../constants");
const ConfigManager_1 = require("../structures/ConfigManager");
class AnalyticsClient {
constructor() {
this.client = new posthog_node_1.default(constants_1.POSTHOG_TOKEN, {});
this.configManager = new ConfigManager_1.ConfigManager();
}
capture(event) {
if (this.configManager.config.analyticsDisabled)
return;
this.client.capture(event);
}
enable() {
this.configManager.removeKey("analyticsDisabled");
this.client.capture({ event: constants_1.AnalyticsEvent.OptIn, distinctId: "cli" });
}
disable() {
this.client.capture({ event: constants_1.AnalyticsEvent.OptOut, distinctId: "cli" });
this.configManager.setValue("analyticsDisabled", true);
}
status() {
return this.configManager.config.analyticsDisabled ? "disabled" : "enabled";
}
}
exports.AnalyticsClient = AnalyticsClient;

View file

@ -0,0 +1,55 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Command_1 = require("../structures/Command");
const constants_1 = require("../constants");
const utils_1 = require("../utils");
const Client_1 = require("./Client");
const client = new Client_1.AnalyticsClient();
function optOut() {
return __awaiter(this, void 0, void 0, function* () {
try {
// opt them out
client.disable();
console.log((0, utils_1.success)("Successfully opted out of Budibase analytics. You can opt in at any time by running 'budi analytics opt-in'"));
}
catch (err) {
console.log((0, utils_1.error)(`Error opting out of Budibase analytics. Please try again later - ${err}`));
}
});
}
function optIn() {
return __awaiter(this, void 0, void 0, function* () {
try {
// opt them in
client.enable();
console.log((0, utils_1.success)("Successfully opted in to Budibase analytics. Thank you for helping us make Budibase better!"));
}
catch (err) {
console.log((0, utils_1.error)("Error opting in to Budibase analytics. Please try again later."));
}
});
}
function status() {
return __awaiter(this, void 0, void 0, function* () {
try {
console.log((0, utils_1.success)(`Budibase analytics ${client.status()}`));
}
catch (err) {
console.log((0, utils_1.error)("Error fetching analytics status. Please try again later."));
}
});
}
exports.default = new Command_1.Command(`${constants_1.CommandWord.ANALYTICS}`)
.addHelp("Control the analytics you send to Budibase.")
.addSubOption("--optin", "Opt in to sending analytics to Budibase", optIn)
.addSubOption("--optout", "Opt out of sending analytics to Budibase.", optOut)
.addSubOption("--status", "Check whether you are currently opted in to Budibase analytics.", status);

119
packages/cli/dist/src/backups/index.js vendored Normal file
View file

@ -0,0 +1,119 @@
"use strict";
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 fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const db_1 = require("../core/db");
const utils_1 = require("../utils");
const utils_2 = require("./utils");
const objectStore_1 = require("./objectStore");
const tar = require("tar");
function exportBackup(opts) {
return __awaiter(this, void 0, void 0, function* () {
const envFile = opts.env || undefined;
let filename = opts["export"] || opts;
if (typeof filename !== "string") {
filename = `backup-${new Date().toISOString()}.tar.gz`;
}
const config = yield (0, utils_2.getConfig)(envFile);
const dbList = (yield (0, db_1.getAllDbs)(config["COUCH_DB_URL"]));
const { Remote, Local } = (0, utils_2.getPouches)(config);
if (fs_1.default.existsSync(utils_2.TEMP_DIR)) {
fs_1.default.rmSync(utils_2.TEMP_DIR, { recursive: true });
}
const couchDir = (0, path_1.join)(utils_2.TEMP_DIR, utils_2.COUCH_DIR);
fs_1.default.mkdirSync(utils_2.TEMP_DIR);
fs_1.default.mkdirSync(couchDir);
console.log("CouchDB Export");
const bar = (0, utils_1.progressBar)(dbList.length);
let count = 0;
for (let db of dbList) {
bar.update(++count);
const remote = new Remote(db);
const local = new Local((0, path_1.join)(utils_2.TEMP_DIR, utils_2.COUCH_DIR, db));
yield (0, utils_2.replication)(remote, local);
}
bar.stop();
console.log("S3 Export");
yield (0, objectStore_1.exportObjects)();
tar.create({
sync: true,
gzip: true,
file: filename,
cwd: (0, path_1.join)(utils_2.TEMP_DIR),
}, [utils_2.COUCH_DIR, utils_2.MINIO_DIR]);
fs_1.default.rmSync(utils_2.TEMP_DIR, { recursive: true });
console.log(`Generated export file - ${filename}`);
});
}
function importBackup(opts) {
return __awaiter(this, void 0, void 0, function* () {
const envFile = opts.env || undefined;
const filename = opts["import"] || opts;
const config = yield (0, utils_2.getConfig)(envFile);
if (!filename || !fs_1.default.existsSync(filename)) {
console.error("Cannot import without specifying a valid file to import");
process.exit(-1);
}
if (fs_1.default.existsSync(utils_2.TEMP_DIR)) {
fs_1.default.rmSync(utils_2.TEMP_DIR, { recursive: true });
}
fs_1.default.mkdirSync(utils_2.TEMP_DIR);
tar.extract({
sync: true,
cwd: (0, path_1.join)(utils_2.TEMP_DIR),
file: filename,
});
const { Remote, Local } = (0, utils_2.getPouches)(config);
const dbList = fs_1.default.readdirSync((0, path_1.join)(utils_2.TEMP_DIR, utils_2.COUCH_DIR));
console.log("CouchDB Import");
const bar = (0, utils_1.progressBar)(dbList.length);
let count = 0;
for (let db of dbList) {
bar.update(++count);
const remote = new Remote(db);
const local = new Local((0, path_1.join)(utils_2.TEMP_DIR, utils_2.COUCH_DIR, db));
yield (0, utils_2.replication)(local, remote);
}
bar.stop();
console.log("MinIO Import");
yield (0, objectStore_1.importObjects)();
// finish by letting the system know that a restore has occurred
try {
yield (0, utils_1.httpCall)(`http://localhost:${config.MAIN_PORT}/api/system/restored`, "POST");
}
catch (err) {
// ignore error - it will be an older system
}
console.log("Import complete");
fs_1.default.rmSync(utils_2.TEMP_DIR, { recursive: true });
});
}
function pickOne(opts) {
return __awaiter(this, void 0, void 0, function* () {
if (opts["import"]) {
return importBackup(opts);
}
else if (opts["export"]) {
return exportBackup(opts);
}
});
}
exports.default = new Command_1.Command(`${constants_1.CommandWord.BACKUPS}`)
.addHelp("Allows building backups of Budibase, as well as importing a backup to a new instance.")
.addSubOption("--export [filename]", "Export a backup from an existing Budibase installation.", exportBackup)
.addSubOption("--import [filename]", "Import a backup to a new Budibase installation.", importBackup)
.addSubOption("--env [envFile]", "Provide an environment variable file to configure the CLI.", pickOne);

View file

@ -0,0 +1,82 @@
"use strict";
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 });
exports.importObjects = exports.exportObjects = void 0;
const backend_core_1 = require("@budibase/backend-core");
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
const utils_1 = require("./utils");
const utils_2 = require("../utils");
const { ObjectStoreBuckets, ObjectStore, retrieve, uploadDirectory, makeSureBucketExists, } = backend_core_1.objectStore;
const bucketList = Object.values(ObjectStoreBuckets);
function exportObjects() {
return __awaiter(this, void 0, void 0, function* () {
const path = (0, path_1.join)(utils_1.TEMP_DIR, utils_1.MINIO_DIR);
fs_1.default.mkdirSync(path);
let fullList = [];
let errorCount = 0;
for (let bucket of bucketList) {
const client = ObjectStore(bucket);
try {
yield client.headBucket().promise();
}
catch (err) {
errorCount++;
continue;
}
const list = (yield client.listObjectsV2().promise());
fullList = fullList.concat(list.Contents.map(el => (Object.assign(Object.assign({}, el), { bucket }))));
}
if (errorCount === bucketList.length) {
throw new Error("Unable to access MinIO/S3 - check environment config.");
}
const bar = (0, utils_2.progressBar)(fullList.length);
let count = 0;
for (let object of fullList) {
const filename = object.Key;
const data = yield retrieve(object.bucket, filename);
const possiblePath = filename.split("/");
if (possiblePath.length > 1) {
const dirs = possiblePath.slice(0, possiblePath.length - 1);
fs_1.default.mkdirSync((0, path_1.join)(path, object.bucket, ...dirs), { recursive: true });
}
fs_1.default.writeFileSync((0, path_1.join)(path, object.bucket, ...possiblePath), data);
bar.update(++count);
}
bar.stop();
});
}
exports.exportObjects = exportObjects;
function importObjects() {
return __awaiter(this, void 0, void 0, function* () {
const path = (0, path_1.join)(utils_1.TEMP_DIR, utils_1.MINIO_DIR);
const buckets = fs_1.default.readdirSync(path);
let total = 0;
buckets.forEach(bucket => {
const files = fs_1.default.readdirSync((0, path_1.join)(path, bucket));
total += files.length;
});
const bar = (0, utils_2.progressBar)(total);
let count = 0;
for (let bucket of buckets) {
const client = ObjectStore(bucket);
yield makeSureBucketExists(client, bucket);
const files = yield uploadDirectory(bucket, (0, path_1.join)(path, bucket), "/");
count += files.length;
bar.update(count);
}
bar.stop();
});
}
exports.importObjects = importObjects;

110
packages/cli/dist/src/backups/utils.js vendored Normal file
View file

@ -0,0 +1,110 @@
"use strict";
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 });
exports.getPouches = exports.replication = exports.getConfig = exports.loadEnvironment = exports.askQuestions = exports.checkURLs = exports.MINIO_DIR = exports.COUCH_DIR = exports.TEMP_DIR = void 0;
const dotenv_1 = __importDefault(require("dotenv"));
const fs_1 = __importDefault(require("fs"));
const questions_1 = require("../questions");
const db_1 = require("../core/db");
const backend_core_1 = require("@budibase/backend-core");
exports.TEMP_DIR = ".temp";
exports.COUCH_DIR = "couchdb";
exports.MINIO_DIR = "minio";
const REQUIRED = [
{ value: "MAIN_PORT", default: "10000" },
{
value: "COUCH_DB_URL",
default: "http://budibase:budibase@localhost:10000/db/",
},
{ value: "MINIO_URL", default: "http://localhost:10000" },
{ value: "MINIO_ACCESS_KEY" },
{ value: "MINIO_SECRET_KEY" },
];
function checkURLs(config) {
const mainPort = config["MAIN_PORT"], username = config["COUCH_DB_USER"], password = config["COUCH_DB_PASSWORD"];
if (!config["COUCH_DB_URL"] && mainPort && username && password) {
config["COUCH_DB_URL"] = `http://${username}:${password}@localhost:${mainPort}/db/`;
}
if (!config["MINIO_URL"]) {
config["MINIO_URL"] = `http://localhost:${mainPort}/`;
}
return config;
}
exports.checkURLs = checkURLs;
function askQuestions() {
return __awaiter(this, void 0, void 0, function* () {
console.log("*** NOTE: use a .env file to load these parameters repeatedly ***");
let config = {};
for (let property of REQUIRED) {
config[property.value] = yield (0, questions_1.string)(property.value, property.default);
}
return config;
});
}
exports.askQuestions = askQuestions;
function loadEnvironment(path) {
if (!fs_1.default.existsSync(path)) {
throw "Unable to file specified .env file";
}
const env = fs_1.default.readFileSync(path, "utf8");
const config = checkURLs(dotenv_1.default.parse(env));
for (let required of REQUIRED) {
if (!config[required.value]) {
throw `Cannot find "${required.value}" property in .env file`;
}
}
return config;
}
exports.loadEnvironment = loadEnvironment;
// true is the default value passed by commander
function getConfig(envFile = true) {
return __awaiter(this, void 0, void 0, function* () {
let config;
if (envFile !== true) {
config = loadEnvironment(envFile);
}
else {
config = yield askQuestions();
}
// fill out environment
for (let key of Object.keys(config)) {
backend_core_1.env._set(key, config[key]);
}
return config;
});
}
exports.getConfig = getConfig;
function replication(from, to) {
return __awaiter(this, void 0, void 0, function* () {
const pouch = (0, db_1.getPouch)();
try {
yield pouch.replicate(from, to, {
batch_size: 1000,
batches_limit: 5,
// @ts-ignore
style: "main_only",
});
}
catch (err) {
throw new Error(`Replication failed - ${JSON.stringify(err)}`);
}
});
}
exports.replication = replication;
function getPouches(config) {
const Remote = (0, db_1.getPouch)(config["COUCH_DB_URL"]);
const Local = (0, db_1.getPouch)();
return { Remote, Local };
}
exports.getPouches = getPouches;

9
packages/cli/dist/src/constants.js vendored Normal file
View file

@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GENERATED_USER_EMAIL = exports.POSTHOG_TOKEN = exports.AnalyticsEvent = exports.InitType = exports.CommandWord = void 0;
var types_1 = require("@budibase/types");
Object.defineProperty(exports, "CommandWord", { enumerable: true, get: function () { return types_1.CommandWord; } });
Object.defineProperty(exports, "InitType", { enumerable: true, get: function () { return types_1.InitType; } });
Object.defineProperty(exports, "AnalyticsEvent", { enumerable: true, get: function () { return types_1.AnalyticsEvent; } });
exports.POSTHOG_TOKEN = "phc_yGOn4i7jWKaCTapdGR6lfA4AvmuEQ2ijn5zAVSFYPlS";
exports.GENERATED_USER_EMAIL = "admin@admin.com";

55
packages/cli/dist/src/core/db.js vendored Normal file
View file

@ -0,0 +1,55 @@
"use strict";
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 });
exports.getAllDbs = exports.getPouch = void 0;
const pouchdb_1 = __importDefault(require("pouchdb"));
const utils_1 = require("../utils");
const node_fetch_1 = __importDefault(require("node-fetch"));
/**
* Fully qualified URL including username and password, or nothing for local
*/
function getPouch(url) {
let POUCH_DB_DEFAULTS;
if (!url) {
POUCH_DB_DEFAULTS = {
prefix: undefined,
adapter: "leveldb",
};
}
else {
POUCH_DB_DEFAULTS = {
prefix: url,
};
}
const replicationStream = require("pouchdb-replication-stream");
pouchdb_1.default.plugin(replicationStream.plugin);
// @ts-ignore
pouchdb_1.default.adapter("writableStream", replicationStream.adapters.writableStream);
return pouchdb_1.default.defaults(POUCH_DB_DEFAULTS);
}
exports.getPouch = getPouch;
function getAllDbs(url) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield (0, node_fetch_1.default)((0, utils_1.checkSlashesInUrl)(encodeURI(`${url}/_all_dbs`)), {
method: "GET",
});
if (response.status === 200) {
return yield response.json();
}
else {
throw "Cannot connect to CouchDB instance";
}
});
}
exports.getAllDbs = getAllDbs;

4
packages/cli/dist/src/environment.js vendored Normal file
View file

@ -0,0 +1,4 @@
"use strict";
process.env.NO_JS = "1";
process.env.JS_BCRYPT = "1";
process.env.DISABLE_JWT_WARNING = "1";

13
packages/cli/dist/src/events.js vendored Normal file
View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.captureEvent = void 0;
const Client_1 = require("./analytics/Client");
const client = new Client_1.AnalyticsClient();
function captureEvent(event, properties) {
client.capture({
distinctId: "cli",
event,
properties,
});
}
exports.captureEvent = captureEvent;

49
packages/cli/dist/src/exec.js vendored Normal file
View file

@ -0,0 +1,49 @@
"use strict";
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 });
exports.runPkgCommand = exports.utilityInstalled = exports.exec = void 0;
const util_1 = __importDefault(require("util"));
const runCommand = util_1.default.promisify(require("child_process").exec);
function exec(command, dir = "./") {
return __awaiter(this, void 0, void 0, function* () {
const { stdout } = yield runCommand(command, { cwd: dir });
return stdout;
});
}
exports.exec = exec;
function utilityInstalled(utilName) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield exec(`${utilName} --version`);
return true;
}
catch (err) {
return false;
}
});
}
exports.utilityInstalled = utilityInstalled;
function runPkgCommand(command, dir = "./") {
return __awaiter(this, void 0, void 0, function* () {
const yarn = yield exports.utilityInstalled("yarn");
const npm = yield exports.utilityInstalled("npm");
if (!yarn && !npm) {
throw new Error("Must have yarn or npm installed to run build.");
}
const npmCmd = command === "install" ? `npm ${command}` : `npm run ${command}`;
const cmd = yarn ? `yarn ${command} --ignore-engines` : npmCmd;
yield exports.exec(cmd, dir);
});
}
exports.runPkgCommand = runPkgCommand;

View file

@ -0,0 +1,32 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateUser = void 0;
const { success } = require("../utils");
const { updateDockerComposeService } = require("./utils");
const randomString = require("randomstring");
const { GENERATED_USER_EMAIL } = require("../constants");
function generateUser(password, silent) {
return __awaiter(this, void 0, void 0, function* () {
const email = GENERATED_USER_EMAIL;
if (!password) {
password = randomString.generate({ length: 6 });
}
updateDockerComposeService((service) => {
service.environment["BB_ADMIN_USER_EMAIL"] = email;
service.environment["BB_ADMIN_USER_PASSWORD"] = password;
});
if (!silent) {
console.log(success(`User admin credentials configured, access with email: ${email} - password: ${password}`));
}
});
}
exports.generateUser = generateUser;

21
packages/cli/dist/src/hosting/index.js vendored Normal file
View file

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Command_1 = require("../structures/Command");
const constants_1 = require("../constants");
const init_1 = require("./init");
const start_1 = require("./start");
const stop_1 = require("./stop");
const status_1 = require("./status");
const update_1 = require("./update");
const genUser_1 = require("./genUser");
const watch_1 = require("./watch");
exports.default = new Command_1.Command(`${constants_1.CommandWord.HOSTING}`)
.addHelp("Controls self hosting on the Budibase platform.")
.addSubOption("--init [type]", "Configure a self hosted platform in current directory, type can be unspecified, 'quick' or 'single'.", init_1.init)
.addSubOption("--start", "Start the configured platform in current directory.", start_1.start)
.addSubOption("--status", "Check the status of currently running services.", status_1.status)
.addSubOption("--stop", "Stop the configured platform in the current directory.", stop_1.stop)
.addSubOption("--update", "Update the Budibase images to the latest version.", update_1.update)
.addSubOption("--watch-plugin-dir [directory]", "Add plugin directory watching to a Budibase install.", watch_1.watchPlugins)
.addSubOption("--gen-user", "Create an admin user automatically as part of first start.", genUser_1.generateUser)
.addSubOption("--single", "Specify this with init to use the single image.");

117
packages/cli/dist/src/hosting/init.js vendored Normal file
View file

@ -0,0 +1,117 @@
"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 });
exports.init = void 0;
const constants_1 = require("../constants");
const questions_1 = require("../questions");
const events_1 = require("../events");
const makeFiles = __importStar(require("./makeFiles"));
const utils_1 = require("../utils");
const utils_2 = require("./utils");
const watch_1 = require("./watch");
const genUser_1 = require("./genUser");
const node_fetch_1 = __importDefault(require("node-fetch"));
const DO_USER_DATA_URL = "http://169.254.169.254/metadata/v1/user-data";
function getInitConfig(type, isQuick, port) {
return __awaiter(this, void 0, void 0, function* () {
const config = isQuick ? makeFiles.QUICK_CONFIG : {};
if (type === constants_1.InitType.DIGITAL_OCEAN) {
try {
const output = yield (0, node_fetch_1.default)(DO_USER_DATA_URL);
const data = yield output.text();
const response = (0, utils_1.parseEnv)(data);
for (let [key, value] of Object.entries(makeFiles.ConfigMap)) {
if (response[key]) {
config[value] = response[key];
}
}
}
catch (err) {
// don't need to handle error, just don't do anything
}
}
// override port
if (port) {
config[makeFiles.ConfigMap.MAIN_PORT] = port;
}
return config;
});
}
function init(opts) {
return __awaiter(this, void 0, void 0, function* () {
let type, isSingle, watchDir, genUser, port, silent;
if (typeof opts === "string") {
type = opts;
}
else {
type = opts["init"];
isSingle = opts["single"];
watchDir = opts["watchPluginDir"];
genUser = opts["genUser"];
port = opts["port"];
silent = opts["silent"];
}
const isQuick = type === constants_1.InitType.QUICK || type === constants_1.InitType.DIGITAL_OCEAN;
yield (0, utils_2.checkDockerConfigured)();
if (!isQuick) {
const shouldContinue = yield (0, questions_1.confirmation)("This will create multiple files in current directory, should continue?");
if (!shouldContinue) {
console.log("Stopping.");
return;
}
}
(0, events_1.captureEvent)(constants_1.AnalyticsEvent.SelfHostInit, {
type,
});
const config = yield getInitConfig(type, isQuick, port);
if (!isSingle) {
yield (0, utils_2.downloadDockerCompose)();
yield makeFiles.makeEnv(config, silent);
}
else {
yield makeFiles.makeSingleCompose(config, silent);
}
if (watchDir) {
yield (0, watch_1.watchPlugins)(watchDir, silent);
}
if (genUser) {
const inputPassword = typeof genUser === "string" ? genUser : null;
yield (0, genUser_1.generateUser)(inputPassword, silent);
}
});
}
exports.init = init;

View file

@ -0,0 +1,144 @@
"use strict";
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 });
exports.getComposeProperty = exports.getEnvProperty = exports.makeSingleCompose = exports.makeEnv = exports.QUICK_CONFIG = exports.ConfigMap = exports.ENV_PATH = exports.COMPOSE_PATH = void 0;
const questions_1 = require("../questions");
const utils_1 = require("../utils");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const yaml_1 = __importDefault(require("yaml"));
const utils_2 = require("./utils");
const randomString = require("randomstring");
const SINGLE_IMAGE = "budibase/budibase:latest";
const VOL_NAME = "budibase_data";
exports.COMPOSE_PATH = path_1.default.resolve("./docker-compose.yaml");
exports.ENV_PATH = path_1.default.resolve("./.env");
function getSecrets(opts = { single: false }) {
const secrets = [
"API_ENCRYPTION_KEY",
"JWT_SECRET",
"MINIO_ACCESS_KEY",
"MINIO_SECRET_KEY",
"REDIS_PASSWORD",
"INTERNAL_API_KEY",
];
const obj = {};
secrets.forEach(secret => (obj[secret] = randomString.generate()));
// setup couch creds separately
if (opts && opts.single) {
obj["COUCHDB_USER"] = "admin";
obj["COUCHDB_PASSWORD"] = randomString.generate();
}
else {
obj["COUCH_DB_USER"] = "admin";
obj["COUCH_DB_PASSWORD"] = randomString.generate();
}
return obj;
}
function getSingleCompose(port) {
const singleComposeObj = {
version: "3",
services: {
budibase: {
restart: "unless-stopped",
image: SINGLE_IMAGE,
ports: [`${port}:80`],
environment: getSecrets({ single: true }),
volumes: [`${VOL_NAME}:/data`],
},
},
volumes: {
[VOL_NAME]: {
driver: "local",
},
},
};
return yaml_1.default.stringify(singleComposeObj);
}
function getEnv(port) {
const partOne = (0, utils_1.stringifyToDotEnv)({
MAIN_PORT: port,
});
const partTwo = (0, utils_1.stringifyToDotEnv)(getSecrets());
const partThree = (0, utils_1.stringifyToDotEnv)({
APP_PORT: 4002,
WORKER_PORT: 4003,
MINIO_PORT: 4004,
COUCH_DB_PORT: 4005,
REDIS_PORT: 6379,
WATCHTOWER_PORT: 6161,
BUDIBASE_ENVIRONMENT: "PRODUCTION",
});
return [
"# Use the main port in the builder for your self hosting URL, e.g. localhost:10000",
partOne,
"# This section contains all secrets pertaining to the system",
partTwo,
"# This section contains variables that do not need to be altered under normal circumstances",
partThree,
].join("\n");
}
exports.ConfigMap = {
MAIN_PORT: "port",
};
exports.QUICK_CONFIG = {
key: "budibase",
port: 10000,
};
function make(path, contentsFn, inputs = {}, silent) {
return __awaiter(this, void 0, void 0, function* () {
const port = inputs.port ||
(yield (0, questions_1.number)("Please enter the port on which you want your installation to run: ", 10000));
const fileContents = contentsFn(port);
fs_1.default.writeFileSync(path, fileContents);
if (!silent) {
console.log((0, utils_1.success)(`Configuration has been written successfully - please check ${path} for more details.`));
}
});
}
function makeEnv(inputs = {}, silent) {
return __awaiter(this, void 0, void 0, function* () {
return make(exports.ENV_PATH, getEnv, inputs, silent);
});
}
exports.makeEnv = makeEnv;
function makeSingleCompose(inputs = {}, silent) {
return __awaiter(this, void 0, void 0, function* () {
return make(exports.COMPOSE_PATH, getSingleCompose, inputs, silent);
});
}
exports.makeSingleCompose = makeSingleCompose;
function getEnvProperty(property) {
const props = fs_1.default.readFileSync(exports.ENV_PATH, "utf8").split(property);
if (props[0].charAt(0) === "=") {
property = props[0];
}
else {
property = props[1];
}
return property.split("=")[1].split("\n")[0];
}
exports.getEnvProperty = getEnvProperty;
function getComposeProperty(property) {
const { service } = (0, utils_2.getAppService)(exports.COMPOSE_PATH);
if (property === "port" && Array.isArray(service.ports)) {
const port = service.ports[0];
return port.split(":")[0];
}
else if (service.environment) {
return service.environment[property];
}
return null;
}
exports.getComposeProperty = getComposeProperty;

63
packages/cli/dist/src/hosting/start.js vendored Normal file
View file

@ -0,0 +1,63 @@
"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 });
exports.start = void 0;
const utils_1 = require("./utils");
const utils_2 = require("../utils");
const makeFiles = __importStar(require("./makeFiles"));
const docker_compose_1 = __importDefault(require("docker-compose"));
const fs_1 = __importDefault(require("fs"));
function start() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, utils_1.checkDockerConfigured)();
(0, utils_1.checkInitComplete)();
console.log((0, utils_2.info)("Starting services, this may take a moment - first time this may take a few minutes to download images."));
let port;
if (fs_1.default.existsSync(makeFiles.ENV_PATH)) {
port = makeFiles.getEnvProperty("MAIN_PORT");
}
else {
port = makeFiles.getComposeProperty("port");
}
yield (0, utils_1.handleError)(() => __awaiter(this, void 0, void 0, function* () {
// need to log as it makes it more clear
yield docker_compose_1.default.upAll({ cwd: "./", log: true });
}));
console.log((0, utils_2.success)(`Services started, please go to http://localhost:${port} for next steps.`));
});
}
exports.start = start;

30
packages/cli/dist/src/hosting/status.js vendored Normal file
View file

@ -0,0 +1,30 @@
"use strict";
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 });
exports.status = void 0;
const utils_1 = require("./utils");
const utils_2 = require("../utils");
const docker_compose_1 = __importDefault(require("docker-compose"));
function status() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, utils_1.checkDockerConfigured)();
(0, utils_1.checkInitComplete)();
console.log((0, utils_2.info)("Budibase status"));
yield (0, utils_1.handleError)(() => __awaiter(this, void 0, void 0, function* () {
const response = yield docker_compose_1.default.ps();
console.log(response.out);
}));
});
}
exports.status = status;

30
packages/cli/dist/src/hosting/stop.js vendored Normal file
View file

@ -0,0 +1,30 @@
"use strict";
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 });
exports.stop = void 0;
const utils_1 = require("./utils");
const utils_2 = require("../utils");
const docker_compose_1 = __importDefault(require("docker-compose"));
function stop() {
return __awaiter(this, void 0, void 0, function* () {
yield (0, utils_1.checkDockerConfigured)();
(0, utils_1.checkInitComplete)();
console.log((0, utils_2.info)("Stopping services, this may take a moment."));
yield (0, utils_1.handleError)(() => __awaiter(this, void 0, void 0, function* () {
yield docker_compose_1.default.stop();
}));
console.log((0, utils_2.success)("Services have been stopped successfully."));
});
}
exports.stop = stop;

View file

@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

62
packages/cli/dist/src/hosting/update.js vendored Normal file
View file

@ -0,0 +1,62 @@
"use strict";
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 });
exports.update = void 0;
const utils_1 = require("./utils");
const questions_1 = require("../questions");
const docker_compose_1 = __importDefault(require("docker-compose"));
const makeFiles_1 = require("./makeFiles");
const utils_2 = require("../utils");
const start_1 = require("./start");
const BB_COMPOSE_SERVICES = ["app-service", "worker-service", "proxy-service"];
const BB_SINGLE_SERVICE = ["budibase"];
function update() {
return __awaiter(this, void 0, void 0, function* () {
const { services } = (0, utils_1.getServices)(makeFiles_1.COMPOSE_PATH);
const isSingle = Object.keys(services).length === 1;
yield (0, utils_1.checkDockerConfigured)();
(0, utils_1.checkInitComplete)();
if (!isSingle &&
(yield (0, questions_1.confirmation)("Do you wish to update you docker-compose.yaml?"))) {
// get current MinIO image
const image = yield (0, utils_1.getServiceImage)("minio");
yield (0, utils_1.downloadDockerCompose)();
// replace MinIO image
(0, utils_1.setServiceImage)("minio", image);
}
yield (0, utils_1.handleError)(() => __awaiter(this, void 0, void 0, function* () {
const status = yield docker_compose_1.default.ps();
const parts = status.out.split("\n");
const isUp = parts[2] && parts[2].indexOf("Up") !== -1;
if (isUp) {
console.log((0, utils_2.info)("Stopping services, this may take a moment."));
yield docker_compose_1.default.stop();
}
console.log((0, utils_2.info)("Beginning update, this may take a few minutes."));
let services;
if (isSingle) {
services = BB_SINGLE_SERVICE;
}
else {
services = BB_COMPOSE_SERVICES;
}
yield docker_compose_1.default.pullMany(services, { log: true });
if (isUp) {
console.log((0, utils_2.success)("Update complete, restarting services..."));
yield (0, start_1.start)();
}
}));
});
}
exports.update = update;

159
packages/cli/dist/src/hosting/utils.js vendored Normal file
View file

@ -0,0 +1,159 @@
"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 });
exports.updateDockerComposeService = exports.getAppService = exports.getServices = exports.handleError = exports.checkInitComplete = exports.checkDockerConfigured = exports.downloadDockerCompose = exports.setServiceImage = exports.getServiceImage = void 0;
const lookpath_1 = require("lookpath");
const fs_1 = __importDefault(require("fs"));
const makeFiles = __importStar(require("./makeFiles"));
const utils_1 = require("../utils");
const yaml_1 = __importDefault(require("yaml"));
const ERROR_FILE = "docker-error.log";
const COMPOSE_URL = "https://raw.githubusercontent.com/Budibase/budibase/master/hosting/docker-compose.yaml";
function composeFilename() {
return COMPOSE_URL.split("/").slice(-1)[0];
}
function getServiceImage(service) {
const filename = composeFilename();
try {
const { services } = getServices(filename);
const serviceKey = Object.keys(services).find(name => name.includes(service));
if (serviceKey) {
return services[serviceKey].image;
}
else {
return null;
}
}
catch (err) {
return null;
}
}
exports.getServiceImage = getServiceImage;
function setServiceImage(service, image) {
const filename = composeFilename();
if (!fs_1.default.existsSync(filename)) {
throw new Error(`File ${filename} not found, cannot update ${service} image.`);
}
const current = getServiceImage(service);
let contents = fs_1.default.readFileSync(filename, "utf8");
contents = contents.replace(`image: ${current}`, `image: ${image}`);
fs_1.default.writeFileSync(filename, contents);
}
exports.setServiceImage = setServiceImage;
function downloadDockerCompose() {
return __awaiter(this, void 0, void 0, function* () {
const filename = composeFilename();
try {
yield (0, utils_1.downloadFile)(COMPOSE_URL, `./${filename}`);
}
catch (err) {
console.error((0, utils_1.error)(`Failed to retrieve compose file - ${err}`));
}
});
}
exports.downloadDockerCompose = downloadDockerCompose;
function checkDockerConfigured() {
return __awaiter(this, void 0, void 0, function* () {
const error = "docker/docker-compose has not been installed, please follow instructions at: https://docs.budibase.com/docs/docker-compose";
const docker = yield (0, lookpath_1.lookpath)("docker");
const compose = yield (0, lookpath_1.lookpath)("docker-compose");
if (!docker || !compose) {
throw error;
}
});
}
exports.checkDockerConfigured = checkDockerConfigured;
function checkInitComplete() {
if (!fs_1.default.existsSync(makeFiles.ENV_PATH) &&
!fs_1.default.existsSync(makeFiles.COMPOSE_PATH)) {
throw "Please run the hosting --init command before any other hosting command.";
}
}
exports.checkInitComplete = checkInitComplete;
function handleError(func) {
return __awaiter(this, void 0, void 0, function* () {
try {
yield func();
}
catch (err) {
if (err && err.err) {
(0, utils_1.logErrorToFile)(ERROR_FILE, err.err);
}
throw `Failed to start - logs written to file: ${ERROR_FILE}`;
}
});
}
exports.handleError = handleError;
function getServices(path) {
if (!fs_1.default.existsSync(path)) {
throw new Error(`No yaml found at path: ${path}`);
}
const dockerYaml = fs_1.default.readFileSync(path, "utf8");
const parsedYaml = yaml_1.default.parse(dockerYaml);
return { yaml: parsedYaml, services: parsedYaml.services };
}
exports.getServices = getServices;
function getAppService(path) {
const { yaml, services } = getServices(path), serviceList = Object.keys(services);
let service;
if (services["app-service"]) {
service = services["app-service"];
}
else if (serviceList.length === 1) {
service = services[serviceList[0]];
}
return { yaml, service };
}
exports.getAppService = getAppService;
function updateDockerComposeService(
// eslint-disable-next-line no-unused-vars
updateFn) {
const opts = ["docker-compose.yaml", "docker-compose.yml"];
const dockerFilePath = opts.find(name => fs_1.default.existsSync(name));
if (!dockerFilePath) {
console.log((0, utils_1.error)("Unable to locate docker-compose YAML."));
return;
}
const { yaml: parsedYaml, service } = getAppService(dockerFilePath);
if (!service) {
console.log((0, utils_1.error)("Unable to locate service within compose file, is it a valid Budibase configuration?"));
return;
}
updateFn(service);
fs_1.default.writeFileSync(dockerFilePath, yaml_1.default.stringify(parsedYaml));
}
exports.updateDockerComposeService = updateDockerComposeService;

47
packages/cli/dist/src/hosting/watch.js vendored Normal file
View file

@ -0,0 +1,47 @@
"use strict";
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 });
exports.watchPlugins = void 0;
const path_1 = require("path");
const fs_1 = __importDefault(require("fs"));
const utils_1 = require("../utils");
const utils_2 = require("./utils");
function watchPlugins(pluginPath, silent) {
return __awaiter(this, void 0, void 0, function* () {
const PLUGIN_PATH = "/plugins";
// get absolute path
pluginPath = (0, path_1.resolve)(pluginPath);
if (!fs_1.default.existsSync(pluginPath)) {
console.log((0, utils_1.error)(`The directory "${pluginPath}" does not exist, please create and then try again.`));
return;
}
(0, utils_2.updateDockerComposeService)((service) => {
// set environment variable
service.environment["PLUGINS_DIR"] = PLUGIN_PATH;
// add volumes to parsed yaml
if (!service.volumes) {
service.volumes = [];
}
const found = service.volumes.find(vol => vol.includes(PLUGIN_PATH));
if (found) {
service.volumes.splice(service.volumes.indexOf(found), 1);
}
service.volumes.push(`${pluginPath}:${PLUGIN_PATH}`);
});
if (!silent) {
console.log((0, utils_1.success)(`Docker compose configured to watch directory: ${pluginPath}`));
}
});
}
exports.watchPlugins = watchPlugins;

37
packages/cli/dist/src/index.js vendored Executable file
View file

@ -0,0 +1,37 @@
#!/usr/bin/env node
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
process.env.DISABLE_PINO_LOGGER = "1";
require("./prebuilds");
require("./environment");
const options_1 = require("./options");
const commander_1 = require("commander");
const utils_1 = require("./utils");
const package_json_1 = require("../package.json");
// add hosting config
function init() {
return __awaiter(this, void 0, void 0, function* () {
const program = new commander_1.Command()
.addHelpCommand("help", (0, utils_1.getHelpDescription)("Help with Budibase commands."))
.helpOption(false)
.version(package_json_1.version);
// add commands
for (let command of (0, options_1.getCommands)()) {
command.configure(program);
}
// this will stop the program if no command found
yield program.parseAsync(process.argv);
});
}
init().catch(err => {
console.error(`Unexpected error - `, err);
});

14
packages/cli/dist/src/options.js vendored Normal file
View file

@ -0,0 +1,14 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCommands = void 0;
const analytics_1 = __importDefault(require("./analytics"));
const hosting_1 = __importDefault(require("./hosting"));
const backups_1 = __importDefault(require("./backups"));
const plugins_1 = __importDefault(require("./plugins"));
function getCommands() {
return [hosting_1.default, analytics_1.default, backups_1.default, plugins_1.default];
}
exports.getCommands = getCommands;

199
packages/cli/dist/src/plugins/index.js vendored Normal file
View file

@ -0,0 +1,199 @@
"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', 'datasource' or 'automation'."));
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);

View file

@ -0,0 +1,75 @@
"use strict";
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 });
exports.fleshOutSkeleton = exports.getSkeleton = void 0;
const node_fetch_1 = __importDefault(require("node-fetch"));
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = require("path");
const string_templates_1 = require("@budibase/string-templates");
const download = require("download");
const tar = require("tar");
const HBS_FILES = ["package.json.hbs", "schema.json.hbs", "README.md.hbs"];
function getSkeletonUrl(type) {
return __awaiter(this, void 0, void 0, function* () {
const resp = yield (0, node_fetch_1.default)("https://api.github.com/repos/budibase/budibase-skeleton/releases/latest");
if (resp.status >= 300) {
throw new Error("Failed to retrieve skeleton metadata");
}
const json = (yield resp.json());
for (let asset of json["assets"]) {
if (asset.name && asset.name.includes(type)) {
return asset["browser_download_url"];
}
}
throw new Error("No skeleton found in latest release.");
});
}
function getSkeleton(type, name) {
return __awaiter(this, void 0, void 0, function* () {
const url = yield getSkeletonUrl(type);
const tarballFile = (0, path_1.join)(os_1.default.tmpdir(), "skeleton.tar.gz");
// download the full skeleton tarball
fs_1.default.writeFileSync(tarballFile, yield download(url));
fs_1.default.mkdirSync(name);
// extract it and get what we need
yield tar.extract({
file: tarballFile,
C: name,
});
// clear up
fs_1.default.rmSync(tarballFile);
});
}
exports.getSkeleton = getSkeleton;
function fleshOutSkeleton(type, name, description, version) {
return __awaiter(this, void 0, void 0, function* () {
for (let file of HBS_FILES) {
const oldFile = (0, path_1.join)(name, file), newFile = (0, path_1.join)(name, file.substring(0, file.length - 4));
const hbsContents = fs_1.default.readFileSync(oldFile, "utf8");
if (!hbsContents) {
continue;
}
const output = (0, string_templates_1.processStringSync)(hbsContents, {
name,
description,
version,
});
// write the updated file and remove the HBS file
fs_1.default.writeFileSync(newFile, output);
fs_1.default.rmSync(oldFile);
}
});
}
exports.fleshOutSkeleton = fleshOutSkeleton;

46
packages/cli/dist/src/prebuilds.js vendored Normal file
View file

@ -0,0 +1,46 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const os_1 = __importDefault(require("os"));
const path_1 = require("path");
const fs_1 = __importDefault(require("fs"));
const utils_1 = require("./utils");
const PREBUILDS = "prebuilds";
const ARCH = `${os_1.default.platform()}-${os_1.default.arch()}`;
const PREBUILD_DIR = (0, path_1.join)(process.execPath, "..", PREBUILDS, ARCH);
// running as built CLI pkg bundle
if (!process.argv[0].includes("node")) {
checkForBinaries();
}
function checkForBinaries() {
const readDir = (0, path_1.join)(__filename, "..", "..", "..", PREBUILDS, ARCH);
if (fs_1.default.existsSync(PREBUILD_DIR) || !fs_1.default.existsSync(readDir)) {
return;
}
const natives = fs_1.default.readdirSync(readDir);
if (fs_1.default.existsSync(readDir)) {
fs_1.default.mkdirSync(PREBUILD_DIR, { recursive: true });
for (let native of natives) {
const filename = `${native.split(".fake")[0]}.node`;
fs_1.default.cpSync((0, path_1.join)(readDir, native), (0, path_1.join)(PREBUILD_DIR, filename));
}
}
}
function cleanup(evt) {
if (evt && !isNaN(evt)) {
return;
}
if (evt) {
console.error((0, utils_1.error)("Failed to run CLI command - please report with the following message:"));
console.error((0, utils_1.error)(evt));
}
if (fs_1.default.existsSync(PREBUILD_DIR)) {
fs_1.default.rmSync(PREBUILD_DIR, { recursive: true });
}
}
const events = ["exit", "SIGINT", "SIGUSR1", "SIGUSR2", "uncaughtException"];
events.forEach(event => {
process.on(event, cleanup);
});

58
packages/cli/dist/src/questions.js vendored Normal file
View file

@ -0,0 +1,58 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.number = exports.string = exports.confirmation = void 0;
const inquirer = require("inquirer");
function confirmation(question) {
return __awaiter(this, void 0, void 0, function* () {
const config = {
type: "confirm",
message: question,
default: true,
name: "confirmation",
};
return (yield inquirer.prompt(config)).confirmation;
});
}
exports.confirmation = confirmation;
function string(question, defaultString) {
return __awaiter(this, void 0, void 0, function* () {
const config = {
type: "input",
name: "string",
message: question,
};
if (defaultString) {
config.default = defaultString;
}
return (yield inquirer.prompt(config)).string;
});
}
exports.string = string;
function number(question, defaultNumber) {
return __awaiter(this, void 0, void 0, function* () {
const config = {
type: "input",
name: "number",
message: question,
validate: (value) => {
let valid = !isNaN(parseFloat(value));
return valid || "Please enter a number";
},
filter: Number,
};
if (defaultNumber) {
config.default = defaultNumber;
}
return (yield inquirer.prompt(config)).number;
});
}
exports.number = number;

View file

@ -0,0 +1,75 @@
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Command = void 0;
const utils_1 = require("../utils");
class Command {
constructor(command, func) {
// if there are options, need to just get the command name
this.command = command;
this.opts = [];
this.func = func;
}
convertToCommander(lookup) {
const parts = lookup.toLowerCase().split("-");
// camel case, separate out first
const first = parts.shift();
return [first]
.concat(parts.map(part => (0, utils_1.capitaliseFirstLetter)(part)))
.join("");
}
addHelp(help) {
this.help = help;
return this;
}
addSubOption(command, help, func, extras = []) {
this.opts.push({ command, help, func, extras });
return this;
}
configure(program) {
const thisCmd = this;
let command = program.command(thisCmd.command);
if (this.help) {
command = command.description((0, utils_1.getHelpDescription)(thisCmd.help));
}
for (let opt of thisCmd.opts) {
command = command.option(opt.command, (0, utils_1.getSubHelpDescription)(opt.help));
}
command.helpOption("--help", (0, utils_1.getSubHelpDescription)(`Get help with ${this.command} options`));
command.action((options) => __awaiter(this, void 0, void 0, function* () {
try {
let executed = false, found = false;
for (let opt of thisCmd.opts) {
let lookup = opt.command.split(" ")[0].replace("--", "");
// need to handle how commander converts watch-plugin-dir to watchPluginDir
lookup = this.convertToCommander(lookup);
found = !executed && !!options[lookup];
if (found && opt.func) {
const input = Object.keys(options).length > 1 ? options : options[lookup];
yield opt.func(input);
executed = true;
}
}
if (found && !executed) {
console.log((0, utils_1.error)(`${Object.keys(options)[0]} is an option, not an operation.`));
}
else if (!executed) {
console.log((0, utils_1.error)(`Unknown ${this.command} option.`));
command.help();
}
}
catch (err) {
console.log((0, utils_1.error)(err));
}
}));
}
}
exports.Command = Command;

View file

@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigManager = void 0;
const fs = require("fs");
const path = require("path");
const os = require("os");
const { error } = require("../utils");
class ConfigManager {
constructor() {
this.path = path.join(os.homedir(), ".budibase.json");
if (!fs.existsSync(this.path)) {
fs.writeFileSync(this.path, "{}");
}
}
get config() {
try {
return JSON.parse(fs.readFileSync(this.path, "utf8"));
}
catch (err) {
console.log(error("Error parsing configuration file. Please check your .budibase.json is valid."));
return {};
}
}
set config(json) {
fs.writeFileSync(this.path, JSON.stringify(json));
}
getValue(key) {
return this.config[key];
}
setValue(key, value) {
this.config = Object.assign(Object.assign({}, this.config), { [key]: value });
}
removeKey(key) {
const updated = Object.assign({}, this.config);
delete updated[key];
this.config = updated;
}
}
exports.ConfigManager = ConfigManager;

126
packages/cli/dist/src/utils.js vendored Normal file
View file

@ -0,0 +1,126 @@
"use strict";
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 });
exports.stringifyToDotEnv = exports.capitaliseFirstLetter = exports.moveDirectory = exports.checkSlashesInUrl = exports.progressBar = exports.parseEnv = exports.logErrorToFile = exports.info = exports.success = exports.error = exports.getSubHelpDescription = exports.getHelpDescription = exports.httpCall = exports.downloadFile = void 0;
const chalk_1 = __importDefault(require("chalk"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const path_2 = require("path");
const node_fetch_1 = __importDefault(require("node-fetch"));
const progress = require("cli-progress");
function downloadFile(url, filePath) {
return new Promise((resolve, reject) => {
filePath = path_1.default.resolve(filePath);
(0, node_fetch_1.default)(url, {
method: "GET",
})
.then(response => {
const writer = fs_1.default.createWriteStream(filePath);
if (response.body) {
response.body.pipe(writer);
response.body.on("end", resolve);
response.body.on("error", reject);
}
else {
throw new Error(`Unable to retrieve docker-compose file - ${response.status}`);
}
})
.catch(err => {
throw err;
});
});
}
exports.downloadFile = downloadFile;
function httpCall(url, method) {
return __awaiter(this, void 0, void 0, function* () {
const response = yield (0, node_fetch_1.default)(url, {
method,
});
return response.body;
});
}
exports.httpCall = httpCall;
function getHelpDescription(str) {
return chalk_1.default.cyan(str);
}
exports.getHelpDescription = getHelpDescription;
function getSubHelpDescription(str) {
return chalk_1.default.green(str);
}
exports.getSubHelpDescription = getSubHelpDescription;
function error(err) {
process.exitCode = -1;
return chalk_1.default.red(`Error - ${err}`);
}
exports.error = error;
function success(str) {
return chalk_1.default.green(str);
}
exports.success = success;
function info(str) {
return chalk_1.default.cyan(str);
}
exports.info = info;
function logErrorToFile(file, error) {
fs_1.default.writeFileSync(path_1.default.resolve(`./${file}`), `Budibase Error\n${error}`);
}
exports.logErrorToFile = logErrorToFile;
function parseEnv(env) {
const lines = env.toString().split("\n");
let result = {};
for (const line of lines) {
const match = line.match(/^([^=:#]+?)[=:](.*)/);
if (match) {
result[match[1].trim()] = match[2].trim();
}
}
return result;
}
exports.parseEnv = parseEnv;
function progressBar(total) {
const bar = new progress.SingleBar({}, progress.Presets.shades_classic);
bar.start(total, 0);
return bar;
}
exports.progressBar = progressBar;
function checkSlashesInUrl(url) {
return url.replace(/(https?:\/\/)|(\/)+/g, "$1$2");
}
exports.checkSlashesInUrl = checkSlashesInUrl;
function moveDirectory(oldPath, newPath) {
const files = fs_1.default.readdirSync(oldPath);
// check any file exists already
for (let file of files) {
if (fs_1.default.existsSync((0, path_2.join)(newPath, file))) {
throw new Error("Unable to remove top level directory - some skeleton files already exist.");
}
}
for (let file of files) {
fs_1.default.renameSync((0, path_2.join)(oldPath, file), (0, path_2.join)(newPath, file));
}
fs_1.default.rmdirSync(oldPath);
}
exports.moveDirectory = moveDirectory;
function capitaliseFirstLetter(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
exports.capitaliseFirstLetter = capitaliseFirstLetter;
function stringifyToDotEnv(json) {
let str = "";
for (let [key, value] of Object.entries(json)) {
str += `${key}=${value}\n`;
}
return str;
}
exports.stringifyToDotEnv = stringifyToDotEnv;