core-mb 1.0.0 → 1.0.2
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/.github/workflows/node.js.yml +58 -0
- package/.nyc_output/0393f58b-d3a0-4d83-8010-334fc96e8c86.json +1 -0
- package/.nyc_output/0edf14d3-019a-4204-aae9-8d7d2491500b.json +1 -0
- package/.nyc_output/1db7cb73-4e51-46c0-96e8-3d1edd65f98c.json +1 -0
- package/.nyc_output/29ead10f-a723-4574-aeaf-5eff2ebcafac.json +1 -0
- package/.nyc_output/30473bab-10b9-4d55-8f30-42cbd631a50e.json +1 -0
- package/.nyc_output/4514ee29-1cb6-4243-abab-937ae44e87fe.json +1 -0
- package/.nyc_output/5268e9ea-7320-41e0-8dbf-37139a2b07e9.json +1 -0
- package/.nyc_output/581a75aa-21fc-470f-a998-ad9752b568ff.json +1 -0
- package/.nyc_output/6492905d-a035-44ac-b40d-84d04d64d3c2.json +1 -0
- package/.nyc_output/67ba5e3c-ca1d-4dbf-9155-6a154788cb55.json +1 -0
- package/.nyc_output/688e0703-cbfb-4f94-ac42-66472ac00a0c.json +1 -0
- package/.nyc_output/6c1e2427-a36b-407d-96d2-929a885e565d.json +1 -0
- package/.nyc_output/781a9e98-6dff-42dc-9bb2-126b65619cf3.json +1 -0
- package/.nyc_output/960ffee6-798c-4670-b1fa-39f6cebaa70b.json +1 -0
- package/.nyc_output/9661b441-490d-4793-881a-570493cf4d77.json +1 -0
- package/.nyc_output/9fe3622e-5b2a-42b2-a7ec-6f42c052afc9.json +1 -0
- package/.nyc_output/c37e92ff-6103-4b4b-be8e-2e23adc44ba1.json +1 -0
- package/.nyc_output/cfc973a7-b63b-4ed5-a568-019c4813486f.json +1 -0
- package/.nyc_output/d4490352-b4a2-45e0-beb3-a146203ce7a1.json +1 -0
- package/.nyc_output/da65eb21-2244-42c2-a24a-136a49caa10b.json +1 -0
- package/.nyc_output/e58bd293-d9b2-4a7a-bd45-b6f603743e81.json +1 -0
- package/.nyc_output/e5ef7a91-bcbd-46a0-848e-423e6aec9090.json +1 -0
- package/.nyc_output/f73cc576-f3eb-476a-bb88-9030aaaca351.json +1 -0
- package/.nyc_output/processinfo/0393f58b-d3a0-4d83-8010-334fc96e8c86.json +1 -0
- package/.nyc_output/processinfo/0edf14d3-019a-4204-aae9-8d7d2491500b.json +1 -0
- package/.nyc_output/processinfo/1db7cb73-4e51-46c0-96e8-3d1edd65f98c.json +1 -0
- package/.nyc_output/processinfo/29ead10f-a723-4574-aeaf-5eff2ebcafac.json +1 -0
- package/.nyc_output/processinfo/30473bab-10b9-4d55-8f30-42cbd631a50e.json +1 -0
- package/.nyc_output/processinfo/4514ee29-1cb6-4243-abab-937ae44e87fe.json +1 -0
- package/.nyc_output/processinfo/5268e9ea-7320-41e0-8dbf-37139a2b07e9.json +1 -0
- package/.nyc_output/processinfo/581a75aa-21fc-470f-a998-ad9752b568ff.json +1 -0
- package/.nyc_output/processinfo/6492905d-a035-44ac-b40d-84d04d64d3c2.json +1 -0
- package/.nyc_output/processinfo/67ba5e3c-ca1d-4dbf-9155-6a154788cb55.json +1 -0
- package/.nyc_output/processinfo/688e0703-cbfb-4f94-ac42-66472ac00a0c.json +1 -0
- package/.nyc_output/processinfo/6c1e2427-a36b-407d-96d2-929a885e565d.json +1 -0
- package/.nyc_output/processinfo/781a9e98-6dff-42dc-9bb2-126b65619cf3.json +1 -0
- package/.nyc_output/processinfo/960ffee6-798c-4670-b1fa-39f6cebaa70b.json +1 -0
- package/.nyc_output/processinfo/9661b441-490d-4793-881a-570493cf4d77.json +1 -0
- package/.nyc_output/processinfo/9fe3622e-5b2a-42b2-a7ec-6f42c052afc9.json +1 -0
- package/.nyc_output/processinfo/c37e92ff-6103-4b4b-be8e-2e23adc44ba1.json +1 -0
- package/.nyc_output/processinfo/cfc973a7-b63b-4ed5-a568-019c4813486f.json +1 -0
- package/.nyc_output/processinfo/d4490352-b4a2-45e0-beb3-a146203ce7a1.json +1 -0
- package/.nyc_output/processinfo/da65eb21-2244-42c2-a24a-136a49caa10b.json +1 -0
- package/.nyc_output/processinfo/e58bd293-d9b2-4a7a-bd45-b6f603743e81.json +1 -0
- package/.nyc_output/processinfo/e5ef7a91-bcbd-46a0-848e-423e6aec9090.json +1 -0
- package/.nyc_output/processinfo/f73cc576-f3eb-476a-bb88-9030aaaca351.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/README.md +12 -4
- package/__unitest__/phone.number.crypto.spec.ts +9 -9
- package/coverage/config.ts.html +178 -0
- package/coverage/index.html +31 -16
- package/coverage/lcov-report/config.ts.html +178 -0
- package/coverage/lcov-report/index.html +31 -16
- package/coverage/lcov-report/phone.number.helper.ts.html +1 -1
- package/coverage/lcov-report/security.helper.ts.html +19 -46
- package/coverage/lcov.info +58 -36
- package/coverage/phone.number.helper.ts.html +1 -1
- package/coverage/security.helper.ts.html +19 -46
- package/dist/config.d.ts +12 -0
- package/dist/config.js +24 -0
- package/dist/date.helper.d.ts +1 -0
- package/dist/date.helper.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/security.helper.d.ts +6 -2
- package/dist/security.helper.js +10 -14
- package/dist/validation.helper.d.ts +6 -0
- package/dist/validation.helper.js +32 -0
- package/jest.config.js +2 -1
- package/jest.setup.ts +8 -0
- package/package.json +6 -2
- package/src/config.ts +31 -0
- package/src/date.helper.ts +3 -0
- package/src/index.ts +1 -0
- package/src/security.helper.ts +9 -18
- package/src/validation.helper.ts +36 -0
- package/test-report.html +1 -1
- package/src/aes.helper.ts +0 -101
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for config.ts</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="index.html">All files</a> config.ts</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">80% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>8/10</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">50% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>2/4</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">100% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>3/3</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">80% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>8/10</span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
<p class="quiet">
|
|
55
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
+
</p>
|
|
57
|
+
<template id="filterTemplate">
|
|
58
|
+
<div class="quiet">
|
|
59
|
+
Filter:
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
<div class='status-line high'></div>
|
|
65
|
+
<pre><table class="coverage">
|
|
66
|
+
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
+
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
+
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
+
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
+
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
+
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
+
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
+
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
+
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
+
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
+
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
+
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
+
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
+
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
+
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
+
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
+
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
+
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
+
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
+
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
+
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
+
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
+
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
+
<a name='L25'></a><a href='#L25'>25</a>
|
|
91
|
+
<a name='L26'></a><a href='#L26'>26</a>
|
|
92
|
+
<a name='L27'></a><a href='#L27'>27</a>
|
|
93
|
+
<a name='L28'></a><a href='#L28'>28</a>
|
|
94
|
+
<a name='L29'></a><a href='#L29'>29</a>
|
|
95
|
+
<a name='L30'></a><a href='#L30'>30</a>
|
|
96
|
+
<a name='L31'></a><a href='#L31'>31</a>
|
|
97
|
+
<a name='L32'></a><a href='#L32'>32</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
98
|
+
<span class="cline-any cline-neutral"> </span>
|
|
99
|
+
<span class="cline-any cline-neutral"> </span>
|
|
100
|
+
<span class="cline-any cline-neutral"> </span>
|
|
101
|
+
<span class="cline-any cline-neutral"> </span>
|
|
102
|
+
<span class="cline-any cline-yes">2x</span>
|
|
103
|
+
<span class="cline-any cline-neutral"> </span>
|
|
104
|
+
<span class="cline-any cline-neutral"> </span>
|
|
105
|
+
<span class="cline-any cline-neutral"> </span>
|
|
106
|
+
<span class="cline-any cline-neutral"> </span>
|
|
107
|
+
<span class="cline-any cline-neutral"> </span>
|
|
108
|
+
<span class="cline-any cline-yes">2x</span>
|
|
109
|
+
<span class="cline-any cline-yes">2x</span>
|
|
110
|
+
<span class="cline-any cline-neutral"> </span>
|
|
111
|
+
<span class="cline-any cline-neutral"> </span>
|
|
112
|
+
<span class="cline-any cline-neutral"> </span>
|
|
113
|
+
<span class="cline-any cline-yes">2x</span>
|
|
114
|
+
<span class="cline-any cline-no"> </span>
|
|
115
|
+
<span class="cline-any cline-neutral"> </span>
|
|
116
|
+
<span class="cline-any cline-yes">2x</span>
|
|
117
|
+
<span class="cline-any cline-yes">2x</span>
|
|
118
|
+
<span class="cline-any cline-neutral"> </span>
|
|
119
|
+
<span class="cline-any cline-neutral"> </span>
|
|
120
|
+
<span class="cline-any cline-neutral"> </span>
|
|
121
|
+
<span class="cline-any cline-neutral"> </span>
|
|
122
|
+
<span class="cline-any cline-yes">1x</span>
|
|
123
|
+
<span class="cline-any cline-no"> </span>
|
|
124
|
+
<span class="cline-any cline-neutral"> </span>
|
|
125
|
+
<span class="cline-any cline-yes">1x</span>
|
|
126
|
+
<span class="cline-any cline-neutral"> </span>
|
|
127
|
+
<span class="cline-any cline-neutral"> </span>
|
|
128
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">export interface ConfigProperties {
|
|
129
|
+
aesKey: string;
|
|
130
|
+
hmacKey: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export class CoreMBConfig {
|
|
134
|
+
private static instance: CoreMBConfig;
|
|
135
|
+
public readonly aesKey: Buffer;
|
|
136
|
+
public readonly hmacKey: Buffer;
|
|
137
|
+
|
|
138
|
+
private constructor(props: ConfigProperties) {
|
|
139
|
+
this.aesKey = Buffer.from(props.aesKey, "base64");
|
|
140
|
+
this.hmacKey = Buffer.from(props.hmacKey, "base64");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public static initialize(props: ConfigProperties): CoreMBConfig {
|
|
144
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>if (CoreMBConfig.instance) {
|
|
145
|
+
<span class="cstat-no" title="statement not covered" > throw new Error("CoreMBConfig has already been initialized");</span>
|
|
146
|
+
}
|
|
147
|
+
CoreMBConfig.instance = new CoreMBConfig(props);
|
|
148
|
+
return CoreMBConfig.instance;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Access the singleton instance
|
|
152
|
+
public static getInstance(): CoreMBConfig {
|
|
153
|
+
<span class="missing-if-branch" title="if path not taken" >I</span>if (!CoreMBConfig.instance) {
|
|
154
|
+
<span class="cstat-no" title="statement not covered" > throw new Error("CoreMBConfig has not been initialized yet");</span>
|
|
155
|
+
}
|
|
156
|
+
return CoreMBConfig.instance;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
</pre></td></tr></table></pre>
|
|
160
|
+
|
|
161
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
162
|
+
</div><!-- /wrapper -->
|
|
163
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
164
|
+
Code coverage generated by
|
|
165
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
166
|
+
at 2025-08-23T08:06:17.175Z
|
|
167
|
+
</div>
|
|
168
|
+
<script src="prettify.js"></script>
|
|
169
|
+
<script>
|
|
170
|
+
window.onload = function () {
|
|
171
|
+
prettyPrint();
|
|
172
|
+
};
|
|
173
|
+
</script>
|
|
174
|
+
<script src="sorter.js"></script>
|
|
175
|
+
<script src="block-navigation.js"></script>
|
|
176
|
+
</body>
|
|
177
|
+
</html>
|
|
178
|
+
|
|
@@ -23,30 +23,30 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">95.12% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>39/41</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">75% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>6/8</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
<div class='fl pad1y space-right2'>
|
|
40
40
|
<span class="strong">100% </span>
|
|
41
41
|
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>
|
|
42
|
+
<span class='fraction'>7/7</span>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">95% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>38/40</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -79,6 +79,21 @@
|
|
|
79
79
|
</tr>
|
|
80
80
|
</thead>
|
|
81
81
|
<tbody><tr>
|
|
82
|
+
<td class="file high" data-value="config.ts"><a href="config.ts.html">config.ts</a></td>
|
|
83
|
+
<td data-value="80" class="pic high">
|
|
84
|
+
<div class="chart"><div class="cover-fill" style="width: 80%"></div><div class="cover-empty" style="width: 20%"></div></div>
|
|
85
|
+
</td>
|
|
86
|
+
<td data-value="80" class="pct high">80%</td>
|
|
87
|
+
<td data-value="10" class="abs high">8/10</td>
|
|
88
|
+
<td data-value="50" class="pct medium">50%</td>
|
|
89
|
+
<td data-value="4" class="abs medium">2/4</td>
|
|
90
|
+
<td data-value="100" class="pct high">100%</td>
|
|
91
|
+
<td data-value="3" class="abs high">3/3</td>
|
|
92
|
+
<td data-value="80" class="pct high">80%</td>
|
|
93
|
+
<td data-value="10" class="abs high">8/10</td>
|
|
94
|
+
</tr>
|
|
95
|
+
|
|
96
|
+
<tr>
|
|
82
97
|
<td class="file high" data-value="phone.number.helper.ts"><a href="phone.number.helper.ts.html">phone.number.helper.ts</a></td>
|
|
83
98
|
<td data-value="100" class="pic high">
|
|
84
99
|
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
@@ -95,17 +110,17 @@
|
|
|
95
110
|
|
|
96
111
|
<tr>
|
|
97
112
|
<td class="file high" data-value="security.helper.ts"><a href="security.helper.ts.html">security.helper.ts</a></td>
|
|
98
|
-
<td data-value="
|
|
99
|
-
<div class="chart"><div class="cover-fill" style="width:
|
|
113
|
+
<td data-value="100" class="pic high">
|
|
114
|
+
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
100
115
|
</td>
|
|
101
|
-
<td data-value="
|
|
102
|
-
<td data-value="
|
|
103
|
-
<td data-value="
|
|
104
|
-
<td data-value="
|
|
116
|
+
<td data-value="100" class="pct high">100%</td>
|
|
117
|
+
<td data-value="24" class="abs high">24/24</td>
|
|
118
|
+
<td data-value="100" class="pct high">100%</td>
|
|
119
|
+
<td data-value="0" class="abs high">0/0</td>
|
|
105
120
|
<td data-value="100" class="pct high">100%</td>
|
|
106
121
|
<td data-value="3" class="abs high">3/3</td>
|
|
107
|
-
<td data-value="
|
|
108
|
-
<td data-value="
|
|
122
|
+
<td data-value="100" class="pct high">100%</td>
|
|
123
|
+
<td data-value="24" class="abs high">24/24</td>
|
|
109
124
|
</tr>
|
|
110
125
|
|
|
111
126
|
</tbody>
|
|
@@ -116,7 +131,7 @@
|
|
|
116
131
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
132
|
Code coverage generated by
|
|
118
133
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2025-08-
|
|
134
|
+
at 2025-08-23T08:06:17.175Z
|
|
120
135
|
</div>
|
|
121
136
|
<script src="prettify.js"></script>
|
|
122
137
|
<script>
|
|
@@ -109,7 +109,7 @@ export function normalize(phoneRaw: string): string {
|
|
|
109
109
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
110
110
|
Code coverage generated by
|
|
111
111
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
112
|
-
at 2025-08-
|
|
112
|
+
at 2025-08-23T08:06:17.175Z
|
|
113
113
|
</div>
|
|
114
114
|
<script src="prettify.js"></script>
|
|
115
115
|
<script>
|
|
@@ -23,16 +23,16 @@
|
|
|
23
23
|
<div class='clearfix'>
|
|
24
24
|
|
|
25
25
|
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">
|
|
26
|
+
<span class="strong">100% </span>
|
|
27
27
|
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>
|
|
28
|
+
<span class='fraction'>24/24</span>
|
|
29
29
|
</div>
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">
|
|
33
|
+
<span class="strong">100% </span>
|
|
34
34
|
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>
|
|
35
|
+
<span class='fraction'>0/0</span>
|
|
36
36
|
</div>
|
|
37
37
|
|
|
38
38
|
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">
|
|
47
|
+
<span class="strong">100% </span>
|
|
48
48
|
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>
|
|
49
|
+
<span class='fraction'>24/24</span>
|
|
50
50
|
</div>
|
|
51
51
|
|
|
52
52
|
|
|
@@ -142,18 +142,11 @@
|
|
|
142
142
|
<a name='L77'></a><a href='#L77'>77</a>
|
|
143
143
|
<a name='L78'></a><a href='#L78'>78</a>
|
|
144
144
|
<a name='L79'></a><a href='#L79'>79</a>
|
|
145
|
-
<a name='L80'></a><a href='#L80'>80</a>
|
|
146
|
-
<
|
|
147
|
-
<a name='L82'></a><a href='#L82'>82</a>
|
|
148
|
-
<a name='L83'></a><a href='#L83'>83</a>
|
|
149
|
-
<a name='L84'></a><a href='#L84'>84</a>
|
|
150
|
-
<a name='L85'></a><a href='#L85'>85</a>
|
|
151
|
-
<a name='L86'></a><a href='#L86'>86</a>
|
|
152
|
-
<a name='L87'></a><a href='#L87'>87</a>
|
|
153
|
-
<a name='L88'></a><a href='#L88'>88</a>
|
|
154
|
-
<a name='L89'></a><a href='#L89'>89</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
145
|
+
<a name='L80'></a><a href='#L80'>80</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
146
|
+
<span class="cline-any cline-yes">1x</span>
|
|
155
147
|
<span class="cline-any cline-yes">1x</span>
|
|
156
148
|
<span class="cline-any cline-neutral"> </span>
|
|
149
|
+
<span class="cline-any cline-yes">1x</span>
|
|
157
150
|
<span class="cline-any cline-neutral"> </span>
|
|
158
151
|
<span class="cline-any cline-neutral"> </span>
|
|
159
152
|
<span class="cline-any cline-neutral"> </span>
|
|
@@ -162,22 +155,11 @@
|
|
|
162
155
|
<span class="cline-any cline-neutral"> </span>
|
|
163
156
|
<span class="cline-any cline-neutral"> </span>
|
|
164
157
|
<span class="cline-any cline-neutral"> </span>
|
|
165
|
-
<span class="cline-any cline-yes">1x</span>
|
|
166
|
-
<span class="cline-any cline-yes">1x</span>
|
|
167
|
-
<span class="cline-any cline-neutral"> </span>
|
|
168
|
-
<span class="cline-any cline-yes">1x</span>
|
|
169
|
-
<span class="cline-any cline-no"> </span>
|
|
170
158
|
<span class="cline-any cline-neutral"> </span>
|
|
171
159
|
<span class="cline-any cline-neutral"> </span>
|
|
172
160
|
<span class="cline-any cline-neutral"> </span>
|
|
173
161
|
<span class="cline-any cline-neutral"> </span>
|
|
174
162
|
<span class="cline-any cline-yes">1x</span>
|
|
175
|
-
<span class="cline-any cline-yes">1x</span>
|
|
176
|
-
<span class="cline-any cline-neutral"> </span>
|
|
177
|
-
<span class="cline-any cline-neutral"> </span>
|
|
178
|
-
<span class="cline-any cline-neutral"> </span>
|
|
179
|
-
<span class="cline-any cline-neutral"> </span>
|
|
180
|
-
<span class="cline-any cline-neutral"> </span>
|
|
181
163
|
<span class="cline-any cline-yes">8x</span>
|
|
182
164
|
<span class="cline-any cline-yes">8x</span>
|
|
183
165
|
<span class="cline-any cline-yes">8x</span>
|
|
@@ -240,8 +222,11 @@
|
|
|
240
222
|
<span class="cline-any cline-yes">4x</span>
|
|
241
223
|
<span class="cline-any cline-neutral"> </span>
|
|
242
224
|
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import * as crypto from "crypto";
|
|
225
|
+
import { CoreMBConfig } from "./config";
|
|
243
226
|
import { normalize } from "./phone.number.helper";
|
|
244
227
|
|
|
228
|
+
const config = CoreMBConfig.getInstance();
|
|
229
|
+
|
|
245
230
|
export type PhoneCipherRecord = {
|
|
246
231
|
// Base64 strings suitable for storage in text columns
|
|
247
232
|
ciphertext: string; // Encrypted phone number
|
|
@@ -250,24 +235,12 @@ export type PhoneCipherRecord = {
|
|
|
250
235
|
hmacIndex: string; // HMAC-SHA256(phoneNormalized) for search/dedup
|
|
251
236
|
};
|
|
252
237
|
|
|
253
|
-
const aesKeyB64 = process.env.PHONE_AES_KEY;
|
|
254
|
-
const hmacKeyB64 = process.env.PHONE_HMAC_KEY;
|
|
255
|
-
|
|
256
|
-
<span class="missing-if-branch" title="if path not taken" >I</span>if (!aesKeyB64 || !hmacKeyB64) {
|
|
257
|
-
<span class="cstat-no" title="statement not covered" > throw new Error(</span>
|
|
258
|
-
"PHONE_AES_KEY and PHONE_HMAC_KEY must be set (base64-encoded)."
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const aesKey = Buffer.from(aesKeyB64, "base64");
|
|
263
|
-
const hmacKey = Buffer.from(hmacKeyB64, "base64");
|
|
264
|
-
|
|
265
238
|
/** Create an HMAC index for lookups without revealing the number.
|
|
266
239
|
* Store this alongside the encrypted data and index it in the DB.
|
|
267
240
|
*/
|
|
268
|
-
function hmacIndex(phoneRaw: string): string {
|
|
241
|
+
export function hmacIndex(phoneRaw: string): string {
|
|
269
242
|
const normalized = normalize(phoneRaw);
|
|
270
|
-
const h = crypto.createHmac("sha256", hmacKey);
|
|
243
|
+
const h = crypto.createHmac("sha256", config.hmacKey);
|
|
271
244
|
h.update(normalized, "utf8");
|
|
272
245
|
return h.digest("base64");
|
|
273
246
|
}
|
|
@@ -275,7 +248,7 @@ function hmacIndex(phoneRaw: string): string {
|
|
|
275
248
|
/** Encrypt a phone number using AES-256-GCM.
|
|
276
249
|
* Returns base64-encoded ciphertext, iv and authTag suitable for storage.
|
|
277
250
|
*/
|
|
278
|
-
export function
|
|
251
|
+
export function phoneEncrypt(
|
|
279
252
|
phoneRaw: string
|
|
280
253
|
): Omit<PhoneCipherRecord, "hmacIndex"> & { hmacIndex: string } {
|
|
281
254
|
const normalized = normalize(phoneRaw);
|
|
@@ -283,7 +256,7 @@ export function encrypt(
|
|
|
283
256
|
// 12-byte IV is recommended for GCM
|
|
284
257
|
const iv = crypto.randomBytes(12);
|
|
285
258
|
|
|
286
|
-
const cipher = crypto.createCipheriv("aes-256-gcm", aesKey, iv);
|
|
259
|
+
const cipher = crypto.createCipheriv("aes-256-gcm", config.aesKey, iv);
|
|
287
260
|
|
|
288
261
|
// Optional: bind additional data (AAD), e.g., tenant ID to prevent cross-tenant swaps
|
|
289
262
|
// cipher.setAAD(Buffer.from(tenantId, 'utf8'));
|
|
@@ -306,14 +279,14 @@ export function encrypt(
|
|
|
306
279
|
/** Decrypt a previously stored record. Throws if tampered.
|
|
307
280
|
* Returns the normalized phone string.
|
|
308
281
|
*/
|
|
309
|
-
export function
|
|
282
|
+
export function phoneDecrypt(
|
|
310
283
|
record: Pick<PhoneCipherRecord, "ciphertext" | "iv" | "authTag">
|
|
311
284
|
): string {
|
|
312
285
|
const iv = Buffer.from(record.iv, "base64");
|
|
313
286
|
const authTag = Buffer.from(record.authTag, "base64");
|
|
314
287
|
const ciphertext = Buffer.from(record.ciphertext, "base64");
|
|
315
288
|
|
|
316
|
-
const decipher = crypto.createDecipheriv("aes-256-gcm", aesKey, iv);
|
|
289
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", config.aesKey, iv);
|
|
317
290
|
|
|
318
291
|
// If you used setAAD on encrypt, you MUST set the same AAD here
|
|
319
292
|
// decipher.setAAD(Buffer.from(tenantId, 'utf8'));
|
|
@@ -334,7 +307,7 @@ export function decrypt(
|
|
|
334
307
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
335
308
|
Code coverage generated by
|
|
336
309
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
337
|
-
at 2025-08-
|
|
310
|
+
at 2025-08-23T08:06:17.175Z
|
|
338
311
|
</div>
|
|
339
312
|
<script src="prettify.js"></script>
|
|
340
313
|
<script>
|
package/coverage/lcov.info
CHANGED
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
TN:
|
|
2
|
+
SF:src/config.ts
|
|
3
|
+
FN:11,(anonymous_0)
|
|
4
|
+
FN:16,(anonymous_1)
|
|
5
|
+
FN:25,(anonymous_2)
|
|
6
|
+
FNF:3
|
|
7
|
+
FNH:3
|
|
8
|
+
FNDA:2,(anonymous_0)
|
|
9
|
+
FNDA:2,(anonymous_1)
|
|
10
|
+
FNDA:1,(anonymous_2)
|
|
11
|
+
DA:6,2
|
|
12
|
+
DA:12,2
|
|
13
|
+
DA:13,2
|
|
14
|
+
DA:17,2
|
|
15
|
+
DA:18,0
|
|
16
|
+
DA:20,2
|
|
17
|
+
DA:21,2
|
|
18
|
+
DA:26,1
|
|
19
|
+
DA:27,0
|
|
20
|
+
DA:29,1
|
|
21
|
+
LF:10
|
|
22
|
+
LH:8
|
|
23
|
+
BRDA:17,0,0,0
|
|
24
|
+
BRDA:17,0,1,2
|
|
25
|
+
BRDA:26,1,0,0
|
|
26
|
+
BRDA:26,1,1,1
|
|
27
|
+
BRF:4
|
|
28
|
+
BRH:2
|
|
29
|
+
end_of_record
|
|
30
|
+
TN:
|
|
2
31
|
SF:src/phone.number.helper.ts
|
|
3
32
|
FN:7,normalize
|
|
4
33
|
FNF:1
|
|
@@ -21,47 +50,40 @@ BRH:4
|
|
|
21
50
|
end_of_record
|
|
22
51
|
TN:
|
|
23
52
|
SF:src/security.helper.ts
|
|
24
|
-
FN:
|
|
25
|
-
FN:
|
|
26
|
-
FN:
|
|
53
|
+
FN:18,hmacIndex
|
|
54
|
+
FN:28,phoneEncrypt
|
|
55
|
+
FN:59,phoneDecrypt
|
|
27
56
|
FNF:3
|
|
28
57
|
FNH:3
|
|
29
58
|
FNDA:8,hmacIndex
|
|
30
|
-
FNDA:8,
|
|
31
|
-
FNDA:6,
|
|
59
|
+
FNDA:8,phoneEncrypt
|
|
60
|
+
FNDA:6,phoneDecrypt
|
|
32
61
|
DA:1,1
|
|
33
62
|
DA:2,1
|
|
34
|
-
DA:
|
|
35
|
-
DA:
|
|
36
|
-
DA:
|
|
37
|
-
DA:
|
|
38
|
-
DA:
|
|
39
|
-
DA:
|
|
40
|
-
DA:
|
|
41
|
-
DA:
|
|
42
|
-
DA:30,8
|
|
63
|
+
DA:3,1
|
|
64
|
+
DA:5,1
|
|
65
|
+
DA:18,1
|
|
66
|
+
DA:19,8
|
|
67
|
+
DA:20,8
|
|
68
|
+
DA:21,8
|
|
69
|
+
DA:22,8
|
|
70
|
+
DA:28,1
|
|
43
71
|
DA:31,8
|
|
44
|
-
DA:
|
|
45
|
-
DA:
|
|
46
|
-
DA:
|
|
47
|
-
DA:
|
|
48
|
-
DA:
|
|
49
|
-
DA:
|
|
50
|
-
DA:
|
|
51
|
-
DA:
|
|
72
|
+
DA:34,8
|
|
73
|
+
DA:36,8
|
|
74
|
+
DA:41,8
|
|
75
|
+
DA:46,8
|
|
76
|
+
DA:48,8
|
|
77
|
+
DA:59,1
|
|
78
|
+
DA:62,6
|
|
79
|
+
DA:63,6
|
|
80
|
+
DA:64,6
|
|
81
|
+
DA:66,6
|
|
52
82
|
DA:71,6
|
|
53
|
-
DA:
|
|
54
|
-
DA:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
LF:27
|
|
60
|
-
LH:26
|
|
61
|
-
BRDA:15,0,0,0
|
|
62
|
-
BRDA:15,0,1,1
|
|
63
|
-
BRDA:15,1,0,1
|
|
64
|
-
BRDA:15,1,1,1
|
|
65
|
-
BRF:4
|
|
66
|
-
BRH:3
|
|
83
|
+
DA:73,5
|
|
84
|
+
DA:78,4
|
|
85
|
+
LF:24
|
|
86
|
+
LH:24
|
|
87
|
+
BRF:0
|
|
88
|
+
BRH:0
|
|
67
89
|
end_of_record
|
|
@@ -109,7 +109,7 @@ export function normalize(phoneRaw: string): string {
|
|
|
109
109
|
<div class='footer quiet pad2 space-top1 center small'>
|
|
110
110
|
Code coverage generated by
|
|
111
111
|
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
112
|
-
at 2025-08-
|
|
112
|
+
at 2025-08-23T08:06:17.198Z
|
|
113
113
|
</div>
|
|
114
114
|
<script src="prettify.js"></script>
|
|
115
115
|
<script>
|