inkplugin
Version:
INK cli tools for plugin developers.
161 lines (145 loc) • 4.73 kB
JavaScript
const {Command, flags} = require('@oclif/command')
const fs = require('fs')
const path = require('path')
const JSZip = require('jszip')
let packageJSONfile = null
const filesBlackList = [
'.exe',
'.dll',
'.bin',
'.bat',
'.com',
'.sh',
'.vb',
'.dye',
]
const requiredFiles = ['package.json']
const inkLatestVer = '^2.0.0'
function dirRecursiveFileSearch(dir, done) {
// console.log(dir)
const lastDir = dir.split(path.sep).pop()
if ((lastDir[0] === '.' && lastDir !== './') || lastDir === 'node_modules') {
done(null, [])
}
var results = []
fs.readdir(dir, function (err, list) {
if (err) return done(err)
var pending = list.length
if (!pending) return done(null, results)
list.forEach(function (file) {
file = path.resolve(dir, file)
fs.stat(file, function (_err, stat) {
if (stat && stat.isDirectory()) {
dirRecursiveFileSearch(file, function (_err, res) {
results = results.concat(res)
if (!--pending) done(null, results)
})
} else {
results.push(file)
if (!--pending) done(null, results)
}
})
})
})
}
function validate(fileNames, location) {
let flag = true
// validating it contains all the required files
for (let i = 0; i < requiredFiles.length; i++) {
flag = flag && fileNames.includes(path.join(location, requiredFiles[i]))
if (!flag) return false
}
// check if package.json `main` field points towards entry js file
const rawData = fs.readFileSync(path.join(location, 'package.json'))
packageJSONfile = JSON.parse(rawData)
flag =
flag &&
packageJSONfile &&
packageJSONfile['ink-plugin'] &&
fs.existsSync(path.join(location, packageJSONfile.main))
return flag
}
class PackageCommand extends Command {
async run() {
const {args, flags} = this.parse(PackageCommand)
const location = args.path
const output = flags.output || location
this.log(
'\n******************** INK Cli Packager ********************\n'
)
this.log(`Packaging directory: ${location}\n`)
dirRecursiveFileSearch(location, (err, files) => {
// handling error
if (err) {
return this.log('Unable to scan directory: ' + err)
}
// listing all files using forEach
files = files
.map(f => f.replace(process.cwd() + path.sep, ''))
.filter(
f => !filesBlackList.includes(path.extname(f)) && f !== 'inkapi.js'
) // if its a blacklisted file, remove it
if (validate(files, location)) {
this.log('- ' + files.join('\n- '))
const {name, engines} = packageJSONfile
const zip = new JSZip() // creating main zip
const extension = zip.folder('extension') // creating extension directory inside our zip
files.forEach(file => {
extension.file(
file.replace(location + path.sep, ''),
fs.readFileSync(file)
)
})
zip.file(
'manifest.json',
JSON.stringify({
name: name,
ink: engines ? engines.ink : inkLatestVer,
})
) // creating empty manifest.json file
// write the generated zip file to disk
zip
.generateNodeStream({
type: 'nodebuffer',
streamFiles: true,
compression: 'DEFLATE',
})
.pipe(fs.createWriteStream(path.join(output, `${name}.dye`)))
.on('finish', () => {
this.log(
'\n****************** Packaged Successfully ******************'
)
this.log(
'\nOutput Packaged File: ',
path.join(output, `${name}.dye \n\n`)
)
})
} else {
this.log('Required files are missing in the directory.\n')
this.log('1. It must contain a package.json file.')
this.log(
'2. package.json `main` field should point toward the entry js file\n'
)
}
})
}
}
PackageCommand.description = `package INK plugin project into a DYE file.
It will package your INK plugin project into a DYE file, which can be used to install your plugin in INK editor.
`
PackageCommand.flags = {
output: flags.string({
char: 'o',
description: 'destination path for DYE file', // help description for flag
required: false, // make flag required (this is not common and you should probably use an argument instead)
}),
}
PackageCommand.args = [
{
name: 'path', // name of arg to show in help and reference with args[name]
description: 'Path to plugin project.', // help description
hidden: false, // hide this arg from help
default: './',
},
]
module.exports = PackageCommand