@vope/utils 1.6.0-bate.2 → 1.6.0-bate.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/dist/clamp.d.ts +4 -0
- package/dist/clamp.mjs +11 -0
- package/dist/classnames.d.ts +7 -0
- package/dist/classnames.mjs +17 -0
- package/dist/compare/version.d.ts +5 -0
- package/dist/compare/version.mjs +15 -0
- package/dist/compare/weak-equal.d.ts +4 -0
- package/dist/compare/weak-equal.mjs +33 -0
- package/dist/convert/json.d.ts +12 -0
- package/dist/convert/json.mjs +7 -0
- package/dist/convert/object.d.ts +12 -0
- package/dist/convert/object.mjs +7 -0
- package/dist/convert/strings.d.ts +6 -0
- package/dist/convert/strings.mjs +7 -0
- package/dist/desens.d.ts +40 -0
- package/dist/desens.mjs +51 -0
- package/dist/encoding.d.ts +9 -0
- package/dist/encoding.mjs +56 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +1361 -0
- package/dist/index.mjs +73 -0
- package/dist/input-regex.d.ts +12 -0
- package/dist/input-regex.mjs +8 -0
- package/dist/is/class.d.ts +4 -0
- package/dist/is/class.mjs +22 -0
- package/dist/is/empty.d.ts +4 -0
- package/dist/is/empty.mjs +5 -0
- package/dist/is/key.d.ts +4 -0
- package/dist/is/key.mjs +4 -0
- package/dist/is/null.d.ts +4 -0
- package/dist/is/null.mjs +4 -0
- package/dist/load/image.d.ts +5 -0
- package/dist/load/image.mjs +11 -0
- package/dist/memory/basic.d.ts +79 -0
- package/dist/memory/basic.mjs +167 -0
- package/dist/memory/list.d.ts +8 -0
- package/dist/memory/list.mjs +12 -0
- package/dist/memory/power.d.ts +8 -0
- package/dist/memory/power.mjs +13 -0
- package/dist/memory/simple.d.ts +60 -0
- package/dist/memory/simple.mjs +94 -0
- package/dist/neo4j-anchors.d.ts +50 -0
- package/dist/neo4j-anchors.mjs +169 -0
- package/dist/neo4j.d.ts +82 -0
- package/dist/neo4j.mjs +161 -0
- package/dist/once.d.ts +6 -0
- package/dist/once.mjs +8 -0
- package/dist/parse/num.d.ts +8 -0
- package/dist/parse/num.mjs +31 -0
- package/dist/power/decon.d.ts +9 -0
- package/dist/power/decon.mjs +22 -0
- package/dist/rotate/angle.d.ts +8 -0
- package/dist/rotate/angle.mjs +5 -0
- package/dist/rotate/rad.d.ts +8 -0
- package/dist/rotate/rad.mjs +11 -0
- package/dist/serialize/url-params.d.ts +43 -0
- package/dist/serialize/url-params.mjs +53 -0
- package/dist/storage/offline.d.ts +51 -0
- package/dist/style/css.d.ts +9 -0
- package/dist/style/css.mjs +25 -0
- package/dist/subscriber.d.ts +11 -0
- package/dist/subscriber.mjs +64 -0
- package/dist/table/flex.d.ts +43 -0
- package/dist/table/flex.mjs +96 -0
- package/dist/union.d.ts +34 -0
- package/dist/union.mjs +47 -0
- package/dist/url/join.d.ts +4 -0
- package/dist/url/join.mjs +9 -0
- package/dist/url/params.d.ts +8 -0
- package/dist/url/params.mjs +8 -0
- package/dist/wait.d.ts +4 -0
- package/dist/wait.mjs +4 -0
- package/package.json +3 -4
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { rotateRad } from "./rotate/rad";
|
|
2
|
+
class Neo4jAhchors {
|
|
3
|
+
constructor(neo4j, config) {
|
|
4
|
+
this.neo4j = neo4j;
|
|
5
|
+
this.config = Object.assign({}, config);
|
|
6
|
+
}
|
|
7
|
+
config;
|
|
8
|
+
#anchors = {};
|
|
9
|
+
getDir(start, end) {
|
|
10
|
+
const { neo4j } = this;
|
|
11
|
+
return neo4j.dirKey({
|
|
12
|
+
[neo4j.sourceField]: start,
|
|
13
|
+
[neo4j.targetField]: end
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 设置多边间隔弧长
|
|
18
|
+
*/
|
|
19
|
+
setRaidx(value) {
|
|
20
|
+
this.config.radOffsetRaidx = value;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 当图数据准备好后调用
|
|
24
|
+
*/
|
|
25
|
+
read() {
|
|
26
|
+
const { neo4j } = this;
|
|
27
|
+
const { nodeField, edgeField, sourceField, targetField } = neo4j;
|
|
28
|
+
const anchors = {};
|
|
29
|
+
neo4j.nodes.forEach((node) => {
|
|
30
|
+
const nodeId = node[nodeField];
|
|
31
|
+
let count = 0;
|
|
32
|
+
[
|
|
33
|
+
neo4j.sources.get(nodeId),
|
|
34
|
+
neo4j.targets.get(nodeId)
|
|
35
|
+
].forEach((list, i) => {
|
|
36
|
+
if (!list) return;
|
|
37
|
+
let diffCount = 0;
|
|
38
|
+
let sameCount = 0;
|
|
39
|
+
list.forEach((edge) => {
|
|
40
|
+
const edgeId = edge[edgeField];
|
|
41
|
+
if (edge[sourceField] !== edge[targetField]) {
|
|
42
|
+
const anchor = anchors[edgeId] || (anchors[edgeId] = {});
|
|
43
|
+
anchor[i ? "target" : "source"] = count + diffCount++;
|
|
44
|
+
} else if (edgeId in anchors === false) {
|
|
45
|
+
anchors[edgeId] = {
|
|
46
|
+
source: sameCount,
|
|
47
|
+
target: sameCount++
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
count += diffCount;
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
this.#anchors = anchors;
|
|
55
|
+
}
|
|
56
|
+
calcPoints(edge, index, total, type) {
|
|
57
|
+
const { neo4j, config: { getBox, radOffsetRaidx = 0.3125 } } = this;
|
|
58
|
+
const source = getBox(edge[neo4j.sourceField]);
|
|
59
|
+
const target = getBox(edge[neo4j.targetField]);
|
|
60
|
+
const rad = Math.atan2(
|
|
61
|
+
(source.centerY - target.centerY) * type,
|
|
62
|
+
(source.centerX - target.centerX) * type
|
|
63
|
+
);
|
|
64
|
+
let point = rotateRad([0.5, 0], rad);
|
|
65
|
+
if (total !== 1) {
|
|
66
|
+
point = rotateRad(point, radOffsetRaidx * (total / 2 - 0.5 - index));
|
|
67
|
+
}
|
|
68
|
+
const [x, y] = point;
|
|
69
|
+
return [x + 0.5, 0.5 - y];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 获取指定节点上出入边连接点的坐标
|
|
73
|
+
*/
|
|
74
|
+
getPoints(id) {
|
|
75
|
+
const { neo4j } = this;
|
|
76
|
+
const { dirs, edgeField, sourceField, targetField } = neo4j;
|
|
77
|
+
const anchors = this.#anchors;
|
|
78
|
+
const points = [];
|
|
79
|
+
const caches = {};
|
|
80
|
+
neo4j.sources.get(id)?.forEach((edge) => {
|
|
81
|
+
const source = edge[sourceField];
|
|
82
|
+
const target = edge[targetField];
|
|
83
|
+
const direct = this.getDir(source, target);
|
|
84
|
+
const invert = this.getDir(target, source);
|
|
85
|
+
if (direct in caches) return;
|
|
86
|
+
const directs = dirs.get(direct) || [];
|
|
87
|
+
const inverts = dirs.get(invert) || [];
|
|
88
|
+
const directsLength = directs.length;
|
|
89
|
+
const invertsLength = inverts.length;
|
|
90
|
+
const total = directsLength + invertsLength;
|
|
91
|
+
directs.forEach((data, index) => {
|
|
92
|
+
points[anchors[data[edgeField]].source] = this.calcPoints(data, directsLength - 1 - index, total, -1);
|
|
93
|
+
});
|
|
94
|
+
caches[direct] = direct;
|
|
95
|
+
});
|
|
96
|
+
neo4j.targets.get(id)?.forEach((edge) => {
|
|
97
|
+
const source = edge[sourceField];
|
|
98
|
+
const target = edge[targetField];
|
|
99
|
+
const direct = this.getDir(source, target);
|
|
100
|
+
const invert = this.getDir(target, source);
|
|
101
|
+
if (direct in caches) return;
|
|
102
|
+
const directs = neo4j.dirs.get(direct) || [];
|
|
103
|
+
const inverts = neo4j.dirs.get(invert) || [];
|
|
104
|
+
const directsLength = directs.length;
|
|
105
|
+
const invertsLength = inverts.length;
|
|
106
|
+
const total = directsLength + invertsLength;
|
|
107
|
+
directs.forEach((data, index) => {
|
|
108
|
+
points[anchors[data[edgeField]].target] = this.calcPoints(data, invertsLength + index, total, 1);
|
|
109
|
+
});
|
|
110
|
+
caches[direct] = direct;
|
|
111
|
+
});
|
|
112
|
+
return points;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 查找边连接点的位置
|
|
116
|
+
*/
|
|
117
|
+
findAnchor(id) {
|
|
118
|
+
const anchor = this.#anchors[id];
|
|
119
|
+
if (!anchor) return null;
|
|
120
|
+
return {
|
|
121
|
+
source: anchor.source || 0,
|
|
122
|
+
target: anchor.target || 0
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 获取指定边控制点距离两端点连线的距离(可理解为控制边的弯曲程度)
|
|
127
|
+
* @description 返回值是一个相对值,需要乘以一个基数值(基数值应为负值,如-30)
|
|
128
|
+
*/
|
|
129
|
+
getOffset(id) {
|
|
130
|
+
const { neo4j } = this;
|
|
131
|
+
const edge = neo4j.edges.get(id);
|
|
132
|
+
if (!edge) return -1;
|
|
133
|
+
const { dirs, edgeField, sourceField, targetField } = neo4j;
|
|
134
|
+
const source = edge[sourceField];
|
|
135
|
+
const target = edge[targetField];
|
|
136
|
+
const directs = dirs.get(this.getDir(source, target)) || [];
|
|
137
|
+
const inverts = dirs.get(this.getDir(target, source)) || [];
|
|
138
|
+
let count = 0;
|
|
139
|
+
let index = 0;
|
|
140
|
+
[directs, inverts].some((list) => {
|
|
141
|
+
const result = list.some((data, i) => {
|
|
142
|
+
if (data[edgeField] === id) {
|
|
143
|
+
index = i + count;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
count += list.length;
|
|
148
|
+
return result;
|
|
149
|
+
});
|
|
150
|
+
const directsSize = directs.length;
|
|
151
|
+
const invertsSize = inverts.length;
|
|
152
|
+
const total = directsSize + invertsSize;
|
|
153
|
+
if (total === 1) return -1;
|
|
154
|
+
if (directsSize === 0 || invertsSize === 0) {
|
|
155
|
+
return total / 2 - index - 0.5;
|
|
156
|
+
} else {
|
|
157
|
+
return Math.abs(directsSize - invertsSize) * (directsSize >= invertsSize ? 1 : -1) / 2 - index - 0.5;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 清理数据
|
|
162
|
+
*/
|
|
163
|
+
clear() {
|
|
164
|
+
this.#anchors = {};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
Neo4jAhchors as default
|
|
169
|
+
};
|
package/dist/neo4j.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Equal } from '@type-challenges/utils';
|
|
2
|
+
import { GetGivenProps } from '@vope/types';
|
|
3
|
+
import { MemoryList } from './memory/list';
|
|
4
|
+
import { MemorySimple } from './memory/simple';
|
|
5
|
+
interface Config<INode extends object, IEdge extends object> {
|
|
6
|
+
/**
|
|
7
|
+
* 点主键字段
|
|
8
|
+
*/
|
|
9
|
+
nid: Extract<GetGivenProps<INode, string>, string>;
|
|
10
|
+
/**
|
|
11
|
+
* 边主键字段
|
|
12
|
+
*/
|
|
13
|
+
eid: Extract<GetGivenProps<IEdge, string>, string>;
|
|
14
|
+
/**
|
|
15
|
+
* (边)出点字段
|
|
16
|
+
*/
|
|
17
|
+
sourceKey: Extract<GetGivenProps<IEdge, string>, string>;
|
|
18
|
+
/**
|
|
19
|
+
* (边)入点字段
|
|
20
|
+
*/
|
|
21
|
+
targetKey: Extract<GetGivenProps<IEdge, string>, string>;
|
|
22
|
+
/**
|
|
23
|
+
* (边)方向键
|
|
24
|
+
*/
|
|
25
|
+
dir?(edge: IEdge): string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 图管理
|
|
29
|
+
*/
|
|
30
|
+
export default class Neo4j<INode extends object, IEdge extends object> {
|
|
31
|
+
#private;
|
|
32
|
+
get nodeField(): keyof INode;
|
|
33
|
+
get edgeField(): keyof IEdge;
|
|
34
|
+
get sourceField(): keyof IEdge;
|
|
35
|
+
get targetField(): keyof IEdge;
|
|
36
|
+
get dirKey(): (edge: IEdge) => string;
|
|
37
|
+
/**
|
|
38
|
+
* 点视图
|
|
39
|
+
*/
|
|
40
|
+
nodes: Shield<MemorySimple<INode, string>>;
|
|
41
|
+
/**
|
|
42
|
+
* 边视图
|
|
43
|
+
*/
|
|
44
|
+
edges: Shield<MemorySimple<IEdge, string>>;
|
|
45
|
+
/**
|
|
46
|
+
* (边)出点视图
|
|
47
|
+
*/
|
|
48
|
+
sources: Shield<MemoryList<IEdge, string>>;
|
|
49
|
+
/**
|
|
50
|
+
* (边)入点视图
|
|
51
|
+
*/
|
|
52
|
+
targets: Shield<MemoryList<IEdge, string>>;
|
|
53
|
+
/**
|
|
54
|
+
* (边)方向视图
|
|
55
|
+
*/
|
|
56
|
+
dirs: Shield<MemoryList<IEdge, string>>;
|
|
57
|
+
constructor(nodeList: INode[], edgeList: IEdge[], { nid, eid, sourceKey, targetKey, dir, }: Config<INode, IEdge>);
|
|
58
|
+
/**
|
|
59
|
+
* 点操作
|
|
60
|
+
*/
|
|
61
|
+
node(type: 'add', value: INode): void;
|
|
62
|
+
node(type: 'delete', value: string): IEdge[];
|
|
63
|
+
/**
|
|
64
|
+
* 边操作
|
|
65
|
+
*/
|
|
66
|
+
edge(type: 'add', value: IEdge): void;
|
|
67
|
+
edge(type: 'delete', value: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* 清理图管理数据
|
|
70
|
+
*/
|
|
71
|
+
clear(): void;
|
|
72
|
+
}
|
|
73
|
+
declare const shield_keys: {
|
|
74
|
+
push: number;
|
|
75
|
+
clear: number;
|
|
76
|
+
delete: number;
|
|
77
|
+
deleteType: number;
|
|
78
|
+
};
|
|
79
|
+
type Shield<T> = {
|
|
80
|
+
[P in Exclude<keyof T, keyof typeof shield_keys>]: T[P] extends (...args: infer A) => infer B ? Equal<[B], [T]> extends true ? (...args: A) => Shield<T> : T[P] : T[P];
|
|
81
|
+
};
|
|
82
|
+
export {};
|
package/dist/neo4j.mjs
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { hash8strings } from "./convert/strings";
|
|
2
|
+
import { MemoryList } from "./memory/list";
|
|
3
|
+
import { MemorySimple } from "./memory/simple";
|
|
4
|
+
class Neo4j {
|
|
5
|
+
#nPrimaryKey;
|
|
6
|
+
#ePrimaryKey;
|
|
7
|
+
#sourceKey;
|
|
8
|
+
#targetKey;
|
|
9
|
+
#dirKey;
|
|
10
|
+
#nodes;
|
|
11
|
+
#edges;
|
|
12
|
+
#sources;
|
|
13
|
+
#targets;
|
|
14
|
+
#dirs;
|
|
15
|
+
get nodeField() {
|
|
16
|
+
return this.#nPrimaryKey;
|
|
17
|
+
}
|
|
18
|
+
get edgeField() {
|
|
19
|
+
return this.#ePrimaryKey;
|
|
20
|
+
}
|
|
21
|
+
get sourceField() {
|
|
22
|
+
return this.#sourceKey;
|
|
23
|
+
}
|
|
24
|
+
get targetField() {
|
|
25
|
+
return this.#targetKey;
|
|
26
|
+
}
|
|
27
|
+
get dirKey() {
|
|
28
|
+
return this.#dirKey;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 点视图
|
|
32
|
+
*/
|
|
33
|
+
nodes;
|
|
34
|
+
/**
|
|
35
|
+
* 边视图
|
|
36
|
+
*/
|
|
37
|
+
edges;
|
|
38
|
+
/**
|
|
39
|
+
* (边)出点视图
|
|
40
|
+
*/
|
|
41
|
+
sources;
|
|
42
|
+
/**
|
|
43
|
+
* (边)入点视图
|
|
44
|
+
*/
|
|
45
|
+
targets;
|
|
46
|
+
/**
|
|
47
|
+
* (边)方向视图
|
|
48
|
+
*/
|
|
49
|
+
dirs;
|
|
50
|
+
constructor(nodeList, edgeList, {
|
|
51
|
+
nid,
|
|
52
|
+
eid,
|
|
53
|
+
sourceKey,
|
|
54
|
+
targetKey,
|
|
55
|
+
dir = (edge) => edge[sourceKey] + "|" + edge[targetKey]
|
|
56
|
+
}) {
|
|
57
|
+
shield(this, "nodes", this.#nodes = new MemorySimple(this.#nPrimaryKey = nid));
|
|
58
|
+
shield(this, "edges", this.#edges = new MemorySimple(this.#ePrimaryKey = eid));
|
|
59
|
+
shield(this, "sources", this.#sources = new MemoryList(this.#sourceKey = sourceKey));
|
|
60
|
+
shield(this, "targets", this.#targets = new MemoryList(this.#targetKey = targetKey));
|
|
61
|
+
shield(this, "dirs", this.#dirs = new MemoryList(this.#dirKey = dir));
|
|
62
|
+
nodeList.forEach((node) => this.node("add", node));
|
|
63
|
+
edgeList.forEach((edge) => this.edge("add", edge));
|
|
64
|
+
}
|
|
65
|
+
node(type, value) {
|
|
66
|
+
const nodes = this.#nodes;
|
|
67
|
+
if (type === "add") {
|
|
68
|
+
nodes.push(value);
|
|
69
|
+
} else if (type === "delete") {
|
|
70
|
+
const node = nodes.get(value);
|
|
71
|
+
if (!node) return [];
|
|
72
|
+
nodes.delete(node);
|
|
73
|
+
const id = node[this.#nPrimaryKey];
|
|
74
|
+
const sourceKey = this.#sourceKey;
|
|
75
|
+
const targetKey = this.#targetKey;
|
|
76
|
+
const edges = this.#edges;
|
|
77
|
+
const sources = this.#sources;
|
|
78
|
+
const targets = this.#targets;
|
|
79
|
+
const dirs = this.#dirs;
|
|
80
|
+
const list = [];
|
|
81
|
+
sources.get(id)?.reduce((_, edge) => {
|
|
82
|
+
edges.delete(edge);
|
|
83
|
+
targets.delete(edge);
|
|
84
|
+
edge[sourceKey] === edge[targetKey] || dirs.delete(edge);
|
|
85
|
+
list.push(edge);
|
|
86
|
+
return true;
|
|
87
|
+
}, false) && sources.deleteType(id);
|
|
88
|
+
targets.get(id)?.reduce((_, edge) => {
|
|
89
|
+
edges.delete(edge);
|
|
90
|
+
sources.delete(edge);
|
|
91
|
+
edge[sourceKey] === edge[targetKey] || dirs.delete(edge);
|
|
92
|
+
list.push(edge);
|
|
93
|
+
return true;
|
|
94
|
+
}, false) && targets.deleteType(id);
|
|
95
|
+
return list;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
edge(type, value) {
|
|
99
|
+
const sourceKey = this.#sourceKey;
|
|
100
|
+
const targetKey = this.#targetKey;
|
|
101
|
+
const edges = this.#edges;
|
|
102
|
+
const sources = this.#sources;
|
|
103
|
+
const targets = this.#targets;
|
|
104
|
+
const dirs = this.#dirs;
|
|
105
|
+
if (type === "add") {
|
|
106
|
+
const edge = value;
|
|
107
|
+
edges.push(edge);
|
|
108
|
+
sources.push(edge);
|
|
109
|
+
targets.push(edge);
|
|
110
|
+
edge[sourceKey] === edge[targetKey] || dirs.push(edge);
|
|
111
|
+
} else if (type === "delete") {
|
|
112
|
+
const edge = edges.get(value);
|
|
113
|
+
if (!edge) return false;
|
|
114
|
+
edges.delete(edge);
|
|
115
|
+
sources.delete(edge);
|
|
116
|
+
targets.delete(edge);
|
|
117
|
+
edge[sourceKey] === edge[targetKey] || dirs.delete(edge);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* 清理图管理数据
|
|
123
|
+
*/
|
|
124
|
+
clear() {
|
|
125
|
+
this.#nodes.clear();
|
|
126
|
+
this.#edges.clear();
|
|
127
|
+
this.#sources.clear();
|
|
128
|
+
this.#targets.clear();
|
|
129
|
+
this.#dirs.clear();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const shield_keys = hash8strings([
|
|
133
|
+
"push",
|
|
134
|
+
"delete",
|
|
135
|
+
"deleteType",
|
|
136
|
+
"clear"
|
|
137
|
+
]);
|
|
138
|
+
const shield = (obj, key, origin) => {
|
|
139
|
+
const proxy = new Proxy({}, {
|
|
140
|
+
get(target, p) {
|
|
141
|
+
if (p in shield_keys) return;
|
|
142
|
+
const value = origin[p];
|
|
143
|
+
if (typeof value === "function") {
|
|
144
|
+
return function(...args) {
|
|
145
|
+
const result = origin[p](...args);
|
|
146
|
+
return result === origin ? proxy : result;
|
|
147
|
+
};
|
|
148
|
+
} else {
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
Object.defineProperty(obj, key, {
|
|
154
|
+
get() {
|
|
155
|
+
return proxy;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
export {
|
|
160
|
+
Neo4j as default
|
|
161
|
+
};
|
package/dist/once.d.ts
ADDED
package/dist/once.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isNumber } from "lodash-es";
|
|
2
|
+
const pow = Math.floor(Math.log10(Number.MAX_SAFE_INTEGER));
|
|
3
|
+
const re_num = /^([-+]?)0*(\d+)(?:(n)|(?:\.(\d+))?(?:[Ee]([-+]?)(\d+))?)$/;
|
|
4
|
+
const parseNum = (num) => {
|
|
5
|
+
if (isNumber(num) || typeof num === "bigint") return num;
|
|
6
|
+
const match = num.match(re_num);
|
|
7
|
+
if (!match) return Number.NaN;
|
|
8
|
+
const [, valueSymbol, integer, bigint, decimal, powSymbol, powValue] = match;
|
|
9
|
+
if (bigint === "n") return BigInt(valueSymbol + integer);
|
|
10
|
+
const powSize = integer.length - 1 + (powValue ? powSymbol === "-" ? -powValue : +powValue : 0);
|
|
11
|
+
if (powSize < pow || powSize === pow && +integer.slice(0, -1) < Number.MAX_SAFE_INTEGER / 10) return +num;
|
|
12
|
+
try {
|
|
13
|
+
const bigValue = BigInt(integer.slice(0, powSize + 1).padEnd(powSize + 1, "0"));
|
|
14
|
+
let smallValue;
|
|
15
|
+
if (decimal && powValue && powSymbol !== "-") {
|
|
16
|
+
const powNum = +powValue;
|
|
17
|
+
const effectDecimal = decimal.slice(0, Math.min(pow, powNum));
|
|
18
|
+
const tinyValue = decimal.length > pow && powNum > pow ? BigInt(+decimal.slice(pow, powNum)) * BigInt(10 ** Math.max(powNum - decimal.length, 0)) : BigInt(0);
|
|
19
|
+
smallValue = BigInt(effectDecimal) * BigInt(10 ** (powNum - effectDecimal.length)) + tinyValue;
|
|
20
|
+
} else {
|
|
21
|
+
smallValue = BigInt(0);
|
|
22
|
+
}
|
|
23
|
+
const value = bigValue + smallValue;
|
|
24
|
+
return valueSymbol === "-" ? value * BigInt(-1) : value;
|
|
25
|
+
} catch {
|
|
26
|
+
return Number.NaN;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
parseNum
|
|
31
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const ERROR_MESSAGE = {
|
|
2
|
+
INT: "\u53C2\u6570\u5FC5\u987B\u662F\u6574\u6570",
|
|
3
|
+
MIN: "\u591A\u4E2A2\u7684\u6B63\u6574\u6570\u5E42(\u4E24\u4E24\u4E0D\u76F8\u7B49)\u4E4B\u548C\u5FC5\u5B9A\u5927\u4E8E\u7B49\u4E8E1"
|
|
4
|
+
};
|
|
5
|
+
const deconPowersSum = (sum, sort) => {
|
|
6
|
+
if (sum < 1) {
|
|
7
|
+
throw new Error(ERROR_MESSAGE.MIN);
|
|
8
|
+
} else if (sum !== Math.floor(sum)) {
|
|
9
|
+
throw new Error(ERROR_MESSAGE.INT);
|
|
10
|
+
}
|
|
11
|
+
const list = [];
|
|
12
|
+
let cache = sum;
|
|
13
|
+
while (cache) {
|
|
14
|
+
const power = Math.log2(cache) ^ 0;
|
|
15
|
+
list.push(power);
|
|
16
|
+
cache -= Math.pow(2, power);
|
|
17
|
+
}
|
|
18
|
+
return sort === "asc" ? list.reverse() : list;
|
|
19
|
+
};
|
|
20
|
+
export {
|
|
21
|
+
deconPowersSum
|
|
22
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const rotateRad = (from, rad, visit = [0, 0]) => {
|
|
2
|
+
const x = from[0] - visit[0];
|
|
3
|
+
const y = from[1] - visit[1];
|
|
4
|
+
return [
|
|
5
|
+
x * Math.cos(rad) + y * Math.sin(rad) + visit[0],
|
|
6
|
+
y * Math.cos(rad) - x * Math.sin(rad) + visit[1]
|
|
7
|
+
];
|
|
8
|
+
};
|
|
9
|
+
export {
|
|
10
|
+
rotateRad
|
|
11
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Equal } from '@type-challenges/utils';
|
|
2
|
+
import { UnionToTuple } from '@vope/types';
|
|
3
|
+
type NativeMap = {
|
|
4
|
+
string: string;
|
|
5
|
+
boolean: boolean;
|
|
6
|
+
number: number;
|
|
7
|
+
bigint: bigint;
|
|
8
|
+
date: Date;
|
|
9
|
+
regexp: RegExp;
|
|
10
|
+
null: null;
|
|
11
|
+
};
|
|
12
|
+
type NativeValue = keyof NativeMap;
|
|
13
|
+
interface AccessorValue<T = any> {
|
|
14
|
+
cube(text: string): T;
|
|
15
|
+
flat(value: T): string;
|
|
16
|
+
}
|
|
17
|
+
type NativeUnion = UnionToTuple<{
|
|
18
|
+
[P in NativeValue]: [NativeMap[P], P];
|
|
19
|
+
}[NativeValue]>;
|
|
20
|
+
type Signal<T, U extends any[] = NativeUnion> = U extends [infer A1, ...infer A2] ? A1 extends [infer V, infer K] ? Equal<T, V> extends true ? K : Signal<T, A2> : Signal<T, A2> : never;
|
|
21
|
+
/**
|
|
22
|
+
* 转换套件类型
|
|
23
|
+
*/
|
|
24
|
+
export type Serializes<T extends object> = {
|
|
25
|
+
[P in keyof T & string]: Signal<T[P]> | AccessorValue<T[P]>;
|
|
26
|
+
};
|
|
27
|
+
type Cube<T> = [T] extends [NativeValue] ? NativeMap[T] : [T] extends [AccessorValue<infer B>] ? B : never;
|
|
28
|
+
type Cubes<T extends object, S extends Serializes<T>> = {
|
|
29
|
+
[P in Extract<keyof T, keyof S> & string]: Cube<S[P]>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* 将URL查询参数转换成(复杂)对象
|
|
33
|
+
* @param text URL查询参数字符串
|
|
34
|
+
* @param serializes 转换套件
|
|
35
|
+
*/
|
|
36
|
+
export declare const cubeURLParams: <T extends object, S extends Serializes<T>>(text: string, serializes: S) => Cubes<T, S>;
|
|
37
|
+
/**
|
|
38
|
+
* 将(复杂)对象转换成URL查询参数
|
|
39
|
+
* @param data 数据
|
|
40
|
+
* @param serializes 转换套件
|
|
41
|
+
*/
|
|
42
|
+
export declare const flatURLParams: <T extends object, S extends Serializes<T>>(data: T, serializes: S) => string;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isString } from "lodash-es";
|
|
2
|
+
import { isKey } from "../is/key";
|
|
3
|
+
const cubes = {
|
|
4
|
+
string: (text) => text,
|
|
5
|
+
boolean: (text) => text === "true",
|
|
6
|
+
number: (text) => Number(text),
|
|
7
|
+
bigint: (text) => BigInt(text),
|
|
8
|
+
date: (text) => new Date(text),
|
|
9
|
+
regexp: (text) => new RegExp(text),
|
|
10
|
+
null: () => null
|
|
11
|
+
};
|
|
12
|
+
const flats = {
|
|
13
|
+
string: (data) => flatEncode(data),
|
|
14
|
+
boolean: (data) => `${data}`,
|
|
15
|
+
number: (data) => `${data}`,
|
|
16
|
+
bigint: (data) => `${data}`,
|
|
17
|
+
date: (data) => data.toJSON(),
|
|
18
|
+
regexp: (data) => flatEncode(data.source),
|
|
19
|
+
null: () => "null"
|
|
20
|
+
};
|
|
21
|
+
const cubeURLParams = (text, serializes) => {
|
|
22
|
+
const params = new URLSearchParams(text);
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const [key, value] of params) {
|
|
25
|
+
const serialize = serializes[key];
|
|
26
|
+
if (!serialize) continue;
|
|
27
|
+
if (isString(serialize) && isKey(serialize, cubes)) {
|
|
28
|
+
result[key] = cubes[serialize](value);
|
|
29
|
+
} else {
|
|
30
|
+
result[key] = serialize.cube(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
const re_flat = /\+/g;
|
|
36
|
+
const flatEncode = (text) => text.replace(re_flat, () => "%2B");
|
|
37
|
+
const flatURLParams = (data, serializes) => {
|
|
38
|
+
const params = new URLSearchParams();
|
|
39
|
+
for (const key in data) {
|
|
40
|
+
const value = data[key];
|
|
41
|
+
const serialize = serializes[key];
|
|
42
|
+
if (!serialize) continue;
|
|
43
|
+
params.append(
|
|
44
|
+
key,
|
|
45
|
+
isString(serialize) && isKey(serialize, flats) ? flats[serialize](value) : serialize.flat(value)
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return params.toString();
|
|
49
|
+
};
|
|
50
|
+
export {
|
|
51
|
+
cubeURLParams,
|
|
52
|
+
flatURLParams
|
|
53
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface ICrypto<From, To> {
|
|
2
|
+
encrypt(plain: From): To | Promise<To>;
|
|
3
|
+
decrypt(cipher: To): From | Promise<From>;
|
|
4
|
+
}
|
|
5
|
+
interface Options<From, To> {
|
|
6
|
+
/** 存储名称 */
|
|
7
|
+
name: string;
|
|
8
|
+
/** 存储认证 */
|
|
9
|
+
token?: string;
|
|
10
|
+
/** 存储期限 */
|
|
11
|
+
expire?: number;
|
|
12
|
+
/** 存储加密 */
|
|
13
|
+
crypto: ICrypto<From, To>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 离线存储
|
|
17
|
+
*/
|
|
18
|
+
export declare class OfflineStorage<From, To> {
|
|
19
|
+
#private;
|
|
20
|
+
get size(): number;
|
|
21
|
+
get mounted(): boolean;
|
|
22
|
+
constructor({ name, expire: newExpire, token: newToken, crypto, }: Options<From, To>);
|
|
23
|
+
ready(): Promise<this>;
|
|
24
|
+
/**
|
|
25
|
+
* 校验存储是否过期
|
|
26
|
+
*/
|
|
27
|
+
validateExpire(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* 校验
|
|
30
|
+
*/
|
|
31
|
+
validate(callback: (error?: Error) => void, expireMessage?: string): void;
|
|
32
|
+
/**
|
|
33
|
+
* 插入数据
|
|
34
|
+
*/
|
|
35
|
+
push(data: From): Promise<number>;
|
|
36
|
+
/**
|
|
37
|
+
* 修改数据
|
|
38
|
+
*/
|
|
39
|
+
update(index: number, data: From): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* 获取数据
|
|
42
|
+
*/
|
|
43
|
+
get(index: number): Promise<From | null>;
|
|
44
|
+
/**
|
|
45
|
+
* 清理存储
|
|
46
|
+
*/
|
|
47
|
+
clear(): Promise<void>;
|
|
48
|
+
static default<T>(options: string | Omit<Options<T, T>, 'crypto'>): OfflineStorage<T, T>;
|
|
49
|
+
static clear(token?: string, callback?: (name: string) => boolean): Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export {};
|