@yongdall/context 0.1.0
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/index.d.mts +122 -0
- package/index.mjs +329 -0
- package/index.mjs.map +1 -0
- package/package.json +15 -0
package/index.d.mts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
//#region packages/context/index.d.mts
|
|
2
|
+
/**
|
|
3
|
+
* 创建一个存储单元
|
|
4
|
+
* @template T
|
|
5
|
+
* @overload
|
|
6
|
+
* @param {T} def
|
|
7
|
+
* @returns {[() => T, (v: T) => boolean]}
|
|
8
|
+
*/
|
|
9
|
+
declare function createStore<T>(def: T): [() => T, (v: T) => boolean];
|
|
10
|
+
/**
|
|
11
|
+
* 创建一个存储单元
|
|
12
|
+
* @template T
|
|
13
|
+
* @overload
|
|
14
|
+
* @param {T} [def]
|
|
15
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
16
|
+
*/
|
|
17
|
+
declare function createStore<T>(def?: T | undefined): [() => T | undefined, (v: T) => boolean];
|
|
18
|
+
/**
|
|
19
|
+
* @template T
|
|
20
|
+
* @param {() => T} fn
|
|
21
|
+
* @returns {() => T}
|
|
22
|
+
*/
|
|
23
|
+
declare function createComputed<T>(fn: () => T): () => T;
|
|
24
|
+
/**
|
|
25
|
+
* 创建一个存储单元
|
|
26
|
+
* @template T
|
|
27
|
+
* @template TS
|
|
28
|
+
* @overload
|
|
29
|
+
* @param {string} name
|
|
30
|
+
* @param {(data: T) => TS | PromiseLike<TS>} serialize
|
|
31
|
+
* @param {(data: TS) => T | PromiseLike<T>} deserialize
|
|
32
|
+
* @param {T} def
|
|
33
|
+
* @returns {[() => T, (v: T) => boolean]}
|
|
34
|
+
*/
|
|
35
|
+
declare function createStoreSerializable<T, TS>(name: string, serialize: (data: T) => TS | PromiseLike<TS>, deserialize: (data: TS) => T | PromiseLike<T>, def: T): [() => T, (v: T) => boolean];
|
|
36
|
+
/**
|
|
37
|
+
* 创建一个存储单元
|
|
38
|
+
* @template T
|
|
39
|
+
* @template TS
|
|
40
|
+
* @overload
|
|
41
|
+
* @param {string} name
|
|
42
|
+
* @param {(data: T) => TS | PromiseLike<TS>} serialize
|
|
43
|
+
* @param {(data: TS) => T | PromiseLike<T>} deserialize
|
|
44
|
+
* @param {T} [def]
|
|
45
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
46
|
+
*/
|
|
47
|
+
declare function createStoreSerializable<T, TS>(name: string, serialize: (data: T) => TS | PromiseLike<TS>, deserialize: (data: TS) => T | PromiseLike<T>, def?: T | undefined): [() => T | undefined, (v: T) => boolean];
|
|
48
|
+
declare function serialize(): Promise<Record<string, any> | null>;
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param {Record<string, any>} data
|
|
52
|
+
*/
|
|
53
|
+
declare function deserialize(data: Record<string, any>): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* @template {object} T
|
|
56
|
+
* @param {() => T} fn
|
|
57
|
+
*/
|
|
58
|
+
declare function createOnceStore<T extends object>(fn: () => T): () => T;
|
|
59
|
+
/**
|
|
60
|
+
* @template {(...args: any) => any} T
|
|
61
|
+
* @param {T} fn
|
|
62
|
+
* @param {(...p: Parameters<T>) => string} getKey
|
|
63
|
+
* @param {(...p: Parameters<T>) => boolean} [isForce]
|
|
64
|
+
* @returns {T}
|
|
65
|
+
*/
|
|
66
|
+
declare function createKeyStore<T extends (...args: any) => any>(fn: T, getKey: (...p: Parameters<T>) => string, isForce?: (...p: Parameters<T>) => boolean): T;
|
|
67
|
+
/**
|
|
68
|
+
* 是否存在上下文
|
|
69
|
+
* @param {boolean} [must]
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
declare function has(must?: boolean): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* 创建一个上下文函数列表
|
|
75
|
+
* @template {*[]} T
|
|
76
|
+
* @returns {[(fn: (...v: T) => Promise<void> | void) => (() => void) | undefined, (...v: T) => void | Promise<void>]}
|
|
77
|
+
*/
|
|
78
|
+
declare function createFnList<T extends any[]>(): [(fn: (...v: T) => Promise<void> | void) => (() => void) | undefined, (...v: T) => void | Promise<void>];
|
|
79
|
+
/**
|
|
80
|
+
* @template T
|
|
81
|
+
* @template {*[]} TArgs
|
|
82
|
+
* @param {Env} env
|
|
83
|
+
* @param {(...args: TArgs) => PromiseLike<T> | T} fn
|
|
84
|
+
* @param {TArgs} args
|
|
85
|
+
* @returns {Promise<T>}
|
|
86
|
+
*/
|
|
87
|
+
declare function _run<T, TArgs extends any[]>(env: Env, fn: (...args: TArgs) => PromiseLike<T> | T, ...args: TArgs): Promise<T>;
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @returns {Env}
|
|
91
|
+
*/
|
|
92
|
+
declare function getEnv(): Env;
|
|
93
|
+
declare function getDomain(): string;
|
|
94
|
+
/**
|
|
95
|
+
* @template T
|
|
96
|
+
* @template {*[]} TArgs
|
|
97
|
+
* @param {(...args: TArgs) => T} fn
|
|
98
|
+
* @param {TArgs} args
|
|
99
|
+
* @returns {T}
|
|
100
|
+
*/
|
|
101
|
+
declare function parentRun<T, TArgs extends any[]>(fn: (...args: TArgs) => T, ...args: TArgs): T;
|
|
102
|
+
/**
|
|
103
|
+
*
|
|
104
|
+
* @param {string} key
|
|
105
|
+
* @param {any} [value]
|
|
106
|
+
* @returns
|
|
107
|
+
*/
|
|
108
|
+
declare function setState(key: string, value?: any): void;
|
|
109
|
+
/**
|
|
110
|
+
*
|
|
111
|
+
* @param {string} key
|
|
112
|
+
* @returns
|
|
113
|
+
*/
|
|
114
|
+
declare function getState(key: string): any;
|
|
115
|
+
type Env = {
|
|
116
|
+
domain: string;
|
|
117
|
+
};
|
|
118
|
+
declare const addDone: (fn: (...v: any[]) => Promise<void> | void) => (() => void) | undefined;
|
|
119
|
+
declare const addCatch: (fn: (...v: any[]) => Promise<void> | void) => (() => void) | undefined;
|
|
120
|
+
declare const addFinally: (fn: (...v: any[]) => Promise<void> | void) => (() => void) | undefined;
|
|
121
|
+
//#endregion
|
|
122
|
+
export { Env, _run, addCatch, addDone, addFinally, createComputed, createFnList, createKeyStore, createOnceStore, createStore, createStoreSerializable, deserialize, getDomain, getEnv, getState, has, parentRun, serialize, setState };
|
package/index.mjs
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
|
|
3
|
+
//#region packages/context/index.mjs
|
|
4
|
+
const asyncLocalStorage = new AsyncLocalStorage();
|
|
5
|
+
const parentKey = Symbol();
|
|
6
|
+
const envKey = Symbol();
|
|
7
|
+
/**
|
|
8
|
+
* 创建一个存储单元
|
|
9
|
+
* @template T
|
|
10
|
+
* @overload
|
|
11
|
+
* @param {T} def
|
|
12
|
+
* @returns {[() => T, (v: T) => boolean]}
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* 创建一个存储单元
|
|
16
|
+
* @template T
|
|
17
|
+
* @overload
|
|
18
|
+
* @param {T} [def]
|
|
19
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* 创建一个存储单元
|
|
23
|
+
* @template T
|
|
24
|
+
* @param {T} [def]
|
|
25
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
26
|
+
*/
|
|
27
|
+
function createStore(def) {
|
|
28
|
+
const symbol = Symbol();
|
|
29
|
+
function get() {
|
|
30
|
+
const state = asyncLocalStorage.getStore();
|
|
31
|
+
if (state && symbol in state) return state[symbol];
|
|
32
|
+
return def;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @param {T} v
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
function set(v) {
|
|
40
|
+
const state = asyncLocalStorage.getStore();
|
|
41
|
+
if (!state) return false;
|
|
42
|
+
state[symbol] = v;
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return [get, set];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* @template T
|
|
49
|
+
* @param {() => T} fn
|
|
50
|
+
* @returns {() => T}
|
|
51
|
+
*/
|
|
52
|
+
function createComputed(fn) {
|
|
53
|
+
const symbol = Symbol();
|
|
54
|
+
return () => {
|
|
55
|
+
const state = asyncLocalStorage.getStore();
|
|
56
|
+
if (!state) return fn();
|
|
57
|
+
if (symbol in state) return state[symbol];
|
|
58
|
+
const v = fn();
|
|
59
|
+
state[symbol] = v;
|
|
60
|
+
return v;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** @type {Record<symbol, [string, (data: any) => any]>} */
|
|
64
|
+
const allSerialize = Object.create(null);
|
|
65
|
+
/** @type {Record<string, [symbol, (data: any) => any]>} */
|
|
66
|
+
const allDeserialize = Object.create(null);
|
|
67
|
+
/**
|
|
68
|
+
* 创建一个存储单元
|
|
69
|
+
* @template T
|
|
70
|
+
* @template TS
|
|
71
|
+
* @overload
|
|
72
|
+
* @param {string} name
|
|
73
|
+
* @param {(data: T) => TS | PromiseLike<TS>} serialize
|
|
74
|
+
* @param {(data: TS) => T | PromiseLike<T>} deserialize
|
|
75
|
+
* @param {T} def
|
|
76
|
+
* @returns {[() => T, (v: T) => boolean]}
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* 创建一个存储单元
|
|
80
|
+
* @template T
|
|
81
|
+
* @template TS
|
|
82
|
+
* @overload
|
|
83
|
+
* @param {string} name
|
|
84
|
+
* @param {(data: T) => TS | PromiseLike<TS>} serialize
|
|
85
|
+
* @param {(data: TS) => T | PromiseLike<T>} deserialize
|
|
86
|
+
* @param {T} [def]
|
|
87
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
88
|
+
*/
|
|
89
|
+
/**
|
|
90
|
+
* 创建一个存储单元
|
|
91
|
+
* @template T
|
|
92
|
+
* @template TS
|
|
93
|
+
* @param {string} name
|
|
94
|
+
* @param {(data: T) => TS | PromiseLike<TS>} serialize
|
|
95
|
+
* @param {(data: TS) => T | PromiseLike<T>} deserialize
|
|
96
|
+
* @param {T} [def]
|
|
97
|
+
* @returns {[() => T | undefined, (v: T) => boolean]}
|
|
98
|
+
*/
|
|
99
|
+
function createStoreSerializable(name, serialize, deserialize, def) {
|
|
100
|
+
const symbol = Symbol();
|
|
101
|
+
allSerialize[symbol] = [name, serialize];
|
|
102
|
+
allDeserialize[name] = [symbol, deserialize];
|
|
103
|
+
function get() {
|
|
104
|
+
const state = asyncLocalStorage.getStore();
|
|
105
|
+
if (state && symbol in state) return state[symbol];
|
|
106
|
+
return def;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @param {T} v
|
|
111
|
+
* @returns
|
|
112
|
+
*/
|
|
113
|
+
function set(v) {
|
|
114
|
+
const state = asyncLocalStorage.getStore();
|
|
115
|
+
if (!state) return false;
|
|
116
|
+
state[symbol] = v;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
return [get, set];
|
|
120
|
+
}
|
|
121
|
+
async function serialize() {
|
|
122
|
+
const state = asyncLocalStorage.getStore();
|
|
123
|
+
if (!state) return null;
|
|
124
|
+
/** @type {Record<string, any>} */
|
|
125
|
+
const data = {};
|
|
126
|
+
for (const [symbol, [name, serialize]] of Object.entries(allSerialize)) {
|
|
127
|
+
const value = state[symbol];
|
|
128
|
+
if (value === void 0) continue;
|
|
129
|
+
data[name] = await serialize(value);
|
|
130
|
+
}
|
|
131
|
+
return data;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
*
|
|
135
|
+
* @param {Record<string, any>} data
|
|
136
|
+
*/
|
|
137
|
+
async function deserialize(data) {
|
|
138
|
+
const state = asyncLocalStorage.getStore();
|
|
139
|
+
if (!state) return;
|
|
140
|
+
for (const [name, value] of Object.entries(data)) {
|
|
141
|
+
if (data === void 0) continue;
|
|
142
|
+
const f = allDeserialize[name];
|
|
143
|
+
if (!f) continue;
|
|
144
|
+
const [symbol, deserialize] = f;
|
|
145
|
+
state[symbol] = await deserialize(value);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* @template {object} T
|
|
150
|
+
* @param {() => T} fn
|
|
151
|
+
*/
|
|
152
|
+
function createOnceStore(fn) {
|
|
153
|
+
const [getter, setter] = createStore(null);
|
|
154
|
+
/**
|
|
155
|
+
* @returns {T}
|
|
156
|
+
*/
|
|
157
|
+
return function() {
|
|
158
|
+
const p = getter();
|
|
159
|
+
if (p) return p;
|
|
160
|
+
const result = fn();
|
|
161
|
+
setter(result);
|
|
162
|
+
return result;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* @template {(...args: any) => any} T
|
|
167
|
+
* @param {T} fn
|
|
168
|
+
* @param {(...p: Parameters<T>) => string} getKey
|
|
169
|
+
* @param {(...p: Parameters<T>) => boolean} [isForce]
|
|
170
|
+
* @returns {T}
|
|
171
|
+
*/
|
|
172
|
+
function createKeyStore(fn, getKey, isForce) {
|
|
173
|
+
const [getter, setter] = createStore(null);
|
|
174
|
+
/**
|
|
175
|
+
* @param {Parameters<T>} params
|
|
176
|
+
* @returns {ReturnType<T>}
|
|
177
|
+
*/
|
|
178
|
+
function run(...params) {
|
|
179
|
+
let p = getter();
|
|
180
|
+
if (!p) {
|
|
181
|
+
p = {};
|
|
182
|
+
setter(p);
|
|
183
|
+
}
|
|
184
|
+
const key = getKey(...params);
|
|
185
|
+
if (Object.hasOwn(p, key) && !isForce?.(...params)) return p[key];
|
|
186
|
+
const result = fn(...params);
|
|
187
|
+
p[key] = result;
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
return run;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* 是否存在上下文
|
|
194
|
+
* @param {boolean} [must]
|
|
195
|
+
* @returns {boolean}
|
|
196
|
+
*/
|
|
197
|
+
function has(must) {
|
|
198
|
+
if (asyncLocalStorage.getStore()) return true;
|
|
199
|
+
if (must) throw new Error("不在上下文中");
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* 创建一个上下文函数列表
|
|
204
|
+
* @template {*[]} T
|
|
205
|
+
* @returns {[(fn: (...v: T) => Promise<void> | void) => (() => void) | undefined, (...v: T) => void | Promise<void>]}
|
|
206
|
+
*/
|
|
207
|
+
function createFnList() {
|
|
208
|
+
const symbol = Symbol();
|
|
209
|
+
/**
|
|
210
|
+
* @param {(...v: T) => Promise<void> | void} fn
|
|
211
|
+
* @returns {(() => void) | undefined}
|
|
212
|
+
*/
|
|
213
|
+
function add(fn) {
|
|
214
|
+
const state = asyncLocalStorage.getStore();
|
|
215
|
+
if (!state) return;
|
|
216
|
+
/**
|
|
217
|
+
* @param {T} v
|
|
218
|
+
* @returns
|
|
219
|
+
*/
|
|
220
|
+
const f = async (...v) => {
|
|
221
|
+
try {
|
|
222
|
+
return await fn(...v);
|
|
223
|
+
} catch (e) {
|
|
224
|
+
console.error(e);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
/** @type {Set<any>} */
|
|
228
|
+
let list = state[symbol];
|
|
229
|
+
if (!list) list = state[symbol] = /* @__PURE__ */ new Set();
|
|
230
|
+
list.add(f);
|
|
231
|
+
return () => {
|
|
232
|
+
list.delete(f);
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* @param {T} v
|
|
237
|
+
* @returns {void | Promise<void>}
|
|
238
|
+
*/
|
|
239
|
+
function run(...v) {
|
|
240
|
+
const list = asyncLocalStorage.getStore()?.[symbol];
|
|
241
|
+
if (!list) return;
|
|
242
|
+
return Promise.all([...list].map((f) => f(...v))).then(() => {});
|
|
243
|
+
}
|
|
244
|
+
return [add, run];
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* @typedef {object} Env
|
|
248
|
+
* @property {string} domain
|
|
249
|
+
*/
|
|
250
|
+
const [addDone, runDone] = createFnList();
|
|
251
|
+
const [addCatch, runCatch] = createFnList();
|
|
252
|
+
const [addFinally, runFinally] = createFnList();
|
|
253
|
+
/**
|
|
254
|
+
* @template T
|
|
255
|
+
* @template {*[]} TArgs
|
|
256
|
+
* @param {Env} env
|
|
257
|
+
* @param {(...args: TArgs) => PromiseLike<T> | T} fn
|
|
258
|
+
* @param {TArgs} args
|
|
259
|
+
* @returns {Promise<T>}
|
|
260
|
+
*/
|
|
261
|
+
async function _run(env, fn, ...args) {
|
|
262
|
+
const state = {
|
|
263
|
+
[parentKey]: asyncLocalStorage.getStore(),
|
|
264
|
+
[envKey]: env
|
|
265
|
+
};
|
|
266
|
+
try {
|
|
267
|
+
const r = await asyncLocalStorage.run(state, fn, ...args);
|
|
268
|
+
await asyncLocalStorage.run(state, () => runDone(r));
|
|
269
|
+
return r;
|
|
270
|
+
} catch (e) {
|
|
271
|
+
await asyncLocalStorage.run(state, () => runCatch(e));
|
|
272
|
+
throw e;
|
|
273
|
+
} finally {
|
|
274
|
+
await asyncLocalStorage.run(state, () => runFinally());
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
*
|
|
279
|
+
* @returns {Env}
|
|
280
|
+
*/
|
|
281
|
+
function getEnv() {
|
|
282
|
+
return asyncLocalStorage.getStore()?.[envKey] || { domain: "" };
|
|
283
|
+
}
|
|
284
|
+
function getDomain() {
|
|
285
|
+
return getEnv().domain;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* @template T
|
|
289
|
+
* @template {*[]} TArgs
|
|
290
|
+
* @param {(...args: TArgs) => T} fn
|
|
291
|
+
* @param {TArgs} args
|
|
292
|
+
* @returns {T}
|
|
293
|
+
*/
|
|
294
|
+
function parentRun(fn, ...args) {
|
|
295
|
+
const state = asyncLocalStorage.getStore();
|
|
296
|
+
if (!state) throw new Error("不再上下文中");
|
|
297
|
+
const p = state?.[parentKey];
|
|
298
|
+
if (!p) throw new Error("不存在父级上下文");
|
|
299
|
+
return asyncLocalStorage.run(p || state, fn, ...args);
|
|
300
|
+
}
|
|
301
|
+
const stateSymbol = Symbol();
|
|
302
|
+
/**
|
|
303
|
+
*
|
|
304
|
+
* @param {string} key
|
|
305
|
+
* @param {any} [value]
|
|
306
|
+
* @returns
|
|
307
|
+
*/
|
|
308
|
+
function setState(key, value = true) {
|
|
309
|
+
const store = asyncLocalStorage.getStore();
|
|
310
|
+
if (!store) return;
|
|
311
|
+
(store[stateSymbol] ||= /* @__PURE__ */ new Map()).set(key, value);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
*
|
|
315
|
+
* @param {string} key
|
|
316
|
+
* @returns
|
|
317
|
+
*/
|
|
318
|
+
function getState(key) {
|
|
319
|
+
const store = asyncLocalStorage.getStore();
|
|
320
|
+
if (!store) return;
|
|
321
|
+
/** @type {Map<string, any>} */
|
|
322
|
+
const state = store[stateSymbol];
|
|
323
|
+
if (!state) return;
|
|
324
|
+
return state.get(key);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
//#endregion
|
|
328
|
+
export { _run, addCatch, addDone, addFinally, createComputed, createFnList, createKeyStore, createOnceStore, createStore, createStoreSerializable, deserialize, getDomain, getEnv, getState, has, parentRun, serialize, setState };
|
|
329
|
+
//# sourceMappingURL=index.mjs.map
|
package/index.mjs.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../packages/context/index.mjs"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\n\nconst asyncLocalStorage = new AsyncLocalStorage();\nconst parentKey = Symbol();\nconst envKey = Symbol();\n\n/**\n * 创建一个存储单元\n * @template T\n * @overload\n * @param {T} def\n * @returns {[() => T, (v: T) => boolean]}\n */\n/**\n * 创建一个存储单元\n * @template T\n * @overload\n * @param {T} [def]\n * @returns {[() => T | undefined, (v: T) => boolean]}\n */\n/**\n * 创建一个存储单元\n * @template T\n * @param {T} [def]\n * @returns {[() => T | undefined, (v: T) => boolean]}\n */\nexport function createStore(def) {\n\tconst symbol = Symbol();\n\tfunction get() {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (state && symbol in state) {\n\t\t\treturn state[symbol];\n\t\t}\n\t\treturn def;\n\t}\n\t/**\n\t * \n\t * @param {T} v \n\t * @returns \n\t */\n\tfunction set(v) {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (!state) { return false; }\n\n\t\tstate[symbol] = v;\n\t\treturn true;\n\t}\n\treturn [get, set];\n}\n\n/**\n * @template T\n * @param {() => T} fn \n * @returns {() => T}\n */\nexport function createComputed(fn) {\n\tconst symbol = Symbol();\n\treturn () => {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (!state) { return fn(); }\n\t\tif (symbol in state) {\n\t\t\treturn state[symbol];\n\t\t}\n\t\tconst v = fn();\n\t\tstate[symbol] = v;\n\t\treturn v;\n\t}\n}\n/** @type {Record<symbol, [string, (data: any) => any]>} */\nconst allSerialize = Object.create(null);\n/** @type {Record<string, [symbol, (data: any) => any]>} */\nconst allDeserialize = Object.create(null);\n\n/**\n * 创建一个存储单元\n * @template T\n * @template TS\n * @overload\n * @param {string} name\n * @param {(data: T) => TS | PromiseLike<TS>} serialize \n * @param {(data: TS) => T | PromiseLike<T>} deserialize\n * @param {T} def\n * @returns {[() => T, (v: T) => boolean]}\n */\n/**\n * 创建一个存储单元\n * @template T\n * @template TS\n * @overload\n * @param {string} name\n * @param {(data: T) => TS | PromiseLike<TS>} serialize \n * @param {(data: TS) => T | PromiseLike<T>} deserialize\n * @param {T} [def]\n * @returns {[() => T | undefined, (v: T) => boolean]}\n */\n/**\n * 创建一个存储单元\n * @template T\n * @template TS\n * @param {string} name\n * @param {(data: T) => TS | PromiseLike<TS>} serialize \n * @param {(data: TS) => T | PromiseLike<T>} deserialize\n * @param {T} [def]\n * @returns {[() => T | undefined, (v: T) => boolean]}\n */\nexport function createStoreSerializable(name, serialize, deserialize, def) {\n\tconst symbol = Symbol();\n\tallSerialize[symbol] = [name, serialize];\n\tallDeserialize[name] = [symbol, deserialize];\n\tfunction get() {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (state && symbol in state) {\n\t\t\treturn state[symbol];\n\t\t}\n\t\treturn def;\n\t}\n\t/**\n\t * \n\t * @param {T} v \n\t * @returns \n\t */\n\tfunction set(v) {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (!state) { return false; }\n\n\t\tstate[symbol] = v;\n\t\treturn true;\n\t}\n\treturn [get, set];\n}\nexport async function serialize() {\n\tconst state = asyncLocalStorage.getStore();\n\tif (!state) { return null; }\n\t/** @type {Record<string, any>} */\n\tconst data = {};\n\tfor (const [symbol, [name, serialize]] of Object.entries(allSerialize)) {\n\t\tconst value = state[symbol];\n\t\tif (value === void 0) { continue; }\n\t\tdata[name] = await serialize(value);\n\t}\n\treturn data;\n}\n\n/**\n * \n * @param {Record<string, any>} data \n */\nexport async function deserialize(data) {\n\tconst state = asyncLocalStorage.getStore();\n\tif (!state) { return; }\n\tfor (const [name, value] of Object.entries(data)) {\n\t\tif (data === void 0) { continue; }\n\t\tconst f = allDeserialize[name];\n\t\tif (!f) { continue; }\n\t\tconst [symbol, deserialize] = f;\n\t\tstate[symbol] = await deserialize(value);\n\t}\n\n}\n\n\n/**\n * @template {object} T\n * @param {() => T} fn \n */\nexport function createOnceStore(fn) {\n\tconst [getter, setter] = createStore(/** @type {T?} */(null));\n\t/**\n\t * @returns {T}\n\t */\n\treturn function () {\n\t\tconst p = getter();\n\t\tif (p) { return p; }\n\t\tconst result = fn();\n\t\tsetter(result);\n\t\treturn result;\n\t};\n}\n\n/**\n * @template {(...args: any) => any} T\n * @param {T} fn \n * @param {(...p: Parameters<T>) => string} getKey \n * @param {(...p: Parameters<T>) => boolean} [isForce] \n * @returns {T}\n */\nexport function createKeyStore(fn, getKey, isForce) {\n\tconst [getter, setter] = createStore(/** @type {Record<string, ReturnType<T>>?} */(null));\n\t/**\n\t * @param {Parameters<T>} params\n\t * @returns {ReturnType<T>}\n\t */\n\t function run(...params) {\n\t\tlet p = getter();\n\t\tif (!p) {\n\t\t\tp = {};\n\t\t\tsetter(p);\n\t\t}\n\t\tconst key = getKey(...params);\n\t\tif (Object.hasOwn(p, key) && !isForce?.(...params)) {\n\t\t\treturn p[key];\n\t\t}\n\t\tconst result = fn(...params);\n\t\tp[key] = result;\n\t\treturn result;\n\t};\n\treturn /** @type {T} */(run);\n}\n\n/**\n * 是否存在上下文\n * @param {boolean} [must] \n * @returns {boolean}\n */\nexport function has(must) {\n\tif (asyncLocalStorage.getStore()) { return true; }\n\tif (must) { throw new Error('不在上下文中'); }\n\treturn false;\n}\n/**\n * 创建一个上下文函数列表\n * @template {*[]} T\n * @returns {[(fn: (...v: T) => Promise<void> | void) => (() => void) | undefined, (...v: T) => void | Promise<void>]}\n*/\nexport function createFnList() {\n\tconst symbol = Symbol();\n\t/**\n\t * @param {(...v: T) => Promise<void> | void} fn\n\t * @returns {(() => void) | undefined}\n\t */\n\tfunction add(fn) {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\tif (!state) { return; }\n\t\t/**\n\t\t * @param {T} v \n\t\t * @returns \n\t\t */\n\t\tconst f = async (...v) => {\n\t\t\ttry {\n\t\t\t\treturn await fn(...v);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(e);\n\t\t\t}\n\t\t};\n\t\t/** @type {Set<any>} */\n\t\tlet list = state[symbol];\n\t\tif (!list) {\n\t\t\tlist = state[symbol] = new Set();\n\t\t}\n\t\tlist.add(f);\n\t\treturn () => { list.delete(f); };\n\t}\n\t/**\n\t * @param {T} v \n\t * @returns {void | Promise<void>}\n\t */\n\tfunction run(...v) {\n\t\tconst list = asyncLocalStorage.getStore()?.[symbol];\n\t\tif (!list) { return; }\n\t\treturn Promise.all([...list].map(f => f(...v))).then(() => { });\n\n\t}\n\treturn [add, run];\n}\n\n/**\n * @typedef {object} Env\n * @property {string} domain\n */\n\nconst [addDone, runDone] = createFnList();\nconst [addCatch, runCatch] = createFnList();\nconst [addFinally, runFinally] = createFnList();\n/**\n * @template T\n * @template {*[]} TArgs\n * @param {Env} env \n * @param {(...args: TArgs) => PromiseLike<T> | T} fn \n * @param {TArgs} args \n * @returns {Promise<T>}\n */\nexport async function _run(env, fn, ...args) {\n\tconst state = { [parentKey]: asyncLocalStorage.getStore(), [envKey]: env };\n\ttry {\n\t\tconst r = await asyncLocalStorage.run(state, fn, ...args);\n\t\tawait asyncLocalStorage.run(state, () => runDone(r));\n\t\treturn r;\n\t} catch (e) {\n\t\tawait asyncLocalStorage.run(state, () => runCatch(e));\n\t\tthrow e;\n\t} finally {\n\t\tawait asyncLocalStorage.run(state, () => runFinally());\n\t}\n}\n/**\n * \n * @returns {Env}\n */\nexport function getEnv() {\n\t\tconst state = asyncLocalStorage.getStore();\n\t\treturn state?.[envKey] || {domain: ''};\n\t\n\n}\nexport function getDomain() {\n\t\treturn getEnv().domain;\n}\n\n\n/**\n * @template T\n * @template {*[]} TArgs\n * @param {(...args: TArgs) => T} fn \n * @param {TArgs} args \n * @returns {T}\n */\nexport function parentRun(fn, ...args) {\n\tconst state = asyncLocalStorage.getStore();\n\tif (!state) {\n\t\tthrow new Error('不再上下文中');\n\t}\n\tconst p = state?.[parentKey];\n\tif (!p) {\n\t\tthrow new Error('不存在父级上下文');\n\t}\n\treturn asyncLocalStorage.run(p || state, fn, ...args);\n}\n\nexport { addDone, addCatch, addFinally };\n\n\nconst stateSymbol = Symbol();\n/**\n * \n * @param {string} key \n * @param {any} [value] \n * @returns \n */\nexport function setState(key, value = true) {\n\tconst store = asyncLocalStorage.getStore();\n\tif (!store) { return; }\n\t/** @type {Map<string, any>} */\n\tconst state = store[stateSymbol] ||= new Map();\n\tstate.set(key, value);\n}\n/**\n * \n * @param {string} key \n * @returns \n */\nexport function getState(key) {\n\tconst store = asyncLocalStorage.getStore();\n\tif (!store) { return; }\n\t/** @type {Map<string, any>} */\n\tconst state = store[stateSymbol];\n\tif (!state) { return; }\n\treturn state.get(key);\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yongdall/context",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"main": "./index.mjs",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./index.mjs"
|
|
7
|
+
},
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"description": "",
|
|
10
|
+
"keywords": [],
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {},
|
|
14
|
+
"devDependencies": {}
|
|
15
|
+
}
|