wenay-common 1.0.243 → 1.0.245

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.
@@ -1,46 +1,55 @@
1
1
  export type Listener<T extends any[]> = (...r: T) => void;
2
2
  type NormalizeTuple<T> = T extends any[] ? T : [T];
3
3
  export declare function funcListenCallbackBase<T>(b: (e: Listener<NormalizeTuple<T>>) => (void | (() => void)), data?: {
4
- event?: (type: "add" | "remove", count: number, api: ReturnType<typeof funcListenCallbackBase<any>>) => void;
4
+ event?: (type: "add" | "remove", count: number, api: ReturnType<typeof funcListenCallbackBase<T>>) => void;
5
5
  fast?: boolean;
6
6
  }): {
7
7
  func: Listener<NormalizeTuple<T>>;
8
8
  isRun: () => boolean;
9
9
  run: () => void;
10
10
  close: () => void;
11
- addListen: (cb: Listener<NormalizeTuple<T>>) => () => void;
11
+ eventClose: (cb: () => void) => () => void;
12
+ removeEventClose: (cb: () => void) => void;
13
+ addListen: (cb: Listener<NormalizeTuple<T>>, cbClose?: () => void) => () => void;
12
14
  removeListen: (cb: Listener<NormalizeTuple<T>> | null) => void;
13
15
  count: () => number;
14
16
  readonly getAllKeys: Listener<NormalizeTuple<T>>[];
15
17
  };
