UNPKG

@fxext/cli

Version:

fanxing miniapp cli

196 lines (176 loc) 6.45 kB
const fs = require("fs"); const path = require("path"); const https = require("https"); const httpProxy = require('http-proxy'); const inquirer = require('inquirer'); const qrcode = require('qrcode-terminal'); const connect = require("connect"); const harmon = require('harmon'); const getCertificate = require('./ssl/getCertificate'); const log = require('../log'); const { getLocalIP } = require('../utils'); const projectConfig = require('../project.config.json'); async function serve() { let url = process.argv[2]; if (!url) { url = 'http://localhost:7456'; } const reg = new RegExp('(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'); if (!reg.test(url)) { log.error("请输入正确的http调试地址"); return; } // 选择小程序模式 async function selectAppMode() { const { miniAppMode, miniAppId } = await inquirer.prompt([ { type: 'input', message: '请输入小程序appId', name: 'miniAppId', validate: (value) => { const appIdStr = String(value).trim(); if (appIdStr.length) { return true; } return '请输入小程序appId'; } }, { type: 'list', message: '请选项小程序模式', name: 'miniAppMode', choices: [ { name: '主播模式' }, { name: '用户模式' } ] } ]); return { miniAppMode, miniAppId }; } // 获取项目配置,如果没有,则生成默认配置 const projectConfigPath = path.join(process.cwd(), 'project.config.json'); let config; if (fs.existsSync(projectConfigPath)) { config = JSON.parse(fs.readFileSync(projectConfigPath)); } else { const gameName = path.basename(process.cwd()); projectConfig.name = gameName; const { miniAppMode, miniAppId } = await selectAppMode(); projectConfig.builder.appMode = miniAppMode === '主播模式' ? 0 : 1; projectConfig.builder.appId = miniAppId; projectConfig.builder.buildConfig = [ { layoutType: 'm', framework: 'cocos' }, { layoutType: 'streamer_pc', framework: 'cocos' } ]; fs.writeFileSync(projectConfigPath, JSON.stringify( projectConfig, null, 2)); config = projectConfig; } const app = connect(); const selects = []; const simpleselect = {}; const { sdkVersion, appId, appMode = 0, sdkType, version, buildConfig, https: useHttps } = config.builder; let sdkFileName = appMode === 1 ? 'fx-ext-user.js' : 'fx-ext.js'; if (sdkType === 'partner') { sdkFileName = 'fx-ext-partner.js'; } // 需要插入html - head里面的内容 const insertHTML = [ `<meta http-equiv="Content-Security-Policy" content="connect-src 'self' https://*.kgimg.com https://*.kugou.com; default-src 'self' https://*.kgimg.com https://*.kugou.com; block-all-mixed-content; img-src 'self' https://*.kgimg.com https://*.kugou.com; font-src 'self' https://*.kgimg.com https://*.kugou.com; style-src 'self' https://*.kgimg.com https://*.kugou.com 'unsafe-inline'; script-src 'unsafe-eval' 'unsafe-inline' 'self' https://*.kgimg.com https://*.kugou.com; frame-src https://fanxing.kugou.com https://mfanxing.kugou.com https://localhost:*; object-src 'none';" />`, `<script src="https://s4fx.kgimg.com/pub2/fx-ext/${sdkVersion}/${sdkFileName}"></script>` ] simpleselect.query = 'title'; simpleselect.func = function (node) { let insert = `<title>${config.name}</title>`; insertHTML.forEach(item => { insert += item; }); node.createWriteStream({ outer: true }).end(insert); } selects.push(simpleselect); app.use(harmon([], selects, true)); const proxy = httpProxy.createProxyServer({ target: url }); app.use('/streamer_pc.html', function (req, res) { proxy.web(req, res); }); app.use('/index.html', function (req, res) { proxy.web(req, res); }); app.use('/m/app.json', function (req, res) { const appJsonPath = path.join(process.cwd(), './m/app.json'); res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('content-type', 'application/json'); if (fs.existsSync(appJsonPath)) { res.end(fs.readFileSync(appJsonPath)); } else { res.statusCode = 404; res.end(); } }); app.use('/streamer_pc/app.json', function (req, res) { const appJsonPath = path.join(process.cwd(), './streamer_pc/app.json'); res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('content-type', 'application/json'); if (fs.existsSync(appJsonPath)) { res.end(fs.readFileSync(appJsonPath)); } else { res.statusCode = 404; res.end(); } }); app.use('/', function (req, res) { proxy.web(req, res); }); const selfSignCert = getCertificate(); const server = https.createServer({ key : selfSignCert, cert: selfSignCert }, app).listen(config.builder.port, config.builder.host === 'localhost' ? '0.0.0.0' : config.builder.host); server.on('upgrade', function(req, socket, head) { proxy.ws(req, socket, head); }); const { port, host } = config.builder; const mode = appMode === '主播模式' ? 0 : 1; const qrcodeUrl = `https://${getLocalIP()}:${port}/index.html?type=miniapp&miniAppId=${appId}&appMode=${mode}`; qrcode.generate(qrcodeUrl, { small: true }); log.hint('\nAPP端调试二维码,详情查看:https://fanxing.kugou.com/open/doc/pages/develop/debug/app.html\n'); if (version >= 2) { const messages = [ `App running at:`, `- 本地IP地址: ${getLocalIP()}`, `- 开发端口号: ${port}`, '请将该信息配置到开发者中心', '', `本地服务:` ]; for (const entryItem of buildConfig) { if (entryItem.framework === 'cocos') { if (entryItem.layoutType === 'm') { messages.push(`Web面板:${useHttps ? 'https' : 'http'}://${host}:${port}/index.html`); } else if (entryItem.layoutType === 'streamer_pc') { messages.push(`伴侣面板:${useHttps ? 'https' : 'http'}://${host}:${port}/streamer_pc.html`); } } } log.hint(messages.join('\n')); } else { log.hint(`App running at:\n- Local: https://${host}:${port}\n- Network: https://${getLocalIP()}:${port}\n- 请将该信息配置到开发者中心`); } } module.exports = serve;