fix: js 语法错误导致 dev 退出

This commit is contained in:
winixt 2022-09-27 10:14:29 +08:00
parent 7fdc61ab9d
commit 2840b462ec
5 changed files with 182 additions and 126 deletions

View File

@ -16,9 +16,7 @@ export const getName = (absPath, absSrcPath) => {
// model files with namespace // model files with namespace
const dirList = path.dirname(relativePath).split(path.sep); const dirList = path.dirname(relativePath).split(path.sep);
try { try {
const validDirs = dirList.filter( const validDirs = dirList.filter((ele) => !['src', 'page', 'pages', 'model', 'models'].includes(ele));
ele => !['src', 'page', 'pages', 'model', 'models'].includes(ele)
);
if (validDirs && validDirs.length) { if (validDirs && validDirs.length) {
return `${validDirs.join('.')}.${getFileName(relativePath)}`; return `${validDirs.join('.')}.${getFileName(relativePath)}`;
} }
@ -33,25 +31,22 @@ export const getPath = (absPath) => {
return winPath(path.join(info.dir, info.name).replace(/'/, "'")); return winPath(path.join(info.dir, info.name).replace(/'/, "'"));
}; };
export const genImports = imports => imports export const genImports = (imports) => imports.map((ele, index) => `import model${index} from "${winPath(getPath(ele))}";`).join(EOL);
.map(
(ele, index) => `import model${index} from "${winPath(getPath(ele))}";`
)
.join(EOL);
export const genExtraModels = (models = [], absSrcPath) => models.map((ele) => { export const genExtraModels = (models = [], absSrcPath) =>
models.map((ele) => {
if (typeof ele === 'string') { if (typeof ele === 'string') {
return { return {
importPath: getPath(ele), importPath: getPath(ele),
importName: path.basename(ele).split('.')[0], importName: path.basename(ele).split('.')[0],
namespace: getName(ele, absSrcPath) namespace: getName(ele, absSrcPath),
}; };
} }
return { return {
importPath: getPath(ele.absPath), importPath: getPath(ele.absPath),
importName: path.basename(ele.absPath).split('.')[0], importName: path.basename(ele.absPath).split('.')[0],
namespace: ele.namespace, namespace: ele.namespace,
exportName: ele.exportName exportName: ele.exportName,
}; };
}); });
@ -63,7 +58,7 @@ export const sort = (ns) => {
const cannotUse = [item.namespace]; const cannotUse = [item.namespace];
for (let i = 0; i <= index; i += 1) { for (let i = 0; i <= index; i += 1) {
if (ns[i].use.filter(v => cannotUse.includes(v)).length) { if (ns[i].use.filter((v) => cannotUse.includes(v)).length) {
if (!cannotUse.includes(ns[i].namespace)) { if (!cannotUse.includes(ns[i].namespace)) {
cannotUse.push(ns[i].namespace); cannotUse.push(ns[i].namespace);
i = -1; i = -1;
@ -71,16 +66,12 @@ export const sort = (ns) => {
} }
} }
const errorList = item.use.filter(v => cannotUse.includes(v)); const errorList = item.use.filter((v) => cannotUse.includes(v));
if (errorList.length) { if (errorList.length) {
throw Error( throw Error(`Circular dependencies: ${item.namespace} can't use ${errorList.join(', ')}`);
`Circular dependencies: ${
item.namespace
} can't use ${errorList.join(', ')}`
);
} }
const intersection = final.filter(v => itemGroup.includes(v)); const intersection = final.filter((v) => itemGroup.includes(v));
if (intersection.length) { if (intersection.length) {
// first intersection // first intersection
const finalIndex = final.indexOf(intersection[0]); const finalIndex = final.indexOf(intersection[0]);
@ -103,20 +94,24 @@ export const sort = (ns) => {
}; };
export const genModels = (imports, absSrcPath) => { export const genModels = (imports, absSrcPath) => {
const contents = imports.map(absPath => ({ const contents = imports.map((absPath) => ({
namespace: getName(absPath, absSrcPath), namespace: getName(absPath, absSrcPath),
content: readFileSync(absPath).toString() content: readFileSync(absPath).toString(),
})); }));
const allUserModel = imports.map(absPath => getName(absPath, absSrcPath)); const allUserModel = imports.map((absPath) => getName(absPath, absSrcPath));
const checkDuplicates = list => new Set(list).size !== list.length; const checkDuplicates = (list) => new Set(list).size !== list.length;
const raw = contents.map((ele, index) => { const raw = contents.map((ele, index) => {
const ast = parser.parse(ele.content, { let ast;
try {
ast = parser.parse(ele.content, {
sourceType: 'module', sourceType: 'module',
plugins: ['jsx', 'typescript'] plugins: ['jsx', 'typescript'],
}); });
} catch (err) {
return [];
}
const use = []; const use = [];
traverse(ast, { traverse(ast, {
@ -132,7 +127,7 @@ export const genModels = (imports, absSrcPath) => {
// console.log(e) // console.log(e)
} }
} }
} },
}); });
return { namespace: ele.namespace, use, importName: `model${index}` }; return { namespace: ele.namespace, use, importName: `model${index}` };
@ -140,17 +135,16 @@ export const genModels = (imports, absSrcPath) => {
const models = sort(raw); const models = sort(raw);
if (checkDuplicates(contents.map(ele => ele.namespace))) { if (checkDuplicates(contents.map((ele) => ele.namespace))) {
throw Error('plugin-model: models 中包含重复的 namespace'); throw Error('plugin-model: models 中包含重复的 namespace');
} }
return raw.sort( return raw.sort((a, b) => models.indexOf(a.namespace) - models.indexOf(b.namespace));
(a, b) => models.indexOf(a.namespace) - models.indexOf(b.namespace)
);
}; };
export const isValidHook = (filePath) => { export const isValidHook = (filePath) => {
const content = readFileSync(filePath, { encoding: 'utf-8' }).toString(); const content = readFileSync(filePath, { encoding: 'utf-8' }).toString();
let valid = false;
try {
const ast = parser.parse(content, { const ast = parser.parse(content, {
sourceType: 'module', sourceType: 'module',
plugins: [ plugins: [
@ -162,20 +156,17 @@ export const isValidHook = (filePath) => {
'nullishCoalescingOperator', 'nullishCoalescingOperator',
'objectRestSpread', 'objectRestSpread',
'optionalChaining', 'optionalChaining',
'decorators-legacy' 'decorators-legacy',
].filter(Boolean) ].filter(Boolean),
}); });
let valid = false;
let identifierName = ''; let identifierName = '';
traverse(ast, { traverse(ast, {
enter(p) { enter(p) {
if (p.isExportDefaultDeclaration()) { if (p.isExportDefaultDeclaration()) {
const { type } = p.node.declaration; const { type } = p.node.declaration;
try { try {
if ( if (type === 'ArrowFunctionExpression' || type === 'FunctionDeclaration') {
type === 'ArrowFunctionExpression'
|| type === 'FunctionDeclaration'
) {
valid = true; valid = true;
} else if (type === 'Identifier') { } else if (type === 'Identifier') {
identifierName = p.node.declaration.name; identifierName = p.node.declaration.name;
@ -184,10 +175,9 @@ export const isValidHook = (filePath) => {
console.error(e); console.error(e);
} }
} }
} },
}); });
try {
if (identifierName) { if (identifierName) {
ast.program.body.forEach((ele) => { ast.program.body.forEach((ele) => {
if (ele.type === 'FunctionDeclaration') { if (ele.type === 'FunctionDeclaration') {
@ -196,11 +186,7 @@ export const isValidHook = (filePath) => {
} }
} }
if (ele.type === 'VariableDeclaration') { if (ele.type === 'VariableDeclaration') {
if ( if (ele.declarations[0].id.name === identifierName && ele.declarations[0].init.type === 'ArrowFunctionExpression') {
ele.declarations[0].id.name === identifierName
&& ele.declarations[0].init.type
=== 'ArrowFunctionExpression'
) {
valid = true; valid = true;
} }
} }
@ -213,7 +199,8 @@ export const isValidHook = (filePath) => {
return valid; return valid;
}; };
export const getValidFiles = (files, modelsDir) => files export const getValidFiles = (files, modelsDir) =>
files
.map((file) => { .map((file) => {
const filePath = path.join(modelsDir, file); const filePath = path.join(modelsDir, file);
const valid = isValidHook(filePath); const valid = isValidHook(filePath);
@ -222,4 +209,4 @@ export const getValidFiles = (files, modelsDir) => files
} }
return ''; return '';
}) })
.filter(ele => !!ele); .filter((ele) => !!ele);

View File

@ -26,10 +26,11 @@ function getDirFilePaths(dir) {
* @param {*} path * @param {*} path
*/ */
function pathToHump(path, root) { function pathToHump(path, root) {
return path.replace(root, '') return path
.replace(root, '')
.replace('.js', '') .replace('.js', '')
.replace(RegExp('(/|\\.|-|_)\\S', 'g'), text => text[1].toUpperCase()) .replace(RegExp('(/|\\.|-|_)\\S', 'g'), (text) => text[1].toUpperCase())
.replace(/\S/, text => text.toLowerCase()); .replace(/\S/, (text) => text.toLowerCase());
} }
/** /**
@ -41,7 +42,7 @@ function getModelTypes(ast, name, namespace = '') {
const types = { const types = {
mutations: {}, mutations: {},
actions: {}, actions: {},
getters: {} getters: {},
}; };
let namespaced = false; let namespaced = false;
if (ast.type !== 'ObjectExpression') return types; if (ast.type !== 'ObjectExpression') return types;
@ -74,12 +75,12 @@ function getModelTypes(ast, name, namespace = '') {
if (namespaced) { if (namespaced) {
types[key][name] = { types[key][name] = {
...subTypes[key], ...subTypes[key],
...types[key][name] ...types[key][name],
}; };
} else { } else {
types[key] = { types[key] = {
...subTypes[key], ...subTypes[key],
...types[key] ...types[key],
}; };
} }
}); });
@ -105,29 +106,36 @@ function parseModel(paths = [], root) {
importModules.push(`import ${moduleName} from '${path}'`); importModules.push(`import ${moduleName} from '${path}'`);
modules.push(moduleName); modules.push(moduleName);
const content = readFileSync(path).toString('utf-8'); const content = readFileSync(path).toString('utf-8');
let ast = parser.parse(content, { let ast;
try {
ast = parser.parse(content, {
sourceType: 'module', sourceType: 'module',
plugins: ['jsx', 'typescript'] plugins: ['jsx', 'typescript'],
}); });
ast = ast.program.body.filter(body => body.type === 'ExportDefaultDeclaration')[0]; ast = ast.program.body.filter((body) => body.type === 'ExportDefaultDeclaration')[0];
} catch (err) {}
if (ast) { if (ast) {
const { mutations, actions, getters } = getModelTypes(ast.declaration, moduleName); const { mutations, actions, getters } = getModelTypes(ast.declaration, moduleName);
MUTATION_TYPES = { MUTATION_TYPES = {
...mutations, ...mutations,
...MUTATION_TYPES ...MUTATION_TYPES,
}; };
ACTION_TYPES = { ACTION_TYPES = {
...actions, ...actions,
...ACTION_TYPES ...ACTION_TYPES,
}; };
GETTER_TYPES = { GETTER_TYPES = {
...getters, ...getters,
...GETTER_TYPES ...GETTER_TYPES,
}; };
} }
}); });
return { return {
modules, importModules, MUTATION_TYPES, ACTION_TYPES, GETTER_TYPES modules,
importModules,
MUTATION_TYPES,
ACTION_TYPES,
GETTER_TYPES,
}; };
} }
@ -155,6 +163,6 @@ export function parseStore(root) {
}); });
return { return {
...parsePlugin(pluginPaths, root), ...parsePlugin(pluginPaths, root),
...parseModel(modelPaths, root) ...parseModel(modelPaths, root),
}; };
} }

View File

@ -28,9 +28,10 @@
"dependencies": { "dependencies": {
"@fesjs/compiler": "^3.0.0-beta.0", "@fesjs/compiler": "^3.0.0-beta.0",
"@fesjs/utils": "^3.0.0-beta.0", "@fesjs/utils": "^3.0.0-beta.0",
"@vue/compiler-sfc": "^3.2.39",
"envinfo": "^7.7.3", "envinfo": "^7.7.3",
"mockjs": "^1.1.0", "express": "^4.17.3",
"express": "^4.17.3" "mockjs": "^1.1.0"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^3.2.37" "vue": "^3.2.37"

View File

@ -58,6 +58,7 @@ const getRoutePath = function (parentRoutePath, fileName, isFile = true) {
}; };
function getRouteMeta(content) { function getRouteMeta(content) {
try {
const ast = parser.parse(content, { const ast = parser.parse(content, {
sourceType: 'module', sourceType: 'module',
plugins: ['jsx', 'typescript'], plugins: ['jsx', 'typescript'],
@ -72,6 +73,7 @@ function getRouteMeta(content) {
const argument = generator(defineRouteExpression.expression.arguments[0]); const argument = generator(defineRouteExpression.expression.arguments[0]);
return JSON.parse(argument.code.replace(/'/g, '"').replace(/(\S+):/g, (global, m1) => `"${m1}":`)); return JSON.parse(argument.code.replace(/'/g, '"').replace(/(\S+):/g, (global, m1) => `"${m1}":`));
} }
} catch (err) {}
return null; return null;
} }

View File

@ -2458,6 +2458,16 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
source-map "^0.6.1" source-map "^0.6.1"
"@vue/compiler-core@3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.39.tgz#0d77e635f4bdb918326669155a2dc977c053943e"
integrity sha512-mf/36OWXqWn0wsC40nwRRGheR/qoID+lZXbIuLnr4/AngM0ov8Xvv8GHunC0rKRIkh60bTqydlqTeBo49rlbqw==
dependencies:
"@babel/parser" "^7.16.4"
"@vue/shared" "3.2.39"
estree-walker "^2.0.2"
source-map "^0.6.1"
"@vue/compiler-dom@3.2.37": "@vue/compiler-dom@3.2.37":
version "3.2.37" version "3.2.37"
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5" resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz#10d2427a789e7c707c872da9d678c82a0c6582b5"
@ -2466,6 +2476,14 @@
"@vue/compiler-core" "3.2.37" "@vue/compiler-core" "3.2.37"
"@vue/shared" "3.2.37" "@vue/shared" "3.2.37"
"@vue/compiler-dom@3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf"
integrity sha512-HMFI25Be1C8vLEEv1hgEO1dWwG9QQ8LTTPmCkblVJY/O3OvWx6r1+zsox5mKPMGvqYEZa6l8j+xgOfUspgo7hw==
dependencies:
"@vue/compiler-core" "3.2.39"
"@vue/shared" "3.2.39"
"@vue/compiler-sfc@3.2.37": "@vue/compiler-sfc@3.2.37":
version "3.2.37" version "3.2.37"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4" resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz#3103af3da2f40286edcd85ea495dcb35bc7f5ff4"
@ -2482,6 +2500,22 @@
postcss "^8.1.10" postcss "^8.1.10"
source-map "^0.6.1" source-map "^0.6.1"
"@vue/compiler-sfc@^3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2"
integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==
dependencies:
"@babel/parser" "^7.16.4"
"@vue/compiler-core" "3.2.39"
"@vue/compiler-dom" "3.2.39"
"@vue/compiler-ssr" "3.2.39"
"@vue/reactivity-transform" "3.2.39"
"@vue/shared" "3.2.39"
estree-walker "^2.0.2"
magic-string "^0.25.7"
postcss "^8.1.10"
source-map "^0.6.1"
"@vue/compiler-ssr@3.2.37": "@vue/compiler-ssr@3.2.37":
version "3.2.37" version "3.2.37"
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff" resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz#4899d19f3a5fafd61524a9d1aee8eb0505313cff"
@ -2490,6 +2524,14 @@
"@vue/compiler-dom" "3.2.37" "@vue/compiler-dom" "3.2.37"
"@vue/shared" "3.2.37" "@vue/shared" "3.2.37"
"@vue/compiler-ssr@3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633"
integrity sha512-EoGCJ6lincKOZGW+0Ky4WOKsSmqL7hp1ZYgen8M7u/mlvvEQUaO9tKKOy7K43M9U2aA3tPv0TuYYQFrEbK2eFQ==
dependencies:
"@vue/compiler-dom" "3.2.39"
"@vue/shared" "3.2.39"
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.1.4", "@vue/devtools-api@^6.2.0", "@vue/devtools-api@^6.2.1": "@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.1.4", "@vue/devtools-api@^6.2.0", "@vue/devtools-api@^6.2.1":
version "6.2.1" version "6.2.1"
resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz#6f2948ff002ec46df01420dfeff91de16c5b4092" resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz#6f2948ff002ec46df01420dfeff91de16c5b4092"
@ -2506,6 +2548,17 @@
estree-walker "^2.0.2" estree-walker "^2.0.2"
magic-string "^0.25.7" magic-string "^0.25.7"
"@vue/reactivity-transform@3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.39.tgz#da6ae6c8fd77791b9ae21976720d116591e1c4aa"
integrity sha512-HGuWu864zStiWs9wBC6JYOP1E00UjMdDWIG5W+FpUx28hV3uz9ODOKVNm/vdOy/Pvzg8+OcANxAVC85WFBbl3A==
dependencies:
"@babel/parser" "^7.16.4"
"@vue/compiler-core" "3.2.39"
"@vue/shared" "3.2.39"
estree-walker "^2.0.2"
magic-string "^0.25.7"
"@vue/reactivity@3.2.37": "@vue/reactivity@3.2.37":
version "3.2.37" version "3.2.37"
resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848" resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.37.tgz#5bc3847ac58828e2b78526e08219e0a1089f8848"
@ -2543,6 +2596,11 @@
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702" resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702"
integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw== integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==
"@vue/shared@3.2.39":
version "3.2.39"
resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
"@vuepress/bundler-vite@2.0.0-beta.49": "@vuepress/bundler-vite@2.0.0-beta.49":
version "2.0.0-beta.49" version "2.0.0-beta.49"
resolved "https://registry.npmmirror.com/@vuepress/bundler-vite/-/bundler-vite-2.0.0-beta.49.tgz#9b10e187e369d687b36751a963e25542b927db62" resolved "https://registry.npmmirror.com/@vuepress/bundler-vite/-/bundler-vite-2.0.0-beta.49.tgz#9b10e187e369d687b36751a963e25542b927db62"