"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildRouter = void 0; 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); } } exports.buildRouter = buildRouter;