@mhmdhammoud/meritt-utils 1.0.2 → 1.0.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/.github/workflows/npm-publish.yml +28 -0
- package/.github/workflows/push.yml +29 -0
- package/.husky/pre-commit +62 -0
- package/README.md +8 -4
- package/ReleaseNotes.md +34 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/lib/cypto.d.ts +14 -22
- package/dist/lib/cypto.js +50 -24
- package/dist/lib/formatter.d.ts +43 -0
- package/dist/lib/formatter.js +121 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +3 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/lib/cypto.ts +54 -25
- package/src/lib/formatter.ts +121 -0
- package/src/lib/index.ts +1 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: NPM Publish on Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
jobs:
|
|
7
|
+
build:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v3
|
|
11
|
+
- uses: actions/setup-node@v3
|
|
12
|
+
with:
|
|
13
|
+
node-version: 16
|
|
14
|
+
- run: npm ci
|
|
15
|
+
|
|
16
|
+
publish-npm:
|
|
17
|
+
needs: build
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v3
|
|
21
|
+
- uses: actions/setup-node@v3
|
|
22
|
+
with:
|
|
23
|
+
node-version: 16
|
|
24
|
+
registry-url: https://registry.npmjs.org/
|
|
25
|
+
- run: npm ci
|
|
26
|
+
- run: npm publish
|
|
27
|
+
env:
|
|
28
|
+
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Changes
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [dev]
|
|
5
|
+
jobs:
|
|
6
|
+
type-check:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v3
|
|
10
|
+
- uses: actions/setup-node@v3
|
|
11
|
+
with:
|
|
12
|
+
node-version: 16
|
|
13
|
+
- run: npm ci
|
|
14
|
+
- run: npm run types
|
|
15
|
+
notify:
|
|
16
|
+
needs: [type-check]
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- name: Notify by Email
|
|
20
|
+
uses: dawidd6/action-send-mail@v2
|
|
21
|
+
with:
|
|
22
|
+
server_address: ${{ secrets.EMAIL_HOST }}
|
|
23
|
+
server_port: 465
|
|
24
|
+
username: ${{ secrets.EMAIL_USERNAME }}
|
|
25
|
+
password: ${{ secrets.EMAIL_PASSWORD }}
|
|
26
|
+
subject: ${{ github.event.head_commit.message }} ${{ github.job }} job of ${{ github.repository }} has ${{ job.status }}
|
|
27
|
+
body: ${{ github.job }} job in worflow ${{ github.workflow }} of ${{ github.repository }} has ${{ job.status }}
|
|
28
|
+
to: mohammad.hammoud.lb@hotmail.com,steef12009@gmail.com,sawwas.omar@gmail.com
|
|
29
|
+
from: Github Action
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
. "$(dirname -- "$0")/_/husky.sh"
|
|
3
|
+
|
|
4
|
+
red='\033[0;31m'
|
|
5
|
+
green='\033[0;32m'
|
|
6
|
+
yellow='\033[0;33m'
|
|
7
|
+
blue='\033[0;34m'
|
|
8
|
+
magenta='\033[0;35m'
|
|
9
|
+
cyan='\033[0;36m'
|
|
10
|
+
clear='\033[0m'
|
|
11
|
+
echo "
|
|
12
|
+
|
|
13
|
+
__ __ ______ _____ _____ _______ _______ _____ ________ __
|
|
14
|
+
| \/ | ____| __ \|_ _|__ __|__ __| | __ \| ____\ \ / /
|
|
15
|
+
| \ / | |__ | |__) | | | | | | | | | | | |__ \ \ / /
|
|
16
|
+
| |\/| | __| | _ / | | | | | | | | | | __| \ \/ /
|
|
17
|
+
| | | | |____| | \ \ _| |_ | | | | | |__| | |____ \ /
|
|
18
|
+
|_| |_|______|_| \_\_____| |_| |_| |_____/|______| \/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
"
|
|
22
|
+
echo -e "Let's hope you are not ${red}DUMB${clear}!"
|
|
23
|
+
|
|
24
|
+
echo -ne '\n'
|
|
25
|
+
|
|
26
|
+
echo -e "${yellow}Or Are You ??${clear}!"
|
|
27
|
+
echo -ne '\n'
|
|
28
|
+
echo -e "${yellow}Running pre-commit hook...${clear}"
|
|
29
|
+
echo -ne '\n'
|
|
30
|
+
echo -ne '\n'
|
|
31
|
+
|
|
32
|
+
echo -ne '##################### (25%)\r'
|
|
33
|
+
sleep 0.3
|
|
34
|
+
echo -ne '############################## (35%)\r'
|
|
35
|
+
sleep 0.3
|
|
36
|
+
echo -ne '###################################### (45%)\r'
|
|
37
|
+
sleep 0.3
|
|
38
|
+
echo -ne '############################################################ (77%)\r'
|
|
39
|
+
sleep 0.3
|
|
40
|
+
echo -ne '################################################################## (100%)\r'
|
|
41
|
+
|
|
42
|
+
echo -ne '\n'
|
|
43
|
+
echo -ne '\n'
|
|
44
|
+
echo -ne '\n'
|
|
45
|
+
|
|
46
|
+
echo -e "${yellow}Running types...${clear}"
|
|
47
|
+
echo -ne '\n'
|
|
48
|
+
npm run types
|
|
49
|
+
echo -ne '\n'
|
|
50
|
+
|
|
51
|
+
echo -e "${green}types passed...${clear} ✅"
|
|
52
|
+
echo -ne '\n'
|
|
53
|
+
echo -e "${yellow}Running linting...${clear}"
|
|
54
|
+
|
|
55
|
+
npm run lint
|
|
56
|
+
echo -e "${green}linting passed...${clear} ✅"
|
|
57
|
+
|
|
58
|
+
echo -ne '\n'
|
|
59
|
+
|
|
60
|
+
echo -e "${yellow}Seems like you are a${clear} ${green}CLEVER DEVELOPER${clear} 👌"
|
|
61
|
+
echo -ne '\n'
|
|
62
|
+
echo -e "${green}GOOD TO GO${clear} 🚀🚀🚀"
|
package/README.md
CHANGED
|
@@ -19,9 +19,13 @@ yarn add @mhmdhammoud/meritt-utils
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
|
-
|
|
22
|
+
// Import the classes you need
|
|
23
|
+
import {Crypto, Formatter} from '@mhmdhammoud/meritt-utils'
|
|
23
24
|
|
|
24
|
-
// Example of
|
|
25
|
-
const
|
|
26
|
-
|
|
25
|
+
// Example of creating a product slug
|
|
26
|
+
const slug = Formatter.slugify('My Product Name') // my-product-name
|
|
27
|
+
|
|
28
|
+
// Example of encrypting and decrypting a string
|
|
29
|
+
|
|
30
|
+
const encryptedMessage = Crypto.encrypt('Hello World', 7) // [23,235,141,414]
|
|
27
31
|
```
|
package/ReleaseNotes.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changes
|
|
2
|
+
|
|
3
|
+
## Version 1.0.3
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added Formatter class for manipulating strings
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import {Formatter} from '@mhmdhammoud/meritt-utils'
|
|
11
|
+
|
|
12
|
+
// Example of creating a product slug
|
|
13
|
+
const slug = Formatter.slugify('My Product Name') // my-product-name
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Fixes and Improvements
|
|
17
|
+
|
|
18
|
+
- Fixed bug in Crypto class where encrypting a string with a key that is not a number would throw an error
|
|
19
|
+
|
|
20
|
+
- Improved Crypto class to allow encrypting and decrypting numbers and objects
|
|
21
|
+
|
|
22
|
+
- Documented Crypto class
|
|
23
|
+
|
|
24
|
+
## Version 1.0.2
|
|
25
|
+
|
|
26
|
+
- Added Crypto class that contains encrypt and decrypt methods for strings, numbers, and objects using a public and private key
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {Crypto} from '@mhmdhammoud/meritt-utils'
|
|
30
|
+
|
|
31
|
+
// Example of encrypting and decrypting a string
|
|
32
|
+
const encryptedMessage = Crypto.encrypt('Hello World', 7) // [23,235,141,414]
|
|
33
|
+
const decryptedMessage = Crypto.decrypt(encryptedMessage, 247) // Hello World
|
|
34
|
+
```
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Crypto = void 0;
|
|
3
|
+
exports.Formatter = exports.Crypto = void 0;
|
|
4
4
|
var lib_1 = require("./lib");
|
|
5
5
|
Object.defineProperty(exports, "Crypto", { enumerable: true, get: function () { return lib_1.Crypto; } });
|
|
6
|
+
var lib_2 = require("./lib");
|
|
7
|
+
Object.defineProperty(exports, "Formatter", { enumerable: true, get: function () { return lib_2.Formatter; } });
|
package/dist/lib/cypto.d.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Crypto class
|
|
3
|
-
* @class Crypto
|
|
4
|
-
* @example
|
|
5
|
-
* ```typescript
|
|
6
|
-
* import crypto from './lib/crypto'
|
|
7
|
-
* ```
|
|
8
|
-
* */
|
|
9
1
|
declare class Crypto {
|
|
10
2
|
private _primeNumberP;
|
|
11
3
|
private _primeNumberQ;
|
|
12
4
|
private _moduloDenominator;
|
|
13
5
|
/**
|
|
14
6
|
* Set the P prime number for the RSA algorithm
|
|
15
|
-
* @param
|
|
16
|
-
* @
|
|
7
|
+
* @param primeP - The prime number P of type string
|
|
8
|
+
* @returns void
|
|
17
9
|
* @example
|
|
18
10
|
* ```typescript
|
|
19
11
|
* crypto.setPrimeP(17)
|
|
@@ -22,8 +14,8 @@ declare class Crypto {
|
|
|
22
14
|
setPrimeP(primeP: number): void;
|
|
23
15
|
/**
|
|
24
16
|
* Set the Q prime number for the RSA algorithm
|
|
25
|
-
* @param
|
|
26
|
-
* @
|
|
17
|
+
* @param primeQ - The prime number Q of type string
|
|
18
|
+
* @returns void
|
|
27
19
|
* @example
|
|
28
20
|
* ```typescript
|
|
29
21
|
* crypto.setPrimeQ(19)
|
|
@@ -32,9 +24,9 @@ declare class Crypto {
|
|
|
32
24
|
setPrimeQ(primeQ: number): void;
|
|
33
25
|
/**
|
|
34
26
|
*
|
|
35
|
-
* @param
|
|
36
|
-
* @param
|
|
37
|
-
* @
|
|
27
|
+
* @param base - The base number of type number
|
|
28
|
+
* @param exponent - The exponent number of type number
|
|
29
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
38
30
|
* @example
|
|
39
31
|
* ```typescript
|
|
40
32
|
* this.modularExponentiation(2, 3)
|
|
@@ -43,20 +35,20 @@ declare class Crypto {
|
|
|
43
35
|
private _modularExponentiation;
|
|
44
36
|
/**
|
|
45
37
|
* Encrypt the message using the public key
|
|
46
|
-
* @param
|
|
47
|
-
* @param
|
|
48
|
-
* @
|
|
38
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
39
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
40
|
+
* @returns The encrypted message of type number[]
|
|
49
41
|
* @example
|
|
50
42
|
* ```typescript
|
|
51
43
|
* crypto.encrypt('Hello World', 7)
|
|
52
44
|
* ```
|
|
53
45
|
* */
|
|
54
|
-
encrypt: (message: string, publicKey: number) => number[];
|
|
46
|
+
encrypt: (message: string | number | Record<any, any>, publicKey: number) => number[];
|
|
55
47
|
/**
|
|
56
48
|
* Decrypt the message using the private key
|
|
57
|
-
* @param
|
|
58
|
-
* @param
|
|
59
|
-
* @
|
|
49
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
50
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
51
|
+
* @returns The decrypted message of type string
|
|
60
52
|
* @example
|
|
61
53
|
* ```typescript
|
|
62
54
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
package/dist/lib/cypto.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* ```
|
|
10
|
-
* */
|
|
3
|
+
/*
|
|
4
|
+
Author : Omar Sawwas
|
|
5
|
+
Date : 2023-06-17
|
|
6
|
+
Description : RSA algorithm
|
|
7
|
+
Version : 1.0
|
|
8
|
+
*/
|
|
11
9
|
class Crypto {
|
|
12
10
|
constructor() {
|
|
13
11
|
// Default variables
|
|
@@ -16,15 +14,18 @@ class Crypto {
|
|
|
16
14
|
this._moduloDenominator = this._primeNumberP * this._primeNumberQ;
|
|
17
15
|
/**
|
|
18
16
|
*
|
|
19
|
-
* @param
|
|
20
|
-
* @param
|
|
21
|
-
* @
|
|
17
|
+
* @param base - The base number of type number
|
|
18
|
+
* @param exponent - The exponent number of type number
|
|
19
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
22
20
|
* @example
|
|
23
21
|
* ```typescript
|
|
24
22
|
* this.modularExponentiation(2, 3)
|
|
25
23
|
* ```
|
|
26
24
|
* */
|
|
27
25
|
this._modularExponentiation = (base, exponent) => {
|
|
26
|
+
if (isNaN(base) || isNaN(exponent)) {
|
|
27
|
+
throw new Error('Provide a valid number');
|
|
28
|
+
}
|
|
28
29
|
if (this._moduloDenominator === 1) {
|
|
29
30
|
return 0;
|
|
30
31
|
}
|
|
@@ -41,33 +42,52 @@ class Crypto {
|
|
|
41
42
|
};
|
|
42
43
|
/**
|
|
43
44
|
* Encrypt the message using the public key
|
|
44
|
-
* @param
|
|
45
|
-
* @param
|
|
46
|
-
* @
|
|
45
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
46
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
47
|
+
* @returns The encrypted message of type number[]
|
|
47
48
|
* @example
|
|
48
49
|
* ```typescript
|
|
49
50
|
* crypto.encrypt('Hello World', 7)
|
|
50
51
|
* ```
|
|
51
52
|
* */
|
|
52
53
|
this.encrypt = (message, publicKey) => {
|
|
53
|
-
|
|
54
|
+
if (isNaN(publicKey)) {
|
|
55
|
+
throw new Error('Public key should be a number');
|
|
56
|
+
}
|
|
57
|
+
if (typeof message === 'number') {
|
|
58
|
+
message = message.toString();
|
|
59
|
+
}
|
|
60
|
+
if (typeof message === 'object') {
|
|
61
|
+
message = JSON.stringify(message);
|
|
62
|
+
}
|
|
63
|
+
const encryptedMessage = [];
|
|
54
64
|
for (let i = 0; i < message.length; i++) {
|
|
55
65
|
const a = message.charCodeAt(i);
|
|
56
|
-
|
|
66
|
+
encryptedMessage.push(this._modularExponentiation(a, publicKey));
|
|
57
67
|
}
|
|
58
|
-
return
|
|
68
|
+
return encryptedMessage;
|
|
59
69
|
};
|
|
60
70
|
/**
|
|
61
71
|
* Decrypt the message using the private key
|
|
62
|
-
* @param
|
|
63
|
-
* @param
|
|
64
|
-
* @
|
|
72
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
73
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
74
|
+
* @returns The decrypted message of type string
|
|
65
75
|
* @example
|
|
66
76
|
* ```typescript
|
|
67
77
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
|
68
78
|
* ```
|
|
69
79
|
* */
|
|
70
80
|
this.decrypt = (encryptedMessage, privateKey) => {
|
|
81
|
+
if (isNaN(privateKey)) {
|
|
82
|
+
throw new Error('Private key should be a number');
|
|
83
|
+
}
|
|
84
|
+
if (!Array.isArray(encryptedMessage)) {
|
|
85
|
+
throw new Error('Encrypted message should be an array');
|
|
86
|
+
}
|
|
87
|
+
const allValidNumbers = encryptedMessage.every((number) => !isNaN(number));
|
|
88
|
+
if (!allValidNumbers) {
|
|
89
|
+
throw new Error('Encrypted message should be an array of numbers');
|
|
90
|
+
}
|
|
71
91
|
const decryptedAsciiMessage = [];
|
|
72
92
|
for (let i = 0; i < encryptedMessage.length; i++) {
|
|
73
93
|
const a = encryptedMessage[i];
|
|
@@ -82,14 +102,17 @@ class Crypto {
|
|
|
82
102
|
}
|
|
83
103
|
/**
|
|
84
104
|
* Set the P prime number for the RSA algorithm
|
|
85
|
-
* @param
|
|
86
|
-
* @
|
|
105
|
+
* @param primeP - The prime number P of type string
|
|
106
|
+
* @returns void
|
|
87
107
|
* @example
|
|
88
108
|
* ```typescript
|
|
89
109
|
* crypto.setPrimeP(17)
|
|
90
110
|
* ```
|
|
91
111
|
* */
|
|
92
112
|
setPrimeP(primeP) {
|
|
113
|
+
if (isNaN(primeP)) {
|
|
114
|
+
throw new Error('Provide a valid number');
|
|
115
|
+
}
|
|
93
116
|
let isPrime = true;
|
|
94
117
|
for (let i = 2; i < primeP; i++) {
|
|
95
118
|
if (primeP % i === 0) {
|
|
@@ -104,14 +127,17 @@ class Crypto {
|
|
|
104
127
|
}
|
|
105
128
|
/**
|
|
106
129
|
* Set the Q prime number for the RSA algorithm
|
|
107
|
-
* @param
|
|
108
|
-
* @
|
|
130
|
+
* @param primeQ - The prime number Q of type string
|
|
131
|
+
* @returns void
|
|
109
132
|
* @example
|
|
110
133
|
* ```typescript
|
|
111
134
|
* crypto.setPrimeQ(19)
|
|
112
135
|
* ```
|
|
113
136
|
* */
|
|
114
137
|
setPrimeQ(primeQ) {
|
|
138
|
+
if (isNaN(primeQ)) {
|
|
139
|
+
throw new Error('Provide a valid number');
|
|
140
|
+
}
|
|
115
141
|
let isPrime = true;
|
|
116
142
|
for (let i = 2; i < primeQ; i++) {
|
|
117
143
|
if (primeQ % i === 0) {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
declare class Formatter {
|
|
2
|
+
/**
|
|
3
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
4
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
5
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
6
|
+
* @returns string
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* formatter.toUpperFirst('hello world')
|
|
10
|
+
* // => 'Hello-World'
|
|
11
|
+
* ```
|
|
12
|
+
* */
|
|
13
|
+
toUpperFirst: (_: string | number, withSpacing?: boolean) => string;
|
|
14
|
+
/**
|
|
15
|
+
* @remarks normalizes input to supported path and file name format.
|
|
16
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
17
|
+
* @param str - String needed to be modified
|
|
18
|
+
* @returns formatted string
|
|
19
|
+
*/
|
|
20
|
+
camelToKebab: (str: string) => string;
|
|
21
|
+
/**
|
|
22
|
+
* @remarks obfuscates email address
|
|
23
|
+
* @param email - email address to be obfuscated
|
|
24
|
+
* @returns obfuscated email address
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
28
|
+
* ```
|
|
29
|
+
* */
|
|
30
|
+
obfuscate: (email: string) => string;
|
|
31
|
+
/**
|
|
32
|
+
* @remarks Generates a slug from a given string
|
|
33
|
+
* @param title - string to be converted to slug
|
|
34
|
+
* @returns slug
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
38
|
+
* ```
|
|
39
|
+
* */
|
|
40
|
+
slugify: (title: string) => string;
|
|
41
|
+
}
|
|
42
|
+
declare const formatter: Formatter;
|
|
43
|
+
export default formatter;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/*
|
|
4
|
+
Author : Mhmd Hammoud
|
|
5
|
+
Date : 2023-06-17
|
|
6
|
+
Description : String manipulation
|
|
7
|
+
Version : 1.0
|
|
8
|
+
*/
|
|
9
|
+
class Formatter {
|
|
10
|
+
constructor() {
|
|
11
|
+
/**
|
|
12
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
13
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
14
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
15
|
+
* @returns string
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* formatter.toUpperFirst('hello world')
|
|
19
|
+
* // => 'Hello-World'
|
|
20
|
+
* ```
|
|
21
|
+
* */
|
|
22
|
+
this.toUpperFirst = (_, withSpacing = true) => {
|
|
23
|
+
if (typeof _ !== 'string')
|
|
24
|
+
throw new Error('Provide a valid string');
|
|
25
|
+
if (withSpacing) {
|
|
26
|
+
return _.split(' ')
|
|
27
|
+
.map((val) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
28
|
+
.join(' ')
|
|
29
|
+
.replace(/ /g, '-')
|
|
30
|
+
.replace(/\//g, '-')
|
|
31
|
+
.replace(/\./g, '');
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return _.split(' ')
|
|
35
|
+
.map((val) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
36
|
+
.join(' ')
|
|
37
|
+
.replace(/\//g, '-')
|
|
38
|
+
.replace(/\./g, '');
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* @remarks normalizes input to supported path and file name format.
|
|
43
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
44
|
+
* @param str - String needed to be modified
|
|
45
|
+
* @returns formatted string
|
|
46
|
+
*/
|
|
47
|
+
this.camelToKebab = (str) => {
|
|
48
|
+
const STRING_DASHERIZE_REGEXP = /\s/g;
|
|
49
|
+
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g;
|
|
50
|
+
return str
|
|
51
|
+
.replace(STRING_DECAMELIZE_REGEXP, '$1-$2')
|
|
52
|
+
.toLowerCase()
|
|
53
|
+
.replace(STRING_DASHERIZE_REGEXP, '-');
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* @remarks obfuscates email address
|
|
57
|
+
* @param email - email address to be obfuscated
|
|
58
|
+
* @returns obfuscated email address
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
62
|
+
* ```
|
|
63
|
+
* */
|
|
64
|
+
this.obfuscate = (email) => {
|
|
65
|
+
if (typeof email !== 'string')
|
|
66
|
+
throw new Error('Provide a valid string');
|
|
67
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
68
|
+
if (!emailRegex.test(email))
|
|
69
|
+
throw new Error('Provide a valid email address');
|
|
70
|
+
const separatorIndex = email.indexOf('@');
|
|
71
|
+
if (separatorIndex < 3) {
|
|
72
|
+
// 'ab@gmail.com' -> '**@gmail.com'
|
|
73
|
+
return (email.slice(0, separatorIndex).replace(/./g, '*') +
|
|
74
|
+
email.slice(separatorIndex));
|
|
75
|
+
}
|
|
76
|
+
// 'test42@gmail.com' -> 'te****@gmail.com'
|
|
77
|
+
return (email.slice(0, 2) +
|
|
78
|
+
email.slice(2, separatorIndex).replace(/./g, '*') +
|
|
79
|
+
email.slice(separatorIndex));
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* @remarks Generates a slug from a given string
|
|
83
|
+
* @param title - string to be converted to slug
|
|
84
|
+
* @returns slug
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
88
|
+
* ```
|
|
89
|
+
* */
|
|
90
|
+
this.slugify = (title) => {
|
|
91
|
+
if (typeof title !== 'string')
|
|
92
|
+
throw new Error('Provide a valid string');
|
|
93
|
+
return title
|
|
94
|
+
.replace(/ /g, '-')
|
|
95
|
+
.replace(/%/g, '-')
|
|
96
|
+
.replace(/#/g, '-')
|
|
97
|
+
.replace(/\?/g, '-')
|
|
98
|
+
.replace(/,/g, '-')
|
|
99
|
+
.replace(/\//g, '-')
|
|
100
|
+
.replace(/\\/g, '-')
|
|
101
|
+
.replace(/\./g, '')
|
|
102
|
+
.replace(/'/g, '')
|
|
103
|
+
.replace(/"/g, '')
|
|
104
|
+
.replace(/\+/g, '-')
|
|
105
|
+
.replace(/\*/g, '-')
|
|
106
|
+
.replace(/\^/g, '-')
|
|
107
|
+
.replace(/@/g, '-')
|
|
108
|
+
.replace(/;/g, '-')
|
|
109
|
+
.replace(/:/g, '-')
|
|
110
|
+
.replace(/!/g, '-')
|
|
111
|
+
.replace(/&/g, '-')
|
|
112
|
+
.replace(/\$/g, '-')
|
|
113
|
+
.replace(/\(/g, '-')
|
|
114
|
+
.replace(/\)/g, '-')
|
|
115
|
+
.trim()
|
|
116
|
+
.toLowerCase();
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const formatter = new Formatter();
|
|
121
|
+
exports.default = formatter;
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.js
CHANGED
|
@@ -3,6 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Crypto = void 0;
|
|
6
|
+
exports.Formatter = exports.Crypto = void 0;
|
|
7
7
|
var cypto_1 = require("./cypto");
|
|
8
8
|
Object.defineProperty(exports, "Crypto", { enumerable: true, get: function () { return __importDefault(cypto_1).default; } });
|
|
9
|
+
var formatter_1 = require("./formatter");
|
|
10
|
+
Object.defineProperty(exports, "Formatter", { enumerable: true, get: function () { return __importDefault(formatter_1).default; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mhmdhammoud/meritt-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"private": false,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"types": "tsc --noemit",
|
|
20
20
|
"prepare": "husky install",
|
|
21
21
|
"lint": "eslint src --fix",
|
|
22
|
-
"prepublish": "
|
|
22
|
+
"prepublish": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"dotenv": "^10.0.0"
|
package/src/index.ts
CHANGED
package/src/lib/cypto.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* ```
|
|
8
|
-
* */
|
|
1
|
+
/*
|
|
2
|
+
Author : Omar Sawwas
|
|
3
|
+
Date : 2023-06-17
|
|
4
|
+
Description : RSA algorithm
|
|
5
|
+
Version : 1.0
|
|
6
|
+
*/
|
|
9
7
|
class Crypto {
|
|
10
8
|
// Default variables
|
|
11
9
|
private _primeNumberP = 17
|
|
@@ -14,14 +12,17 @@ class Crypto {
|
|
|
14
12
|
|
|
15
13
|
/**
|
|
16
14
|
* Set the P prime number for the RSA algorithm
|
|
17
|
-
* @param
|
|
18
|
-
* @
|
|
15
|
+
* @param primeP - The prime number P of type string
|
|
16
|
+
* @returns void
|
|
19
17
|
* @example
|
|
20
18
|
* ```typescript
|
|
21
19
|
* crypto.setPrimeP(17)
|
|
22
20
|
* ```
|
|
23
21
|
* */
|
|
24
22
|
public setPrimeP(primeP: number) {
|
|
23
|
+
if (isNaN(primeP)) {
|
|
24
|
+
throw new Error('Provide a valid number')
|
|
25
|
+
}
|
|
25
26
|
let isPrime = true
|
|
26
27
|
for (let i = 2; i < primeP; i++) {
|
|
27
28
|
if (primeP % i === 0) {
|
|
@@ -37,14 +38,17 @@ class Crypto {
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Set the Q prime number for the RSA algorithm
|
|
40
|
-
* @param
|
|
41
|
-
* @
|
|
41
|
+
* @param primeQ - The prime number Q of type string
|
|
42
|
+
* @returns void
|
|
42
43
|
* @example
|
|
43
44
|
* ```typescript
|
|
44
45
|
* crypto.setPrimeQ(19)
|
|
45
46
|
* ```
|
|
46
47
|
* */
|
|
47
48
|
public setPrimeQ(primeQ: number) {
|
|
49
|
+
if (isNaN(primeQ)) {
|
|
50
|
+
throw new Error('Provide a valid number')
|
|
51
|
+
}
|
|
48
52
|
let isPrime = true
|
|
49
53
|
for (let i = 2; i < primeQ; i++) {
|
|
50
54
|
if (primeQ % i === 0) {
|
|
@@ -60,15 +64,18 @@ class Crypto {
|
|
|
60
64
|
|
|
61
65
|
/**
|
|
62
66
|
*
|
|
63
|
-
* @param
|
|
64
|
-
* @param
|
|
65
|
-
* @
|
|
67
|
+
* @param base - The base number of type number
|
|
68
|
+
* @param exponent - The exponent number of type number
|
|
69
|
+
* @returns The modular exponentiation of the base and the exponent
|
|
66
70
|
* @example
|
|
67
71
|
* ```typescript
|
|
68
72
|
* this.modularExponentiation(2, 3)
|
|
69
73
|
* ```
|
|
70
74
|
* */
|
|
71
75
|
private _modularExponentiation = (base: number, exponent: number) => {
|
|
76
|
+
if (isNaN(base) || isNaN(exponent)) {
|
|
77
|
+
throw new Error('Provide a valid number')
|
|
78
|
+
}
|
|
72
79
|
if (this._moduloDenominator === 1) {
|
|
73
80
|
return 0
|
|
74
81
|
}
|
|
@@ -86,34 +93,56 @@ class Crypto {
|
|
|
86
93
|
|
|
87
94
|
/**
|
|
88
95
|
* Encrypt the message using the public key
|
|
89
|
-
* @param
|
|
90
|
-
* @param
|
|
91
|
-
* @
|
|
96
|
+
* @param message - The message to encrypt of type string|number|Record
|
|
97
|
+
* @param publicKey - The public key to encrypt the message with of type number
|
|
98
|
+
* @returns The encrypted message of type number[]
|
|
92
99
|
* @example
|
|
93
100
|
* ```typescript
|
|
94
101
|
* crypto.encrypt('Hello World', 7)
|
|
95
102
|
* ```
|
|
96
103
|
* */
|
|
97
|
-
public encrypt = (
|
|
98
|
-
|
|
104
|
+
public encrypt = (
|
|
105
|
+
message: string | number | Record<any, any>,
|
|
106
|
+
publicKey: number
|
|
107
|
+
): number[] => {
|
|
108
|
+
if (isNaN(publicKey)) {
|
|
109
|
+
throw new Error('Public key should be a number')
|
|
110
|
+
}
|
|
111
|
+
if (typeof message === 'number') {
|
|
112
|
+
message = message.toString()
|
|
113
|
+
}
|
|
114
|
+
if (typeof message === 'object') {
|
|
115
|
+
message = JSON.stringify(message)
|
|
116
|
+
}
|
|
117
|
+
const encryptedMessage: number[] = []
|
|
99
118
|
for (let i = 0; i < message.length; i++) {
|
|
100
119
|
const a = message.charCodeAt(i)
|
|
101
|
-
|
|
120
|
+
encryptedMessage.push(this._modularExponentiation(a, publicKey))
|
|
102
121
|
}
|
|
103
|
-
return
|
|
122
|
+
return encryptedMessage
|
|
104
123
|
}
|
|
105
124
|
|
|
106
125
|
/**
|
|
107
126
|
* Decrypt the message using the private key
|
|
108
|
-
* @param
|
|
109
|
-
* @param
|
|
110
|
-
* @
|
|
127
|
+
* @param encryptedMessage - The encryptedMessage to decrypt of type number[]
|
|
128
|
+
* @param privateKey - The private key to decrypt the message with of type number
|
|
129
|
+
* @returns The decrypted message of type string
|
|
111
130
|
* @example
|
|
112
131
|
* ```typescript
|
|
113
132
|
* crypto.decrypt([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100], 23)
|
|
114
133
|
* ```
|
|
115
134
|
* */
|
|
116
135
|
public decrypt = (encryptedMessage: number[], privateKey: number): string => {
|
|
136
|
+
if (isNaN(privateKey)) {
|
|
137
|
+
throw new Error('Private key should be a number')
|
|
138
|
+
}
|
|
139
|
+
if (!Array.isArray(encryptedMessage)) {
|
|
140
|
+
throw new Error('Encrypted message should be an array')
|
|
141
|
+
}
|
|
142
|
+
const allValidNumbers = encryptedMessage.every((number) => !isNaN(number))
|
|
143
|
+
if (!allValidNumbers) {
|
|
144
|
+
throw new Error('Encrypted message should be an array of numbers')
|
|
145
|
+
}
|
|
117
146
|
const decryptedAsciiMessage: number[] = []
|
|
118
147
|
for (let i = 0; i < encryptedMessage.length; i++) {
|
|
119
148
|
const a = encryptedMessage[i]
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Author : Mhmd Hammoud
|
|
3
|
+
Date : 2023-06-17
|
|
4
|
+
Description : String manipulation
|
|
5
|
+
Version : 1.0
|
|
6
|
+
*/
|
|
7
|
+
class Formatter {
|
|
8
|
+
/**
|
|
9
|
+
* @remarks Normalizes input by removing underscores and hyphens and capitalizing the first letter of the sentence.
|
|
10
|
+
* @param stringToBeChanged - to be formatted without underscores and hyphens
|
|
11
|
+
* @param withWhiteSpacing - Determines if white spacing is needed in the final string or not (default: true)
|
|
12
|
+
* @returns string
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* formatter.toUpperFirst('hello world')
|
|
16
|
+
* // => 'Hello-World'
|
|
17
|
+
* ```
|
|
18
|
+
* */
|
|
19
|
+
toUpperFirst = (_: string | number, withSpacing = true) => {
|
|
20
|
+
if (typeof _ !== 'string') throw new Error('Provide a valid string')
|
|
21
|
+
if (withSpacing) {
|
|
22
|
+
return _.split(' ')
|
|
23
|
+
.map((val: string) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
24
|
+
.join(' ')
|
|
25
|
+
.replace(/ /g, '-')
|
|
26
|
+
.replace(/\//g, '-')
|
|
27
|
+
.replace(/\./g, '')
|
|
28
|
+
} else {
|
|
29
|
+
return _.split(' ')
|
|
30
|
+
.map((val: string) => val.charAt(0).toUpperCase() + val.slice(1))
|
|
31
|
+
.join(' ')
|
|
32
|
+
.replace(/\//g, '-')
|
|
33
|
+
.replace(/\./g, '')
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @remarks normalizes input to supported path and file name format.
|
|
39
|
+
* Changes camelCase strings to kebab-case, replaces spaces with dash and keeps underscores. *
|
|
40
|
+
* @param str - String needed to be modified
|
|
41
|
+
* @returns formatted string
|
|
42
|
+
*/
|
|
43
|
+
camelToKebab = (str: string) => {
|
|
44
|
+
const STRING_DASHERIZE_REGEXP = /\s/g
|
|
45
|
+
const STRING_DECAMELIZE_REGEXP = /([a-z\d])([A-Z])/g
|
|
46
|
+
return str
|
|
47
|
+
.replace(STRING_DECAMELIZE_REGEXP, '$1-$2')
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.replace(STRING_DASHERIZE_REGEXP, '-')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @remarks obfuscates email address
|
|
54
|
+
* @param email - email address to be obfuscated
|
|
55
|
+
* @returns obfuscated email address
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* formatter.obfuscate('johndoe@email.com') // => jo*****@gmail.com
|
|
59
|
+
* ```
|
|
60
|
+
* */
|
|
61
|
+
obfuscate = (email: string) => {
|
|
62
|
+
if (typeof email !== 'string') throw new Error('Provide a valid string')
|
|
63
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
64
|
+
if (!emailRegex.test(email))
|
|
65
|
+
throw new Error('Provide a valid email address')
|
|
66
|
+
const separatorIndex = email.indexOf('@')
|
|
67
|
+
if (separatorIndex < 3) {
|
|
68
|
+
// 'ab@gmail.com' -> '**@gmail.com'
|
|
69
|
+
return (
|
|
70
|
+
email.slice(0, separatorIndex).replace(/./g, '*') +
|
|
71
|
+
email.slice(separatorIndex)
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
// 'test42@gmail.com' -> 'te****@gmail.com'
|
|
75
|
+
return (
|
|
76
|
+
email.slice(0, 2) +
|
|
77
|
+
email.slice(2, separatorIndex).replace(/./g, '*') +
|
|
78
|
+
email.slice(separatorIndex)
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @remarks Generates a slug from a given string
|
|
84
|
+
* @param title - string to be converted to slug
|
|
85
|
+
* @returns slug
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* formatter.slugify('Hello World') // => hello-world
|
|
89
|
+
* ```
|
|
90
|
+
* */
|
|
91
|
+
slugify = (title: string) => {
|
|
92
|
+
if (typeof title !== 'string') throw new Error('Provide a valid string')
|
|
93
|
+
return title
|
|
94
|
+
.replace(/ /g, '-')
|
|
95
|
+
.replace(/%/g, '-')
|
|
96
|
+
.replace(/#/g, '-')
|
|
97
|
+
.replace(/\?/g, '-')
|
|
98
|
+
.replace(/,/g, '-')
|
|
99
|
+
.replace(/\//g, '-')
|
|
100
|
+
.replace(/\\/g, '-')
|
|
101
|
+
.replace(/\./g, '')
|
|
102
|
+
.replace(/'/g, '')
|
|
103
|
+
.replace(/"/g, '')
|
|
104
|
+
.replace(/\+/g, '-')
|
|
105
|
+
.replace(/\*/g, '-')
|
|
106
|
+
.replace(/\^/g, '-')
|
|
107
|
+
.replace(/@/g, '-')
|
|
108
|
+
.replace(/;/g, '-')
|
|
109
|
+
.replace(/:/g, '-')
|
|
110
|
+
.replace(/!/g, '-')
|
|
111
|
+
.replace(/&/g, '-')
|
|
112
|
+
.replace(/\$/g, '-')
|
|
113
|
+
.replace(/\(/g, '-')
|
|
114
|
+
.replace(/\)/g, '-')
|
|
115
|
+
.trim()
|
|
116
|
+
.toLowerCase()
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const formatter = new Formatter()
|
|
121
|
+
export default formatter
|
package/src/lib/index.ts
CHANGED