增加了大量和native相关的代码

This commit is contained in:
Xu Chang 2023-11-26 22:43:00 +08:00
parent ca48f105fb
commit 5091c4a730
15 changed files with 517 additions and 327 deletions

View File

@ -1,275 +1,17 @@
const fs = require('fs');
const { relative, resolve } = require('path');
const t = require('@babel/types');
const assert = require('assert');
const { parse } = require('path');
const { injectGetRender } = require('../utils/injectGetRender');
module.exports = (babel) => {
return {
visitor: {
Program(path, state) {
CallExpression(path, state) {
const { cwd, filename } = state;
const rel = relative(cwd, filename).replace(/\\/g, '/');
const tsPage = /(pages|components|namespaces)[\\/][\w|\W]+[\\/]index\.ts$/.test(rel);
const jsPage = /(pages|components|namespaces)[\\/][\w|\W]+[\\/]index\.js$/.test(rel);
if (tsPage || jsPage) {
const tsxFile = filename.replace(
/index\.(ts|js)$/,
tsPage ? 'web.tsx' : 'web.jsx'
);
const jsFile = filename.replace(
/index\.(ts|js)$/,
'web.js'
);
const xmlFile = filename.replace(
/index\.(ts|js)$/,
'index.xml'
);
const xmlFileExists = fs.existsSync(xmlFile);
const tsxFileExists = fs.existsSync(tsxFile);
const jsFileExists = fs.existsSync(jsFile);
const pcTsxFile = filename.replace(
/index\.(ts|js)$/,
tsPage ? 'web.pc.tsx' : 'web.pc.jsx'
);
const pcJsFile = filename.replace(
/index\.(ts|js)$/,
'web.pc.js'
);
const pcTsxFileExists = fs.existsSync(pcTsxFile);
const pcJsFileExists = fs.existsSync(pcJsFile);
/** tsxrender
* if (this.props.width === 'xs') {
const renderMobile = require('./web.tsx').default;
return renderMobile.call(this);
}
else {
const renderScreen = require('./web.pc.tsx').default;
return renderScreen.call(this);
}
*/
const renderTsxStatements = [
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('render'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral(
`./web.${tsPage ? 'tsx' : 'jsx'}`
),
]),
t.identifier('default')
)
),
]),
t.returnStatement(
t.identifier('render')
),
];
const renderJsStatements = [
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('render'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral('./web.js'),
]),
t.identifier('default')
)
),
]),
t.returnStatement(
t.identifier('render')
),
];
const renderPcTsxStatements = [
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('render'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral(
`./web.pc.${tsPage ? 'tsx' : 'jsx'}`
),
]),
t.identifier('default')
)
),
]),
t.returnStatement(
t.identifier('render')
),
];
const renderPcJsStatements = [
t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('render'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral('./web.pc.js'),
]),
t.identifier('default')
)
),
]),
t.returnStatement(
t.identifier('render')
),
];
const getStatements = () => {
const statements = [];
if (tsxFileExists && pcTsxFileExists) {
statements.push(
t.ifStatement(
t.binaryExpression(
'===',
t.memberExpression(
t.memberExpression(
t.thisExpression(),
t.identifier('props')
),
t.identifier('width')
),
t.stringLiteral('xs')
),
t.blockStatement(renderTsxStatements),
t.blockStatement(renderPcTsxStatements)
)
);
} else if (jsFileExists && pcJsFileExists) {
statements.push(
t.ifStatement(
t.binaryExpression(
'===',
t.memberExpression(
t.memberExpression(
t.thisExpression(),
t.identifier('props')
),
t.identifier('width')
),
t.stringLiteral('xs')
),
t.blockStatement(renderJsStatements),
t.blockStatement(renderPcJsStatements)
)
);
} else if (jsFileExists && pcTsxFileExists) {
statements.push(
t.ifStatement(
t.binaryExpression(
'===',
t.memberExpression(
t.memberExpression(
t.thisExpression(),
t.identifier('props')
),
t.identifier('width')
),
t.stringLiteral('xs')
),
t.blockStatement(renderJsStatements),
t.blockStatement(renderPcTsxStatements)
)
);
} else if (tsxFileExists && pcJsFileExists) {
statements.push(
t.ifStatement(
t.binaryExpression(
'===',
t.memberExpression(
t.memberExpression(
t.thisExpression(),
t.identifier('props')
),
t.identifier('width')
),
t.stringLiteral('xs')
),
t.blockStatement(renderTsxStatements),
t.blockStatement(renderPcJsStatements)
)
);
} else if (tsxFileExists) {
statements.push(...renderTsxStatements);
} else if (pcTsxFileExists) {
statements.push(...renderPcTsxStatements);
} else if (jsFileExists) {
statements.push(...renderJsStatements);
} else if (pcJsFileExists) {
statements.push(...renderPcJsStatements);
} else if (!xmlFileExists) {
assert(
false,
`${filename}文件中不存在web.tsx或者web.pc.tsx`
);
}
return statements;
};
const node = path.node;
const body = node.body;
body.forEach((node2) => {
// export default OakComponent({})
if (t.isExportDefaultDeclaration(node2)) {
let node3 = node2.declaration;
if (node3) {
if (t.isTSAsExpression(node3)) {
// export default OakComponent({}) as ....
node3 = node3.expression;
}
}
if (t.isCallExpression(node3) && node3.callee.name === 'OakComponent') {
const statements = getStatements();
node3.arguments.forEach((node4) => {
if (t.isObjectExpression(node4)) {
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(
null,
[],
t.blockStatement(statements)
)
);
node4.properties.unshift(propertyRender);
}
else {
assert(false, `[${filename}]OakComponent调用参数不是ObjectExpression`);
}
});
}
}
// exports.default = OakPage({})、exports.default = OakComponent({})
else if (
t.isExpressionStatement(node2) &&
t.isAssignmentExpression(node2.expression) &&
t.isCallExpression(node2.expression.right) &&
t.isIdentifier(node2.expression.right.callee) &&
node2.expression.right.callee.name ===
'OakComponent'
) {
const statements = getStatements();
node2.expression.right.arguments.forEach(
(node3) => {
if (t.isObjectExpression(node3)) {
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(
null,
[],
t.blockStatement(statements)
)
);
node3.properties.unshift(
propertyRender
);
}
}
);
}
});
const { base } = parse(filename);
const node = path.node;
if (['index.ts', 'index.js'].includes(base) && t.isCallExpression(node) && t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
console.log(filename, base);
injectGetRender(node, cwd, filename, 'web');
}
},
},

