155 lines
3.2 KiB
JavaScript
155 lines
3.2 KiB
JavaScript
const Redis = require('ioredis')
|
|
const commander = require('commander')
|
|
const fs = require('fs')
|
|
const yaml = require('yaml')
|
|
|
|
function isNumeric (v) {
|
|
return isFinite(v) && v !== null && v !== false && v !== true
|
|
}
|
|
|
|
/**
|
|
* @param {any} obj
|
|
* @param {string[]} keys
|
|
* @param {any} value
|
|
*/
|
|
function setKey (obj, keys, value) {
|
|
const key = isNumeric(keys[0]) ? parseInt(keys[0], 10) : keys[0]
|
|
|
|
if (keys.length === 1) {
|
|
obj[key] = value
|
|
return
|
|
}
|
|
|
|
if (!(key in obj)) {
|
|
if (isNumeric(keys[1])) {
|
|
obj[key] = []
|
|
} else {
|
|
obj[key] = {}
|
|
}
|
|
}
|
|
|
|
setKey(obj[key], keys.slice(1), value)
|
|
}
|
|
|
|
/**
|
|
* @param {string} file
|
|
* @return {boolean}
|
|
*/
|
|
async function checkFileExists (file) {
|
|
if (!file) return false
|
|
|
|
try {
|
|
await fs.promises.access(file, fs.constants.W_OK || fs.constants.R_OK)
|
|
} catch (err) {
|
|
console.log(err)
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
function getRedis () {
|
|
const { port, host } = commander
|
|
|
|
const redis = new Redis(port || 6379, host || 'localhost')
|
|
return redis
|
|
}
|
|
|
|
function generateFromStruct (obj, prefix = '') {
|
|
const kvs = []
|
|
if (Object.keys(obj).length === 0) return kvs
|
|
|
|
for (const k in obj) {
|
|
const key = !prefix ? k : [prefix, k].join('/')
|
|
|
|
if (typeof obj[k] === 'object') {
|
|
kvs.push(...generateFromStruct(obj[k], key))
|
|
} else {
|
|
kvs.push({ key, value: `${obj[k]}` })
|
|
}
|
|
}
|
|
|
|
return kvs
|
|
}
|
|
|
|
async function importData () {
|
|
const { file } = commander
|
|
if (!await checkFileExists(file)) throw new Error(`check file (${file}) fail`)
|
|
const redis = getRedis()
|
|
|
|
const str = await fs.promises.readFile(file, 'utf8')
|
|
const obj = yaml.parse(str)
|
|
|
|
const kvs = generateFromStruct(obj)
|
|
|
|
try {
|
|
// clean redis
|
|
await redis.flushdb()
|
|
for (const o of kvs) {
|
|
console.log(`set: ${o.key} => ${o.value}`)
|
|
await redis.set(o.key, o.value)
|
|
}
|
|
} finally {
|
|
await redis.disconnect()
|
|
}
|
|
}
|
|
|
|
async function exportData () {
|
|
const { file } = commander
|
|
const redis = getRedis()
|
|
|
|
const obj = {}
|
|
|
|
try {
|
|
let cursor = ''
|
|
while (cursor !== '0') {
|
|
const result = await redis.scan(cursor || '0')
|
|
|
|
console.log(result)
|
|
cursor = result[0]
|
|
|
|
for (const k of result[1]) {
|
|
const str = await redis.get(k)
|
|
if (!str) continue
|
|
setKey(obj, k.split('/'), str)
|
|
}
|
|
}
|
|
|
|
await fs.promises.writeFile(file, yaml.stringify(obj))
|
|
} finally {
|
|
await redis.disconnect()
|
|
}
|
|
}
|
|
|
|
commander.option('-r, --run <module>', 'run tool module [import, export]')
|
|
.option('-p, --port [port]', 'redis server port default: 6379')
|
|
.option('-h, --host [host]', 'redis host addr default: localhost')
|
|
.option('-f, --file <file path>', 'yaml config path')
|
|
.parse(process.argv)
|
|
|
|
; (async () => {
|
|
const { run, port, host, file } = commander
|
|
|
|
console.log(run, port, host, file)
|
|
|
|
switch (run) {
|
|
case 'import':
|
|
await importData()
|
|
break
|
|
case 'export':
|
|
await exportData()
|
|
break
|
|
default:
|
|
throw new Error('run module not support')
|
|
}
|
|
|
|
// for (const key in json) {
|
|
// const strs = key.split('/')
|
|
// setKey(obj, strs, json[key])
|
|
// }
|
|
|
|
// // console.log(yaml.stringify(obj))
|
|
|
|
// await fs.promises.writeFile('store.yml', yaml.stringify(obj))
|
|
})().then(console.log).catch(console.log)
|