@budibase/cli 1.3.21-alpha.0 → 1.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -7
- package/src/constants.js +0 -4
- package/src/hosting/index.js +9 -3
- package/src/index.js +0 -1
- package/src/options.js +1 -2
- package/src/prebuilds.js +2 -17
- package/src/utils.js +0 -17
- package/src/environment.js +0 -2
- package/src/events.js +0 -11
- package/src/exec.js +0 -27
- package/src/plugins/index.js +0 -164
- package/src/plugins/skeleton.js +0 -60
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/cli",
|
|
3
|
-
"version": "1.3.21
|
|
3
|
+
"version": "1.3.21",
|
|
4
4
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,18 +26,14 @@
|
|
|
26
26
|
"outputPath": "build"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@budibase/backend-core": "1.3.21
|
|
30
|
-
"@budibase/string-templates": "1.3.21-alpha.0",
|
|
31
|
-
"@budibase/types": "1.3.21-alpha.0",
|
|
29
|
+
"@budibase/backend-core": "^1.3.21",
|
|
32
30
|
"axios": "0.21.2",
|
|
33
31
|
"chalk": "4.1.0",
|
|
34
32
|
"cli-progress": "3.11.2",
|
|
35
33
|
"commander": "7.1.0",
|
|
36
34
|
"docker-compose": "0.23.6",
|
|
37
35
|
"dotenv": "16.0.1",
|
|
38
|
-
"download": "8.0.0",
|
|
39
36
|
"inquirer": "8.0.0",
|
|
40
|
-
"joi": "17.6.0",
|
|
41
37
|
"lookpath": "1.1.0",
|
|
42
38
|
"node-fetch": "2",
|
|
43
39
|
"pkg": "5.7.0",
|
|
@@ -52,5 +48,5 @@
|
|
|
52
48
|
"eslint": "^7.20.0",
|
|
53
49
|
"renamer": "^4.0.0"
|
|
54
50
|
},
|
|
55
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "19ed43cb817a650c859e9d237c5053cd3ee54526"
|
|
56
52
|
}
|
package/src/constants.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
const { Event } = require("@budibase/types")
|
|
2
|
-
|
|
3
1
|
exports.CommandWords = {
|
|
4
2
|
BACKUPS: "backups",
|
|
5
3
|
HOSTING: "hosting",
|
|
6
4
|
ANALYTICS: "analytics",
|
|
7
5
|
HELP: "help",
|
|
8
|
-
PLUGIN: "plugins",
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
exports.InitTypes = {
|
|
@@ -17,7 +14,6 @@ exports.AnalyticsEvents = {
|
|
|
17
14
|
OptOut: "analytics:opt:out",
|
|
18
15
|
OptIn: "analytics:opt:in",
|
|
19
16
|
SelfHostInit: "hosting:init",
|
|
20
|
-
PluginInit: Event.PLUGIN_INIT,
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
exports.POSTHOG_TOKEN = "phc_yGOn4i7jWKaCTapdGR6lfA4AvmuEQ2ijn5zAVSFYPlS"
|
package/src/hosting/index.js
CHANGED
|
@@ -13,7 +13,7 @@ const fs = require("fs")
|
|
|
13
13
|
const compose = require("docker-compose")
|
|
14
14
|
const makeEnv = require("./makeEnv")
|
|
15
15
|
const axios = require("axios")
|
|
16
|
-
const
|
|
16
|
+
const AnalyticsClient = require("../analytics/Client")
|
|
17
17
|
|
|
18
18
|
const BUDIBASE_SERVICES = ["app-service", "worker-service", "proxy-service"]
|
|
19
19
|
const ERROR_FILE = "docker-error.log"
|
|
@@ -22,6 +22,8 @@ const FILE_URLS = [
|
|
|
22
22
|
]
|
|
23
23
|
const DO_USER_DATA_URL = "http://169.254.169.254/metadata/v1/user-data"
|
|
24
24
|
|
|
25
|
+
const client = new AnalyticsClient()
|
|
26
|
+
|
|
25
27
|
async function downloadFiles() {
|
|
26
28
|
const promises = []
|
|
27
29
|
for (let url of FILE_URLS) {
|
|
@@ -70,8 +72,12 @@ async function init(type) {
|
|
|
70
72
|
return
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
client.capture({
|
|
76
|
+
distinctId: "cli",
|
|
77
|
+
event: AnalyticsEvents.SelfHostInit,
|
|
78
|
+
properties: {
|
|
79
|
+
type,
|
|
80
|
+
},
|
|
75
81
|
})
|
|
76
82
|
await downloadFiles()
|
|
77
83
|
const config = isQuick ? makeEnv.QUICK_CONFIG : {}
|
package/src/index.js
CHANGED
package/src/options.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const analytics = require("./analytics")
|
|
2
2
|
const hosting = require("./hosting")
|
|
3
3
|
const backups = require("./backups")
|
|
4
|
-
const plugins = require("./plugins")
|
|
5
4
|
|
|
6
5
|
exports.getCommands = () => {
|
|
7
|
-
return [hosting.command, analytics.command, backups.command
|
|
6
|
+
return [hosting.command, analytics.command, backups.command]
|
|
8
7
|
}
|
package/src/prebuilds.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
const os = require("os")
|
|
2
2
|
const { join } = require("path")
|
|
3
3
|
const fs = require("fs")
|
|
4
|
-
const { error } = require("./utils")
|
|
5
4
|
const PREBUILDS = "prebuilds"
|
|
6
5
|
const ARCH = `${os.platform()}-${os.arch()}`
|
|
7
6
|
const PREBUILD_DIR = join(process.execPath, "..", PREBUILDS, ARCH)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
if (!process.argv[0].includes("node")) {
|
|
11
|
-
checkForBinaries()
|
|
12
|
-
}
|
|
8
|
+
checkForBinaries()
|
|
13
9
|
|
|
14
10
|
function checkForBinaries() {
|
|
15
11
|
const readDir = join(__filename, "..", "..", PREBUILDS, ARCH)
|
|
@@ -26,18 +22,7 @@ function checkForBinaries() {
|
|
|
26
22
|
}
|
|
27
23
|
}
|
|
28
24
|
|
|
29
|
-
function cleanup(
|
|
30
|
-
if (!isNaN(evt)) {
|
|
31
|
-
return
|
|
32
|
-
}
|
|
33
|
-
if (evt) {
|
|
34
|
-
console.error(
|
|
35
|
-
error(
|
|
36
|
-
"Failed to run CLI command - please report with the following message:"
|
|
37
|
-
)
|
|
38
|
-
)
|
|
39
|
-
console.error(error(evt))
|
|
40
|
-
}
|
|
25
|
+
function cleanup() {
|
|
41
26
|
if (fs.existsSync(PREBUILD_DIR)) {
|
|
42
27
|
fs.rmSync(PREBUILD_DIR, { recursive: true })
|
|
43
28
|
}
|
package/src/utils.js
CHANGED
|
@@ -3,7 +3,6 @@ const fs = require("fs")
|
|
|
3
3
|
const axios = require("axios")
|
|
4
4
|
const path = require("path")
|
|
5
5
|
const progress = require("cli-progress")
|
|
6
|
-
const { join } = require("path")
|
|
7
6
|
|
|
8
7
|
exports.downloadFile = async (url, filePath) => {
|
|
9
8
|
filePath = path.resolve(filePath)
|
|
@@ -68,19 +67,3 @@ exports.progressBar = total => {
|
|
|
68
67
|
exports.checkSlashesInUrl = url => {
|
|
69
68
|
return url.replace(/(https?:\/\/)|(\/)+/g, "$1$2")
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
exports.moveDirectory = (oldPath, newPath) => {
|
|
73
|
-
const files = fs.readdirSync(oldPath)
|
|
74
|
-
// check any file exists already
|
|
75
|
-
for (let file of files) {
|
|
76
|
-
if (fs.existsSync(join(newPath, file))) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
"Unable to remove top level directory - some skeleton files already exist."
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
for (let file of files) {
|
|
83
|
-
fs.renameSync(join(oldPath, file), join(newPath, file))
|
|
84
|
-
}
|
|
85
|
-
fs.rmdirSync(oldPath)
|
|
86
|
-
}
|
package/src/environment.js
DELETED
package/src/events.js
DELETED
package/src/exec.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
const util = require("util")
|
|
2
|
-
const exec = util.promisify(require("child_process").exec)
|
|
3
|
-
|
|
4
|
-
exports.exec = async (command, dir = "./") => {
|
|
5
|
-
const { stdout } = await exec(command, { cwd: dir })
|
|
6
|
-
return stdout
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
exports.utilityInstalled = async utilName => {
|
|
10
|
-
try {
|
|
11
|
-
await exports.exec(`${utilName} --version`)
|
|
12
|
-
return true
|
|
13
|
-
} catch (err) {
|
|
14
|
-
return false
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
exports.runPkgCommand = async (command, dir = "./") => {
|
|
19
|
-
const yarn = await exports.utilityInstalled("yarn")
|
|
20
|
-
const npm = await exports.utilityInstalled("npm")
|
|
21
|
-
if (!yarn && !npm) {
|
|
22
|
-
throw new Error("Must have yarn or npm installed to run build.")
|
|
23
|
-
}
|
|
24
|
-
const npmCmd = command === "install" ? `npm ${command}` : `npm run ${command}`
|
|
25
|
-
const cmd = yarn ? `yarn ${command}` : npmCmd
|
|
26
|
-
await exports.exec(cmd, dir)
|
|
27
|
-
}
|
package/src/plugins/index.js
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
const Command = require("../structures/Command")
|
|
2
|
-
const { CommandWords, AnalyticsEvents } = require("../constants")
|
|
3
|
-
const { getSkeleton, fleshOutSkeleton } = require("./skeleton")
|
|
4
|
-
const questions = require("../questions")
|
|
5
|
-
const fs = require("fs")
|
|
6
|
-
const { PLUGIN_TYPE_ARR } = require("@budibase/types")
|
|
7
|
-
const { validate } = require("@budibase/backend-core/plugins")
|
|
8
|
-
const { runPkgCommand } = require("../exec")
|
|
9
|
-
const { join } = require("path")
|
|
10
|
-
const { success, error, info, moveDirectory } = require("../utils")
|
|
11
|
-
const { captureEvent } = require("../events")
|
|
12
|
-
|
|
13
|
-
function checkInPlugin() {
|
|
14
|
-
if (!fs.existsSync("package.json")) {
|
|
15
|
-
throw new Error(
|
|
16
|
-
"Please run in a plugin directory - must contain package.json"
|
|
17
|
-
)
|
|
18
|
-
}
|
|
19
|
-
if (!fs.existsSync("schema.json")) {
|
|
20
|
-
throw new Error(
|
|
21
|
-
"Please run in a plugin directory - must contain schema.json"
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async function askAboutTopLevel(name) {
|
|
27
|
-
const files = fs.readdirSync(process.cwd())
|
|
28
|
-
// we are in an empty git repo, don't ask
|
|
29
|
-
if (files.find(file => file === ".git")) {
|
|
30
|
-
return false
|
|
31
|
-
} else {
|
|
32
|
-
console.log(
|
|
33
|
-
info(`By default the plugin will be created in the directory "${name}"`)
|
|
34
|
-
)
|
|
35
|
-
console.log(
|
|
36
|
-
info(
|
|
37
|
-
"if you are already in an empty directory, such as a new Git repo, you can disable this functionality."
|
|
38
|
-
)
|
|
39
|
-
)
|
|
40
|
-
return questions.confirmation("Create top level directory?")
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function init(opts) {
|
|
45
|
-
const type = opts["init"] || opts
|
|
46
|
-
if (!type || !PLUGIN_TYPE_ARR.includes(type)) {
|
|
47
|
-
console.log(
|
|
48
|
-
error(
|
|
49
|
-
"Please provide a type to init, either 'component' or 'datasource'."
|
|
50
|
-
)
|
|
51
|
-
)
|
|
52
|
-
return
|
|
53
|
-
}
|
|
54
|
-
console.log(info("Lets get some details about your new plugin:"))
|
|
55
|
-
const name = await questions.string("Name", `budibase-${type}`)
|
|
56
|
-
if (fs.existsSync(name)) {
|
|
57
|
-
console.log(
|
|
58
|
-
error("Directory by plugin name already exists, pick a new name.")
|
|
59
|
-
)
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
const description = await questions.string(
|
|
63
|
-
"Description",
|
|
64
|
-
`An amazing Budibase ${type}!`
|
|
65
|
-
)
|
|
66
|
-
const version = await questions.string("Version", "1.0.0")
|
|
67
|
-
const topLevel = await askAboutTopLevel(name)
|
|
68
|
-
// get the skeleton
|
|
69
|
-
console.log(info("Retrieving project..."))
|
|
70
|
-
await getSkeleton(type, name)
|
|
71
|
-
await fleshOutSkeleton(type, name, description, version)
|
|
72
|
-
console.log(info("Installing dependencies..."))
|
|
73
|
-
await runPkgCommand("install", join(process.cwd(), name))
|
|
74
|
-
// if no parent directory desired move to cwd
|
|
75
|
-
if (!topLevel) {
|
|
76
|
-
moveDirectory(name, process.cwd())
|
|
77
|
-
console.log(info(`Plugin created in current directory.`))
|
|
78
|
-
} else {
|
|
79
|
-
console.log(info(`Plugin created in directory "${name}"`))
|
|
80
|
-
}
|
|
81
|
-
captureEvent(AnalyticsEvents.PluginInit, {
|
|
82
|
-
type,
|
|
83
|
-
name,
|
|
84
|
-
description,
|
|
85
|
-
version,
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async function verify() {
|
|
90
|
-
// will throw errors if not acceptable
|
|
91
|
-
checkInPlugin()
|
|
92
|
-
console.log(info("Verifying plugin..."))
|
|
93
|
-
const schema = fs.readFileSync("schema.json", "utf8")
|
|
94
|
-
const pkg = fs.readFileSync("package.json", "utf8")
|
|
95
|
-
let name, version
|
|
96
|
-
try {
|
|
97
|
-
const schemaJson = JSON.parse(schema)
|
|
98
|
-
const pkgJson = JSON.parse(pkg)
|
|
99
|
-
if (!pkgJson.name || !pkgJson.version || !pkgJson.description) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
"package.json is missing one of 'name', 'version' or 'description'."
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
name = pkgJson.name
|
|
105
|
-
version = pkgJson.version
|
|
106
|
-
validate(schemaJson)
|
|
107
|
-
return { name, version }
|
|
108
|
-
} catch (err) {
|
|
109
|
-
if (err && err.message && err.message.includes("not valid JSON")) {
|
|
110
|
-
console.log(error(`schema.json is not valid JSON: ${err.message}`))
|
|
111
|
-
} else {
|
|
112
|
-
console.log(error(`Invalid schema/package.json: ${err.message}`))
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function build() {
|
|
118
|
-
const verified = await verify()
|
|
119
|
-
if (!verified.name) {
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
console.log(success("Verified!"))
|
|
123
|
-
console.log(info("Building plugin..."))
|
|
124
|
-
await runPkgCommand("build")
|
|
125
|
-
const output = join("dist", `${verified.name}-${verified.version}.tar.gz`)
|
|
126
|
-
console.log(success(`Build complete - output in: ${output}`))
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async function watch() {
|
|
130
|
-
const verified = await verify()
|
|
131
|
-
if (!verified.name) {
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
const output = join("dist", `${verified.name}-${verified.version}.tar.gz`)
|
|
135
|
-
console.log(info(`Watching - build in: ${output}`))
|
|
136
|
-
try {
|
|
137
|
-
await runPkgCommand("watch")
|
|
138
|
-
} catch (err) {
|
|
139
|
-
// always errors when user escapes
|
|
140
|
-
console.log(success("Watch exited."))
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const command = new Command(`${CommandWords.PLUGIN}`)
|
|
145
|
-
.addHelp(
|
|
146
|
-
"Custom plugins for Budibase, init, build and verify your components and datasources with this tool."
|
|
147
|
-
)
|
|
148
|
-
.addSubOption(
|
|
149
|
-
"--init [type]",
|
|
150
|
-
"Init a new plugin project, with a type of either component or datasource.",
|
|
151
|
-
init
|
|
152
|
-
)
|
|
153
|
-
.addSubOption(
|
|
154
|
-
"--build",
|
|
155
|
-
"Build your plugin, this will verify and produce a final tarball for your project.",
|
|
156
|
-
build
|
|
157
|
-
)
|
|
158
|
-
.addSubOption(
|
|
159
|
-
"--watch",
|
|
160
|
-
"Automatically build any changes to your plugin.",
|
|
161
|
-
watch
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
exports.command = command
|
package/src/plugins/skeleton.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
const fetch = require("node-fetch")
|
|
2
|
-
const download = require("download")
|
|
3
|
-
const fs = require("fs")
|
|
4
|
-
const os = require("os")
|
|
5
|
-
const { join } = require("path")
|
|
6
|
-
const tar = require("tar")
|
|
7
|
-
const { processStringSync } = require("@budibase/string-templates")
|
|
8
|
-
|
|
9
|
-
const HBS_FILES = ["package.json.hbs", "schema.json.hbs", "README.md.hbs"]
|
|
10
|
-
|
|
11
|
-
async function getSkeletonUrl(type) {
|
|
12
|
-
const resp = await fetch(
|
|
13
|
-
"https://api.github.com/repos/budibase/budibase-skeleton/releases/latest"
|
|
14
|
-
)
|
|
15
|
-
if (resp.status >= 300) {
|
|
16
|
-
throw new Error("Failed to retrieve skeleton metadata")
|
|
17
|
-
}
|
|
18
|
-
const json = await resp.json()
|
|
19
|
-
for (let asset of json["assets"]) {
|
|
20
|
-
if (asset.name && asset.name.includes(type)) {
|
|
21
|
-
return asset["browser_download_url"]
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
throw new Error("No skeleton found in latest release.")
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
exports.getSkeleton = async (type, name) => {
|
|
28
|
-
const url = await getSkeletonUrl(type)
|
|
29
|
-
const tarballFile = join(os.tmpdir(), "skeleton.tar.gz")
|
|
30
|
-
|
|
31
|
-
// download the full skeleton tarball
|
|
32
|
-
fs.writeFileSync(tarballFile, await download(url))
|
|
33
|
-
fs.mkdirSync(name)
|
|
34
|
-
// extract it and get what we need
|
|
35
|
-
await tar.extract({
|
|
36
|
-
file: tarballFile,
|
|
37
|
-
C: name,
|
|
38
|
-
})
|
|
39
|
-
// clear up
|
|
40
|
-
fs.rmSync(tarballFile)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
exports.fleshOutSkeleton = async (type, name, description, version) => {
|
|
44
|
-
for (let file of HBS_FILES) {
|
|
45
|
-
const oldFile = join(name, file),
|
|
46
|
-
newFile = join(name, file.substring(0, file.length - 4))
|
|
47
|
-
const hbsContents = fs.readFileSync(oldFile, "utf8")
|
|
48
|
-
if (!hbsContents) {
|
|
49
|
-
continue
|
|
50
|
-
}
|
|
51
|
-
const output = processStringSync(hbsContents, {
|
|
52
|
-
name,
|
|
53
|
-
description,
|
|
54
|
-
version,
|
|
55
|
-
})
|
|
56
|
-
// write the updated file and remove the HBS file
|
|
57
|
-
fs.writeFileSync(newFile, output)
|
|
58
|
-
fs.rmSync(oldFile)
|
|
59
|
-
}
|
|
60
|
-
}
|