tcdona_unilib 1.0.12 → 1.0.15
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/eff/aff.ts +161 -0
- package/eff/aff.util.ts +218 -0
- package/eff/eff.ts +9 -10
- package/package.json +17 -13
- package/staticMeta/enum.api.ts +1 -1
- package/staticMeta/file.yml.ts +11 -2
package/eff/aff.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Result } from 'neverthrow'
|
|
2
|
+
import { err, ok, ResultAsync } from 'neverthrow'
|
|
3
|
+
import {
|
|
4
|
+
Actrl,
|
|
5
|
+
ABORT_REASON,
|
|
6
|
+
shortId,
|
|
7
|
+
type AffFn,
|
|
8
|
+
type NonEmptyArray,
|
|
9
|
+
type ExtractOk,
|
|
10
|
+
type ExtractErr,
|
|
11
|
+
} from './aff.util'
|
|
12
|
+
|
|
13
|
+
export class Aff {
|
|
14
|
+
/**
|
|
15
|
+
* 创建子任务(继承父 signal,支持取消传播)
|
|
16
|
+
*/
|
|
17
|
+
static make<T, E>(
|
|
18
|
+
actrlSpanId: string,
|
|
19
|
+
executor: AffFn<T, E>,
|
|
20
|
+
parentActrl: Actrl,
|
|
21
|
+
): ResultAsync<T, E> {
|
|
22
|
+
const actrl = new Actrl(actrlSpanId)
|
|
23
|
+
const unlink = parentActrl.link(actrl)
|
|
24
|
+
|
|
25
|
+
const executorResult = executor(actrl)
|
|
26
|
+
// 统一处理 PromiseLike 和 ResultAsync,转换为 Promise<Result<T, E>>
|
|
27
|
+
// ResultAsync 实现了 PromiseLike,Promise.resolve 可以处理它
|
|
28
|
+
const promise: Promise<Result<T, E>> = Promise.resolve(
|
|
29
|
+
executorResult as PromiseLike<Result<T, E>>,
|
|
30
|
+
)
|
|
31
|
+
.catch((e) => err(e as E))
|
|
32
|
+
.then((result) => {
|
|
33
|
+
actrl.resultStatus = result.isOk() ? 'ok' : 'err'
|
|
34
|
+
unlink()
|
|
35
|
+
actrl.cancel(ABORT_REASON.COMPLETED)
|
|
36
|
+
return result
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return new ResultAsync(promise)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 创建根级任务(无父 signal)
|
|
44
|
+
*/
|
|
45
|
+
static root<T, E>(executor: AffFn<T, E>): ResultAsync<T, E> {
|
|
46
|
+
return Aff.make('root', executor, new Actrl('$', true))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static all<T extends NonEmptyArray<AffFn<unknown, unknown>>>(
|
|
50
|
+
executors: T,
|
|
51
|
+
parentActrl: Actrl,
|
|
52
|
+
): ResultAsync<
|
|
53
|
+
{ -readonly [P in keyof T]: ExtractOk<T[P]> },
|
|
54
|
+
ExtractErr<T[number]>
|
|
55
|
+
> {
|
|
56
|
+
const actrl = new Actrl('all#' + shortId())
|
|
57
|
+
const unlink = parentActrl.link(actrl)
|
|
58
|
+
|
|
59
|
+
// Result -> Promise 语义转换:err 变成 reject,这样 Promise.all 遇到 err 会立即返回
|
|
60
|
+
const toPromise = (ra: ResultAsync<unknown, unknown>) =>
|
|
61
|
+
ra.then((r) => (r.isOk() ? r.value : Promise.reject(r.error)))
|
|
62
|
+
|
|
63
|
+
const promise = Promise.all(
|
|
64
|
+
executors.map((fn, i) => toPromise(Aff.make(`all-${i}`, fn, actrl))),
|
|
65
|
+
)
|
|
66
|
+
.then((values) => {
|
|
67
|
+
unlink()
|
|
68
|
+
actrl.cancel(ABORT_REASON.COMPLETED)
|
|
69
|
+
return ok(values) as Result<
|
|
70
|
+
{ -readonly [P in keyof T]: ExtractOk<T[P]> },
|
|
71
|
+
ExtractErr<T[number]>
|
|
72
|
+
>
|
|
73
|
+
})
|
|
74
|
+
.catch((e) => {
|
|
75
|
+
unlink()
|
|
76
|
+
actrl.cancel(ABORT_REASON.SETTLED)
|
|
77
|
+
return err(e) as Result<
|
|
78
|
+
{ -readonly [P in keyof T]: ExtractOk<T[P]> },
|
|
79
|
+
ExtractErr<T[number]>
|
|
80
|
+
>
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
return new ResultAsync(promise)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static any<T extends NonEmptyArray<AffFn<unknown, unknown>>>(
|
|
87
|
+
executors: T,
|
|
88
|
+
parentActrl: Actrl,
|
|
89
|
+
): ResultAsync<ExtractOk<T[number]>, ExtractErr<T[number]>[]> {
|
|
90
|
+
const actrl = new Actrl('any#' + shortId())
|
|
91
|
+
const unlink = parentActrl.link(actrl)
|
|
92
|
+
|
|
93
|
+
// Result -> Promise 语义转换
|
|
94
|
+
const toPromise = (ra: ResultAsync<unknown, unknown>) =>
|
|
95
|
+
ra.then((r) => (r.isOk() ? r.value : Promise.reject(r.error)))
|
|
96
|
+
|
|
97
|
+
const promise = Promise.any(
|
|
98
|
+
executors.map((fn, i) => toPromise(Aff.make(`any-${i}`, fn, actrl))),
|
|
99
|
+
)
|
|
100
|
+
.then((value) => {
|
|
101
|
+
unlink()
|
|
102
|
+
actrl.cancel(ABORT_REASON.SETTLED)
|
|
103
|
+
return ok(value) as Result<
|
|
104
|
+
ExtractOk<T[number]>,
|
|
105
|
+
ExtractErr<T[number]>[]
|
|
106
|
+
>
|
|
107
|
+
})
|
|
108
|
+
.catch((e: AggregateError) => {
|
|
109
|
+
unlink()
|
|
110
|
+
actrl.cancel(ABORT_REASON.COMPLETED)
|
|
111
|
+
return err(e.errors) as Result<
|
|
112
|
+
ExtractOk<T[number]>,
|
|
113
|
+
ExtractErr<T[number]>[]
|
|
114
|
+
>
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return new ResultAsync(promise)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
static race<T extends NonEmptyArray<AffFn<unknown, unknown>>>(
|
|
121
|
+
executors: T,
|
|
122
|
+
parentActrl: Actrl,
|
|
123
|
+
): ResultAsync<ExtractOk<T[number]>, ExtractErr<T[number]>> {
|
|
124
|
+
const actrl = new Actrl('race#' + shortId())
|
|
125
|
+
const unlink = parentActrl.link(actrl)
|
|
126
|
+
|
|
127
|
+
const promise = Promise.race(
|
|
128
|
+
executors.map((fn, i) => Aff.make(`race-${i}`, fn, actrl)),
|
|
129
|
+
).then((firstResult) => {
|
|
130
|
+
unlink()
|
|
131
|
+
actrl.cancel(ABORT_REASON.SETTLED)
|
|
132
|
+
return firstResult as Result<ExtractOk<T[number]>, ExtractErr<T[number]>>
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
return new ResultAsync(promise)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
static allSettled<T extends NonEmptyArray<AffFn<unknown, unknown>>>(
|
|
139
|
+
executors: T,
|
|
140
|
+
parentActrl: Actrl,
|
|
141
|
+
): ResultAsync<
|
|
142
|
+
{ -readonly [P in keyof T]: Result<ExtractOk<T[P]>, ExtractErr<T[P]>> },
|
|
143
|
+
never
|
|
144
|
+
> {
|
|
145
|
+
const actrl = new Actrl('settled#' + shortId())
|
|
146
|
+
const unlink = parentActrl.link(actrl)
|
|
147
|
+
|
|
148
|
+
const promise = Promise.all(
|
|
149
|
+
executors.map((fn, i) => Aff.make(`allSettled-${i}`, fn, actrl)),
|
|
150
|
+
).then((results) => {
|
|
151
|
+
unlink()
|
|
152
|
+
actrl.cancel(ABORT_REASON.COMPLETED)
|
|
153
|
+
return ok(results) as Result<
|
|
154
|
+
{ -readonly [P in keyof T]: Result<ExtractOk<T[P]>, ExtractErr<T[P]>> },
|
|
155
|
+
never
|
|
156
|
+
>
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
return new ResultAsync(promise)
|
|
160
|
+
}
|
|
161
|
+
}
|
package/eff/aff.util.ts
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { Result } from 'neverthrow'
|
|
2
|
+
import { err, ok, ResultAsync } from 'neverthrow'
|
|
3
|
+
import { tcNanoid } from '../staticMeta/string.nanoid'
|
|
4
|
+
|
|
5
|
+
export type ActrlSpan = {
|
|
6
|
+
id: string
|
|
7
|
+
parent: string
|
|
8
|
+
status: 'init'
|
|
9
|
+
startTime: number
|
|
10
|
+
duration: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class Actrl {
|
|
14
|
+
readonly ac: AbortController
|
|
15
|
+
public traceid: string = ''
|
|
16
|
+
public span: ActrlSpan = {
|
|
17
|
+
id: '',
|
|
18
|
+
parent: '',
|
|
19
|
+
status: 'init',
|
|
20
|
+
startTime: 0,
|
|
21
|
+
duration: 0,
|
|
22
|
+
}
|
|
23
|
+
private isRoot = false
|
|
24
|
+
public depth = 0 // 基于父子关系的真实深度
|
|
25
|
+
public resultStatus: 'ok' | 'err' | null = null // 任务返回状态
|
|
26
|
+
public logs: string[] = [] // 日志数组,用于收集日志信息
|
|
27
|
+
private rootLogs: string[] | null = null // 指向根 Actrl 的 logs,用于统一收集所有日志
|
|
28
|
+
|
|
29
|
+
constructor(spanid: string, isRoot = false) {
|
|
30
|
+
this.ac = new AbortController()
|
|
31
|
+
this.span.id = spanid
|
|
32
|
+
this.isRoot = isRoot
|
|
33
|
+
this.depth = isRoot ? 0 : 0
|
|
34
|
+
if (isRoot) {
|
|
35
|
+
this.rootLogs = this.logs // 根 Actrl 的 rootLogs 指向自己的 logs
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
get aborted() {
|
|
40
|
+
return this.ac.signal.aborted
|
|
41
|
+
}
|
|
42
|
+
get reason(): unknown {
|
|
43
|
+
return this.ac.signal.reason
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
cancel(reason?: unknown) {
|
|
47
|
+
this.ac.abort(reason)
|
|
48
|
+
}
|
|
49
|
+
link(childActrl: Actrl) {
|
|
50
|
+
// 让子 Actrl 共享根 Actrl 的 logs
|
|
51
|
+
childActrl.rootLogs = this.rootLogs || this.logs
|
|
52
|
+
// 获取目标日志数组(根 Actrl 的 logs)
|
|
53
|
+
const getTargetLogs = () => this.rootLogs || this.logs
|
|
54
|
+
|
|
55
|
+
if (this.isRoot) {
|
|
56
|
+
this.traceid = tcNanoid()
|
|
57
|
+
childActrl.traceid = this.traceid
|
|
58
|
+
childActrl.depth = 1
|
|
59
|
+
|
|
60
|
+
const indent = formatIndent(childActrl.depth)
|
|
61
|
+
const displayId = childActrl.span.id
|
|
62
|
+
getTargetLogs().push(formatLogStart(indent, displayId))
|
|
63
|
+
|
|
64
|
+
if (this.ac.signal.aborted) {
|
|
65
|
+
childActrl.cancel(this.ac.signal.reason)
|
|
66
|
+
getTargetLogs().push(
|
|
67
|
+
formatLogCancel(indent, childActrl.span.id, 'parent aborted'),
|
|
68
|
+
)
|
|
69
|
+
return noop
|
|
70
|
+
}
|
|
71
|
+
const handler = () => {
|
|
72
|
+
childActrl.cancel(this.ac.signal.reason)
|
|
73
|
+
// 记录取消日志(当父任务因为 SETTLED 被取消时)
|
|
74
|
+
if (this.ac.signal.reason === ABORT_REASON.SETTLED) {
|
|
75
|
+
getTargetLogs().push(formatLogCancel(indent, childActrl.span.id))
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
this.ac.signal.addEventListener('abort', handler, { once: true })
|
|
79
|
+
return () => {
|
|
80
|
+
// 判断是否被外部取消(reason 是 'settled' 表示被其他任务抢先完成)
|
|
81
|
+
const isCancelled =
|
|
82
|
+
childActrl.aborted && childActrl.reason === ABORT_REASON.SETTLED
|
|
83
|
+
let status = ''
|
|
84
|
+
if (isCancelled) {
|
|
85
|
+
status = ' [cancelled]'
|
|
86
|
+
} else if (childActrl.resultStatus) {
|
|
87
|
+
status = ' [' + childActrl.resultStatus + ']'
|
|
88
|
+
}
|
|
89
|
+
getTargetLogs().push(formatLogEnd(indent, childActrl.span.id, status))
|
|
90
|
+
this.ac.signal.removeEventListener('abort', handler)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
childActrl.traceid = this.traceid
|
|
94
|
+
childActrl.span.parent = this.span.id
|
|
95
|
+
childActrl.depth = this.depth + 1
|
|
96
|
+
|
|
97
|
+
const indent = formatIndent(childActrl.depth)
|
|
98
|
+
const displayId = formatDisplayId(this.span.id, childActrl.span.id)
|
|
99
|
+
childActrl.span.id = displayId
|
|
100
|
+
getTargetLogs().push(formatLogStart(indent, displayId))
|
|
101
|
+
|
|
102
|
+
if (this.ac.signal.aborted) {
|
|
103
|
+
childActrl.cancel(this.ac.signal.reason)
|
|
104
|
+
getTargetLogs().push(
|
|
105
|
+
formatLogCancel(indent, childActrl.span.id, 'parent aborted'),
|
|
106
|
+
)
|
|
107
|
+
return noop
|
|
108
|
+
}
|
|
109
|
+
const handler = () => {
|
|
110
|
+
childActrl.cancel(this.ac.signal.reason)
|
|
111
|
+
// 记录取消日志(当父任务因为 SETTLED 被取消时)
|
|
112
|
+
if (this.ac.signal.reason === ABORT_REASON.SETTLED) {
|
|
113
|
+
getTargetLogs().push(formatLogCancel(indent, childActrl.span.id))
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
this.ac.signal.addEventListener('abort', handler, { once: true })
|
|
117
|
+
return () => {
|
|
118
|
+
// 判断是否被外部取消(reason 是 'settled' 表示被其他任务抢先完成)
|
|
119
|
+
const isCancelled =
|
|
120
|
+
childActrl.aborted && childActrl.reason === ABORT_REASON.SETTLED
|
|
121
|
+
let status = ''
|
|
122
|
+
if (isCancelled) {
|
|
123
|
+
status = ' [cancelled]'
|
|
124
|
+
} else if (childActrl.resultStatus) {
|
|
125
|
+
status = ' [' + childActrl.resultStatus + ']'
|
|
126
|
+
}
|
|
127
|
+
getTargetLogs().push(formatLogEnd(indent, childActrl.span.id, status))
|
|
128
|
+
this.ac.signal.removeEventListener('abort', handler)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
on(
|
|
132
|
+
type: string,
|
|
133
|
+
listener: EventListenerOrEventListenerObject,
|
|
134
|
+
options?: boolean | AddEventListenerOptions,
|
|
135
|
+
) {
|
|
136
|
+
this.ac.signal.addEventListener(type, listener, options)
|
|
137
|
+
}
|
|
138
|
+
off(
|
|
139
|
+
type: string,
|
|
140
|
+
listener: EventListenerOrEventListenerObject,
|
|
141
|
+
options?: boolean | EventListenerOptions,
|
|
142
|
+
) {
|
|
143
|
+
this.ac.signal.removeEventListener(type, listener, options)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export type AffFn<T, E> = (
|
|
148
|
+
actrl: Actrl,
|
|
149
|
+
) => PromiseLike<Result<T, E>> | ResultAsync<T, E>
|
|
150
|
+
export type NonEmptyArray<T> = readonly [T, ...T[]]
|
|
151
|
+
export type ExtractOk<T> = T extends AffFn<infer U, unknown> ? U : never
|
|
152
|
+
export type ExtractErr<T> = T extends AffFn<unknown, infer E> ? E : never
|
|
153
|
+
|
|
154
|
+
export const ABORT_REASON = { SETTLED: 'settled', COMPLETED: 'completed' } as const
|
|
155
|
+
export const noop = () => {}
|
|
156
|
+
|
|
157
|
+
// ============================================================
|
|
158
|
+
// 日志格式化函数
|
|
159
|
+
// ============================================================
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 生成缩进字符串
|
|
163
|
+
*/
|
|
164
|
+
export const formatIndent = (depth: number): string => {
|
|
165
|
+
return ' '.repeat(depth)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 格式化显示 ID(取父级最后一段 + 当前 id)
|
|
170
|
+
*/
|
|
171
|
+
export const formatDisplayId = (parentId: string, childId: string): string => {
|
|
172
|
+
const parentShort = parentId.split('/').pop() || parentId
|
|
173
|
+
return parentShort + '/' + childId
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 格式化开始日志
|
|
178
|
+
*/
|
|
179
|
+
export const formatLogStart = (indent: string, id: string): string => {
|
|
180
|
+
return indent + '→ ' + id
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 格式化结束日志
|
|
185
|
+
*/
|
|
186
|
+
export const formatLogEnd = (indent: string, id: string, status?: string): string => {
|
|
187
|
+
return indent + '← ' + id + (status || '')
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 格式化取消日志
|
|
192
|
+
*/
|
|
193
|
+
export const formatLogCancel = (
|
|
194
|
+
indent: string,
|
|
195
|
+
id: string,
|
|
196
|
+
reason?: string,
|
|
197
|
+
): string => {
|
|
198
|
+
if (reason === 'parent aborted') {
|
|
199
|
+
return indent + '✗ ' + id + ' [cancelled: parent aborted]'
|
|
200
|
+
}
|
|
201
|
+
return indent + '✗ ' + id + ' [cancelled]'
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 打印日志
|
|
206
|
+
*/
|
|
207
|
+
export const printLogs = (logs: string[], title?: string): void => {
|
|
208
|
+
if (logs.length > 0) {
|
|
209
|
+
if (title) {
|
|
210
|
+
console.log(`=== ${title} ===`)
|
|
211
|
+
}
|
|
212
|
+
console.log(logs.join('\n'))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 简短 id 生成器
|
|
217
|
+
let _idCounter = 0
|
|
218
|
+
export const shortId = () => (++_idCounter).toString(36)
|
package/eff/eff.ts
CHANGED
|
@@ -31,15 +31,15 @@ const noop = () => {}
|
|
|
31
31
|
/**
|
|
32
32
|
* 将父 signal abort 传播到子 controller,返回解绑函数
|
|
33
33
|
*/
|
|
34
|
-
const
|
|
34
|
+
const link = (
|
|
35
35
|
parentSignal: AbortSignal,
|
|
36
|
-
|
|
36
|
+
childController: AbortController,
|
|
37
37
|
): (() => void) => {
|
|
38
38
|
if (parentSignal.aborted) {
|
|
39
|
-
|
|
39
|
+
childController.abort(parentSignal.reason)
|
|
40
40
|
return noop
|
|
41
41
|
}
|
|
42
|
-
const handler = () =>
|
|
42
|
+
const handler = () => childController.abort(parentSignal.reason)
|
|
43
43
|
parentSignal.addEventListener('abort', handler, { once: true })
|
|
44
44
|
return () => parentSignal.removeEventListener('abort', handler)
|
|
45
45
|
}
|
|
@@ -68,10 +68,9 @@ const runAll = <T, E, R, ER>(
|
|
|
68
68
|
},
|
|
69
69
|
) => void,
|
|
70
70
|
): ResultAsync<R, ER> =>
|
|
71
|
-
Eff.create(({ signal }) => {
|
|
71
|
+
Eff.create(({ signal: parentSignal }) => {
|
|
72
72
|
const controller = new AbortController()
|
|
73
|
-
const
|
|
74
|
-
const unlink = linkSignal(signal, controller)
|
|
73
|
+
const unlink = link(parentSignal, controller)
|
|
75
74
|
|
|
76
75
|
return new Promise((resolve) => {
|
|
77
76
|
let done = false
|
|
@@ -90,7 +89,7 @@ const runAll = <T, E, R, ER>(
|
|
|
90
89
|
resolve(r)
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
if (
|
|
92
|
+
if (parentSignal.aborted) {
|
|
94
93
|
settle(ok([] as R))
|
|
95
94
|
return
|
|
96
95
|
}
|
|
@@ -98,7 +97,7 @@ const runAll = <T, E, R, ER>(
|
|
|
98
97
|
let remaining = executors.length
|
|
99
98
|
|
|
100
99
|
executors.forEach((executor, i) => {
|
|
101
|
-
Eff.create(executor,
|
|
100
|
+
Eff.create(executor, controller.signal).then((r) => {
|
|
102
101
|
if (done) return
|
|
103
102
|
remaining--
|
|
104
103
|
onResult(r, i, settle, context)
|
|
@@ -129,7 +128,7 @@ export class Eff {
|
|
|
129
128
|
parentSignal: AbortSignal,
|
|
130
129
|
): ResultAsync<T, E> {
|
|
131
130
|
const controller = new AbortController()
|
|
132
|
-
const unlink =
|
|
131
|
+
const unlink = link(parentSignal, controller)
|
|
133
132
|
|
|
134
133
|
const promise: Promise<Result<T, E>> = Promise.resolve()
|
|
135
134
|
.then(() => executor({ signal: controller.signal }))
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tcdona_unilib",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "Unified dependency aggregation layer for shared libraries",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"exports": {
|
|
8
8
|
"./astgrep": "./ast-grep.ts",
|
|
9
|
+
"./eff/aff": "./eff/aff.ts",
|
|
10
|
+
"./eff/aff.util": "./eff/aff.util.ts",
|
|
9
11
|
"./eff/eff": "./eff/eff.ts",
|
|
10
12
|
"./eff/effcan": "./eff/effcan.ts",
|
|
11
13
|
"./eff/throwable": "./eff/throwable.ts",
|
|
@@ -46,32 +48,33 @@
|
|
|
46
48
|
"./viteplugin/*.ts": "./viteplugin/*.ts"
|
|
47
49
|
},
|
|
48
50
|
"scripts": {
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
+
"test": "vitest",
|
|
52
|
+
"viteplugin": "vite build -c viteplugin/vite.config.ts"
|
|
51
53
|
},
|
|
52
54
|
"keywords": [],
|
|
53
55
|
"author": "",
|
|
54
56
|
"license": "ISC",
|
|
55
57
|
"devDependencies": {
|
|
56
58
|
"@types/bun": "^1.3.5",
|
|
57
|
-
"@types/node": "^20.
|
|
58
|
-
"vitest": "^4.0.16"
|
|
59
|
+
"@types/node": "^20.19.28"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
|
-
"@ast-grep/napi": "^0.40.
|
|
62
|
-
"@dotenvx/dotenvx": "^1.51.
|
|
63
|
-
"@inquirer/prompts": "^8.
|
|
62
|
+
"@ast-grep/napi": "^0.40.5",
|
|
63
|
+
"@dotenvx/dotenvx": "^1.51.4",
|
|
64
|
+
"@inquirer/prompts": "^8.2.0",
|
|
64
65
|
"@types/big.js": "^6.2.2",
|
|
66
|
+
"@types/js-yaml": "^4.0.9",
|
|
65
67
|
"@types/turndown": "^5.0.6",
|
|
66
|
-
"animejs": "^4.
|
|
68
|
+
"animejs": "^4.2.2",
|
|
67
69
|
"big.js": "^7.0.1",
|
|
68
70
|
"clipboardy": "^5.0.2",
|
|
69
71
|
"dayjs": "^1.11.19",
|
|
70
72
|
"effector": "^23.4.4",
|
|
71
73
|
"es-toolkit": "^1.43.0",
|
|
72
|
-
"exome": "^2.8.
|
|
74
|
+
"exome": "^2.8.1",
|
|
73
75
|
"hono": "^4.11.3",
|
|
74
76
|
"hotkeys-js": "^4.0.0",
|
|
77
|
+
"js-yaml": "^4.1.1",
|
|
75
78
|
"koka": "^1.0.9",
|
|
76
79
|
"koka-domain": "^1.0.0",
|
|
77
80
|
"magic-regexp": "^0.10.0",
|
|
@@ -82,11 +85,12 @@
|
|
|
82
85
|
"pathe": "^2.0.3",
|
|
83
86
|
"pinyin-pro": "^3.27.0",
|
|
84
87
|
"prettier": "^3.7.4",
|
|
85
|
-
"tinypool": "^2.
|
|
88
|
+
"tinypool": "^2.1.0",
|
|
86
89
|
"turndown": "^7.2.2",
|
|
87
|
-
"vite": "^7.3.
|
|
90
|
+
"vite": "^7.3.1",
|
|
91
|
+
"vitest": "^4.0.17",
|
|
88
92
|
"vue": "^3.5.26",
|
|
89
|
-
"zod": "^4.
|
|
93
|
+
"zod": "^4.3.5",
|
|
90
94
|
"zx": "^8.8.5"
|
|
91
95
|
}
|
|
92
96
|
}
|
package/staticMeta/enum.api.ts
CHANGED
|
@@ -105,9 +105,9 @@ export class TcErr extends Error {
|
|
|
105
105
|
cons.error(
|
|
106
106
|
getTimestamp(),
|
|
107
107
|
`[${fileId.conf.srcFile}:${fileId.conf.id}]${fileId.conf.tag.length > 0 ? `[${fileId.conf.tag.join(', ')}]` : ''}`,
|
|
108
|
-
cause,
|
|
109
108
|
rest,
|
|
110
109
|
)
|
|
110
|
+
cons.log(cause)
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
package/staticMeta/file.yml.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { fs, YAML } from 'zx'
|
|
2
|
-
|
|
3
2
|
/**
|
|
4
3
|
* YAML 文件读写:无 data 参数时读取,有 data 参数时写入
|
|
5
4
|
*/
|
|
@@ -8,7 +7,7 @@ export function yml(path: string, data?: unknown): unknown {
|
|
|
8
7
|
fs.writeFileSync(
|
|
9
8
|
path,
|
|
10
9
|
// @ts-expect-error YAML.stringify 类型定义有误
|
|
11
|
-
YAML.stringify(data, { singleQuote: true
|
|
10
|
+
YAML.stringify(data, { singleQuote: true }),
|
|
12
11
|
'utf-8',
|
|
13
12
|
)
|
|
14
13
|
} else {
|
|
@@ -16,3 +15,13 @@ export function yml(path: string, data?: unknown): unknown {
|
|
|
16
15
|
return YAML.parse(ymlContent)
|
|
17
16
|
}
|
|
18
17
|
}
|
|
18
|
+
|
|
19
|
+
import { default as jsYAML } from 'js-yaml'
|
|
20
|
+
export const yml2 = (path: string, data?: unknown): unknown => {
|
|
21
|
+
if (typeof data !== 'undefined') {
|
|
22
|
+
fs.writeFileSync(path, jsYAML.dump(data, { sortKeys: true }), 'utf-8')
|
|
23
|
+
} else {
|
|
24
|
+
const ymlContent = fs.readFileSync(path, 'utf-8')
|
|
25
|
+
return jsYAML.load(ymlContent)
|
|
26
|
+
}
|
|
27
|
+
}
|