16
- export declare function funcListenCallback<T>(a: (e: (Listener<NormalizeTuple<T>> | null)) => (void | (() => void)), event?: (type: "add" | "remove", count: number, api: ReturnType<typeof funcListenCallbackBase<T>>) => void, fast?: boolean): {
18
+ export declare function funcListenCallbackFast<T>(a: (e: (Listener<NormalizeTuple<T>> | null)) => (void | (() => void))): {
17
19
  func: Listener<NormalizeTuple<T>>;
18
20
  isRun: () => boolean;
19
21
  run: () => void;
20
22
  close: () => void;
21
- addListen: (cb: Listener<NormalizeTuple<T>>) => () => void;
23
+ eventClose: (cb: () => void) => () => void;
24
+ removeEventClose: (cb: () => void) => void;
25
+ addListen: (cb: Listener<NormalizeTuple<T>>, cbClose?: (() => void) | undefined) => () => void;
22
26
  removeListen: (cb: Listener<NormalizeTuple<T>> | null) => void;
23
27
  count: () => number;
24
28
  readonly getAllKeys: Listener<NormalizeTuple<T_1>>[];
25
29
  };
26
- export declare function funcListenCallbackFast<T>(a: (e: (Listener<NormalizeTuple<T>> | null)) => (void | (() => void))): {
30
+ export declare function funcListenCallback<T>(a: (e: (Listener<NormalizeTuple<T>> | null)) => (void | (() => void)), event?: (type: "add" | "remove", count: number, api: ReturnType<typeof funcListenCallbackBase<T>>) => void, fast?: boolean): {
27
31
  func: Listener<NormalizeTuple<T>>;
28
32
  isRun: () => boolean;
29
33
  run: () => void;
30
34
  close: () => void;
31
- addListen: (cb: Listener<NormalizeTuple<T>>) => () => void;
35
+ eventClose: (cb: () => void) => () => void;
36
+ removeEventClose: (cb: () => void) => void;
37
+ addListen: (cb: Listener<NormalizeTuple<T>>, cbClose?: (() => void) | undefined) => () => void;
32
38
  removeListen: (cb: Listener<NormalizeTuple<T>> | null) => void;
33
39
  count: () => number;
34
40
  readonly getAllKeys: Listener<NormalizeTuple<T_1>>[];
35
41
  };
36
- export declare function UseListen<T>(data?: Parameters<typeof funcListenCallbackBase>[1]): readonly [(...a: NormalizeTuple<T>) => void, {
42
+ export declare function UseListen<T>(data?: Parameters<typeof funcListenCallbackBase<T>>[1]): readonly [(...a: NormalizeTuple<T>) => void, {
37
43
  func: Listener<NormalizeTuple<T>>;
38
44
  isRun: () => boolean;
39
45
  run: () => void;
40
46
  close: () => void;
41
- addListen: (cb: Listener<NormalizeTuple<T>>) => () => void;
47
+ eventClose: (cb: () => void) => () => void;
48
+ removeEventClose: (cb: () => void) => void;
49
+ addListen: (cb: Listener<NormalizeTuple<T>>, cbClose?: (() => void) | undefined) => () => void;
42
50
  removeListen: (cb: Listener<NormalizeTuple<T>> | null) => void;
43
51
  count: () => number;
44
52
  readonly getAllKeys: Listener<NormalizeTuple<T_1>>[];
45
53
  }];
54
+ export declare function isListenCallback(obj: any): obj is ReturnType<typeof funcListenCallbackBase>;
46
55
  export {};
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.funcListenCallbackBase = funcListenCallbackBase;
4
- exports.funcListenCallback = funcListenCallback;
5
4
  exports.funcListenCallbackFast = funcListenCallbackFast;
5
+ exports.funcListenCallback = funcListenCallback;
6
6
  exports.UseListen = UseListen;
7
+ exports.isListenCallback = isListenCallback;
7
8
  function funcListenCallbackBase(b, data) {
8
- const { fast = false, event } = data ?? {};
9
+ const { fast = true, event } = data ?? {};
9
10
  const obj = new Map();
11
+ const evClose = new Map();
12
+ const sinh = new Map();
10
13
  let a = (...e) => { obj.forEach(z => z(...e)); };
11
14
  let close = null;
12
15
  let cached = null;
@@ -42,9 +45,38 @@ function funcListenCallbackBase(b, data) {
42
45
  close: () => {
43
46
  close?.();
44
47
  close = null;
48
+ obj.clear();
49
+ if (fast)
50
+ rebuild();
51
+ sinh.clear();
52
+ evClose.forEach(cb => cb());
53
+ evClose.clear();
45
54
  },
46
- addListen: (cb) => {
55
+ eventClose: (cb) => {
56
+ evClose.set(cb, cb);
57
+ return () => { evClose.delete(cb); };
58
+ },
59
+ removeEventClose: (cb) => {
60
+ const e = sinh.get(cb);
61
+ if (e)
62
+ evClose.delete(e);
63
+ sinh.delete(cb);
64
+ evClose.delete(cb);
65
+ },
66
+ addListen: (cb, cbClose) => {
47
67
  obj.set(cb, cb);
68
+ if (cbClose) {
69
+ if (evClose.has(cb)) {
70
+ const r = evClose.get(cb);
71
+ if (r !== cbClose) {
72
+ evClose.delete(r);
73
+ evClose.delete(cb);
74
+ sinh.delete(r);
75
+ }
76
+ }
77
+ evClose.set(cb, cbClose);
78
+ sinh.set(cbClose, cb);
79
+ }
48
80
  if (fast)
49
81
  rebuild();
50
82
  event?.("add", obj.size, api);
@@ -52,8 +84,14 @@ function funcListenCallbackBase(b, data) {
52
84
  },
53
85
  removeListen: (cb) => {
54
86
  obj.delete(cb);
87
+ const e = evClose.get(cb);
55
88
  if (fast)
56
89
  rebuild();
90
+ evClose.delete(cb);
91
+ if (e) {
92
+ evClose.delete(e);
93
+ sinh.delete(e);
94
+ }
57
95
  event?.("remove", obj.size, api);
58
96
  },
59
97
  count: () => obj.size,
@@ -61,12 +99,12 @@ function funcListenCallbackBase(b, data) {
61
99
  };
62
100
  return api;
63
101
  }
64
- function funcListenCallback(a, event, fast = true) {
65
- return funcListenCallbackBase(a, { event, fast });
66
- }
67
102
  function funcListenCallbackFast(a) {
68
103
  return funcListenCallbackBase(a, { fast: true });
69
104
  }
105
+ function funcListenCallback(a, event, fast = true) {
106
+ return funcListenCallbackBase(a, { event, fast });
107
+ }
70
108
  function UseListen(data = { fast: true }) {
71
109
  let t;
72
110
  const a = funcListenCallbackBase((e) => { t = e; }, { fast: true, ...data });
@@ -74,3 +112,18 @@ function UseListen(data = { fast: true }) {
74
112
  t = a.func;
75
113
  return [t, a];
76
114
  }
115
+ function isListenCallback(obj) {
116
+ if (obj == null || typeof obj !== "object")
117
+ return false;
118
+ const obj2 = obj;
119
+ return (typeof obj2.addListen === "function" &&
120
+ typeof obj2.removeListen === "function" &&
121
+ typeof obj2.eventClose === "function" &&
122
+ typeof obj2.func === "function" &&
123
+ typeof obj2.count === "function");
124
+ }
125
+ function f() {
126
+ const [set, out] = UseListen();
127
+ out.addListen(e => {
128
+ });
129
+ }
@@ -28,7 +28,7 @@ function isLeafValue(value) {
28
28
  }
29
29
  function funcListenBySocket2(e, d) {
30
30
  const { stop, addListenClose, status, paramsModify } = d ?? {};
31
- const { addListen, removeListen } = e;
31
+ const { addListen, removeListen, eventClose } = e;
32
32
  let last = null;
33
33
  let active = null;
34
34
  function removeCallback() {
@@ -0,0 +1,39 @@
1
+ import { funcListenCallback, funcListenCallbackBase, Listener } from "./Listen";
2
+ type ListenCallbackResult<T extends any[] = any[]> = ReturnType<typeof funcListenCallback<T>>;
3
+ export declare function listenSocket<Z extends any[] = any[]>(e: ListenCallbackResult<Z>, d?: {
4
+ readonly status?: () => boolean;
5
+ readonly addListenClose?: ListenCallbackResult<any>;
6
+ readonly stop?: (x: Listener<Z>) => any;
7
+ readonly paramsModify?: (...e: Z) => any[];
8
+ }): {
9
+ callback: (z: Listener<Z>) => Promise<void>;
10
+ removeCallback: () => boolean;
11
+ };
12
+ export declare function listenSocketFirst<Z extends any[] = any[]>(e: ListenCallbackResult<Z>, options?: Omit<Parameters<typeof listenSocket>[1], "paramsModify">): {
13
+ callback: (z: (a: Z[0]) => void) => void;
14
+ removeCallback: () => boolean;
15
+ };
16
+ export declare function listenSocketAll<Z extends any[] = any[]>(e: ListenCallbackResult<Z>, options?: Omit<Parameters<typeof listenSocket>[1], "paramsModify">): {
17
+ callback: (z: (...args: Z) => void) => void;
18
+ removeCallback: () => boolean;
19
+ };
20
+ type SmartCallback<Z extends any[]> = Z extends [infer Single] ? (a: Single) => void : (...args: Z) => void;
21
+ export declare function listenSocketSmart<Z extends any[] = any[]>(e: ListenCallbackResult<Z>, options?: Omit<Parameters<typeof listenSocket>[1], "paramsModify">): {
22
+ callback: (z: SmartCallback<Z>) => void;
23
+ removeCallback: () => boolean;
24
+ };
25
+ type Obj = Record<string, any>;
26
+ export declare function matchKeys<T extends Obj, T2 extends Obj>(obj1: T, obj2: T2): boolean;
27
+ export declare function matchKeysList<T extends Obj>(obj1: T, keys: string[]): boolean;
28
+ export declare function deepMapByKeysList<T, T3>(obj1: T, keys: string[], func: (a: any) => T3): T | T3 | null;
29
+ type ListenBase<T extends any[]> = ReturnType<typeof funcListenCallbackBase<T>>;
30
+ type InferArgs<T> = T extends ListenBase<infer R> ? R : never;
31
+ type SocketResult<T extends any[]> = ReturnType<typeof listenSocket<T>>;
32
+ export type DeepSocketListen<T> = {
33
+ [K in keyof T]: T[K] extends ListenBase<any> ? SocketResult<InferArgs<T[K]>> : T[K] extends typeof Promise ? T[K] : T[K] extends (...a: any) => any ? T[K] : T[K] extends object ? DeepSocketListen<T[K]> : T[K];
34
+ };
35
+ export declare function deepMapByKeys<T, T2 extends Obj, T3>(obj1: T, obj2: T2, func: (a: T2) => T3): T3 | T | null;
36
+ export declare function deepListenFirst<T>(obj: T, data?: Parameters<typeof listenSocketFirst>[1]): DeepSocketListen<T>;
37
+ export declare function deepListenAll<T>(obj: T, data?: Parameters<typeof listenSocketAll>[1]): DeepSocketListen<T>;
38
+ export declare function deepListenSmart<T>(obj: T, data?: Parameters<typeof listenSocketSmart>[1]): DeepSocketListen<T>;
39
+ export {};
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listenSocket = listenSocket;
4
+ exports.listenSocketFirst = listenSocketFirst;
5
+ exports.listenSocketAll = listenSocketAll;
6
+ exports.listenSocketSmart = listenSocketSmart;
7
+ exports.matchKeys = matchKeys;
8
+ exports.matchKeysList = matchKeysList;
9
+ exports.deepMapByKeysList = deepMapByKeysList;
10
+ exports.deepMapByKeys = deepMapByKeys;
11
+ exports.deepListenFirst = deepListenFirst;
12
+ exports.deepListenAll = deepListenAll;
13
+ exports.deepListenSmart = deepListenSmart;
14
+ const isProxy_1 = require("./isProxy");
15
+ const Listen_1 = require("./Listen");
16
+ function isLeafValue(value) {
17
+ return (value == null ||
18
+ typeof value === "function" ||
19
+ value instanceof Function ||
20
+ typeof value !== "object" ||
21
+ (0, isProxy_1.isProxy)(value));
22
+ }
23
+ function listenSocket(e, d) {
24
+ const { stop, addListenClose, status, paramsModify } = d ?? {};
25
+ const { addListen, removeListen, eventClose, removeEventClose } = e;
26
+ let last = null;
27
+ let active = null;
28
+ let resolveWait = null;
29
+ function finish() {
30
+ if (resolveWait) {
31
+ resolveWait();
32
+ resolveWait = null;
33
+ }
34
+ }
35
+ function removeCallback() {
36
+ if (last) {
37
+ stop?.(last);
38
+ last = null;
39
+ }
40
+ if (active) {
41
+ removeListen(active);
42
+ active = null;
43
+ }
44
+ addListenClose?.removeListen(removeCallback);
45
+ finish();
46
+ return true;
47
+ }
48
+ async function callback(z) {
49
+ if (last)
50
+ stop?.(last);
51
+ if (active) {
52
+ removeListen(active);
53
+ }
54
+ if (resolveWait) {
55
+ resolveWait();
56
+ resolveWait = null;
57
+ }
58
+ last = z;
59
+ let handler = z;
60
+ if (paramsModify) {
61
+ const orig = handler;
62
+ handler = (...a) => orig(...paramsModify(...a));
63
+ }
64
+ if (status) {
65
+ const wrapped = handler;
66
+ handler = (...a) => {
67
+ if (status())
68
+ wrapped(...a);
69
+ else
70
+ removeCallback();
71
+ };
72
+ }
73
+ const inner = handler;
74
+ active = (...a) => {
75
+ if (a[0] === "___STOP") {
76
+ z(...a);
77
+ if (last) {
78
+ stop?.(last);
79
+ }
80
+ last = null;
81
+ if (active) {
82
+ removeListen(active);
83
+ active = null;
84
+ }
85
+ addListenClose?.removeListen(removeCallback);
86
+ finish();
87
+ return;
88
+ }
89
+ inner(...a);
90
+ };
91
+ addListen(active, removeCallback);
92
+ addListenClose?.addListen(removeCallback);
93
+ return new Promise((resolve) => {
94
+ resolveWait = () => { resolve(); };
95
+ });
96
+ }
97
+ return { callback, removeCallback };
98
+ }
99
+ function listenSocketFirst(e, options) {
100
+ const r = listenSocket(e, {
101
+ ...options,
102
+ paramsModify: ((...args) => [args[0]]),
103
+ });
104
+ return {
105
+ callback: r.callback,
106
+ removeCallback: r.removeCallback,
107
+ };
108
+ }
109
+ function listenSocketAll(e, options) {
110
+ const r = listenSocket(e, { ...options });
111
+ return {
112
+ callback: r.callback,
113
+ removeCallback: r.removeCallback,
114
+ };
115
+ }
116
+ function listenSocketSmart(e, options) {
117
+ const r = listenSocket(e, { ...options });
118
+ return {
119
+ callback: r.callback,
120
+ removeCallback: r.removeCallback,
121
+ };
122
+ }
123
+ function matchKeys(obj1, obj2) {
124
+ return matchKeysList(obj1, Object.keys(obj2));
125
+ }
126
+ function matchKeysList(obj1, keys) {
127
+ const k1 = Object.keys(obj1);
128
+ return k1.length === keys.length && new Set([...k1, ...keys]).size === keys.length;
129
+ }
130
+ function deepMapByKeysList(obj1, keys, func) {
131
+ if (isLeafValue(obj1))
132
+ return obj1;
133
+ if (matchKeysList(obj1, keys))
134
+ return func(obj1);
135
+ return Object.fromEntries(Object.entries(obj1).map(([k, v]) => [k, deepMapByKeysList(v, keys, func)]));
136
+ }
137
+ function deepMapByKeys(obj1, obj2, func) {
138
+ if (isLeafValue(obj1))
139
+ return obj1;
140
+ const keys = Object.keys(obj2);
141
+ if (matchKeysList(obj1, keys))
142
+ return func(obj1);
143
+ return Object.fromEntries(Object.entries(obj1).map(([k, v]) => [k, deepMapByKeysList(v, keys, func)]));
144
+ }
145
+ const NOOP_LISTEN = (0, Listen_1.funcListenCallbackBase)((_e) => { });
146
+ function deepListenFirst(obj, data) {
147
+ return deepMapByKeys(obj, NOOP_LISTEN, (e) => listenSocketFirst(e, data));
148
+ }
149
+ function deepListenAll(obj, data) {
150
+ return deepMapByKeys(obj, NOOP_LISTEN, (e) => listenSocketAll(e, data));
151
+ }
152
+ function deepListenSmart(obj, data) {
153
+ return deepMapByKeys(obj, NOOP_LISTEN, (e) => listenSocketSmart(e, data));
154
+ }
@@ -18,7 +18,7 @@ export declare function funcListenCallbackSnapshot<T extends realSocket2<any | a
18
18
  memo: T4;
19
19
  snapshot?: (memo: T4) => T3;
20
20
  }): {
21
- run: (cb: import("./Listen").Listener<[data: getTypeCallback<T>, memo: T3]>) => () => void;
21
+ run: (cb: import("./Listen").Listener<[data: getTypeCallback<T>, memo: T3]>, cbClose?: (() => void) | undefined) => () => void;
22
22
  snapshot: () => T3 | undefined;
23
23
  memo: T4;
24
24
  listenA: {
@@ -26,7 +26,9 @@ export declare function funcListenCallbackSnapshot<T extends realSocket2<any | a
26
26
  isRun: () => boolean;
27
27
  run: () => void;
28
28
  close: () => void;
29
- addListen: (cb: import("./Listen").Listener<[data: getTypeCallback<T>, memo: T3]>) => () => void;
29
+ eventClose: (cb: () => void) => () => void;
30
+ removeEventClose: (cb: () => void) => void;
31
+ addListen: (cb: import("./Listen").Listener<[data: getTypeCallback<T>, memo: T3]>, cbClose?: (() => void) | undefined) => () => void;
30
32
  removeListen: (cb: import("./Listen").Listener<[data: getTypeCallback<T>, memo: T3]> | null) => void;
31
33
  count: () => number;
32
34
  readonly getAllKeys: import("./Listen").Listener<T_1 extends any[] ? T_1 : [T_1]>[];
@@ -9,7 +9,9 @@ export declare function SocketServerHook(opt?: {
9
9
  isRun: () => boolean;
10
10
  run: () => void;
11
11
  close: () => void;
12
- addListen: (cb: import("./Listen").Listener<[unknown]>) => () => void;
12
+ eventClose: (cb: () => void) => () => void;
13
+ removeEventClose: (cb: () => void) => void;
14
+ addListen: (cb: import("./Listen").Listener<[unknown]>, cbClose?: (() => void) | undefined) => () => void;
13
15
  removeListen: (cb: import("./Listen").Listener<[unknown]> | null) => void;
14
16
  count: () => number;
15
17
  readonly getAllKeys: import("./Listen").Listener<T extends any[] ? T : [T]>[];
@@ -20,7 +22,9 @@ export declare function SocketServerHook(opt?: {
20
22
  isRun: () => boolean;
21
23
  run: () => void;
22
24
  close: () => void;
23
- addListen: (cb: import("./Listen").Listener<[unknown]>) => () => void;
25
+ eventClose: (cb: () => void) => () => void;
26
+ removeEventClose: (cb: () => void) => void;
27
+ addListen: (cb: import("./Listen").Listener<[unknown]>, cbClose?: (() => void) | undefined) => () => void;
24
28
  removeListen: (cb: import("./Listen").Listener<[unknown]> | null) => void;
25
29
  count: () => number;
26
30
  readonly getAllKeys: import("./Listen").Listener<T extends any[] ? T : [T]>[];
@@ -1,4 +1,13 @@
1
- type Socket = {
1
+ export type RpcLimits = {
2
+ maxDepth?: number;
3
+ maxKeys?: number;
4
+ maxArgs?: number;
5
+ maxArrayLen?: number;
6
+ maxStringLen?: number;
7
+ maxCallbacks?: number;
8
+ maxPathLen?: number;
9
+ };
10
+ export type SocketTmpl = {
2
11
  emit: (e: string, d: any) => void;
3
12
  on: (e: string, cb: (d: any) => void) => void;
4
13
  };
@@ -21,6 +30,7 @@ type PromiseServerHooks<T> = {
21
30
  request?: any;
22
31
  error?: any;
23
32
  }) => void | Promise<void>;
33
+ resolveTransform?: (value: any, key: string, parent: any) => any;
24
34
  };
25
35
  type UnwrapPromise<T> = T extends Promise<infer R> ? R : T;
26
36
  type ClientAPI<T> = {
@@ -36,15 +46,16 @@ type ClientApiHandle = {
36
46
  callbackDelete: (fn: Function) => void;
37
47
  callbackEnd: (fn: Function) => void;
38
48
  };
39
- declare function createAPIFacadeServer<T extends object>({ socket, object: target, socketKey: key, debug, hooks }: {
40
- socket: Socket;
49
+ declare function createAPIFacadeServer<T extends object>({ socket, object: target, socketKey: key, debug, hooks, limits }: {
50
+ socket: SocketTmpl;
41
51
  object: T;
42
52
  socketKey: string;
43
53
  debug?: boolean;
44
54
  hooks?: PromiseServerHooks<T>;
55
+ limits?: RpcLimits;
45
56
  }): void;
46
57
  declare function createAPIFacadeClient<T extends object>({ socket, socketKey: key, limit }: {
47
- socket: Socket;
58
+ socket: SocketTmpl;
48
59
  socketKey: string;
49
60
  limit?: number;
50
61
  }): {
@@ -9,6 +9,22 @@ const FN_MARKER = "$_f";
9
9
  const BANNED_KEYS = new Set(["__proto__", "constructor", "prototype"]);
10
10
  const isSafeKey = (k) => !BANNED_KEYS.has(k);
11
11
  const hasOwn = (obj, k) => Object.prototype.hasOwnProperty.call(obj, k);
12
+ const DEFAULT_LIMITS = {
13
+ maxDepth: 32,
14
+ maxKeys: 1000,
15
+ maxArgs: 64,
16
+ maxArrayLen: 10_000,
17
+ maxStringLen: 1_000_000,
18
+ maxCallbacks: 100,
19
+ maxPathLen: 16,
20
+ };
21
+ const resolveLimits = (opts) => opts ? { ...DEFAULT_LIMITS, ...opts } : DEFAULT_LIMITS;
22
+ class PayloadLimitError extends Error {
23
+ constructor(reason) {
24
+ super(`Payload limit exceeded: ${reason}`);
25
+ this.name = "PayloadLimitError";
26
+ }
27
+ }
12
28
  const createIdPool = () => {
13
29
  const s = [];
14
30
  let n = 0;
@@ -18,17 +34,29 @@ const createIdPool = () => {
18
34
  };
19
35
  };
20
36
  exports.createIdPool = createIdPool;
21
- function walk(val, onLeaf) {
37
+ function walk(val, onLeaf, lim, depth = 0) {
38
+ if (lim) {
39
+ if (depth > lim.maxDepth)
40
+ throw new PayloadLimitError("max depth exceeded");
41
+ if (typeof val === "string" && val.length > lim.maxStringLen)
42
+ throw new PayloadLimitError("string too long");
43
+ }
22
44
  if (val == null || typeof val !== "object")
23
45
  return onLeaf(val);
24
46
  if (val[FN_MARKER] !== undefined)
25
47
  return onLeaf(val);
26
- if (Array.isArray(val))
27
- return val.map(v => walk(v, onLeaf));
48
+ if (Array.isArray(val)) {
49
+ if (lim && val.length > lim.maxArrayLen)
50
+ throw new PayloadLimitError("array too long");
51
+ return val.map(v => walk(v, onLeaf, lim, depth + 1));
52
+ }
53
+ const keys = Object.keys(val);
54
+ if (lim && keys.length > lim.maxKeys)
55
+ throw new PayloadLimitError("too many keys in object");
28
56
  const o = {};
29
- for (const k of Object.keys(val))
57
+ for (const k of keys)
30
58
  if (isSafeKey(k))
31
- o[k] = walk(val[k], onLeaf);
59
+ o[k] = walk(val[k], onLeaf, lim, depth + 1);
32
60
  return o;
33
61
  }
34
62
  function pack(args, pool, cbStore, cbIds) {
@@ -42,10 +70,15 @@ function pack(args, pool, cbStore, cbIds) {
42
70
  return leaf;
43
71
  }));
44
72
  }
45
- function unpack(args, sender, onEnd) {
73
+ function unpack(args, sender, onEnd, lim) {
74
+ let cbCount = 0;
46
75
  return args.map(v => walk(v, leaf => {
47
76
  if (leaf != null && typeof leaf === "object" && leaf[FN_MARKER] !== undefined) {
77
+ if (lim && ++cbCount > lim.maxCallbacks)
78
+ throw new PayloadLimitError("too many callbacks");
48
79
  const id = leaf[FN_MARKER];
80
+ if (typeof id !== "number" || !Number.isFinite(id))
81
+ throw new PayloadLimitError("invalid callback id");
49
82
  const wrapper = (...a) => {
50
83
  if (a[0] === "___STOP") {
51
84
  onEnd(id);
@@ -57,7 +90,7 @@ function unpack(args, sender, onEnd) {
57
90
  return wrapper;
58
91
  }
59
92
  return leaf;
60
- }));
93
+ }, lim));
61
94
  }
62
95
  const errToObj = (e) => e instanceof Error ? { name: e.name, message: e.message, stack: e.stack } : e;
63
96
  const _stopRegistry = new WeakMap();
@@ -72,15 +105,32 @@ const resolveCA = (path, args) => {
72
105
  return [path.slice(0, -1), args[1] ?? []];
73
106
  return [path, args];
74
107
  };
75
- function createServer(socket, key, target, hooks) {
108
+ function createServer(socket, key, target, hooks, limits) {
109
+ const lim = resolveLimits(limits);
76
110
  const methods = [];
77
111
  const contexts = [];
78
112
  const routeMap = {};
113
+ function transformTree(obj) {
114
+ if (obj == null || typeof obj !== "object")
115
+ return obj;
116
+ const out = {};
117
+ for (const k of Object.keys(obj)) {
118
+ if (!isSafeKey(k))
119
+ continue;
120
+ let v = obj[k];
121
+ if (hooks?.resolveTransform)
122
+ v = hooks.resolveTransform(v, k, obj);
123
+ out[k] = typeof v === "function" ? v : v != null && typeof v === "object" ? transformTree(v) : v;
124
+ }
125
+ return out;
126
+ }
127
+ const resolved = hooks?.resolveTransform ? transformTree(target) : target;
79
128
  (function index(obj, prefix) {
80
129
  for (const k of Object.keys(obj)) {
81
130
  if (!isSafeKey(k))
82
131
  continue;
83
- const v = obj[k], path = prefix ? prefix + "." + k : k;
132
+ const v = obj[k];
133
+ const path = prefix ? prefix + "." + k : k;
84
134
  if (typeof v === "function") {
85
135
  routeMap[path] = methods.length;
86
136
  methods.push(v);
@@ -89,7 +139,7 @@ function createServer(socket, key, target, hooks) {
89
139
  else if (v && typeof v === "object")
90
140
  index(v, path);
91
141
  }
92
- })(target, "");
142
+ })(resolved, "");
93
143
  function serialize(obj) {
94
144
  const out = {};
95
145
  for (const k of Object.keys(obj)) {
@@ -100,7 +150,7 @@ function createServer(socket, key, target, hooks) {
100
150
  }
101
151
  return out;
102
152
  }
103
- const strictSchema = serialize(target);
153
+ const strictSchema = serialize(resolved);
104
154
  const send = (d) => socket.emit(key, d);
105
155
  send([Pkt.MAP, routeMap, strictSchema]);
106
156
  socket.on(key, async (msg) => {
@@ -154,12 +204,17 @@ function createServer(socket, key, target, hooks) {
154
204
  curr = undefined;
155
205
  break;
156
206
  }
207
+ const parent = curr;
157
208
  curr = curr[seg];
209
+ if (hooks?.resolveTransform)
210
+ curr = hooks.resolveTransform(curr, seg, parent);
158
211
  }
159
212
  const last = ref[ref.length - 1];
160
213
  if (curr != null && typeof curr === "object" && hasOwn(curr, last)) {
161
214
  ctx = curr;
162
215
  fn = curr[last];
216
+ if (hooks?.resolveTransform)
217
+ fn = hooks.resolveTransform(fn, last, curr);
163
218
  }
164
219
  }
165
220
  }
@@ -180,7 +235,7 @@ function createServer(socket, key, target, hooks) {
180
235
  return;
181
236
  }
182
237
  }
183
- const args = unpack(rawArgs, (cbId, cbArgs) => send([Pkt.CB, cbId, cbArgs]), (cbId) => send([Pkt.CB_END, cbId]));
238
+ const args = unpack(rawArgs, (cbId, cbArgs) => send([Pkt.CB, cbId, cbArgs]), (cbId) => send([Pkt.CB_END, cbId]), lim);
184
239
  const res = await fn.apply(ctx, args);
185
240
  if (wait)
186
241
  send([Pkt.RESP, reqId, res]);
@@ -341,12 +396,12 @@ function createClient(socket, key, opts) {
341
396
  },
342
397
  };
343
398
  }
344
- function createAPIFacadeServer({ socket, object: target, socketKey: key, debug = false, hooks }) {
399
+ function createAPIFacadeServer({ socket, object: target, socketKey: key, debug = false, hooks, limits }) {
345
400
  if (debug) {
346
401
  const origOn = socket.on.bind(socket);
347
402
  socket.on = (e, cb) => origOn(e, (d) => { console.log("[RPC IN]", typeof d === "object" ? JSON.stringify(d) : d); cb(d); });
348
403
  }
349
- createServer(socket, key, target, hooks);
404
+ createServer(socket, key, target, hooks, limits);
350
405
  }
351
406
  function createAPIFacadeClient({ socket, socketKey: key, limit }) {
352
407
  return createClient(socket, key, { limit });
@@ -0,0 +1,20 @@
1
+ import { funcListenCallbackBase } from "./Listen";
2
+ import { type PromiseServerHooks } from "./commonsServerMini2";
3
+ type Socket = {
4
+ emit: (e: string, d: any) => void;
5
+ on: (e: string, cb: (d: any) => void) => void;
6
+ };
7
+ type ListenCallbackBase<T extends any[] = any[]> = ReturnType<typeof funcListenCallbackBase<T>>;
8
+ type AutoClientAPI<T> = {
9
+ [K in keyof T]: T[K] extends ListenCallbackBase<infer Args> ? (callback: (...args: Args) => void) => void : T[K] extends (...args: infer A) => infer R ? T[K] : T[K] extends object ? AutoClientAPI<T[K]> : T[K];
10
+ };
11
+ export declare function CreatAPIFacadeServerAuto<T extends object>({ socket, object: target, socketKey: key, debug, hooks }: {
12
+ socket: Socket;
13
+ object: T;
14
+ socketKey: string;
15
+ debug?: boolean;
16
+ hooks?: PromiseServerHooks<AutoClientAPI<T>>;
17
+ }): {
18
+ wrapped: AutoClientAPI<T>;
19
+ };
20
+ export type { AutoClientAPI };
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreatAPIFacadeServerAuto = CreatAPIFacadeServerAuto;
4
+ const Listen_1 = require("./Listen");
5
+ const isProxy_1 = require("./isProxy");
6
+ const commonsServerMini2_1 = require("./commonsServerMini2");
7
+ const listenCache = new WeakMap();
8
+ function wrapIfListen(value) {
9
+ if (value == null || typeof value !== "object")
10
+ return value;
11
+ if (listenCache.has(value)) {
12
+ return listenCache.get(value) ?? value;
13
+ }
14
+ if ((0, Listen_1.isListenCallback)(value)) {
15
+ const wrapper = (callback) => {
16
+ value.addListen(callback, () => {
17
+ try {
18
+ callback("___STOP");
19
+ }
20
+ catch (_) { }
21
+ });
22
+ };
23
+ listenCache.set(value, wrapper);
24
+ return wrapper;
25
+ }
26
+ listenCache.set(value, null);
27
+ return value;
28
+ }
29
+ const proxyCache = new WeakMap();
30
+ function autoWrap(obj) {
31
+ if (proxyCache.has(obj))
32
+ return proxyCache.get(obj);
33
+ const proxy = new Proxy(obj, {
34
+ get(target, prop, receiver) {
35
+ const raw = Reflect.get(target, prop, receiver);
36
+ if (raw == null || typeof raw !== "object")
37
+ return raw;
38
+ if (typeof raw === "function")
39
+ return raw;
40
+ const converted = wrapIfListen(raw);
41
+ if (converted !== raw)
42
+ return converted;
43
+ if (!(0, isProxy_1.isProxy)(raw))
44
+ return autoWrap(raw);
45
+ return autoWrap(raw);
46
+ },
47
+ ownKeys(target) {
48
+ return Reflect.ownKeys(target);
49
+ },
50
+ getOwnPropertyDescriptor(target, prop) {
51
+ return Reflect.getOwnPropertyDescriptor(target, prop);
52
+ },
53
+ has(target, prop) {
54
+ return Reflect.has(target, prop);
55
+ },
56
+ });
57
+ proxyCache.set(obj, proxy);
58
+ return proxy;
59
+ }
60
+ function CreatAPIFacadeServerAuto({ socket, object: target, socketKey: key, debug, hooks }) {
61
+ const wrapped = autoWrap(target);
62
+ (0, commonsServerMini2_1.CreatAPIFacadeServer2)({
63
+ socket,
64
+ object: wrapped,
65
+ socketKey: key,
66
+ debug,
67
+ hooks,
68
+ });
69
+ return { wrapped };
70
+ }
@@ -0,0 +1,15 @@
1
+ import { funcListenCallbackBase } from "./Listen";
2
+ import { DeepSocketListen } from "./ListenBySocket2";
3
+ import { type PromiseServerHooks, type ClientAPI, SocketTmpl, type RpcLimits } from "./commonsServerMini2";
4
+ type ListenCallbackBase<T extends any[] = any[]> = ReturnType<typeof funcListenCallbackBase<T>>;
5
+ export declare function CreatAPIFacadeServerAuto2<T extends object>({ socket, object: target, socketKey: key, debug, hooks, disconnectListen, limits }: {
6
+ socket: SocketTmpl;
7
+ object: T;
8
+ socketKey: string;
9
+ debug?: boolean;
10
+ hooks?: Omit<PromiseServerHooks<DeepSocketListen<T>>, "resolveTransform">;
11
+ disconnectListen?: ListenCallbackBase<any>;
12
+ limits?: RpcLimits;
13
+ }): void;
14
+ export type AutoClientAPI<T> = ClientAPI<DeepSocketListen<T>>;
15
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreatAPIFacadeServerAuto2 = CreatAPIFacadeServerAuto2;
4
+ const Listen_1 = require("./Listen");
5
+ const ListenBySocket2_1 = require("./ListenBySocket2");
6
+ const commonsServerMini2_1 = require("./commonsServerMini2");
7
+ function CreatAPIFacadeServerAuto2({ socket, object: target, socketKey: key, debug, hooks, disconnectListen, limits }) {
8
+ const cache = new WeakMap();
9
+ function getListenSocket(parent, disconnectListen) {
10
+ let result = cache.get(parent);
11
+ if (!result) {
12
+ result = (0, ListenBySocket2_1.listenSocket)(parent, { addListenClose: disconnectListen });
13
+ cache.set(parent, result);
14
+ }
15
+ return result;
16
+ }
17
+ (0, commonsServerMini2_1.CreatAPIFacadeServer2)({
18
+ socket, object: target, socketKey: key, debug, limits,
19
+ hooks: {
20
+ ...hooks,
21
+ resolveTransform: (value, k, parent) => {
22
+ if (k !== "callback" && k !== "removeCallback")
23
+ return value;
24
+ if (!(0, Listen_1.isListenCallback)(parent))
25
+ return value;
26
+ return getListenSocket(parent, disconnectListen)[k];
27
+ },
28
+ },
29
+ });
30
+ }
@@ -0,0 +1,6 @@
1
+ type IterableObjectOptions<V> = {
2
+ resolve: () => Map<string, V>;
3
+ onChange?: (type: "set" | "delete", key: string, value?: V) => void;
4
+ };
5
+ declare function createIterableObject<V>(options: IterableObjectOptions<V>): Iterable<[string, V]> & Record<string, V>;
6
+ declare function test2(): void;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ function createIterableObject(options) {
3
+ const { resolve, onChange } = options;
4
+ return new Proxy({}, {
5
+ get(_, key) {
6
+ if (key === Symbol.iterator)
7
+ return () => resolve()[Symbol.iterator]();
8
+ if (typeof key === "string")
9
+ return resolve().get(key);
10
+ },
11
+ set(_, key, value) {
12
+ if (!onChange || typeof key !== "string")
13
+ return false;
14
+ onChange("set", key, value);
15
+ return true;
16
+ },
17
+ deleteProperty(_, key) {
18
+ if (!onChange || typeof key !== "string")
19
+ return false;
20
+ onChange("delete", key);
21
+ return true;
22
+ },
23
+ has(_, key) {
24
+ return typeof key === "string" && resolve().has(key);
25
+ },
26
+ ownKeys() {
27
+ return [...resolve().keys()];
28
+ },
29
+ getOwnPropertyDescriptor(_, key) {
30
+ if (typeof key === "string" && resolve().has(key)) {
31
+ return {
32
+ configurable: true,
33
+ enumerable: true,
34
+ writable: !!onChange,
35
+ value: resolve().get(key)
36
+ };
37
+ }
38
+ }
39
+ });
40
+ }
41
+ function test2() {
42
+ const storage = new Map();
43
+ storage.set("a", 1);
44
+ const ro = createIterableObject({ resolve: () => storage });
45
+ for (const [k, v] of ro) {
46
+ console.log(ro[k], k, v);
47
+ }
48
+ const rw = createIterableObject({
49
+ resolve: () => storage,
50
+ onChange(type, key, value) {
51
+ if (type === "set")
52
+ storage.set(key, value);
53
+ if (type === "delete")
54
+ storage.delete(key);
55
+ console.log(`[${type}] ${key}`, value);
56
+ }
57
+ });
58
+ rw["b"] = 2;
59
+ delete rw["a"];
60
+ for (const [k, v] of rw) {
61
+ console.log(k, v);
62
+ rw["c"] = 3;
63
+ }
64
+ }
@@ -26,7 +26,7 @@ function joinListens(listens, keyExtractor) {
26
26
  const tid = getKey(data[0]);
27
27
  if (!buckets.has(tid))
28
28
  buckets.set(tid, new Map());
29
- buckets.get(tid).set(portId, data);
29
+ buckets.get(tid).set(portId, data.length <= 1 ? data[0] : data);
30
30
  tryFire(tid);
31
31
  });
32
32
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ console.log("=== ОБЫЧНЫЙ ERROR.STACK ===");
4
+ console.log(new Error().stack);
5
+ console.log("=== PREPARE STACK TRACE ===");
6
+ const originalPrepareStackTrace = Error.prepareStackTrace;
7
+ Error.prepareStackTrace = (_, stack) => stack;
8
+ const stack = new Error().stack;
9
+ Error.prepareStackTrace = originalPrepareStackTrace;
10
+ console.log("Stack frames:");
11
+ for (let i = 0; i < Math.min(stack.length, 3); i++) {
12
+ const frame = stack[i];
13
+ console.log(`Frame[${i}]: ${frame.getFileName()}:${frame.getLineNumber()}:${frame.getColumnNumber()}`);
14
+ }
@@ -200,6 +200,7 @@ export type IParamsExpandable = {
200
200
  export type IParamsExpandableReadonly = ReadonlyFull<IParamsExpandable>;
201
201
  export declare function isParamGroupOrArray<TParam extends IParamReadonly>(param: TParam): param is Extract<TParam, ReadonlyFull<IParamGroup | IParamArr<any>>>;
202
202
  export declare function isParamGroup<TParam extends IParamReadonly>(param: TParam): param is Extract<TParam, ReadonlyFull<IParamGroup>>;
203
+ export declare function isSimpleParams2<TParams extends IParamsReadonly>(params: TParams | SimpleParams): boolean;
203
204
  export declare function isSimpleParams<TParams extends IParamsReadonly>(params: TParams | SimpleParams): boolean;
204
205
  type ObjectKeyPath<TObject extends object = object, TValue = unknown> = readonly string[];
205
206
  export declare function iterateParams<TObj extends IParamsReadonly, TVal extends IParamReadonly = TObj[string]>(obj: TObj, currentPath?: ObjectKeyPath<TObj, TVal>): Generator<[key: string, value: TVal, path: ObjectKeyPath<TObj, TVal>]>;
@@ -4,6 +4,7 @@ exports.CParamsReadonly = exports.CParams = void 0;
4
4
  exports.isParamBase = isParamBase;
5
5
  exports.isParamGroupOrArray = isParamGroupOrArray;
6
6
  exports.isParamGroup = isParamGroup;
7
+ exports.isSimpleParams2 = isSimpleParams2;
7
8
  exports.isSimpleParams = isSimpleParams;
8
9
  exports.iterateParams = iterateParams;
9
10
  exports.enableAllParams = enableAllParams;
@@ -32,7 +33,7 @@ function isParamGroupOrArray(param) {
32
33
  function isParamGroup(param) {
33
34
  return isParamGroupOrArray(param) && !Array.isArray(param.value);
34
35
  }
35
- function isSimpleParams(params) {
36
+ function isSimpleParams2(params) {
36
37
  let t = false;
37
38
  for (let key in params) {
38
39
  const tr = params[key]["value"];
@@ -48,6 +49,24 @@ function isSimpleParams(params) {
48
49
  }
49
50
  return false;
50
51
  }
52
+ function isSimpleParams(params) {
53
+ for (let key in params) {
54
+ const param = params[key];
55
+ if (param == null || typeof param !== "object") {
56
+ return true;
57
+ }
58
+ if (!("value" in param)) {
59
+ return true;
60
+ }
61
+ const val = param.value;
62
+ if (typeof val === "object" && val !== null && !(val instanceof Date) && !Array.isArray(val)) {
63
+ const r = isSimpleParams(val);
64
+ if (r)
65
+ return true;
66
+ }
67
+ }
68
+ return false;
69
+ }
51
70
  function* iterateParams(obj, currentPath = []) {
52
71
  for (let [key, param] of Object.entries(obj)) {
53
72
  let keyPath = currentPath.concat(key);
@@ -164,6 +183,51 @@ let p0 = p.p1;
164
183
  let p3 = p.p3;
165
184
  let p4 = p.p4;
166
185
  let p5 = p.p5?.p1;
186
+ function test22() {
187
+ const base = {
188
+ kBorrow: {
189
+ value: 1,
190
+ name: 'borrow step',
191
+ range: { max: 3, min: 1, step: 0.1 }
192
+ },
193
+ checkBorrow: { value: false, name: 'check borrow' },
194
+ checkBorrowFutures: { value: false, name: 'check borrow for futures' },
195
+ depoMulti: {
196
+ value: 1,
197
+ name: 'koef depoMulti',
198
+ range: { min: 0.01, max: 4, step: 0.01 }
199
+ },
200
+ depoMulti2: {
201
+ value: 2,
202
+ name: 'koef depoMulti',
203
+ range: { min: 0.01, max: 4, step: 0.01 }
204
+ }
205
+ };
206
+ const params = {
207
+ kBorrow: {
208
+ value: 2,
209
+ name: 'borrow step',
210
+ range: { max: 3, min: 1, step: 0.1 }
211
+ },
212
+ checkBorrow: { value: true, name: 'check borrow' },
213
+ checkBorrowFutures: { value: true, name: 'check borrow for futures' },
214
+ depoMulti: {
215
+ value: 1.32,
216
+ name: 'koef depoMulti',
217
+ range: { min: 0.01, max: 4, step: 0.01 }
218
+ },
219
+ depoMulti3: {
220
+ value: 1,
221
+ name: 'koef depoMulti',
222
+ range: { min: 0.01, max: 4, step: 0.01 }
223
+ }
224
+ };
225
+ const tr = GetSimpleParams(params);
226
+ console.log(tr);
227
+ const i = mergeParamValuesToInfos(base, tr);
228
+ console.log(i);
229
+ }
230
+ test22();
167
231
  function convert_(valuesObj, srcObj) {
168
232
  let resObj = {};
169
233
  if (srcObj instanceof Array)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wenay-common",
3
- "version": "1.0.243",
3
+ "version": "1.0.245",
4
4
  "description": "Common library",
5
5
  "strict": true,
6
6
  "main": "lib/index.js",