View File

@ -0,0 +1,39 @@
const { resolve } = require('path');
const watchFolders = process.env.NODE_ENV === 'production' ? ['../src', '../node_modules'] : [
'../src', '../node_modules', '../../oak-domain', '../../oak-common-aspect', '../../oak-external-sdk',
'../../oak-frontend-base', '../../oak-general-business', '../../oak-memory-tree-store'
];
const sourceExts = (process.env.NODE_ENV === 'production' || process.env.PROD === 'true') ?
['prod.ts', 'ts', 'tsx', 'prod.js', 'js', 'jsx', 'less', 'json'] :
['dev.ts', 'ts', 'tsx', 'dev.js', 'js', 'jsx', 'less', 'json'];
const NullModules = ['fs', 'url'];
/**
* Metro configuration
* https://facebook.github.io/metro/docs/configuration
*
* @type {import('metro-config').MetroConfig}
*/
const config = {
transformer: {
babelTransformerPath: resolve(__dirname, 'transformer.js'),
// hermesParser: true,
},
resolver: {
sourceExts,
resolveRequest: (context, moduleName, platform) => {
if (NullModules.includes(moduleName)) {
return {
type: 'empty',
};
}
return context.resolveRequest(context, moduleName, platform);
},
nodeModulesPaths: [resolve(process.cwd(), '..', 'node_modules')], // development模式下oak的库是以文件方式链接其自身的node_modules里可能会缺失一些库
},
watchFolders,
};
module.exports = config;

