UNPKG

4.56 kBJavaScriptView Raw
1'use strict'
2
3const fs = require('fs-extra')
4const path = require('path')
5const glob = require('glob')
6const { execa } = require('@mara/devkit')
7const C = require('../config/const')
8
9// 【注意】utils.js 为纯工具库,请不要依赖 config/index.js
10
11// From create-react-app
12// Make sure any symlinks in the project folder are resolved:
13// https://github.com/facebookincubator/create-react-app/issues/637
14const appDirectory = fs.realpathSync(process.cwd())
15
16function rootPath(relativePath) {
17 return path.resolve(appDirectory, relativePath)
18}
19
20/**
21 * 获取入口文件名列表
22 * @return {Array} 入口名数组
23 */
24function getViews(entryGlob) {
25 const entries = getEntries(`${process.cwd()}/${entryGlob}`)
26 return Object.keys(entries)
27}
28
29/**
30 * 获取指定路径下的入口文件
31 * @param {String} globPath 通配符路径
32 * @param {String} preDep 前置模块
33 * @return {Object} 入口名:路径 键值对
34 * {
35 * viewA: ['a.js'],
36 * viewB: ['b.js']
37 * }
38 */
39function getEntries(globPath, preDep = []) {
40 const files = glob.sync(rootPath(globPath))
41 const hasPreDep = preDep.length > 0
42 const getViewName = filepath => {
43 const dirname = path.dirname(path.relative(`${C.VIEWS_DIR}/`, filepath))
44 // 兼容组件,src/index.js
45 return dirname === '..' ? 'index' : dirname
46 }
47
48 // glob 按照字母顺序取 .js 与 .ts 文件
49 // 通过 reverse 强制使 js 文件在 ts 之后,达到覆盖目的
50 // 保证 index.js 优先原则
51 return files.reverse().reduce((entries, filepath) => {
52 const name = getViewName(filepath)
53 // preDep 支持数组或字符串。所以这里使用 concat 方法
54 entries[name] = hasPreDep ? [].concat(preDep, filepath) : filepath
55
56 return entries
57 }, {})
58}
59
60function getEntryPoints(globPath, preDep = []) {
61 const files = glob.sync(rootPath(globPath))
62 const getChunkName = filepath => {
63 const extname = path.extname(filepath)
64 const basename = path.posix.basename(filepath, extname)
65
66 return basename.replace(/^index\./, '') + '.servant'
67 }
68
69 return files.reduce((chunks, filepath) => {
70 const name = getChunkName(filepath)
71 // preDep 支持数组或字符串。所以这里使用 concat 方法
72 chunks[name] = [].concat(preDep, filepath)
73
74 return chunks
75 }, {})
76}
77
78/**
79 * 解析日期
80 * @param {Date | Number} target 日期对象或时间戳
81 * @return {Object} 结果对象
82 */
83function parseDate(target) {
84 const f = n => (n > 9 ? n : '0' + n)
85 const date = target instanceof Date ? target : new Date(target)
86 return {
87 y: date.getFullYear(),
88 M: f(date.getMonth() + 1),
89 d: f(date.getDate()),
90 h: f(date.getHours()),
91 m: f(date.getMinutes()),
92 s: f(date.getSeconds())
93 }
94}
95
96/**
97 * 格式化日期为 yyyy-MM-dd 格式
98 * @param {Date | Number} dt 日期对象或时间戳
99 * @return {String} 格式化结果
100 */
101function pubDate(dt) {
102 const date = parseDate(dt)
103 return `${date.y}-${date.M}-${date.d}`
104}
105
106/**
107 * 生成 banner
108 * @return {String} 包含项目版本号,构建日期
109 */
110function banner(version, target = '') {
111 return (
112 `@version ${version}\n` +
113 `@date ${pubDate(new Date())}\n` +
114 // 对 bundle 文件添加 @generated 标识
115 // 在 code review 面板忽略相关 diff
116 `@generated ${target}`
117 )
118}
119
120function isNotEmptyArray(target) {
121 return Array.isArray(target) && target.length
122}
123
124function isObject(obj) {
125 return Object.prototype.toString.call(obj) === '[object Object]'
126}
127
128function assetsPath(_path) {
129 return path.posix.join('static', _path)
130}
131
132function readJson(file) {
133 return fs.readJsonSync(file, { throws: false })
134}
135
136function sortObject(obj, keyOrder, dontSortByUnicode) {
137 if (!obj) return
138 const res = {}
139
140 if (keyOrder) {
141 keyOrder.forEach(key => {
142 res[key] = obj[key]
143 delete obj[key]
144 })
145 }
146
147 const keys = Object.keys(obj)
148
149 !dontSortByUnicode && keys.sort()
150 keys.forEach(key => {
151 res[key] = obj[key]
152 })
153
154 return res
155}
156
157function relativePath(filePath) {
158 return '.' + path.sep + path.relative(appDirectory, filePath)
159}
160
161function bumpProjectVersion(version = 'prerelease') {
162 return execa.sync('npm', ['--no-git-tag-version', 'version', version])
163}
164
165function isInstalled(name) {
166 try {
167 require.resolve(name)
168 return true
169 } catch (e) {
170 return false
171 }
172}
173
174module.exports = {
175 assetsPath,
176 bumpProjectVersion,
177 isObject,
178 getViews,
179 getEntries,
180 getEntryPoints,
181 rootPath,
182 parseDate,
183 pubDate,
184 banner,
185 isNotEmptyArray,
186 isInstalled,
187 sortObject,
188 readJson,
189 relativePath
190}