ranuts 0.1.0-alpha.1 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/assets/img/sort/bubble.gif +0 -0
- package/assets/img/sort/complexity.png +0 -0
- package/assets/img/sort/select.gif +0 -0
- package/assets/img/sort/sort.png +0 -0
- package/assets/img/tree/balanceTree.png +0 -0
- package/dist/index.js.map +0 -1
- package/dist/index.umd.cjs.map +0 -1
- package/dist/src/file/fileInfo.d.ts +0 -7
- package/dist/src/file/fs.d.ts +0 -2
- package/dist/src/file/readDir.d.ts +0 -6
- package/dist/src/file/readFile.d.ts +0 -8
- package/dist/src/file/watchFile.d.ts +0 -8
- package/dist/src/file/writeFile.d.ts +0 -8
- package/dist/src/mode/subscribe.d.ts +0 -16
- package/dist/src/ranlog/behavior.d.ts +0 -1
- package/dist/src/ranlog/env.d.ts +0 -5
- package/dist/src/ranlog/error.d.ts +0 -2
- package/dist/src/ranlog/index.d.ts +0 -26
- package/dist/src/ranlog/performance.d.ts +0 -21
- package/dist/src/ranlog/report.d.ts +0 -7
- package/dist/src/ranlog/request.d.ts +0 -18
- package/dist/src/ranlog/utils.d.ts +0 -19
- package/dist/src/utils/filterObj.d.ts +0 -8
- package/dist/src/utils/str2Xml.d.ts +0 -8
- package/dist/src/vnode/h.d.ts +0 -6
- package/dist/src/vnode/hooks.d.ts +0 -23
- package/dist/src/vnode/htmlDomApi.d.ts +0 -33
- package/dist/src/vnode/init.d.ts +0 -2
- package/dist/src/vnode/is.d.ts +0 -5
- package/dist/src/vnode/modules/attributes.d.ts +0 -8
- package/dist/src/vnode/modules/class.d.ts +0 -8
- package/dist/src/vnode/modules/index.d.ts +0 -7
- package/dist/src/vnode/modules/listeners.d.ts +0 -14
- package/dist/src/vnode/modules/props.d.ts +0 -8
- package/dist/src/vnode/modules/style.d.ts +0 -14
- package/dist/src/vnode/vnode.d.ts +0 -31
- package/src/astParser/Parser.ts +0 -654
- package/src/astParser/Tokenizer.ts +0 -447
- package/src/astParser/nodeTypes.ts +0 -194
- package/src/astParser/utils.ts +0 -27
- package/src/babel/parser.ts +0 -10
- package/src/colors/fmt.ts +0 -29
- package/src/colors/isColorSupported.ts +0 -13
- package/src/file/appendFile.ts +0 -29
- package/src/file/fileInfo.ts +0 -22
- package/src/file/fs.ts +0 -9
- package/src/file/readDir.ts +0 -18
- package/src/file/readFile.ts +0 -26
- package/src/file/watchFile.ts +0 -31
- package/src/file/writeFile.ts +0 -38
- package/src/mode/subscribe.ts +0 -89
- package/src/ran/commit.ts +0 -0
- package/src/ran/dom.ts +0 -0
- package/src/ran/hooks.ts +0 -0
- package/src/ran/reconcile.ts +0 -0
- package/src/ran/schedule.ts +0 -0
- package/src/ranlog/behavior.ts +0 -5
- package/src/ranlog/console.ts +0 -16
- package/src/ranlog/env.ts +0 -29
- package/src/ranlog/error.ts +0 -11
- package/src/ranlog/performance.ts +0 -65
- package/src/ranlog/report.ts +0 -33
- package/src/ranlog/request.ts +0 -60
- package/src/ranlog/utils.ts +0 -92
- package/src/ranpack/ast/Declaration.ts +0 -120
- package/src/ranpack/ast/Node.ts +0 -7
- package/src/ranpack/ast/Reference.ts +0 -32
- package/src/ranpack/ast/Scope.ts +0 -80
- package/src/ranpack/bundle.ts +0 -50
- package/src/ranpack/graph.ts +0 -143
- package/src/ranpack/module.ts +0 -431
- package/src/ranpack/moduleLoader.ts +0 -73
- package/src/ranpack/plugins.ts +0 -70
- package/src/ranpack/statement.ts +0 -66
- package/src/ranpack/utils/buildScope.ts +0 -77
- package/src/ranpack/utils/findReference.ts +0 -36
- package/src/ranpack/utils/isFunctionDeclaration.ts +0 -41
- package/src/ranpack/utils/makeLegalIdentifier.ts +0 -18
- package/src/ranpack/utils/object.ts +0 -8
- package/src/ranpack/utils/resolve.ts +0 -32
- package/src/ranpack/utils/walk.ts +0 -66
- package/src/ranpack/ws.ts +0 -269
- package/src/server/connectType.ts +0 -9
- package/src/server/encodeUrl.ts +0 -46
- package/src/server/escapeHtml.ts +0 -46
- package/src/server/get.ts +0 -36
- package/src/server/jitter.ts +0 -77
- package/src/server/mimeType.ts +0 -858
- package/src/server/paresUrl.ts +0 -40
- package/src/server/send.ts +0 -89
- package/src/server/server.ts +0 -67
- package/src/server/status.ts +0 -191
- package/src/server/traverse.ts +0 -54
- package/src/server/websocket.ts +0 -200
- package/src/sort/bubble.ts +0 -21
- package/src/sort/bucket.ts +0 -11
- package/src/sort/count.ts +0 -10
- package/src/sort/heap.ts +0 -10
- package/src/sort/insert.ts +0 -20
- package/src/sort/merge.ts +0 -35
- package/src/sort/quick.ts +0 -50
- package/src/sort/radix.ts +0 -11
- package/src/sort/randomArray.ts +0 -21
- package/src/sort/select.ts +0 -23
- package/src/sort/shell.ts +0 -22
- package/src/utils/compose.ts +0 -37
- package/src/utils/filterObj.ts +0 -21
- package/src/utils/mergeObj.ts +0 -12
- package/src/utils/startTask.ts +0 -15
- package/src/utils/str2Xml.ts +0 -26
- package/src/utils/taskEnd.ts +0 -14
- package/src/vnode/h.ts +0 -108
- package/src/vnode/hooks.ts +0 -25
- package/src/vnode/htmlDomApi.ts +0 -199
- package/src/vnode/init.ts +0 -429
- package/src/vnode/is.ts +0 -17
- package/src/vnode/modules/attributes.ts +0 -70
- package/src/vnode/modules/class.ts +0 -46
- package/src/vnode/modules/listeners.ts +0 -123
- package/src/vnode/modules/props.ts +0 -41
- package/src/vnode/modules/style.ts +0 -118
- package/src/vnode/vnode.ts +0 -65
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import tty from 'node:tty'
|
|
2
|
-
import process from 'node:process'
|
|
3
|
-
|
|
4
|
-
const isColorSupported =
|
|
5
|
-
!('NO_COLOR' in process.env || process.argv.includes('--no-color')) &&
|
|
6
|
-
('FORCE_COLOR' in process.env ||
|
|
7
|
-
process.argv.includes('--color') ||
|
|
8
|
-
process.platform === 'win32' ||
|
|
9
|
-
(tty.isatty(1) && process.env.TERM !== 'dumb') ||
|
|
10
|
-
'CI' in process.env)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export default isColorSupported
|
package/src/file/appendFile.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import fs from './fs'
|
|
2
|
-
import readFile from './readFile'
|
|
3
|
-
|
|
4
|
-
type Error = NodeJS.ErrnoException | null
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @description: 给一个已经存在的文件追加内容
|
|
8
|
-
* @param {string} path 文件路径
|
|
9
|
-
* @param {string} content 新加的内容
|
|
10
|
-
* @return {Promise}
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const appendFile = (
|
|
14
|
-
path: string,
|
|
15
|
-
content: string,
|
|
16
|
-
): Promise<Ranuts.Identification> =>
|
|
17
|
-
new Promise((resolve, reject) => {
|
|
18
|
-
if (!fs._identification)
|
|
19
|
-
return reject({ _identification: false, data: 'fs is not loaded' })
|
|
20
|
-
fs.appendFile(path, content, (err: Error) => {
|
|
21
|
-
err
|
|
22
|
-
? reject({ _identification: false, data: err })
|
|
23
|
-
: readFile(path).then((result: Ranuts.Identification) => {
|
|
24
|
-
resolve(result)
|
|
25
|
-
})
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
export default appendFile
|
package/src/file/fileInfo.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import fs from './fs'
|
|
2
|
-
|
|
3
|
-
type Error = NodeJS.ErrnoException | null
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description: 查询一个文件的详细信息,一般用于区分文件还是目录(data.isDirectory())
|
|
7
|
-
* @param {string} path 文件路径
|
|
8
|
-
* @return {Promise}
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const queryFileInfo = (path: string): Promise<Ranuts.Identification> =>
|
|
12
|
-
new Promise((resolve, reject) => {
|
|
13
|
-
if (!fs._identification)
|
|
14
|
-
return reject({ _identification: false, data: 'fs is not loaded' })
|
|
15
|
-
fs.stat(path, (err: Error, data: string) => {
|
|
16
|
-
err
|
|
17
|
-
? reject({ _identification: false, data: err })
|
|
18
|
-
: resolve({ _identification: true, data })
|
|
19
|
-
})
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
export default queryFileInfo
|
package/src/file/fs.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const fs = {}
|
|
2
|
-
let fileSystem: any = fs
|
|
3
|
-
if (typeof process !== 'undefined' && typeof fileSystem.Stats === 'function') {
|
|
4
|
-
fileSystem._identification = true
|
|
5
|
-
} else {
|
|
6
|
-
fileSystem = { _identification: false, message: 'require is not defined' }
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export default fileSystem
|
package/src/file/readDir.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import fs from './fs'
|
|
2
|
-
|
|
3
|
-
interface Options {
|
|
4
|
-
dirPath: string
|
|
5
|
-
ignores?: Array<string>
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const readDir = (options: Options): Array<string> => {
|
|
9
|
-
const { dirPath } = options
|
|
10
|
-
try {
|
|
11
|
-
return fs.readdirSync(dirPath)
|
|
12
|
-
} catch (error) {
|
|
13
|
-
console.log('readDir error', error)
|
|
14
|
-
throw error
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default readDir
|
package/src/file/readFile.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import fs from './fs'
|
|
2
|
-
|
|
3
|
-
type Error = NodeJS.ErrnoException | null
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description: 读取一个文件,读取成功返回状态码和文件内容
|
|
7
|
-
* @param {string} path 文件路径
|
|
8
|
-
* @param {string} format 读取格式,默认utf-8
|
|
9
|
-
* @return {Promise}
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const readFile = (
|
|
13
|
-
path: string,
|
|
14
|
-
format: string = 'utf-8',
|
|
15
|
-
): Promise<Ranuts.Identification> =>
|
|
16
|
-
new Promise((resolve, reject) => {
|
|
17
|
-
if (!fs._identification)
|
|
18
|
-
return reject({ _identification: false, data: 'fs is not loaded' })
|
|
19
|
-
fs.readFile(path, format, (err: Error, data: string) => {
|
|
20
|
-
err
|
|
21
|
-
? reject({ _identification: false, data: err })
|
|
22
|
-
: resolve({ _identification: true, data })
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
export default readFile
|
package/src/file/watchFile.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Stats } from 'node:fs'
|
|
2
|
-
import fs from './fs'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @description: 观察一个文件是否被改变,返回状态
|
|
6
|
-
* @param {string} path 监听的文件路径
|
|
7
|
-
* @param {number} interval 监听的时间,单位毫秒,默认20毫秒
|
|
8
|
-
* @return {Promise}
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const watchFile = (
|
|
12
|
-
path: string,
|
|
13
|
-
interval: number = 20,
|
|
14
|
-
): Promise<Ranuts.Identification> =>
|
|
15
|
-
new Promise((resolve, reject) => {
|
|
16
|
-
if (!fs._identification)
|
|
17
|
-
return reject({ _identification: false, data: 'fs is not loaded' })
|
|
18
|
-
fs.watchFile(path, { interval }, (curr: Stats, prev: Stats) => {
|
|
19
|
-
if (curr.mtime !== prev.mtime) {
|
|
20
|
-
fs.unwatchFile(path)
|
|
21
|
-
resolve({ _identification: true, data: { msg: 'file is changed' } })
|
|
22
|
-
} else {
|
|
23
|
-
resolve({
|
|
24
|
-
_identification: false,
|
|
25
|
-
data: { msg: 'file is not changed' },
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
export default watchFile
|
package/src/file/writeFile.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import fs from './fs'
|
|
2
|
-
|
|
3
|
-
type Error = NodeJS.ErrnoException | null
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description: 根据文件路径创建文件,如果文件存在会清空再写入,如果不存在会创建
|
|
7
|
-
* @param {string} path 文件路径
|
|
8
|
-
* @param {string} content 文件内容
|
|
9
|
-
* @return {Promise}
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const writeFile = (
|
|
13
|
-
path: string,
|
|
14
|
-
content: string,
|
|
15
|
-
): Promise<Ranuts.Identification> =>
|
|
16
|
-
new Promise((resolve, reject) => {
|
|
17
|
-
if (!fs._identification)
|
|
18
|
-
return reject({ _identification: false, data: 'fs is not loaded' })
|
|
19
|
-
fs.writeFile(
|
|
20
|
-
path,
|
|
21
|
-
content,
|
|
22
|
-
{
|
|
23
|
-
mode: 438, // 可读可写666,转化为十进制就是438
|
|
24
|
-
flag: 'w+', // r+并不会清空再写入,w+会清空再写入
|
|
25
|
-
encoding: 'utf-8',
|
|
26
|
-
},
|
|
27
|
-
(err: Error) => {
|
|
28
|
-
if (err) {
|
|
29
|
-
reject({ _identification: false, data: err })
|
|
30
|
-
throw err
|
|
31
|
-
} else {
|
|
32
|
-
resolve({ _identification: true, data: { path, content } })
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
export default writeFile
|
package/src/mode/subscribe.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
type Callback = (...args: any) => unknown
|
|
2
|
-
|
|
3
|
-
type EventName = string | symbol
|
|
4
|
-
|
|
5
|
-
type EventItem = {
|
|
6
|
-
name?: string | symbol
|
|
7
|
-
callback: Callback
|
|
8
|
-
initialCallback?: Callback
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class Subscribe {
|
|
12
|
-
_events: Record<EventName, Array<EventItem>>
|
|
13
|
-
constructor() {
|
|
14
|
-
this._events = {}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
on = (eventName: EventName, eventItem: EventItem | Callback): void => {
|
|
18
|
-
if (this._events[eventName] && eventName !== Symbol.for('new-listener')) {
|
|
19
|
-
// 注册一个 newListener 用于监听新的事件订阅
|
|
20
|
-
this.emit(Symbol.for('new-listener'), eventName)
|
|
21
|
-
}
|
|
22
|
-
// 由于一个事件可能注册多个回调函数,所以使用数组来存储事件队列
|
|
23
|
-
const callbacks = this._events[eventName] || []
|
|
24
|
-
if (typeof eventItem === 'function') {
|
|
25
|
-
callbacks.push({
|
|
26
|
-
name: eventName,
|
|
27
|
-
callback: eventItem,
|
|
28
|
-
})
|
|
29
|
-
} else {
|
|
30
|
-
callbacks.push(eventItem)
|
|
31
|
-
}
|
|
32
|
-
this._events[eventName] = callbacks
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
emit = (eventName: EventName, ...args: Array<unknown>): void => {
|
|
36
|
-
const callbacks = this._events[eventName] || []
|
|
37
|
-
callbacks.forEach((item) => {
|
|
38
|
-
const { callback } = item
|
|
39
|
-
callback(...args)
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
once = (eventName: EventName, eventItem: EventItem | Callback): void => {
|
|
44
|
-
let one: EventItem
|
|
45
|
-
if (typeof eventItem === 'function') {
|
|
46
|
-
one = {
|
|
47
|
-
name: eventName,
|
|
48
|
-
callback: (...args: Array<unknown>) => {
|
|
49
|
-
eventItem(...args)
|
|
50
|
-
this.off(eventName, one)
|
|
51
|
-
},
|
|
52
|
-
initialCallback: eventItem,
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
const { callback } = eventItem
|
|
56
|
-
one = {
|
|
57
|
-
name: eventName,
|
|
58
|
-
callback: (...args: Array<unknown>) => {
|
|
59
|
-
callback(...args)
|
|
60
|
-
this.off(eventName, one)
|
|
61
|
-
},
|
|
62
|
-
initialCallback: callback,
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
// 由于需要在回调函数执行后,取消订阅当前事件,所以需要对传入的回调函数做一层包装,然后绑定包装后的函数
|
|
66
|
-
|
|
67
|
-
// 考虑:如果当前事件在未执行,被用户取消订阅,能否取消?
|
|
68
|
-
// 由于:我们订阅事件的时候,修改了原回调函数的引用,所以,用户触发 off 的时候不能找到对应的回调函数
|
|
69
|
-
// 所以,我们需要在当前函数与用户传入的回调函数做一个绑定,我们通过自定义属性来实现
|
|
70
|
-
this.on(eventName, one)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
off = (eventName: EventName, eventItem: EventItem | Callback): void => {
|
|
74
|
-
// 找到事件对应的回调函数,删除对应的回调函数
|
|
75
|
-
const callbacks = this._events[eventName] || []
|
|
76
|
-
const newCallbacks = callbacks.filter((item) => {
|
|
77
|
-
if (typeof eventItem === 'function') {
|
|
78
|
-
return item.callback !== eventItem && item.initialCallback !== eventItem
|
|
79
|
-
} else {
|
|
80
|
-
const { callback } = eventItem
|
|
81
|
-
/* 用于once的取消订阅 */
|
|
82
|
-
return item.callback !== callback && item.initialCallback !== callback
|
|
83
|
-
}
|
|
84
|
-
})
|
|
85
|
-
this._events[eventName] = newCallbacks
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export default Subscribe
|
package/src/ran/commit.ts
DELETED
|
File without changes
|
package/src/ran/dom.ts
DELETED
|
File without changes
|
package/src/ran/hooks.ts
DELETED
|
File without changes
|
package/src/ran/reconcile.ts
DELETED
|
File without changes
|
package/src/ran/schedule.ts
DELETED
|
File without changes
|
package/src/ranlog/behavior.ts
DELETED
package/src/ranlog/console.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Noop, replaceOld } from './utils'
|
|
2
|
-
|
|
3
|
-
export const consoleHooks = (hooks: (...args: unknown[]) => void = Noop): void => {
|
|
4
|
-
const consoleTypeList = ['log', 'info', 'warn', 'error', 'assert'];
|
|
5
|
-
consoleTypeList.forEach((type: string) => {
|
|
6
|
-
const replacement = (originalConsole: any) => {
|
|
7
|
-
return function (...args: any[]): void {
|
|
8
|
-
if (originalConsole) {
|
|
9
|
-
hooks(type, ...args)
|
|
10
|
-
originalConsole.apply(console, args)
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
replaceOld(console, type, replacement)
|
|
15
|
-
});
|
|
16
|
-
}
|
package/src/ranlog/env.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { isString } from './utils'
|
|
3
|
-
/**
|
|
4
|
-
* @description: Gets the current environment configuration
|
|
5
|
-
* @return {string}
|
|
6
|
-
*/
|
|
7
|
-
export const getHost = (env?: string): string => {
|
|
8
|
-
let host = ''
|
|
9
|
-
if (env && isString(env)) {
|
|
10
|
-
if (/trunk|neibu|release/.test(env)) {
|
|
11
|
-
host = `.${env}`
|
|
12
|
-
} else if (/test/.test(env)) {
|
|
13
|
-
host = env
|
|
14
|
-
} else if (/prod/.test(env)) {
|
|
15
|
-
host = ''
|
|
16
|
-
} else {
|
|
17
|
-
host = ''
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
} else {
|
|
21
|
-
const env = /\w(\.trunk|\.neibu|\.release|test)\./.exec(
|
|
22
|
-
window.location.hostname
|
|
23
|
-
);
|
|
24
|
-
if (env) {
|
|
25
|
-
host = env[1]
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return host ? `https://log${host}.chaxus.com` : "https://log.chaxus.com";
|
|
29
|
-
}
|
package/src/ranlog/error.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Noop } from './utils'
|
|
2
|
-
import type { Hooks } from './utils'
|
|
3
|
-
|
|
4
|
-
export const handleError = (hooks: Hooks = Noop): void => {
|
|
5
|
-
window.addEventListener('unhandledrejection', (error) => {hooks(error)}, true);
|
|
6
|
-
window.addEventListener('error', (error) => {
|
|
7
|
-
hooks(error)
|
|
8
|
-
return false // 取消默认事件
|
|
9
|
-
}, true) // 捕获阶段
|
|
10
|
-
}
|
|
11
|
-
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
interface BasicType {
|
|
3
|
-
[x:string]: number | undefined
|
|
4
|
-
dnsSearch: number; // DNS 解析耗时
|
|
5
|
-
tcpConnect: number; // TCP 连接耗时
|
|
6
|
-
sslConnect: number; // SSL安全连接耗时
|
|
7
|
-
request: number; // TTFB 网络请求耗时
|
|
8
|
-
response: number; // 数据传输耗时
|
|
9
|
-
parseDomTree: number; // DOM 解析耗时
|
|
10
|
-
resource: number; // 资源加载耗时
|
|
11
|
-
domReady: number; // DOM Ready
|
|
12
|
-
httpHead: number; // http 头部大小
|
|
13
|
-
interactive: number; // 首次可交互时间
|
|
14
|
-
complete: number; // 页面完全加载
|
|
15
|
-
redirect: number; // 重定向次数
|
|
16
|
-
redirectTime: number; // 重定向耗时
|
|
17
|
-
duration: number; // 资源请求的总耗时 responseEnd-startTime
|
|
18
|
-
fp: number | undefined; // 渲染出第一个像素点,白屏时间
|
|
19
|
-
fcp: number | undefined; // 渲染出第一个内容,首屏结束时间
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function getPerformance(): BasicType {
|
|
23
|
-
const [performanceNavigationTiming] = performance.getEntriesByType('navigation')
|
|
24
|
-
const [firstPaint, firstContentfulPaint] = performance.getEntriesByType('paint')
|
|
25
|
-
const {
|
|
26
|
-
domainLookupEnd,
|
|
27
|
-
domainLookupStart,
|
|
28
|
-
connectEnd,
|
|
29
|
-
connectStart,
|
|
30
|
-
secureConnectionStart,
|
|
31
|
-
loadEventStart,
|
|
32
|
-
domInteractive,
|
|
33
|
-
domContentLoadedEventEnd,
|
|
34
|
-
duration,
|
|
35
|
-
responseStart,
|
|
36
|
-
requestStart,
|
|
37
|
-
responseEnd,
|
|
38
|
-
fetchStart,
|
|
39
|
-
transferSize,
|
|
40
|
-
encodedBodySize,
|
|
41
|
-
redirectEnd,
|
|
42
|
-
redirectStart,
|
|
43
|
-
redirectCount
|
|
44
|
-
} = performanceNavigationTiming as PerformanceNavigationTiming;
|
|
45
|
-
const { startTime: fp } = firstPaint;
|
|
46
|
-
const { startTime: fcp } = firstContentfulPaint;
|
|
47
|
-
return {
|
|
48
|
-
dnsSearch: domainLookupEnd - domainLookupStart,
|
|
49
|
-
tcpConnect: connectEnd - connectStart,
|
|
50
|
-
sslConnect: connectEnd - secureConnectionStart,
|
|
51
|
-
request: responseStart - requestStart,
|
|
52
|
-
response: responseEnd - responseStart,
|
|
53
|
-
parseDomTree: domInteractive - responseEnd,
|
|
54
|
-
resource: loadEventStart - domContentLoadedEventEnd,
|
|
55
|
-
domReady: domContentLoadedEventEnd - fetchStart,
|
|
56
|
-
interactive: domInteractive - fetchStart,
|
|
57
|
-
complete: loadEventStart - fetchStart,
|
|
58
|
-
httpHead: transferSize - encodedBodySize,
|
|
59
|
-
redirect: redirectCount,
|
|
60
|
-
redirectTime: redirectEnd - redirectStart,
|
|
61
|
-
duration: duration,
|
|
62
|
-
fp: fp,
|
|
63
|
-
fcp: fcp,
|
|
64
|
-
};
|
|
65
|
-
}
|
package/src/ranlog/report.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { querystring } from './utils'
|
|
2
|
-
import { getHost } from './env'
|
|
3
|
-
|
|
4
|
-
interface BeaconPayload {
|
|
5
|
-
url?: string,
|
|
6
|
-
type?: string,
|
|
7
|
-
payload: Record<string, unknown>
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const sendBeacon = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload) => {
|
|
12
|
-
const requestUrl = url ? url : getHost()
|
|
13
|
-
if (navigator.sendBeacon) { // 判断sendBeacon是否支持可用
|
|
14
|
-
const param = new Blob([JSON.stringify(payload)], { type });
|
|
15
|
-
return navigator.sendBeacon(requestUrl, param)
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const sendImage = ({ url = "", payload = {} }) => {
|
|
20
|
-
const requestUrl = url ? url : getHost()
|
|
21
|
-
const image = new Image();
|
|
22
|
-
image.width = 1;
|
|
23
|
-
image.height = 1;
|
|
24
|
-
image.src = `${requestUrl}?${querystring(payload)}`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const report = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload): boolean | undefined | void => {
|
|
28
|
-
const requestUrl = url ? url : getHost()
|
|
29
|
-
if (typeof navigator.sendBeacon !== 'undefined') { // 判断sendBeacon是否支持可用
|
|
30
|
-
return sendBeacon({ url: requestUrl, type, payload })
|
|
31
|
-
}
|
|
32
|
-
return sendImage({ url: requestUrl, payload })
|
|
33
|
-
}
|
package/src/ranlog/request.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { Noop, replaceOld } from './utils'
|
|
2
|
-
import type { Hooks } from './utils'
|
|
3
|
-
|
|
4
|
-
interface Options {
|
|
5
|
-
requestHook: Hooks,
|
|
6
|
-
responseHook: Hooks,
|
|
7
|
-
errorHook: Hooks
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* @description: fetch
|
|
11
|
-
* @param {Partial} options
|
|
12
|
-
*/
|
|
13
|
-
export const handleFetchHook = (options: Partial<Options> = {}): void => {
|
|
14
|
-
if (typeof window !== 'undefined') {
|
|
15
|
-
const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options
|
|
16
|
-
const replacement = (originalFetch: any) => {
|
|
17
|
-
return (url: string, config?: any) => {
|
|
18
|
-
requestHook(url, config)
|
|
19
|
-
return originalFetch.apply(window, [url, config])
|
|
20
|
-
.then((response: Response) => {
|
|
21
|
-
responseHook(url, config, response)
|
|
22
|
-
return response
|
|
23
|
-
})
|
|
24
|
-
.catch((error: Error) => {
|
|
25
|
-
errorHook(url, error)
|
|
26
|
-
throw error;
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
replaceOld(window, 'fetch', replacement)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* @description: xhr
|
|
35
|
-
* @param {Partial} options
|
|
36
|
-
* @return {*}
|
|
37
|
-
*/
|
|
38
|
-
export const handleXhrHook = (options: Partial<Options> = {}): void => {
|
|
39
|
-
const originalXhrProto = XMLHttpRequest.prototype;
|
|
40
|
-
const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options
|
|
41
|
-
const replacementXhrOpen = (originalOpen: any) => {
|
|
42
|
-
return function (this: XMLHttpRequest, ...args: unknown[]): void {
|
|
43
|
-
requestHook(args)
|
|
44
|
-
originalOpen.apply(this, args);
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
replaceOld(originalXhrProto, 'open', replacementXhrOpen);
|
|
48
|
-
const replacementXhrSend = (originalSend: any) => {
|
|
49
|
-
return function (this: any, ...args: any[]): void {
|
|
50
|
-
this.addEventListener('loadend', function (this: unknown) {
|
|
51
|
-
responseHook(this)
|
|
52
|
-
});
|
|
53
|
-
this.addEventListener('error', function (this: unknown) {
|
|
54
|
-
errorHook(this)
|
|
55
|
-
});
|
|
56
|
-
originalSend.apply(this, args);
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
replaceOld(originalXhrProto, 'send', replacementXhrSend);
|
|
60
|
-
}
|
package/src/ranlog/utils.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export function querystring(data = {}): string {
|
|
3
|
-
if (typeof data !== "object") {
|
|
4
|
-
throw new TypeError("param must be object");
|
|
5
|
-
}
|
|
6
|
-
return Object.entries(data).reduce((searchParams, [name, value]) => value === undefined || value == null ? searchParams : (searchParams.append(decodeURIComponent(name), decodeURIComponent(value)), searchParams), new URLSearchParams()).toString();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function randomString(len: number = 8): string {
|
|
10
|
-
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
|
11
|
-
const maxPos = chars.length;
|
|
12
|
-
let pwd = '';
|
|
13
|
-
for (let i = 0; i < len; i++) {
|
|
14
|
-
pwd += chars.charAt(Math.floor(Math.random() * maxPos))
|
|
15
|
-
}
|
|
16
|
-
return `${Date.now()}-${pwd}`;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function getCookie(name: string): string {
|
|
20
|
-
const cookieList = window.document.cookie.match(
|
|
21
|
-
new RegExp(`(^| )${name}(?:=([^;]*))?(;|$)`)
|
|
22
|
-
);
|
|
23
|
-
if (cookieList && cookieList[2]) return cookieList[2];
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function createData(params: Record<string, unknown> = {}): Record<string, unknown> {
|
|
28
|
-
return Object.assign({}, {
|
|
29
|
-
id: randomString(),
|
|
30
|
-
path: window.location.href,
|
|
31
|
-
time: Date.now(),
|
|
32
|
-
userAgent: window.navigator.userAgent,
|
|
33
|
-
referrer: document.referrer,
|
|
34
|
-
ip: window.returnCitySN || { cid: "", cip: "", cname: "" },
|
|
35
|
-
userId: getCookie('chaxus_prod')
|
|
36
|
-
}, params)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const throttle = (fn: Function, wait: number = 300): Function => {
|
|
40
|
-
let timer: NodeJS.Timeout | null = null;
|
|
41
|
-
return function (this: unknown, ...args: unknown[]) {
|
|
42
|
-
const context = this;
|
|
43
|
-
if (!timer) {
|
|
44
|
-
timer = setTimeout(() => {
|
|
45
|
-
timer = null;
|
|
46
|
-
fn.apply(context, args);
|
|
47
|
-
}, wait);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export const Noop = ():void => {}
|
|
53
|
-
|
|
54
|
-
export function changeHumpToLowerCase(str: string): string { // str ====> fullName
|
|
55
|
-
const arr = str.split(""); // 将字符串用split拆为单个字母为元素的数组,fullName ====> ["f", "u", "l", "l", "N", "a", "m", "e"]
|
|
56
|
-
const lowerCase = arr.map(val => {
|
|
57
|
-
if (val.toUpperCase() === val) { // 由此判断出,当前字符为大写字母
|
|
58
|
-
return "_" + val.toLowerCase(); // 在大写字母前面加上下划线,并将该大写字母转为小写字母
|
|
59
|
-
} else {
|
|
60
|
-
return val;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
// 此时lowerCase =====> ["f", "u", "l", "l", "_n", "a", "m", "e"]
|
|
64
|
-
str = lowerCase.join(""); // 将数组元素连接起来,不用分隔符,这里必须用"" ,若省略的话,join方法会默认用逗号连接
|
|
65
|
-
return str; // 此时,str ====> full_name
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 重写对象上面的某个属性
|
|
70
|
-
*
|
|
71
|
-
* @export
|
|
72
|
-
* @param {IAnyObject} source 需要被重写的对象
|
|
73
|
-
* @param {string} name 需要被重写对象的key
|
|
74
|
-
* @param {(...args: any[]) => any} replacement 以原有的函数作为参数,执行并重写原有函数
|
|
75
|
-
* @param {boolean} isForced 是否强制重写(可能原先没有该属性)
|
|
76
|
-
*/
|
|
77
|
-
export function replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): void {
|
|
78
|
-
if (typeof source === "undefined") return;
|
|
79
|
-
if (name in source || isForced) {
|
|
80
|
-
const original = source[name];
|
|
81
|
-
const wrapped = replacement(original);
|
|
82
|
-
if (typeof wrapped === 'function') {
|
|
83
|
-
source[name] = wrapped;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export const isString = (obj: unknown): boolean => {
|
|
89
|
-
return toString.call(obj) === '[object String]';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export type Hooks = (...args: unknown[]) => void
|