View File

@ -0,0 +1,108 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
* @oncall react_native
*/
"use strict";
const traverse = require('@babel/traverse').default;
const t = require('@babel/types');
const path = require('path');
const less = require('less');
const css2rn = require("css-to-react-native-transform").default;
const { parseSync, transformFromAstSync, transformSync: babelTransform } = require("@babel/core");
const nullthrows = require("nullthrows");
const { injectGetRender } = require('../utils/injectGetRender');
async function renderToCSS({ src, filename, options = {} }) {
const { lessOptions = {} } = options;
const { css } = await less.render(src, { paths: [path.dirname(filename)], ...lessOptions });
return css;
}
function renderCSSToReactNative(css) {
return css2rn(css, { parseMediaQueries: true });
}
function transform({ filename, options, plugins, src }) {
const OLD_BABEL_ENV = process.env.BABEL_ENV;
process.env.BABEL_ENV = options.dev
? "development"
: process.env.BABEL_ENV || "production";
try {
const babelConfig = {
caller: {
name: "oak",
bundler: "oak",
platform: options.platform,
},
ast: true,
babelrc: options.enableBabelRCLookup,
code: false,
cwd: options.projectRoot,
highlightCode: true,
filename,
plugins,
sourceType: "module",
// NOTE(EvanBacon): We split the parse/transform steps up to accommodate
// Hermes parsing, but this defaults to cloning the AST which increases
// the transformation time by a fair amount.
// You get this behavior by default when using Babel's `transform` method directly.
cloneInputAst: false,
};
const transInner = (src) => {
const sourceAst = options.hermesParser
? require("hermes-parser").parse(src, {
babel: true,
sourceType: babelConfig.sourceType,
})
: parseSync(src, babelConfig);
const transformResult = transformFromAstSync(sourceAst, src, babelConfig);
// 为page和componet下的OakComponent注入getRender函数去取得同目录下的render.native.tsx
const resultAst = transformResult.ast;
const { base } = path.parse(filename);
if (['index.ts', 'index.js'].includes(base)) {
traverse(resultAst, {
CallExpression(path) {
const node = path.node;
if (t.isIdentifier(node.callee) && node.callee.name === 'OakComponent') {
injectGetRender(node, options.projectRoot, filename, 'native');
}
}
})
}
// injectGetRender(transformResult.ast.program.body, path.resolve(process.cwd(), '..'), filename, 'native');
return {
ast: nullthrows(transformResult.ast),
metadata: transformResult.metadata,
};
};
if (filename.endsWith('less')) {
return renderToCSS({ src, filename, options }).then((css) => {
const cssObject = renderCSSToReactNative(css);
const newSrc = `module.exports = ${JSON.stringify(cssObject)}`;
return transInner(newSrc);
});
}
return transInner(src);
} finally {
if (OLD_BABEL_ENV) {
process.env.BABEL_ENV = OLD_BABEL_ENV;
}
}
}
module.exports = {
transform,
};

View File

