257 lines
13 KiB
JavaScript
257 lines
13 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.buildRouter = buildRouter;
|
||
const tslib_1 = require("tslib");
|
||
const path_1 = require("path");
|
||
const fs_extra_1 = require("fs-extra");
|
||
const assert_1 = tslib_1.__importDefault(require("assert"));
|
||
const ts = tslib_1.__importStar(require("typescript"));
|
||
const node_watch_1 = tslib_1.__importDefault(require("node-watch"));
|
||
const env_1 = require("./env");
|
||
const { factory } = ts;
|
||
const NameSpaceDescDict = {};
|
||
function checkPageDir(dir, relativePath, ns, type) {
|
||
let changed = false;
|
||
const { pages } = NameSpaceDescDict[ns];
|
||
const subdirs = [];
|
||
const files = (0, fs_extra_1.readdirSync)(dir);
|
||
files.forEach((file) => {
|
||
const filepath = (0, path_1.join)(dir, file);
|
||
const stat = (0, fs_extra_1.statSync)(filepath);
|
||
if (stat.isFile() &&
|
||
['web.tsx', 'web.pc.tsx', 'render.native.tsx', 'render.ios.tsx', 'render.android.tsx', 'index.xml'].includes(file)) {
|
||
if (!pages.hasOwnProperty(dir)) {
|
||
const indexJsonFile = (0, path_1.join)(dir, 'index.json');
|
||
let oakDisablePulldownRefresh = false;
|
||
if ((0, fs_extra_1.existsSync)(indexJsonFile)) {
|
||
const { enablePullDownRefresh = true, } = require(indexJsonFile);
|
||
oakDisablePulldownRefresh =
|
||
!enablePullDownRefresh;
|
||
}
|
||
pages[dir] = {
|
||
path: relativePath.replace(/\\/g, '/'),
|
||
oakDisablePulldownRefresh,
|
||
hasNative: ['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file),
|
||
hasWeb: ['web.tsx', 'web.pc.tsx'].includes(file),
|
||
hasWechatMp: file === 'index.xml',
|
||
};
|
||
changed = true;
|
||
}
|
||
else {
|
||
if (['render.native.tsx', 'render.ios.tsx', 'render.android.tsx'].includes(file) && type === 'native') {
|
||
if (pages[dir].hasNative === false) {
|
||
pages[dir].hasNative = true;
|
||
changed = true;
|
||
}
|
||
}
|
||
else if (['web.tsx', 'web.pc.tsx'].includes(file) && type === 'web') {
|
||
if (pages[dir].hasWeb === false) {
|
||
pages[dir].hasWeb = true;
|
||
changed = true;
|
||
}
|
||
}
|
||
else {
|
||
if (pages[dir].hasWechatMp === false && type === 'wechatMp') {
|
||
pages[dir].hasWechatMp = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (stat.isDirectory()) {
|
||
subdirs.push(file);
|
||
}
|
||
});
|
||
return {
|
||
subdirs,
|
||
changed,
|
||
};
|
||
}
|
||
function traverseNsDir(nsDir, ns, type) {
|
||
NameSpaceDescDict[ns] = {
|
||
pages: {}
|
||
};
|
||
const { pages } = NameSpaceDescDict[ns];
|
||
const traverse = (dir, relativePath) => {
|
||
const { subdirs } = checkPageDir(dir, relativePath, ns, type);
|
||
subdirs.forEach((subdir) => {
|
||
const dir2 = (0, path_1.join)(dir, subdir);
|
||
const relativePath2 = (0, path_1.join)(relativePath, subdir);
|
||
traverse(dir2, relativePath2);
|
||
});
|
||
};
|
||
traverse(nsDir, '');
|
||
}
|
||
function traversePageDir(projectDir, type) {
|
||
const pageDir = (0, path_1.join)(projectDir, 'src', 'pages');
|
||
const namespaces = (0, fs_extra_1.readdirSync)(pageDir);
|
||
namespaces.forEach((ns) => {
|
||
const nsDir = (0, path_1.join)(pageDir, ns);
|
||
const stat = (0, fs_extra_1.statSync)(nsDir);
|
||
if (stat.isDirectory()) {
|
||
traverseNsDir(nsDir, ns, type);
|
||
}
|
||
});
|
||
}
|
||
function makeWebAllRouters(namespaceDir, projectDir, routerFileDir) {
|
||
const nss = (0, fs_extra_1.readdirSync)(namespaceDir);
|
||
return factory.createArrayLiteralExpression(nss.map((ns) => {
|
||
(0, assert_1.default)(NameSpaceDescDict[ns], `${ns}在pages下没有对应的目录`);
|
||
const { pages } = NameSpaceDescDict[ns];
|
||
const nsIndexJsonFile = (0, path_1.join)(namespaceDir, ns, 'index.json');
|
||
let path2 = `/${ns}`;
|
||
let notFound2 = '', first2 = '';
|
||
let params2 = {};
|
||
if ((0, fs_extra_1.existsSync)(nsIndexJsonFile)) {
|
||
const { path, notFound, first, params } = require(nsIndexJsonFile);
|
||
if (path) {
|
||
path2 = path.replace(/\\/g, '/');
|
||
}
|
||
if (notFound) {
|
||
notFound2 = notFound.replace(/\\/g, '/');
|
||
}
|
||
if (first) {
|
||
first2 = first.replace(/\\/g, '/');
|
||
if (first2.startsWith('/')) {
|
||
first2 = first2.slice(1);
|
||
}
|
||
}
|
||
if (params) {
|
||
params2 = params;
|
||
}
|
||
}
|
||
let firstPage;
|
||
const children = Object.values(pages).filter((ele) => ele.hasWeb).map(({ path, oakDisablePulldownRefresh }) => {
|
||
let path2 = path;
|
||
if (params2[path]) {
|
||
// 如果有参数,接在path后面
|
||
path2 += path2 ? `/:${params2[path]}` : `:${params2[path]}`;
|
||
}
|
||
const properties = [
|
||
factory.createPropertyAssignment('path', factory.createStringLiteral(path2)),
|
||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(ns)),
|
||
factory.createPropertyAssignment('meta', factory.createObjectLiteralExpression([
|
||
factory.createPropertyAssignment('oakDisablePulldownRefresh', oakDisablePulldownRefresh ? factory.createTrue() : factory.createFalse())
|
||
])),
|
||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(projectDir, 'src', 'pages', ns, path)).replace(/\\/g, '/'))
|
||
]))]))
|
||
];
|
||
if (first2 === path) {
|
||
const firstProperties = [...properties];
|
||
firstProperties.push(factory.createPropertyAssignment('isFirst', factory.createTrue()));
|
||
firstPage = factory.createObjectLiteralExpression(firstProperties, true);
|
||
}
|
||
return factory.createObjectLiteralExpression(properties, true);
|
||
});
|
||
if (firstPage) {
|
||
children.push(firstPage);
|
||
}
|
||
if (notFound2) {
|
||
children.push(factory.createObjectLiteralExpression([
|
||
factory.createPropertyAssignment('path', factory.createStringLiteral('*')),
|
||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(path2)),
|
||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(projectDir, 'src', 'pages', ns, notFound2)).replace(/\\/g, '/'))
|
||
]))]))
|
||
], true));
|
||
}
|
||
return factory.createObjectLiteralExpression([
|
||
factory.createPropertyAssignment('path', factory.createStringLiteral(path2)),
|
||
factory.createPropertyAssignment('namespace', factory.createStringLiteral(path2)),
|
||
factory.createPropertyAssignment(factory.createIdentifier("Component"), factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("React"), factory.createIdentifier("lazy")), undefined, [factory.createArrowFunction(undefined, undefined, [], undefined, factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), factory.createCallExpression(factory.createIdentifier('import'), undefined, [
|
||
factory.createStringLiteral((0, path_1.relative)(routerFileDir, (0, path_1.join)(namespaceDir, ns)).replace(/\\/g, '/'))
|
||
]))])),
|
||
factory.createPropertyAssignment('children', factory.createArrayLiteralExpression(children))
|
||
], true);
|
||
}), true);
|
||
}
|
||
function judgeUseOakRouterBuilder(statements) {
|
||
const stmt = statements[0];
|
||
return ts.isExpressionStatement(stmt) && ts.isStringLiteral(stmt.expression) && stmt.expression.text === 'use oak router builder';
|
||
}
|
||
function outputInWebAppDir(appDir) {
|
||
const routerFileName = (0, path_1.join)(appDir, 'routers', 'allRouters.ts');
|
||
const templateFileName = (0, path_1.join)(appDir, '../../..', 'node_modules', env_1.OAK_CLI_MODULE_NAME, 'templateFiles', 'allRouters.ts');
|
||
const program = ts.createProgram([templateFileName], {
|
||
removeComments: false,
|
||
});
|
||
const routerFile = program.getSourceFile(templateFileName);
|
||
(0, assert_1.default)(routerFile);
|
||
const namespaceDir = (0, path_1.join)(appDir, 'namespaces');
|
||
const { statements } = routerFile;
|
||
if (judgeUseOakRouterBuilder(statements)) {
|
||
statements.forEach((statement) => {
|
||
if (ts.isVariableStatement(statement)) {
|
||
const declaration = statement.declarationList.declarations.find(declaration => ts.isIdentifier(declaration.name) && declaration.name.text === 'allRouters');
|
||
if (declaration) {
|
||
Object.assign(declaration, {
|
||
initializer: makeWebAllRouters(namespaceDir, (0, path_1.join)(appDir, '../../..'), (0, path_1.dirname)(routerFileName))
|
||
});
|
||
}
|
||
}
|
||
});
|
||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, removeComments: false });
|
||
const result = printer.printNode(ts.EmitHint.Unspecified, routerFile, routerFile);
|
||
(0, fs_extra_1.writeFileSync)(routerFileName, result);
|
||
}
|
||
}
|
||
function outputInWebDir(dir) {
|
||
const srcAppDir = (0, path_1.join)(dir, 'src', 'app');
|
||
outputInWebAppDir(srcAppDir);
|
||
}
|
||
function watchDir(projectDir, startupDir, type) {
|
||
const srcPageDir = (0, path_1.join)(projectDir, 'src', 'pages');
|
||
console.log('watch dir ', srcPageDir);
|
||
if (startupDir.startsWith('web')) {
|
||
const srcAppDir = (0, path_1.join)(projectDir, startupDir, 'src', 'app');
|
||
const tryOutputAppDir = (ns) => {
|
||
const namespaceDir = (0, path_1.join)(srcAppDir, 'namespaces');
|
||
const namespaces = (0, fs_extra_1.readdirSync)(namespaceDir);
|
||
if (namespaces.includes(ns)) {
|
||
outputInWebAppDir(srcAppDir);
|
||
}
|
||
};
|
||
(0, node_watch_1.default)(srcPageDir, {
|
||
recursive: true,
|
||
filter: new RegExp('web\.tsx|web\.pc\.tsx|index\.xml|render\.(native|ios|android)\.tsx'),
|
||
}, (evt, filepath) => {
|
||
const dir = (0, path_1.dirname)(filepath);
|
||
const relativeDir = (0, path_1.relative)((0, path_1.join)(projectDir, 'src', 'pages'), filepath);
|
||
const ns = relativeDir.split('\\')[0];
|
||
const relativePath = (0, path_1.relative)(ns, (0, path_1.dirname)(relativeDir));
|
||
const { pages } = NameSpaceDescDict[ns];
|
||
if (evt === 'remove') {
|
||
if ((0, fs_extra_1.existsSync)(dir)) {
|
||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||
if (changed) {
|
||
tryOutputAppDir(ns);
|
||
}
|
||
}
|
||
else {
|
||
delete pages[dir];
|
||
tryOutputAppDir(ns);
|
||
}
|
||
}
|
||
else {
|
||
const { changed } = checkPageDir(dir, relativePath, ns, type);
|
||
if (changed) {
|
||
tryOutputAppDir(ns);
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|
||
function buildRouter(projectDir, startupDir, watch) {
|
||
const type = startupDir.startsWith('web') ? 'web' : (startupDir.startsWith('native') ? 'native' : 'wechatMp');
|
||
traversePageDir(projectDir, type);
|
||
const subDir = (0, fs_extra_1.readdirSync)(projectDir);
|
||
(0, assert_1.default)(subDir.includes(startupDir));
|
||
if (startupDir.startsWith('web')) {
|
||
outputInWebDir((0, path_1.join)(projectDir, startupDir));
|
||
}
|
||
// todo native
|
||
if (watch) {
|
||
watchDir(projectDir, startupDir, type);
|
||
}
|
||
}
|