vue-cli-plugin-modular-vuex
Version:
vue-cli 3 plugin to create modular vuex stores
110 lines (91 loc) • 3.65 kB
JavaScript
const fs = require('fs')
const path = require('path')
const recast = require('recast')
module.exports = (api, options, rootOptions, invoking) => {
const storeRootDir = './src/store'
const storeRootFile = './src/store/index.js'
const templatesRoot = './templates'
const moduleDir = path.join(storeRootDir, `${options.moduleName}`)
// Verify vuex plugin installed
if (!api.hasPlugin('vuex')) {
api.exitLog('Vuex plugin has not been installed', 'warn')
return
}
// Check store module directory if module already exists
if (fs.existsSync(`src/store/${options.moduleName}`)) {
api.exitLog(`Store module ${options.moduleName} already exists`, 'warn')
return
}
// Render module template files
api.render({
// Render index, actions, getters, mutations template files
[`${moduleDir}/index.js`]: `${templatesRoot}/module/index.js`,
[`${moduleDir}/actions.js`]: `${templatesRoot}/module/actions.js`,
[`${moduleDir}/getters.js`]: `${templatesRoot}/module/getters.js`,
[`${moduleDir}/mutations.js`]: `${templatesRoot}/module/mutations.js`
})
api.exitLog('Rendered template files', 'info')
// Verify storeRootFile exists, if not render
if (!fs.existsSync(`${storeRootFile}`)) {
api.render({
[`${storeRootFile}`]: `${templatesRoot}/index.js`
})
api.exitLog('Store root file rendered', 'info')
}
// inject import declaration for new store module
// api.injectImports(`${storeRootFile}`, `import ${options.moduleName} from './${options.moduleName}'`)
api.onCreateComplete((files) => {
// inject new module name into the root store file modules option
const code = fs.readFileSync(`${storeRootFile}`, 'utf8')
const ast = recast.parse(code)
// New option expression to inject
const expression = `${options.moduleName}`
const objectExpression = recast.parse(expression).program.body[0].expression
// New Import Declaration to inject
const imports = [`import ${options.moduleName} from './${options.moduleName}'`]
// Inject new option expression
recast.types.visit(ast, {
visitObjectExpression({
node
}) {
if (node.properties[0].key.name === 'modules') {
node.properties[0].value.properties.push(objectExpression)
}
return false
}
})
// Inject new Import declaration
const toImport = i => recast.parse(`${i}\n`).program.body[0];
const importDeclarations = []
let lastImportIndex = -1
recast.types.visit(ast, {
visitImportDeclaration({
node
}) {
lastImportIndex = ast.program.body.findIndex(n => n === node)
importDeclarations.push(node)
return false;
}
});
delete ast.program.body[lastImportIndex].loc
const newImport = imports.map(toImport);
ast.program.body.splice(lastImportIndex + 1, 0, ...newImport)
// files[`${storeRootFile}`] = recast.print(ast).code
fs.writeFile(`${storeRootFile}`, recast.print(ast).code, (err) => {
if (err) {
api.exitLog('Error writing to index.js: ' + err, 'error')
return
}
})
// Remove store.js generated from initial vuex plugin installation
if (fs.existsSync('./src/store.js')) {
fs.unlink('./src/store.js', (err) => {
if (err) {
api.exitLog("Failed to delete store.js file generated by vuex plugin:" + err, "warn")
} else {
api.exitLog('Successfully deleted store.js file generated by vuex plugin', "done")
}
})
}
})
}