@ -0,0 +1,194 @@
const { relative, dirname, join } = require('path');
const fs = require('fs');
const t = require('@babel/types');
const traverse = require('@babel/traverse').default;
const assert = require('assert');
/**
*
* @param {*} node
* @param {*} projectRoot
* @param {*} filename
* @param {*} env 'web' | 'native'
*/
function injectGetRender(node, projectRoot, filename, env) {
assert(t.isCallExpression(node) && t.isIdentifier(node.callee) && node.callee.name === 'OakComponent');
const dir = dirname(filename);
if (env === 'web') {
// web要根据this.props.width的宽度决定注入web.tsx还是web.pc.tsx
const tsxFile = join(dir, 'web.tsx');
const jsFile = join(dir, 'web.js');
const jsxFile = join(dir, 'web.jsx');
let webDestFile;
if (fs.existsSync(tsxFile)) {
webDestFile = './web.tsx';
}
else if (fs.existsSync(jsFile)) {
webDestFile = './web.js';
}
else if (fs.existsSync(jsxFile)) {
webDestFile = './web.jsx';
}
const acquireWebFileStmt = webDestFile && t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('oakRenderFn'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral(webDestFile),
]),
t.identifier('default')
)
),
]);
let pcDestFile;
const pcTsxFile = join(dir, 'web.pc.tsx');
const pcJsFile = join(dir, 'web.pc.js');
const pcJsxFile = join(dir, 'web.pc.jsx');
if (fs.existsSync(pcTsxFile)) {
pcDestFile = './web.pc.tsx';
}
else if (fs.existsSync(pcJsFile)) {
pcDestFile = './web.pc.js';
}
else if (fs.existsSync(pcJsxFile)) {
pcDestFile = './web.pc.jsx';
}
const acquirePcFileStmt = pcDestFile && t.variableDeclaration('const', [
t.variableDeclarator(
t.identifier('oakRenderFn'),
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral(pcDestFile),
]),
t.identifier('default')
)
),
]);
const getStatements = () => {
/** tsxgetRender
* if (this.props.width === 'xs') {
const oakRenderFn = require('./web.tsx').default;
return oakRenderFn;
}
else {
const oakRenderFn = require('./web.pc.tsx').default;
return oakRenderFn;
}
*/
const statements = [];
if (acquirePcFileStmt && acquireWebFileStmt) {
statements.push(
t.ifStatement(
t.binaryExpression(
'===',
t.memberExpression(
t.memberExpression(
t.thisExpression(),
t.identifier('props')
),
t.identifier('width')
),
t.stringLiteral('xs')
),
t.blockStatement([
acquireWebFileStmt,
t.returnStatement(
t.identifier('oakRenderFn')
)
]),
t.blockStatement([
acquirePcFileStmt,
t.returnStatement(
t.identifier('oakRenderFn')
)
])
)
);
}
else if (acquirePcFileStmt) {
statements.push(
acquirePcFileStmt,
t.returnStatement(
t.identifier('oakRenderFn')
)
);
}
else if (acquireWebFileStmt) {
statements.push(
acquireWebFileStmt,
t.returnStatement(
t.identifier('oakRenderFn')
)
);
} else {
assert(
false,
`${dir}文件夹中不存在web.tsx或者web.pc.tsx无法渲染`
);
}
return statements;
};
const statements = getStatements();
node.arguments.forEach((node4) => {
if (t.isObjectExpression(node4)) {
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(
null,
[],
t.blockStatement(statements)
)
);
node4.properties.unshift(propertyRender);
}
else {
assert(false, `[${filename}]OakComponent调用参数不是ObjectExpression`);
}
});
}
else {
assert(env === 'native');
/** native(react-nativerender.nativerender.ios/android
* OakComponent({
* getRender() {
* const oakRenderFn = require('./render').default;
* return oakRenderFn;
* },
* })
*/
const arg = node.arguments[0];
assert(t.isObjectExpression(arg));
const propertyRender = t.objectProperty(
t.identifier('getRender'),
t.functionExpression(null, [], t.blockStatement(
[
t.variableDeclaration('var', [
t.variableDeclarator(
t.identifier('oakRenderFn'),
t.memberExpression(
t.callExpression(
t.identifier('require'),
[
t.stringLiteral('./render')
]
),
t.identifier('default')
),
)
]),
t.returnStatement(
t.identifier('oakRenderFn')
)
]
))
);
arg.properties.unshift(propertyRender);
}
}
module.exports = {
injectGetRender
};

View File

