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

wip(uts): add log

上级 5b1eb4f3
export declare const enum UtsTarget {
KOTLIN = "kotlin",
SWIFT = "swift"
}
export declare type UtsMode = 'dev' | 'build';
export interface ToOptions {
/**
* 为 true 时,禁用日志输出,默认为 false
*/
silent?: boolean;
input: {
/**
* 插件根目录
......@@ -24,5 +33,5 @@ export interface ToOptions {
inlineSourcesContent?: boolean;
};
}
export declare function runDev(target: 'kotlin' | 'swift', opts: ToOptions): void;
export declare function runBuild(target: 'kotlin' | 'swift', opts: ToOptions): void | Promise<void>;
export declare function runDev(target: UtsTarget, opts: ToOptions): void;
export declare function runBuild(target: UtsTarget, opts: ToOptions): void | Promise<import("./types").UtsResult[]>;
......@@ -10,16 +10,30 @@ const fast_glob_1 = __importDefault(require("fast-glob"));
const chokidar_1 = require("chokidar");
const api_1 = require("./api");
const utils_1 = require("./utils");
const targetDirs = {
["kotlin" /* KOTLIN */]: 'android',
["swift" /* SWIFT */]: 'ios',
};
function resolveDefaultOutputDir(mode, inputDir) {
return path_1.default.resolve(inputDir, '../dist/' + mode + '/kotlin');
return path_1.default.resolve(inputDir, '../dist/' + mode);
}
function parseOptions(mode, opts) {
function parseOptions(mode, target, opts) {
const { input } = opts;
if (!(input === null || input === void 0 ? void 0 : input.dir)) {
throw new Error(`input.dir is required`);
throw new Error(`input.dir is required.`);
}
if (!fs_extra_1.default.existsSync(input.dir)) {
throw new Error(`${input} is not found`);
throw new Error(`${input} is not found.`);
}
let inputSrcDir = '';
if (target === "kotlin" /* KOTLIN */) {
inputSrcDir = resolveKotlinSrcDir(input.dir);
}
else {
throw new Error(`${target} is unsupported.`);
}
if (!fs_extra_1.default.existsSync(inputSrcDir)) {
throw new Error(`${inputSrcDir} is not found.`);
}
if (!opts.output) {
opts.output = {
......@@ -30,66 +44,102 @@ function parseOptions(mode, opts) {
if (!opts.output.dir) {
opts.output.dir = resolveDefaultOutputDir(mode, input.dir);
}
opts.silent = opts.silent === true;
return opts;
}
const EXTNAME = '.uts';
function watchSwift(_) { }
function buildSwift(_) { }
function watchKotlin({ input: { dir: inputDir, extname }, output: { dir: outputDir, sourceMap }, }) {
const input = {
root: inputDir,
function resolveKotlinSrcDir(dir) {
return path_1.default.join(dir, targetDirs["kotlin" /* KOTLIN */] + '/src');
}
function initInputKotlinOptions(root) {
return {
root,
filename: '',
};
const output = {
outDir: outputDir,
}
function initOutputKotlinOptions(outDir, sourceMap, inlineSourcesContent) {
return {
outDir,
sourceMap,
inlineSourcesContent,
};
}
function watchSwift(_) { }
function buildSwift(_) { }
function watchKotlin({ silent, input: { dir: inputDir, extname }, output: { dir: outputDir, sourceMap, inlineSourcesContent }, }) {
fs_extra_1.default.emptyDirSync(outputDir);
extname = extname || EXTNAME;
const inputSrcDir = resolveKotlinSrcDir(inputDir);
const outputSrcDir = resolveKotlinSrcDir(outputDir);
const input = initInputKotlinOptions(inputSrcDir);
const output = initOutputKotlinOptions(outputSrcDir, sourceMap, !!inlineSourcesContent);
(0, chokidar_1.watch)('**/*' + extname, {
cwd: inputDir,
cwd: inputSrcDir,
ignored: ['**/*.d' + extname],
})
.on('add', (filename) => buildKotlinFile(path_1.default.resolve(inputDir, filename), input, output))
.on('change', (filename) => buildKotlinFile(path_1.default.resolve(inputDir, filename), input, output))
.on('add', (filename) => {
buildKotlinFile(path_1.default.resolve(inputSrcDir, filename), input, output).then((res) => {
!silent && (0, utils_1.printUtsResult)(res);
});
})
.on('change', (filename) => {
buildKotlinFile(path_1.default.resolve(inputSrcDir, filename), input, output).then((res) => {
!silent && (0, utils_1.printUtsResult)(res);
});
})
.on('unlink', (filename) => {
try {
fs_extra_1.default.unlinkSync(path_1.default.resolve(outputDir, filename));
fs_extra_1.default.unlinkSync(path_1.default.resolve(outputSrcDir, filename));
}
catch (e) { }
})
.on('ready', () => {
copyAssets(inputDir, outputDir, extname);
copyAssets("kotlin" /* KOTLIN */, inputDir, outputDir, extname);
});
}
function buildKotlin({ input: { dir: inputDir, extname }, output: { dir: outputDir, sourceMap, inlineSourcesContent }, }) {
function buildKotlin({ silent, input: { dir: inputDir, extname }, output: { dir: outputDir, sourceMap, inlineSourcesContent }, }) {
fs_extra_1.default.emptyDirSync(outputDir);
extname = extname || EXTNAME;
const inputSrcDir = resolveKotlinSrcDir(inputDir);
const outputSrcDir = resolveKotlinSrcDir(outputDir);
const input = initInputKotlinOptions(inputSrcDir);
const output = initOutputKotlinOptions(outputSrcDir, sourceMap, !!inlineSourcesContent);
const files = fast_glob_1.default.sync('**/*' + extname, {
absolute: true,
cwd: inputDir,
cwd: inputSrcDir,
ignore: ['**/*.d' + extname],
});
const input = {
root: inputDir,
filename: '',
};
const output = {
outDir: outputDir,
sourceMap,
inlineSourcesContent: !!inlineSourcesContent,
};
return Promise.all(files.map((filename) => buildKotlinFile(filename, input, output))).then(() => {
return copyAssets(inputDir, outputDir, extname);
return Promise.all(files.map((filename) => buildKotlinFile(filename, input, output)))
.then((res) => {
return copyAssets("kotlin" /* KOTLIN */, inputDir, outputDir, extname).then(() => res);
})
.then((res) => {
!silent && (0, utils_1.printUtsResults)(res);
return res;
});
}
function copyAssets(inputDir, outputDir, extname) {
function copyAssets(target, inputDir, outputDir, extname) {
inputDir = path_1.default.resolve(inputDir);
outputDir = path_1.default.resolve(outputDir);
const kotlinRootDir = path_1.default.join(inputDir, targetDirs["kotlin" /* KOTLIN */]);
const swiftRootDir = path_1.default.join(inputDir, targetDirs["swift" /* SWIFT */]);
return fs_extra_1.default.copy(inputDir, outputDir, {
filter(src) {
return path_1.default.extname(src) !== extname;
if (target === "kotlin" /* KOTLIN */) {
if (src === swiftRootDir) {
return false;
}
}
else if (target === "swift" /* SWIFT */) {
if (src === kotlinRootDir) {
return false;
}
}
return ![extname, '.ts'].includes(path_1.default.extname(src));
},
});
}
function buildKotlinFile(filename, input, output) {
const label = (0, utils_1.normalizePath)(path_1.default.relative(input.root, filename));
const toKotlinOptions = {
input: {
...input,
......@@ -100,27 +150,30 @@ function buildKotlinFile(filename, input, output) {
...output,
},
};
console.time(label);
return (0, api_1.toKotlin)(toKotlinOptions).then(() => {
console.timeEnd(label);
const start = process.hrtime();
return (0, api_1.toKotlin)(toKotlinOptions).then((res) => {
res.time = (0, utils_1.timeEnd)(start);
return res;
});
}
function runDev(target, opts) {
opts = parseOptions('dev', opts);
opts = parseOptions('dev', target, opts);
!opts.silent && (0, utils_1.printStartup)(target, 'development');
switch (target) {
case 'kotlin':
case "kotlin" /* KOTLIN */:
return watchKotlin(opts);
case 'swift':
case "swift" /* SWIFT */:
return watchSwift(opts);
}
}
exports.runDev = runDev;
function runBuild(target, opts) {
opts = parseOptions('build', opts);
opts = parseOptions('build', target, opts);
!opts.silent && (0, utils_1.printStartup)(target, 'production');
switch (target) {
case 'kotlin':
case "kotlin" /* KOTLIN */:
return buildKotlin(opts);
case 'swift':
case "swift" /* SWIFT */:
return buildSwift(opts);
}
}
......
export declare type UtsTarget = 'es3' | 'es5' | 'es2015' | 'es2016' | 'es2017' | 'es2018' | 'es2019' | 'es2020' | 'es2021' | 'es2022';
export interface UtsParserConfig {
/**
* Defaults to `false`.
......@@ -16,10 +15,6 @@ export interface UtsParserConfig {
export declare type UtsParseOptions = UtsParserConfig & {
filename?: string;
comments?: boolean;
/**
* default es2022
*/
target?: UtsTarget;
};
export declare type InputKotlinOptions = UtsParseOptions & {
root: string;
......@@ -43,4 +38,5 @@ export interface UtsSwiftOptions {
}
export interface UtsResult {
filename?: string;
time?: number;
}
......@@ -20,7 +20,8 @@
"cac": "6.7.9",
"chokidar": "^3.5.3",
"fast-glob": "^3.2.11",
"fs-extra": "^10.0.0"
"fs-extra": "^10.0.0",
"picocolors": "^1.0.0"
},
"devDependencies": {
"@types/fs-extra": "^9.0.13"
......
......@@ -25,11 +25,15 @@ export function toKotlin(options: UtsKotlinOptions): Promise<UtsResult> {
} else if (output.sourceMap === false) {
output.sourceMap = ''
}
return bindings.toKotlin(toBuffer(options))
return bindings
.toKotlin(toBuffer(options))
.then((res: string) => JSON.parse(res))
}
export function toSwift(options: UtsSwiftOptions): Promise<UtsResult> {
return bindings.toSwift(toBuffer(options))
return bindings
.toSwift(toBuffer(options))
.then((res: string) => JSON.parse(res))
}
function toBuffer(t: any): Buffer {
......
import { cac } from 'cac'
import { runBuild, runDev, ToOptions } from '.'
import { runBuild, runDev, ToOptions, UtsTarget } from '.'
const cli = cac('uts')
export interface CliOptions {
target: 'kotlin' | 'swift'
target: UtsTarget
silent: boolean
sourceMap: boolean
inlineSourcesContent: boolean
watch: boolean
......@@ -14,9 +15,9 @@ export interface CliOptions {
cli
.command('<input> [output]')
.option('-t, --target <target>', '[string] kotlin | swift', {
default: 'kotlin',
default: UtsTarget.KOTLIN,
})
.option('-s, --sourceMap [sourceMap]', `[boolean] output sourceMap`, {
.option('-s, --sourceMap [sourceMap]', `[boolean|string] output sourceMap`, {
default: false,
})
.option(
......@@ -32,8 +33,12 @@ cli
.option('-e, --extname [extname]', `[string] extname`, {
default: '.uts',
})
.option('--silent', `[boolean] disable log`, {
default: false,
})
.action((input, output, opts: CliOptions) => {
const toOptions: ToOptions = {
silent: opts.silent,
input: {
dir: input,
extname: opts.extname,
......
......@@ -6,9 +6,24 @@ import { watch } from 'chokidar'
import { InputKotlinOptions, toKotlin } from './api'
import { OutputKotlinOptions, UtsKotlinOptions } from './types'
import { normalizePath } from './utils'
import { printStartup, printUtsResult, printUtsResults, timeEnd } from './utils'
export const enum UtsTarget {
KOTLIN = 'kotlin',
SWIFT = 'swift',
}
export type UtsMode = 'dev' | 'build'
const targetDirs = {
[UtsTarget.KOTLIN]: 'android',
[UtsTarget.SWIFT]: 'ios',
} as const
export interface ToOptions {
/**
* 为 true 时,禁用日志输出,默认为 false
*/
silent?: boolean
input: {
/**
* 插件根目录
......@@ -38,18 +53,32 @@ export interface ToOptions {
interface ToKotlinOptions extends ToOptions {}
interface ToSwiftOptions extends ToOptions {}
function resolveDefaultOutputDir(mode: 'dev' | 'build', inputDir: string) {
return path.resolve(inputDir, '../dist/' + mode + '/kotlin')
function resolveDefaultOutputDir(mode: UtsMode, inputDir: string) {
return path.resolve(inputDir, '../dist/' + mode)
}
function parseOptions(mode: 'dev' | 'build', opts: Partial<ToKotlinOptions>) {
function parseOptions(
mode: UtsMode,
target: UtsTarget,
opts: Partial<ToKotlinOptions>
) {
const { input } = opts
if (!input?.dir) {
throw new Error(`input.dir is required`)
throw new Error(`input.dir is required.`)
}
if (!fs.existsSync(input.dir)) {
throw new Error(`${input} is not found`)
throw new Error(`${input} is not found.`)
}
let inputSrcDir: string = ''
if (target === UtsTarget.KOTLIN) {
inputSrcDir = resolveKotlinSrcDir(input.dir)
} else {
throw new Error(`${target} is unsupported.`)
}
if (!fs.existsSync(inputSrcDir)) {
throw new Error(`${inputSrcDir} is not found.`)
}
if (!opts.output) {
opts.output = {
dir: '',
......@@ -59,75 +88,143 @@ function parseOptions(mode: 'dev' | 'build', opts: Partial<ToKotlinOptions>) {
if (!opts.output.dir) {
opts.output.dir = resolveDefaultOutputDir(mode, input.dir)
}
opts.silent = opts.silent === true
return opts as ToKotlinOptions
}
const EXTNAME = '.uts'
function resolveKotlinSrcDir(dir: string) {
return path.join(dir, targetDirs[UtsTarget.KOTLIN] + '/src')
}
function initInputKotlinOptions(root: string): InputKotlinOptions {
return {
root,
filename: '',
}
}
function initOutputKotlinOptions(
outDir: string,
sourceMap: string | boolean,
inlineSourcesContent: boolean
): OutputKotlinOptions {
return {
outDir,
sourceMap,
inlineSourcesContent,
}
}
function watchSwift(_: ToSwiftOptions) {}
function buildSwift(_: ToSwiftOptions) {}
function watchKotlin({
silent,
input: { dir: inputDir, extname },
output: { dir: outputDir, sourceMap },
output: { dir: outputDir, sourceMap, inlineSourcesContent },
}: ToKotlinOptions) {
const input: InputKotlinOptions = {
root: inputDir,
filename: '',
}
const output: OutputKotlinOptions = {
outDir: outputDir,
sourceMap,
}
fs.emptyDirSync(outputDir)
extname = extname || EXTNAME
const inputSrcDir = resolveKotlinSrcDir(inputDir)
const outputSrcDir = resolveKotlinSrcDir(outputDir)
const input = initInputKotlinOptions(inputSrcDir)
const output = initOutputKotlinOptions(
outputSrcDir,
sourceMap,
!!inlineSourcesContent
)
watch('**/*' + extname, {
cwd: inputDir,
cwd: inputSrcDir,
ignored: ['**/*.d' + extname],
})
.on('add', (filename) =>
buildKotlinFile(path.resolve(inputDir, filename), input, output)
)
.on('change', (filename) =>
buildKotlinFile(path.resolve(inputDir, filename), input, output)
)
.on('add', (filename) => {
buildKotlinFile(path.resolve(inputSrcDir, filename), input, output).then(
(res) => {
!silent && printUtsResult(res)
}
)
})
.on('change', (filename) => {
buildKotlinFile(path.resolve(inputSrcDir, filename), input, output).then(
(res) => {
!silent && printUtsResult(res)
}
)
})
.on('unlink', (filename) => {
try {
fs.unlinkSync(path.resolve(outputDir, filename))
fs.unlinkSync(path.resolve(outputSrcDir, filename))
} catch (e) {}
})
.on('ready', () => {
copyAssets(inputDir, outputDir, extname!)
copyAssets(UtsTarget.KOTLIN, inputDir, outputDir, extname!)
})
}
function buildKotlin({
silent,
input: { dir: inputDir, extname },
output: { dir: outputDir, sourceMap, inlineSourcesContent },
}: ToKotlinOptions) {
fs.emptyDirSync(outputDir)
extname = extname || EXTNAME
const inputSrcDir = resolveKotlinSrcDir(inputDir)
const outputSrcDir = resolveKotlinSrcDir(outputDir)
const input = initInputKotlinOptions(inputSrcDir)
const output = initOutputKotlinOptions(
outputSrcDir,
sourceMap,
!!inlineSourcesContent
)
const files = glob.sync('**/*' + extname, {
absolute: true,
cwd: inputDir,
cwd: inputSrcDir,
ignore: ['**/*.d' + extname],
})
const input: InputKotlinOptions = {
root: inputDir,
filename: '',
}
const output: OutputKotlinOptions = {
outDir: outputDir,
sourceMap,
inlineSourcesContent: !!inlineSourcesContent,
}
return Promise.all(
files.map((filename) => buildKotlinFile(filename, input, output))
).then(() => {
return copyAssets(inputDir, outputDir, extname!)
})
)
.then((res) => {
return copyAssets(UtsTarget.KOTLIN, inputDir, outputDir, extname!).then(
() => res
)
})
.then((res) => {
!silent && printUtsResults(res)
return res
})
}
function copyAssets(inputDir: string, outputDir: string, extname: string) {
function copyAssets(
target: UtsTarget,
inputDir: string,
outputDir: string,
extname: string
) {
inputDir = path.resolve(inputDir)
outputDir = path.resolve(outputDir)
const kotlinRootDir = path.join(inputDir, targetDirs[UtsTarget.KOTLIN])
const swiftRootDir = path.join(inputDir, targetDirs[UtsTarget.SWIFT])
return fs.copy(inputDir, outputDir, {
filter(src) {
return path.extname(src) !== extname
if (target === UtsTarget.KOTLIN) {
if (src === swiftRootDir) {
return false
}
} else if (target === UtsTarget.SWIFT) {
if (src === kotlinRootDir) {
return false
}
}
return ![extname, '.ts'].includes(path.extname(src))
},
})
}
......@@ -137,7 +234,6 @@ function buildKotlinFile(
input: InputKotlinOptions,
output: OutputKotlinOptions
) {
const label = normalizePath(path.relative(input.root, filename))
const toKotlinOptions: UtsKotlinOptions = {
input: {
...input,
......@@ -148,28 +244,31 @@ function buildKotlinFile(
...output,
},
}
console.time(label)
return toKotlin(toKotlinOptions).then(() => {
console.timeEnd(label)
const start = process.hrtime()
return toKotlin(toKotlinOptions).then((res) => {
res.time = timeEnd(start)
return res
})
}
export function runDev(target: 'kotlin' | 'swift', opts: ToOptions) {
opts = parseOptions('dev', opts)
export function runDev(target: UtsTarget, opts: ToOptions) {
opts = parseOptions('dev', target, opts)
!opts.silent && printStartup(target, 'development')
switch (target) {
case 'kotlin':
case UtsTarget.KOTLIN:
return watchKotlin(opts)
case 'swift':
case UtsTarget.SWIFT:
return watchSwift(opts)
}
}
export function runBuild(target: 'kotlin' | 'swift', opts: ToOptions) {
opts = parseOptions('build', opts)
export function runBuild(target: UtsTarget, opts: ToOptions) {
opts = parseOptions('build', target, opts)
!opts.silent && printStartup(target, 'production')
switch (target) {
case 'kotlin':
case UtsTarget.KOTLIN:
return buildKotlin(opts)
case 'swift':
case UtsTarget.SWIFT:
return buildSwift(opts)
}
}
export type UtsTarget =
| 'es3'
| 'es5'
| 'es2015'
| 'es2016'
| 'es2017'
| 'es2018'
| 'es2019'
| 'es2020'
| 'es2021'
| 'es2022'
export interface UtsParserConfig {
/**
* Defaults to `false`.
......@@ -28,10 +16,6 @@ export interface UtsParserConfig {
export type UtsParseOptions = UtsParserConfig & {
filename?: string
comments?: boolean
/**
* default es2022
*/
target?: UtsTarget
}
export type InputKotlinOptions = UtsParseOptions & {
......@@ -60,4 +44,5 @@ export interface UtsSwiftOptions {
export interface UtsResult {
filename?: string
time?: number
}
import os from 'os'
import colors from 'picocolors'
import type { UtsTarget } from '.'
import { UtsResult } from './types'
export const isWindows = os.platform() === 'win32'
export function normalizePath(id: string): string {
return isWindows ? id.replace(/\\/g, '/') : id
}
const round = (number: number) => Number(number.toFixed(2))
const hrTimeToMilliseconds = (hrtime: [number, number]) =>
hrtime[0] * 1e3 + hrtime[1] / 1e6
export function timeEnd(start: [number, number]) {
return round(
hrTimeToMilliseconds(process.hrtime()) - hrTimeToMilliseconds(start)
)
}
export function printStartup(target: UtsTarget, mode: string) {
console.log(
colors.cyan(
`uts v${require('../package.json').version} ${colors.green(
`building ${target} for ${mode}...`
)}`
)
)
}
export function printUtsResults(results: UtsResult[]) {
let longest = 0
for (const result of results) {
const l = result.filename!.length
if (l > longest) longest = l
}
console.log(
colors.dim(`${colors.green(`✓`)} ${results.length} files transformed.`)
)
results.forEach((result) => {
printUtsResult(result, longest)
})
}
export function printUtsResult(result: UtsResult, maxLength = 0) {
console.log(
colors.green(result.filename!.padEnd(maxLength + 2)) +
' ' +
colors.dim(result.time + 'ms')
)
}
......@@ -773,11 +773,13 @@ importers:
chokidar: ^3.5.3
fast-glob: ^3.2.11
fs-extra: ^10.0.0
picocolors: ^1.0.0
dependencies:
cac: 6.7.9
chokidar: 3.5.3
fast-glob: 3.2.11
fs-extra: 10.1.0
picocolors: 1.0.0
optionalDependencies:
'@dcloudio/uts-darwin-arm64': link:../uts-darwin-arm64
devDependencies:
......@@ -786,6 +788,9 @@ importers:
packages/uts-darwin-arm64:
specifiers: {}
packages/uts-win32-x64-msvc:
specifiers: {}
packages/vite-plugin-uni:
specifiers:
'@babel/core': ^7.17.9
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册