-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(vue-dsl): add app generate code
- Loading branch information
1 parent
60a6a88
commit 5f8f87b
Showing
16 changed files
with
830 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
class CodeGenerator { | ||
config = {} | ||
genResult = [] | ||
plugins = [] | ||
genLogs = [] | ||
schema = {} | ||
parsedSchema = {} | ||
context = {} | ||
constructor(config) { | ||
this.config = config | ||
this.plugins = config.plugins | ||
} | ||
getContext() { | ||
return { | ||
config: this.config, | ||
genResult: this.genResult, | ||
plugins: this.plugins, | ||
genLogs: this.genLogs, | ||
schema: this.schema, | ||
parsedSchema: this.parsedSchema, | ||
...this.context | ||
} | ||
} | ||
getPluginsByHook(hookName) { | ||
const res = [] | ||
|
||
for (const pluginItem of this.plugins) { | ||
if (typeof pluginItem[hookName] === 'function') { | ||
res.push(pluginItem[hookName]) | ||
} | ||
} | ||
|
||
return res | ||
} | ||
async generate(schema) { | ||
const hooks = ['transformStart', 'parseConfig', 'parseSchema', 'transform', 'transformEnd'] | ||
let err = null | ||
|
||
this.schema = schema | ||
|
||
try { | ||
for (const hookItem of hooks) { | ||
const plugins = this.getPluginsByHook(hookItem) | ||
|
||
await this[hookItem](plugins) | ||
} | ||
} catch (error) { | ||
err = error | ||
} finally { | ||
const plugins = this.getPluginsByHook('transformEnd') | ||
await this.transformEnd(plugins, err) | ||
} | ||
|
||
return { | ||
genResult: this.genResult, | ||
genLogs: this.genLogs | ||
} | ||
} | ||
async transformStart(plugins) { | ||
for (const pluginItem of plugins) { | ||
await pluginItem.apply(this, [this.config]) | ||
} | ||
} | ||
async parseConfig(plugins) { | ||
for (const pluginItem of plugins) { | ||
const newConfig = await pluginItem.apply(this, [this.config]) | ||
|
||
if (newConfig) { | ||
this.config = newConfig | ||
} | ||
} | ||
} | ||
|
||
async parseSchema(plugins) { | ||
for (const pluginItem of plugins) { | ||
const parseResult = await pluginItem.apply(this, [this.schema]) | ||
|
||
if (!parseResult?.id || !parseResult?.result) { | ||
continue | ||
} | ||
|
||
this.parsedSchema[parseResult.id] = parseResult.result | ||
} | ||
} | ||
async transform(plugins) { | ||
for (const pluginItem of plugins) { | ||
const transformRes = await pluginItem.apply(this, [this.parsedSchema]) | ||
|
||
if (!transformRes) { | ||
return | ||
} | ||
|
||
if (Array.isArray(transformRes)) { | ||
this.genResult.push(...transformRes) | ||
} else { | ||
this.genResult.push(transformRes) | ||
} | ||
} | ||
} | ||
async transformEnd(plugins, err) { | ||
for (const pluginItem of plugins) { | ||
await pluginItem.apply(this, [err]) | ||
} | ||
} | ||
replaceGenResult(resultItem) { | ||
const { path, fileName } = resultItem | ||
|
||
const index = this.genResult.findIndex((item) => item.path === path && item.fileName === fileName) | ||
|
||
if (index === -1) { | ||
return | ||
} | ||
|
||
this.genResult.splice(index, 1, resultItem) | ||
} | ||
} | ||
|
||
export default CodeGenerator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,116 @@ | ||
import { generateTemplate } from '../templates/vue-template' | ||
import { generateTemplate as genDefaultStaticTemplate } from '../templates/vue-template' | ||
import { | ||
genBlockPlugin, | ||
genDataSourcePlugin, | ||
genDependenciesPlugin, | ||
genI18nPlugin, | ||
genPagePlugin, | ||
genRouterPlugin, | ||
genTemplatePlugin, | ||
genUtilsPlugin | ||
} from '../plugins' | ||
import CodeGenerator from './codeGenerator' | ||
|
||
const templateMap = { | ||
default: generateTemplate | ||
const inputMock = { | ||
// 应用相关配置信息 | ||
//config: {}, | ||
// 应用相关的 meta 信息 | ||
appMeta: {}, | ||
// 页面区块信息 | ||
componentsTree: [], | ||
blockList: [], | ||
// 数据源信息 | ||
dataSource: [], | ||
// i18n 信息 | ||
i18n: {}, | ||
// utils 信息 | ||
utils: [], | ||
// 全局状态 | ||
globalState: [] | ||
} | ||
|
||
// function | ||
// TODO 解析整个应用用到的区块 | ||
// 1. 解析页面中用到的区块 | ||
// 2. 解析区块中用到的区块 | ||
|
||
function generateI18n() {} | ||
|
||
function generateDataSource() {} | ||
const transformedSchema = { | ||
// 整体应用 meta 信息 | ||
appMeta: { | ||
name: 'test' | ||
}, | ||
// 需要生成的页面 | ||
pageCode: [ | ||
{ | ||
// 类型是页面 | ||
// type: 'PAGE', | ||
// 类型是区块 | ||
// type: 'BLOCK', | ||
// 页面 meta 信息 | ||
meta: {}, | ||
// schema 信息,如果是 文件夹,则不需要 | ||
schema: {} | ||
// ... | ||
} | ||
], | ||
dataSource: {}, | ||
i18n: {}, | ||
routes: {}, | ||
utils: {}, | ||
globalState: [ | ||
{ | ||
actions: {}, | ||
getters: {}, | ||
id: '', | ||
state: {} | ||
} | ||
] | ||
} | ||
|
||
function generatePageOrComponent() {} | ||
// 预处理输入的 schema,转换为标准的格式 | ||
function transformSchema(appSchema) { | ||
const { appMeta, pageCode, dataSource, i18n, utils, globalState } = appSchema | ||
|
||
function generateRouter() {} | ||
const routes = pageCode.map(({ meta: { isHome, router }, fileName }) => ({ | ||
fileName, | ||
isHome, | ||
path: router.startsWith('/') ? router : `/${router}` | ||
})) | ||
|
||
function generateDependencies() {} | ||
const hasRoot = routes.some(({ path }) => path === '/') | ||
|
||
/** | ||
* 整体应用出码 | ||
*/ | ||
export function generateApp(config, appSchema) { | ||
// 预处理 app schema | ||
if (!hasRoot && routes.length) { | ||
const { path: homePath } = routes.find(({ isHome }) => isHome) || { path: routes[0].path } | ||
|
||
// 初始化模板 | ||
const { staticTemplate } = config | ||
routes.unshift({ path: '/', redirect: homePath }) | ||
} | ||
|
||
if (typeof staticTemplate === 'function') { | ||
staticTemplate({}) | ||
return { | ||
appMeta, | ||
pageCode, | ||
dataSource, | ||
i18n, | ||
utils, | ||
globalState, | ||
routes | ||
} | ||
} | ||
|
||
// 国际化出码 | ||
/** | ||
* 整体应用出码 | ||
*/ | ||
export async function generateApp(appSchema) { | ||
const codeGenInstance = new CodeGenerator({ | ||
plugins: [ | ||
genBlockPlugin(), | ||
genDataSourcePlugin(), | ||
genDependenciesPlugin(), | ||
genI18nPlugin(), | ||
genPagePlugin(), | ||
genRouterPlugin(), | ||
genTemplatePlugin(), | ||
genUtilsPlugin() | ||
] | ||
}) | ||
|
||
// 数据源出码 | ||
// 页面出码 | ||
// 区块出码 | ||
// utils 工具类出码 | ||
// 路由出码 | ||
// 依赖出码 | ||
return codeGenInstance.generate(appSchema) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { mergeOptions } from '../utils/mergeOptions' | ||
import { generatePageCode } from '../generator/page' | ||
|
||
const defaultOption = { | ||
blockBasePath: './src/components' | ||
} | ||
|
||
function genBlockPlugin(options = {}) { | ||
const realOptions = mergeOptions(defaultOption, options) | ||
|
||
const { blockBasePath } = realOptions | ||
|
||
return { | ||
name: 'tinyengine-plugin-generatecode-block', | ||
description: 'transform block schema to code', | ||
parseSchema(schema) { | ||
const { blockHistories } = schema | ||
const blockSchema = blockHistories.map((block) => block?.content).filter((schema) => typeof schema === 'object') | ||
|
||
return { | ||
id: 'blocks', | ||
result: blockSchema | ||
} | ||
}, | ||
transform(transformedSchema) { | ||
const { blocks } = transformedSchema | ||
|
||
const resBlocks = [] | ||
|
||
for (const block of blocks) { | ||
const res = generatePageCode({ | ||
pageInfo: { schema: block, name: block.componentName }, | ||
componentsMap: this.schema.componentsMap | ||
}) | ||
|
||
const { errors, ...restInfo } = res[0] | ||
|
||
if (errors?.length > 0) { | ||
this.genLogs.push(...errors) | ||
continue | ||
} | ||
|
||
const { panelName, panelValue } = restInfo | ||
|
||
resBlocks.push({ | ||
fileName: panelName, | ||
path: blockBasePath, | ||
fileContent: panelValue | ||
}) | ||
} | ||
|
||
return resBlocks | ||
} | ||
} | ||
} | ||
|
||
export default genBlockPlugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { mergeOptions } from '../utils/mergeOptions' | ||
|
||
const defaultOption = { | ||
fileName: 'dataSource.json', | ||
path: './src' | ||
} | ||
|
||
function genDataSourcePlugin(options = {}) { | ||
const realOptions = mergeOptions(defaultOption, options) | ||
|
||
const { path, fileName } = realOptions | ||
|
||
return { | ||
name: 'tinyengine-plugin-generatecode-datasource', | ||
description: 'transform schema to dataSource plugin', | ||
parseSchema(schema) { | ||
return { | ||
id: 'dataSource', | ||
result: schema?.dataSource || {} | ||
} | ||
}, | ||
transform(transformedSchema) { | ||
const dataSource = transformedSchema.dataSource | ||
|
||
const { dataHandler, errorHandler, willFetch, list } = dataSource || {} | ||
|
||
const data = { | ||
list: list.map(({ id, name, data }) => ({ id, name, ...data })) | ||
} | ||
|
||
if (dataHandler) { | ||
data.dataHandler = dataHandler | ||
} | ||
|
||
if (errorHandler) { | ||
data.errorHandler = errorHandler | ||
} | ||
|
||
if (willFetch) { | ||
data.willFetch = willFetch | ||
} | ||
|
||
return { | ||
fileName, | ||
path, | ||
fileContent: JSON.stringify(data) | ||
} | ||
} | ||
} | ||
} | ||
|
||
export default genDataSourcePlugin |
Oops, something went wrong.