@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const tip_style_1 = require("./tip-style");
const cross_spawn_1 = tslib_1.__importDefault(require("cross-spawn"));
const path_1 = require("path");
const makeLocale_1 = tslib_1.__importDefault(require("./makeLocale"));
const fs_1 = require("fs");
async function build(cmd) {
if (!cmd.target) {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp or --target wechatMp to he command`)}`);
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`Please add --target web or --target mp(wechatMp) or --target rn(native) to run the project in Web/WechatMp/ReactNative environment`)}`);
return;
}
// 先makeLocale
@ -19,7 +21,7 @@ async function build(cmd) {
: ''} ${cmd.target !== 'web' && cmd.mode !== 'production'
? `split:${!!cmd.split}`
: ''}`)}`);
if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
if (['mp', 'wechatMp'].includes(cmd.target)) {
const result = cross_spawn_1.default.sync(`cross-env`, [
`NODE_ENV=${cmd.mode}`,
`NODE_TARGET=${cmd.target}`,
@ -72,5 +74,41 @@ async function build(cmd) {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`执行失败`)}`);
}
}
else if (['native', 'rn'].includes(cmd.target)) {
const prjDir = process.cwd();
const cwd = (0, path_1.resolve)(prjDir, cmd.subDir || 'native');
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
// rn不支持注入NODE_ENVIRONMENT这样的环境变量cross-env没有用
/* const result = spawn.sync(
'react-native',
[
'start',
],
{
cwd,
stdio: 'inherit',
shell: true,
}
); */
const result = cross_spawn_1.default.sync(`cross-env`, [
`NODE_ENV=${cmd.mode}`,
'OAK_PLATFORM=native',
'react-native',
'start'
].filter(Boolean), {
cwd,
stdio: 'inherit',
shell: true,
});
if (result.status === 0) {
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`执行完成`)}`);
}
else {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`执行失败`)}`);
}
}
else {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`target could only be web or mp(wechatMp) or rn(native)`)}`);
}
}
exports.default = build;

View File

@ -23,7 +23,7 @@ function enhanceErrorMessages(methodName, log) {
this.outputHelp();
console.log(` ` + (0, tip_style_1.error)(log(...args)));
console.log();
process.exit(1);
process.exit(-1);
};
}
const currentNodeVersion = process.versions.node;
@ -38,7 +38,7 @@ if (Number(major) < minNodeVersion) {
minNodeVersion +
' or higher. \n' +
'Please update your version of Node.');
process.exit(1);
process.exit(-1);
}
commander_1.default.version(config_1.CLI_VERSION, '-v, --version').usage('<command> [options]');
commander_1.default
@ -87,8 +87,8 @@ commander_1.default
.action(create_1.update);
commander_1.default
.command('run')
.option('-i, --initialize', 'true')
.option('-m, --mode <mode>', 'mode')
.option('-p, --platform <platform>', 'platform')
.option('-d, --subDir <subDirName>', 'subDirName')
.description(`run backend server by ${config_1.CLI_NAME}`)
.action(run_1.default);
// output help information on unknown commands

View File

@ -16,7 +16,7 @@ async function make() {
}
else {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`make 执行失败`)}`);
process.exit(1);
process.exit(-1);
}
}
exports.default = make;

View File

