提交 f3effdda 编写于 作者: fxy060608's avatar fxy060608

feat: add uni-automator

上级 313f85a4
......@@ -14,5 +14,6 @@ declare namespace NodeJS {
UNI_NVUE_COMPILER: 'uni-app' | 'weex' | 'vue'
UNI_NVUE_STYLE_COMPILER: 'uni-app' | 'weex'
UNI_APP_CODE_SPLITING?: 'true'
UNI_AUTOMATOR_WS_ENDPOINT?: string
}
}
......@@ -4,6 +4,7 @@
"src/service/index.ts": "dist/uni-app-service.es.js"
},
"output": {
"freeze": false,
"name": "serviceContext",
"format": "iife",
"banner": "export function createServiceContext(weex, plus, instanceContext){\nconst Vue = instanceContext.Vue;\nlet setTimeout = instanceContext.setTimeout;\nlet clearTimeout = instanceContext.clearTimeout;\nlet setInterval = instanceContext.setInterval;\nlet clearInterval = instanceContext.clearInterval;\nconst __uniConfig = instanceContext.__uniConfig;\nconst __uniRoutes = instanceContext.__uniRoutes;\n",
......
......@@ -2157,14 +2157,14 @@ var serviceContext = (function (vue) {
return querySelectorAll(this, selector);
}
var wxInstance = /*#__PURE__*/Object.freeze({
var wxInstance = {
__proto__: null,
createSelectorQuery: createSelectorQuery$1,
createMediaQueryObserver: createMediaQueryObserver$1,
createIntersectionObserver: createIntersectionObserver$1,
selectComponent: selectComponent,
selectAllComponents: selectAllComponents
});
};
function getOpenerEventChannel() {
// TODO App
......@@ -12042,7 +12042,7 @@ var serviceContext = (function (vue) {
});
}, PreloadPageProtocol);
var uni$1 = /*#__PURE__*/Object.freeze({
var uni$1 = {
__proto__: null,
navigateTo: navigateTo,
switchTab: switchTab,
......@@ -12212,7 +12212,7 @@ var serviceContext = (function (vue) {
reLaunch: reLaunch,
unPreloadPage: unPreloadPage,
preloadPage: preloadPage
});
};
const UniServiceJSBridge$1 = /*#__PURE__*/ extend(ServiceJSBridge, {
publishHandler,
......@@ -18952,7 +18952,7 @@ var serviceContext = (function (vue) {
constants: constants_1
};
var pako_esm = /*#__PURE__*/Object.freeze({
var pako_esm = {
__proto__: null,
Deflate: Deflate_1,
Inflate: Inflate_1,
......@@ -18964,7 +18964,7 @@ var serviceContext = (function (vue) {
inflate: inflate_1,
inflateRaw: inflateRaw_1,
ungzip: ungzip_1
});
};
return index;
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
此差异已折叠。
'use strict'
function _interopDefault(ex) {
return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex
}
var fs = _interopDefault(require('fs'))
var debug = _interopDefault(require('debug'))
var parser = _interopDefault(require('postcss-selector-parser'))
var fs$1 = _interopDefault(require('fs-extra'))
var dateFormat = _interopDefault(require('licia/dateFormat'))
var path = require('path')
var util = require('util')
require('address')
require('default-gateway')
require('licia/isStr')
require('licia/getPort')
function transform(selectors) {
selectors.walk((selector) => {
if (selector.type === 'tag') {
const value = selector.value
if (value === 'page') {
//@ts-ignore
{
selector.value = 'body'
}
} else {
selector.value = 'uni-' + value
}
}
})
}
function transSelector(method) {
return {
reflect: async (send, params) => send(method, params, false),
params(params) {
if (params.selector) {
params.selector = parser(transform).processSync(params.selector)
}
return params
},
}
}
const methods = [
'Page.getElement',
'Page.getElements',
'Element.getElement',
'Element.getElements',
]
function initAdapter(adapter) {
methods.forEach((method) => {
adapter[method] = transSelector(method)
})
}
const qrCodeTerminal = require('qrcode-terminal')
const QrCodeReader = require('qrcode-reader')
const isWin = /^win/.test(process.platform)
const normalizePath = (path) => (isWin ? path.replace(/\\/g, '/') : path)
const debugLauncher = debug('automator:launcher')
const APPID = 'HBuilder'
const PACKAGE = 'io.dcloud.HBuilder'
const readdir = util.promisify(fs.readdir)
const stat = util.promisify(fs.stat)
async function getFiles(dir) {
const subdirs = await readdir(dir)
const files = await Promise.all(
subdirs.map(async (subdir) => {
const res = path.resolve(dir, subdir)
return (await stat(res)).isDirectory() ? getFiles(res) : res
})
)
return files.reduce((a, f) => a.concat(f), [])
}
class Launcher {
constructor(options) {
this.id = options.id
this.app = options.executablePath
this.appid = options.appid || APPID
this.package = options.package || PACKAGE
}
shouldPush() {
return this.exists(this.FILE_APP_SERVICE)
.then(() => {
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${
this.FILE_APP_SERVICE
} exists`
)
return false
})
.catch(() => {
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${
this.FILE_APP_SERVICE
} not exists`
)
return true
})
}
push(from) {
return getFiles(from)
.then((files) => {
const pushs = files.map((file) => {
const to = normalizePath(
path.join(this.DIR_WWW, path.relative(from, file))
)
debugLauncher(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} push ${file} ${to}`
)
return this.pushFile(file, to)
})
return Promise.all(pushs)
})
.then((res) => true)
}
get FILE_APP_SERVICE() {
return `${this.DIR_WWW}/app-service.js`
}
}
const debugClient = debug('automator:simctl')
function padZero(str) {
const num = parseInt(str)
return num > 9 ? String(num) : '0' + num
}
class IOS extends Launcher {
constructor() {
super(...arguments)
this.bundleVersion = ''
}
async init() {
const Simctl = require('node-simctl').Simctl
this.tool = new Simctl({ udid: this.id })
try {
await this.tool.bootDevice()
} catch (e) {}
await this.initSDCard()
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id}`)
}
async initSDCard() {
const appInfo = await this.tool.appInfo(this.package)
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} appInfo ${appInfo}`)
const matches = appInfo.match(/DataContainer\s+=\s+"(.*)"/)
if (!matches) {
return Promise.resolve('')
}
const versionMatches = appInfo.match(/CFBundleVersion\s+=\s+(.*);/)
if (!versionMatches) {
return Promise.resolve('')
}
this.sdcard = matches[1].replace('file:', '')
this.bundleVersion = versionMatches[1]
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.sdcard}`)
}
async version() {
return Promise.resolve(this.bundleVersion)
}
formatVersion(version) {
const versions = version.split('.')
if (versions.length !== 3) {
return version
}
return versions[0] + padZero(versions[1]) + padZero(versions[2])
}
async install() {
debugClient(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${this.app}`)
await this.tool.installApp(this.app)
await this.tool.grantPermission(this.package, 'all')
await this.initSDCard()
return Promise.resolve(true)
}
async start() {
try {
await this.tool.terminateApp(this.package)
await this.tool.launchApp(this.package)
} catch (e) {}
return Promise.resolve(true)
}
async exit() {
await this.tool.terminateApp(this.package)
await this.tool.shutdownDevice()
return Promise.resolve(true)
}
async captureScreenshot() {
return Promise.resolve(await this.tool.getScreenshot())
}
exists(file) {
return fs$1.existsSync(file)
? Promise.resolve(true)
: Promise.reject(Error(`${file} not exists`))
}
pushFile(from, to) {
return Promise.resolve(fs$1.copySync(from, to))
}
get DIR_WWW() {
return `${this.sdcard}/Documents/Pandora/apps/${this.appid}/www/`
}
}
const adb = require('adbkit')
const debugClient$1 = debug('automator:adb')
const $EXTERNAL_STORAGE = '$EXTERNAL_STORAGE'
class Android extends Launcher {
async init() {
// adbkit 异常时,可能不会关闭 socket
this.tool = adb.createClient()
if (!this.id) {
const devices = await this.tool.listDevices()
if (!devices.length) {
throw Error(`Device not found`)
}
this.id = devices[0].id
}
this.sdcard = (await this.shell(this.COMMAND_EXTERNAL)).trim()
debugClient$1(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} init ${this.id} ${this.sdcard}`
)
}
version() {
return this.shell(this.COMMAND_VERSION).then((output) => {
const matches = output.match(/versionName=(.*)/)
if (matches && matches.length > 1) {
return matches[1]
}
return ''
})
}
formatVersion(version) {
return version
}
async install() {
let grant = true
try {
const props = await this.tool.getProperties(this.id)
const version = props['ro.build.version.release'].split('.')[0]
if (parseInt(version) < 6) {
grant = false
}
} catch (e) {}
debugClient$1(
`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} install ${
this.app
} permission=${grant}`
)
if (grant) {
const Command = require('adbkit/lib/adb/command.js')
const oldSend = Command.prototype._send
Command.prototype._send = function send(data) {
if (data.indexOf('shell:pm install -r ') === 0) {
data = data.replace('shell:pm install -r ', 'shell:pm install -r -g ')
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ${data} `)
}
return oldSend.call(this, data)
}
}
return this.tool.install(this.id, this.app).then(() => this.init())
}
start() {
return this.exit().then(() => this.shell(this.COMMAND_START))
}
exit() {
return this.shell(this.COMMAND_STOP)
}
captureScreenshot() {
return this.tool.screencap(this.id).then((stream) => {
return new Promise((resolve) => {
const chunks = []
stream.on('data', function (chunk) {
chunks.push(chunk)
})
stream.on('end', function () {
resolve(Buffer.concat(chunks).toString('base64'))
})
})
})
}
exists(file) {
return this.tool.stat(this.id, file)
}
pushFile(from, to) {
return this.tool.push(this.id, from, to)
}
shell(command) {
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} SEND ► ${command}`)
return this.tool
.shell(this.id, command)
.then(adb.util.readAll)
.then((output) => {
const res = output.toString()
debugClient$1(`${dateFormat('yyyy-mm-dd HH:MM:ss:l')} ◀ RECV ${res}`)
return res
})
}
get DIR_WWW() {
return `${this.sdcard}/Android/data/${this.package}/apps/${this.appid}/www`
}
get COMMAND_EXTERNAL() {
return `echo ${$EXTERNAL_STORAGE}`
}
get COMMAND_VERSION() {
return `dumpsys package ${this.package}`
}
get COMMAND_STOP() {
return `am force-stop ${this.package}`
}
get COMMAND_START() {
return `am start -n ${this.package}/io.dcloud.PandoraEntry --es ${this.appid} --ez needUpdateApp false --ez reload true`
}
}
const debugDevtools = debug('automator:devtool')
let launcher
let install = false
function createLauncher(platform, options) {
if (platform === 'ios') {
return new IOS(options)
}
return new Android(options)
}
const VERSIONS_RE = {
android: /android_version=(.*)/,
ios: /iphone_version=(.*)/,
}
function getVersion(version, platform) {
if (version.endsWith('.txt')) {
try {
const versionStr = fs.readFileSync(version).toString()
const matches = versionStr.match(VERSIONS_RE[platform])
if (matches) {
return matches[1]
}
} catch (e) {
console.error(e)
}
}
return version
}
async function validateDevtools(options, puppet) {
options.platform = (
options.platform || process.env.UNI_OS_NAME
).toLocaleLowerCase()
Object.assign(options, options[options.platform])
launcher = createLauncher(options.platform, options)
await launcher.init() // check device
const version = await launcher.version()
if (!version) {
install = true
} else if (options.version) {
const newVersion = launcher.formatVersion(
getVersion(options.version, options.platform)
)
debugDevtools(`version: ${version}`)
debugDevtools(`newVersion: ${newVersion}`)
if (newVersion !== version) {
install = true
}
}
if (install) {
if (!options.executablePath) {
throw Error(
`app-plus->${options.platform}->executablePath is not provided`
)
}
if (!fs.existsSync(options.executablePath)) {
throw Error(`${options.executablePath} not exists`)
}
}
return options
}
async function createDevtools(projectPath, options, puppet) {
if (install) {
//install
await launcher.install()
}
if (install || puppet.compiled || (await launcher.shouldPush())) {
await launcher.push(projectPath)
}
await launcher.start()
}
const adapter = {
'Tool.close': {
reflect: async () => {},
},
'App.exit': {
reflect: async () => launcher.exit(),
},
'App.enableLog': {
reflect: () => Promise.resolve(),
},
'App.captureScreenshot': {
reflect: async (send, params) => {
const data = await launcher.captureScreenshot(params)
debugDevtools(`App.captureScreenshot ${data.length}`)
return {
data,
}
},
},
}
initAdapter(adapter)
const puppet = {
devtools: {
name: 'App',
paths: [],
required: ['manifest.json', 'app-service.js'],
validate: validateDevtools,
create: createDevtools,
},
adapter,
}
module.exports = puppet
......@@ -4,9 +4,12 @@
"description": "@dcloudio/uni-app-plus",
"files": [
"dist",
"lib",
"style"
],
"sideEffects": false,
"sideEffects": [
"lib/automator.js"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
......
......@@ -2,6 +2,7 @@ import '../../style/framework/base.css'
import '@dcloudio/uni-h5/style/framework/nvue.css'
import '@dcloudio/uni-components/style/resize-sensor.css'
import { initView } from '@dcloudio/uni-core'
import { formatAppLog } from '@dcloudio/uni-shared'
import { ON_WEBVIEW_READY } from '../constants'
import { UniViewJSBridge } from './bridge'
import * as uni from './api'
......@@ -13,6 +14,7 @@ import { initViewMethods } from './framework/viewMethods'
;(window as any).UniViewJSBridge = UniViewJSBridge
;(window as any).rpx2px = uni.upx2px
;(window as any).__$__ = $
;(window as any).__f__ = formatAppLog
function onWebviewReady() {
initView()
......
此差异已折叠。
......@@ -9,8 +9,9 @@
</head>
<body>
<div id="app"></div>
<script src="uni-app-view.umd.js"></script>
<!--wxsCode-->
<!--renderjsCode-->
<script src="uni-app-view.umd.js"></script>
<!--automatorCode-->
</body>
</html>
......@@ -27,10 +27,15 @@ function genViewHtml(bundle: OutputBundle) {
? `<script src="${APP_RENDERJS_JS}"></script>`
: ''
const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT
? `<script src="__uniappautomator.js"></script>`
: ''
return viewHtmlStr
.toString()
.replace('<!--wxsCode-->', wxsCode)
.replace('<!--renderjsCode-->', renderjsCode)
.replace('<!--automatorCode-->', automatorCode)
.replace(
'/*__uniConfig*/',
`var __uniConfig = ${JSON.stringify(__uniConfig)}`
......
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var NodeEnvironment = _interopDefault(require('jest-environment-node'));
var Automator = _interopDefault(require('./index.js'));
const automator = new Automator();
class UniAutomatorEnvironment extends NodeEnvironment {
constructor(config, context) {
super(config);
if (process.env.UNI_AUTOMATOR_CONFIG) {
this.launchOptions = require(process.env.UNI_AUTOMATOR_CONFIG);
}
else {
this.launchOptions = config.testEnvironmentOptions;
}
}
async setup() {
await super.setup();
const globalThis = global;
if (!globalThis.__init__) {
globalThis.__init__ = true;
// 必须启用runInBand,否则会launch多次
this.launchOptions.platform =
this.launchOptions.platform || process.env.UNI_PLATFORM;
globalThis.program = await automator.launch(this.launchOptions);
if (this.launchOptions.devtools && this.launchOptions.devtools.remote) {
await globalThis.program.remote(true);
}
}
else {
if (!globalThis.program) {
throw Error(`Program init failed`);
}
}
this.global.program = globalThis.program;
}
async teardown() {
await super.teardown();
}
}
module.exports = UniAutomatorEnvironment;
此差异已折叠。
'use strict';
async function teardown() {
const program = global.program;
program && program.teardown();
await new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
}
module.exports = teardown;
'use strict'
var __importDefault =
(this && this.__importDefault) ||
function (mod) {
return mod && mod.__esModule ? mod : { default: mod }
}
Object.defineProperty(exports, '__esModule', { value: true })
const fs_extra_1 = __importDefault(require('fs-extra'))
const path_1 = __importDefault(require('path'))
const uni_cli_shared_1 = require('@dcloudio/uni-cli-shared')
exports.default = [
uni_cli_shared_1.defineUniMainJsPlugin((opts) => {
return {
name: 'vite:uni-automator',
enforce: 'pre',
configResolved() {
if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
return
}
const pkg = JSON.parse(
fs_extra_1.default.readFileSync(
path_1.default.resolve(__dirname, '../package.json'),
'utf8'
)
)
const automatorJson = JSON.stringify({
version: pkg.version,
wsEndpoint: process.env.UNI_AUTOMATOR_WS_ENDPOINT,
})
fs_extra_1.default.outputFileSync(
path_1.default.resolve(
process.env.UNI_OUTPUT_DIR,
'../.automator/' + process.env.UNI_PLATFORM + '/.automator.json'
),
automatorJson
)
},
transform(code, id) {
if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
return null
}
if (opts.filter(id)) {
const platform = process.env.UNI_PLATFORM
return {
code:
code +
`;import '@dcloudio/uni-${
platform === 'app' ? 'app-plus' : platform
}/lib/automator.js';`,
map: null,
}
}
},
}
}),
]
{
"name": "@dcloudio/uni-automator",
"version": "3.0.0-alpha-3000020210813002",
"description": "@dcloudio/uni-automator",
"main": "dist/index.js",
"files": [
"dist",
"lib"
],
"sideEffects": false,
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
"directory": "packages/uni-automator"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/dcloudio/uni-app/issues"
},
"uni-app": {
"name": "uniAutomator",
"apply": [
"app",
"h5",
"mp-weixin"
]
},
"gitHead": "d5896d19315a106039411c16bbf8b804a865450d",
"dependencies": {
"address": "^1.1.2",
"cross-env": "^7.0.3",
"debug": "^4.3.2",
"default-gateway": "^6.0.3",
"fs-extra": "^10.0.0",
"licia": "^1.29.0",
"postcss-selector-parser": "^6.0.6",
"qrcode-reader": "^1.0.4",
"qrcode-terminal": "^0.12.0",
"ws": "^8.2.0"
}
}
import fs from 'fs-extra'
import path from 'path'
import { defineUniMainJsPlugin } from '@dcloudio/uni-cli-shared'
export default [
defineUniMainJsPlugin((opts) => {
return {
name: 'vite:uni-automator',
enforce: 'pre',
configResolved() {
if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
return
}
const pkg = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf8')
)
const automatorJson = JSON.stringify({
version: pkg.version,
wsEndpoint: process.env.UNI_AUTOMATOR_WS_ENDPOINT,
})
fs.outputFileSync(
path.resolve(
process.env.UNI_OUTPUT_DIR,
'../.automator/' + process.env.UNI_PLATFORM + '/.automator.json'
),
automatorJson
)
},
transform(code, id) {
if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
return null
}
if (opts.filter(id)) {
const platform = process.env.UNI_PLATFORM
return {
code:
code +
`;import '@dcloudio/uni-${
platform === 'app' ? 'app-plus' : platform
}/lib/automator.js';`,
map: null,
}
}
},
}
}),
]
{
"extends": "../../tsconfig.node.json",
"compilerOptions": {
"outDir": "lib"
},
"include": [
"src",
"../shims-node.d.ts",
"../shims-uni-app.d.ts"
]
}
import { RuleSetRule } from 'webpack'
export function createFileLoader(): RuleSetRule {
return {
test: /\.(png|jpg|gif|ttf|eot|woff|woff2)$/i,
use: [
{
loader: 'file-loader',
options: {
publicPath: 'assets',
outputPath: 'assets',
},
},
],
}
}
import { RuleSetRule } from 'webpack'
import { createBabelLoader } from './babelLoader'
import { createCssLoaders } from './cssLoader'
import { createFileLoader } from './fileLoader'
import { createRecyclableLoader } from './recyclableLoader'
import { createTemplateLoader } from './templateLoader'
import { createVueLoader } from './vueLoader'
export function createRules(options: NVueCompilerOptions): RuleSetRule[] {
const rules = [
createFileLoader(),
createVueLoader(options),
createBabelLoader(),
createRecyclableLoader(),
......
......@@ -21,6 +21,7 @@ export const COMMON_EXCLUDE = [
/\/@vue\//,
/\/vue-router\//,
/\/vuex\//,
/\/vue-i18n\//,
/\/@dcloudio\/uni-h5-vue/,
/\/@dcloudio\/uni-shared/,
/\/@dcloudio\/uni-h5\/style/,
......
import path from 'path'
const libDir = path.resolve(__dirname, '../lib')
const libDir = path.resolve(__dirname, '../../lib')
export function initProvide() {
const cryptoDefine = [path.join(libDir, 'crypto.js'), 'default']
return {
__f__: [path.join(__dirname, '../hbx/formatLog.js'), 'formatLog'],
__f__: ['@dcloudio/uni-shared', 'formatAppLog'],
crypto: cryptoDefine,
'window.crypto': cryptoDefine,
'global.crypto': cryptoDefine,
......
此差异已折叠。
此差异已折叠。
......@@ -6,9 +6,12 @@
"module": "./dist/uni-h5.es.js",
"files": [
"dist",
"lib",
"style"
],
"sideEffects": false,
"sideEffects": [
"lib/automator.js"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
......
此差异已折叠。
此差异已折叠。
......@@ -3,6 +3,10 @@
"version": "3.0.0-alpha-3000020210813002",
"description": "uni-app mp-baidu",
"main": "dist/index.js",
"files": [
"dist",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
......
此差异已折叠。
此差异已折叠。
......@@ -3,6 +3,10 @@
"version": "3.0.0-alpha-3000020210813002",
"description": "uni-app mp-weixin",
"main": "dist/index.js",
"files": [
"dist",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/dcloudio/uni-app.git",
......
......@@ -165,6 +165,8 @@ export declare const EventModifierFlags: {
self: number;
};
export declare function formatAppLog(type: 'log' | 'info' | 'debug' | 'warn' | 'error', filename: string, ...args: unknown[]): void;
export declare function formatDateTime({ date, mode }: {
date?: Date | undefined;
mode?: string | undefined;
......
......@@ -54,7 +54,7 @@ export function normalizeLog(
return msgs.join('---COMMA---') + ' ' + filename
}
export function formatLog(
export function formatAppLog(
type: 'log' | 'info' | 'debug' | 'warn' | 'error',
filename: string,
...args: unknown[]
......
export { formatAppLog } from './formatLog'
......@@ -2,6 +2,7 @@ export * from './vue'
export * from './log'
export * from './dom'
export * from './url'
export * from './hbx'
export * from './plus'
export * from './tags'
export * from './vdom'
......
......@@ -21,6 +21,8 @@ export interface CliOptions {
logLevel?: LogLevel
l?: LogLevel
clearScreen?: boolean
autoHost?: string
autoPort?: number
}
cli
......@@ -34,6 +36,8 @@ cli
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
.option('-f, --filter <filter>', `[string] filter debug logs`)
.option('--autoHost', `[string] specify automator hostname`)
.option('--autoPort', `[number] specify automator port`)
cli
.command('')
......
......@@ -8,6 +8,7 @@ export function createOptimizeDeps(
exclude: [
'vue',
'vuex',
'vue-i18n',
'vue-router',
'@dcloudio/uni-app',
'@dcloudio/uni-components',
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册