tiny-engine/scripts/buildMaterials.mjs

203 lines
5.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fsExtra from 'fs-extra'
import path from 'node:path'
import chokidar from 'chokidar'
import fg from 'fast-glob'
import MysqlConnection from './connection.mjs'
import Logger from './logger.mjs'
const logger = new Logger('buildMaterials')
// 物料文件存放文件夹名称
const materialsDir = 'materials'
// 物料资产包
const bundlePath = path.join(process.cwd(), '/packages/design-core/public/mock/bundle.json')
// mockServer应用数据
const appInfoPath = path.join(process.cwd(), '/mockServer/src/services/appinfo.json')
const appInfo = fsExtra.readJSONSync(appInfoPath)
const connection = new MysqlConnection()
/**
* 更新物料资产包和应用mock数据
*/
const write = (bundle) => {
fsExtra.outputJSONSync(bundlePath, bundle, { spaces: 2 })
fsExtra.outputJSONSync(appInfoPath, appInfo, { spaces: 2 })
}
/**
* 校验组件文件数据
* @param {string} file 组件文件路径
* @param {object} component 组件数据
* @returns
*/
const validateComponent = (file, component) => {
const requiredFields = ['component']
const fields = Object.keys(component)
const requiredList = requiredFields.filter((field) => !fields.includes(field))
if (requiredList.length) {
logger.error(`组件文件 ${file} 缺少必要字段:${requiredList.join('、')}`)
return false
}
if (!component.npm) {
logger.warn(`组件文件 ${file} 缺少 npm 字段出码时将不能通过import语句导入组件。`)
return false
}
return true
}
/**
* 校验区块文件数据
* @param {string} file 区块文件路径
* @param {object} block 区块数据
* @returns
*/
const validateBlock = (file, block) => {
const requiredFields = ['label', 'assets']
const fields = Object.keys(block)
const requiredList = requiredFields.filter((field) => !fields.includes(field))
if (requiredList.length) {
logger.error(`区块文件 ${file} 缺少必要字段:${requiredList.join('、')}`)
return false
}
return true
}
/**
* 读取materials目录下的json文件执行下列操作
* 1. 合并生成物料资产包
* 2. 更新应用的组件数据componentsMap
* 3. 连接上数据库后,将组件数据写入数据库(新增或更新)
*/
const generateComponents = () => {
try {
fg([`${materialsDir}/**/*.json`]).then((files) => {
if (!files.length) {
logger.warn('物料文件夹为空,请先执行`pnpm splitMaterials`命令拆分物料资产包')
}
const bundle = {
data: {
framework: 'Vue',
materials: {
components: [],
blocks: [],
snippets: []
}
}
}
const { components = [], snippets = [], blocks = [] } = bundle.data.materials
const componentsMap = []
const appInfoBlocksLabels = appInfo.blockHistories.map((item) => item.label)
files.forEach((file) => {
const material = fsExtra.readJsonSync(file, { throws: false })
if (!material) {
const fileFullPath = path.join(process.cwd(), file)
logger.error(`文件格式有误 (${fileFullPath})`)
return
}
if (file.includes('/blocks/')) {
const valid = validateBlock(file, material)
if (!valid) return
blocks.push(material)
if (!appInfoBlocksLabels.includes(material.label)) {
appInfo.blockHistories.push(material)
}
return
}
const valid = validateComponent(file, material)
if (!valid) return
const { snippets: componentSnippets, category, ...componentInfo } = material
components.push(componentInfo)
const snippet = snippets.find((item) => item.group === category)
if (snippet) {
componentSnippets && snippet.children.push(componentSnippets[0])
} else if (category && componentInfo) {
snippets.push({
group: category,
children: componentSnippets || []
})
}
const { component, npm = {} } = componentInfo
componentsMap.push({ component, npm })
if (connection.connected) {
connection.initDB(material)
}
appInfo.materialHistory.components = componentsMap
write(bundle)
})
})
logger.success('物料资产包构建成功')
} catch (error) {
logger.error(`物料资产包构建失败:${error}`)
}
}
// 监听materials下json文件的变化
const watcher = chokidar.watch(`${materialsDir}/**/*.json`, { ignoreInitial: true })
watcher.on('all', (event, file) => {
const eventMap = {
add: '新增',
change: '更新',
unlink: '删除'
}
const fileFullPath = path.join(process.cwd(), file)
logger.info(`${eventMap[event]}组件文件 (${fileFullPath})`)
// 监听物料文件变化,更新物料资产包
generateComponents()
if (!connection.connected || event === 'unlink') return
const component = fsExtra.readJsonSync(fileFullPath)
if (event === 'change') {
connection.updateComponent(component, fileFullPath)
} else if (event === 'add') {
connection.insertComponent(component, fileFullPath)
}
})
// 连接数据库
connection
.connect()
.then(() => {
connection.initUserComponentsTable().finally(() => {
generateComponents()
})
})
.catch(() => {
// 未能连接数据库也可以执行更新本地mock数据
generateComponents()
})