@ -21,7 +21,7 @@ async function make(cmd, watch) {
}
else {
(0, tip_style_1.Error)(`${(0, tip_style_1.error)(`make 执行失败`)}`);
process.exit(1);
process.exit(-1);
}
}
else {

View File

@ -3,36 +3,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const tip_style_1 = require("./tip-style");
const cross_spawn_1 = tslib_1.__importDefault(require("cross-spawn"));
const path_1 = require("path");
const fs_1 = require("fs");
async function run(options) {
if (options.initialize) {
(0, tip_style_1.Success)(`${(0, tip_style_1.success)('初始化数据库中……')}`);
// ts-node scripts/build-app-domain & npm link ./app-domain
const drop = options.args.includes('drop') || false;
const result = cross_spawn_1.default.sync('ts-node', [require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`], {
const prjDir = process.cwd();
const cwd = (0, path_1.resolve)(process.cwd(), options.subDir || 'native');
if (options.platform === 'ios') {
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
(0, tip_style_1.Success)(`${(0, tip_style_1.primary)('run react-native run-ios')}`);
const result = cross_spawn_1.default.sync('react-native', ['run-ios'], {
cwd,
stdio: 'inherit',
shell: true,
});
if (result.status === 0) {
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`初始化数据库完成`)}`);
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`react-native run-ios success`)}`);
}
else {
Error(`${(0, tip_style_1.error)(`初始化数据库失败`)}`);
process.exit(1);
Error(`${(0, tip_style_1.error)('react-native run-ios fail')}`);
process.exit(-1);
}
}
else {
(0, tip_style_1.Success)(`${(0, tip_style_1.success)('启动服务器……')}`);
console.log(options.mode);
// ts-node scripts/build-app-domain & npm link ./app-domain
const result = cross_spawn_1.default.sync(`cross-env`, [
`NODE_ENV=${options.mode}`,
'OAK_PLATFORM=server',
'ts-node',
require.resolve('../scripts/' + 'start-server.js'),
], {
else if (options.platform === 'android') {
(0, tip_style_1.Success)(`${(0, tip_style_1.primary)('run react-native run-android')}`);
(0, fs_1.copyFileSync)((0, path_1.resolve)(prjDir, 'package.json'), (0, path_1.resolve)(cwd, 'package.json'));
const result = cross_spawn_1.default.sync('react-native', ['run-android'], {
cwd,
stdio: 'inherit',
shell: true,
});
if (result.status === 0) {
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`react-native run-android success`)}`);
}
else {
Error(`${(0, tip_style_1.error)('react-native run-android fail')}`);
process.exit(-1);
}
}
else {
Error((0, tip_style_1.error)(`unrecoganized platfrom: ${options.platform}`));
process.exit(-1);
}
}
exports.default = run;

View File

@ -32,6 +32,7 @@
"@types/node": "^20.6.0",
"@types/shelljs": "^0.8.8",
"@types/uuid": "^8.3.4",
"babel-plugin-module-resolver": "^5.0.0",
"fork-ts-checker-webpack-plugin": "^8.0.0",
"node-watch": "^0.7.4",
"querystring-es3": "^0.2.1",
@ -68,6 +69,7 @@
"css": "^3.0.0",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
"css-to-react-native-transform": "^2.0.0",
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"dotenv-webpack": "^7.1.0",
@ -106,6 +108,7 @@
"prompts": "^2.4.2",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.1",
"react-native": "^0.72.7",
"react-refresh": "^0.11.0",
"required-path": "^1.0.1",
"resolve": "^1.20.0",

View File

@ -8,13 +8,15 @@ import {
Warn,
} from './tip-style';
import spawn from 'cross-spawn';
import { resolve } from 'path';
import makeLocale from './makeLocale';
import { copyFileSync } from 'fs';
export default async function build(cmd: any) {
if (!cmd.target) {
Error(
`${error(
`Please add --target web or --target mp or --target wechatMp to he command`
`Please add --target web or --target mp(wechatMp) or --target rn(native) to run the project in Web/WechatMp/ReactNative environment`
)}`
);
return;
@ -37,7 +39,7 @@ export default async function build(cmd: any) {
}`
)}`
);
if (cmd.target === 'mp' || cmd.target === 'wechatMp') {
if (['mp', 'wechatMp'].includes(cmd.target)) {
const result = spawn.sync(
`cross-env`,
[
@ -103,4 +105,47 @@ export default async function build(cmd: any) {
Error(`${error(`执行失败`)}`);
}
}
else if (['native', 'rn'].includes(cmd.target)) {
const prjDir = process.cwd();
const cwd = resolve(prjDir, cmd.subDir || 'native');
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
// rn不支持注入NODE_ENVIRONMENT这样的环境变量cross-env没有用
/* const result = spawn.sync(
'react-native',
[
'start',
],
{
cwd,
stdio: 'inherit',
shell: true,
}
); */
const result = spawn.sync(
`cross-env`,
[
`NODE_ENV=${cmd.mode}`,
'OAK_PLATFORM=native',
'react-native',
'start'
].filter(Boolean),
{
cwd,
stdio: 'inherit',
shell: true,
}
);
if (result.status === 0) {
Success(`${success(`执行完成`)}`);
} else {
Error(`${error(`执行失败`)}`);
}
}
else {
Error(
`${error(
`target could only be web or mp(wechatMp) or rn(native)`
)}`
);
}
}

View File

@ -21,7 +21,7 @@ function enhanceErrorMessages(methodName: string, log: Function) {
this.outputHelp();
console.log(` ` + error(log(...args)));
console.log();
process.exit(1);
process.exit(-1);
};
}
@ -40,7 +40,7 @@ if (Number(major) < minNodeVersion) {
' or higher. \n' +
'Please update your version of Node.'
);
process.exit(1);
process.exit(-1);
}
program.version(CLI_VERSION, '-v, --version').usage('<command> [options]');
@ -93,10 +93,11 @@ program
.action(update);
program
.command('run')
.option('-i, --initialize', 'true')
.option('-m, --mode <mode>', 'mode')
.option('-p, --platform <platform>', 'platform')
.option('-d, --subDir <subDirName>', 'subDirName')
.description(`run backend server by ${CLI_NAME}`)
.action(run);
// output help information on unknown commands
program.arguments('<command>').action((cmd) => {
program.outputHelp();

View File

@ -26,6 +26,6 @@ export default async function make() {
Success(`${success(`make 执行完成`)}`);
} else {
Error(`${error(`make 执行失败`)}`);
process.exit(1);
process.exit(-1);
}
}

View File

@ -31,7 +31,7 @@ export default async function make(cmd: any, watch?: boolean) {
Success(`${success(`make 执行完成`)}`);
} else {
Error(`${error(`make 执行失败`)}`);
process.exit(1);
process.exit(-1);
}
}
else {

View File

@ -7,44 +7,54 @@ import {
Warn,
} from './tip-style';
import spawn from 'cross-spawn';
import { resolve } from 'path';
import { copyFileSync, unlinkSync } from 'fs';
export default async function run(options: any): Promise<void> {
if (options.initialize) {
Success(`${success('初始化数据库中……')}`);
// ts-node scripts/build-app-domain & npm link ./app-domain
const drop = options.args.includes('drop') || false;
export default async function run(options: any): Promise<void> {
const prjDir = process.cwd();
const cwd = resolve(process.cwd(), options.subDir || 'native');
if (options.platform === 'ios') {
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
Success(`${primary('run react-native run-ios')}`);
const result = spawn.sync(
'ts-node',
[require.resolve('../scripts/' + 'initialize-server.ts'), `${drop}`],
'react-native',
['run-ios'],
{
cwd,
stdio: 'inherit',
shell: true,
}
);
if (result.status === 0) {
Success(`${success(`初始化数据库完成`)}`);
Success(`${success(`react-native run-ios success`)}`);
} else {
Error(`${error(`初始化数据库失败`)}`);
process.exit(1);
Error(`${error('react-native run-ios fail')}`);
process.exit(-1);
}
}
else if (options.platform === 'android') {
Success(`${primary('run react-native run-android')}`);
copyFileSync(resolve(prjDir, 'package.json'), resolve(cwd, 'package.json'));
const result = spawn.sync(
'react-native',
['run-android'],
{
cwd,
stdio: 'inherit',
shell: true,
}
);
if (result.status === 0) {
Success(`${success(`react-native run-android success`)}`);
} else {
Error(`${error('react-native run-android fail')}`);
process.exit(-1);
}
}
else {
Success(`${success('启动服务器……')}`);
console.log(options.mode);
// ts-node scripts/build-app-domain & npm link ./app-domain
const result = spawn.sync(
`cross-env`,
[
`NODE_ENV=${options.mode}`,
'OAK_PLATFORM=server',
'ts-node',
require.resolve('../scripts/' + 'start-server.js'),
],
{
stdio: 'inherit',
shell: true,
}
);
Error(error(`unrecoganized platfrom: ${options.platform}`));
process.exit(-1);
}
}