@mhmdhammoud/meritt-utils 1.0.1 → 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.
@@ -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
- import {Crypto} from '@mhmdhammoud/meritt-utils'
22
+ // Import the classes you need
23
+ import {Crypto, Formatter} from '@mhmdhammoud/meritt-utils'
23
24
 
24
- // Example of getting all Crypto methods
25
- const encryptedMessage = Crypto.encrypt('Hello World', 7)
26
- const decryptedMessage = Crypto.decrypt(encryptedMessage, 7)
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
  ```
@@ -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
@@ -1 +1,2 @@
1
1
  export { Crypto } from './lib';
2
+ export { Formatter } from './lib';
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; } });
@@ -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 {string} primeP - The prime number P
16
- * @memberof Crypto
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 {string} primeQ - The prime number Q
26
- * @memberof Crypto
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 {string} base - The base number
36
- * @param {string} exponent - The exponent number
37
- * @memberof Crypto
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 {string} message - The message to encrypt
47
- * @param {string} publicKey - The public key
48
- * @memberof Crypto
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 {string} encryptedMessage - The ciphertext to decrypt
58
- * @param {string} privateKey - The private key
59
- * @memberof Crypto
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
- * The Crypto class
5
- * @class Crypto
6
- * @example
7
- * ```typescript
8
- * import crypto from './lib/crypto'
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 {string} base - The base number
20
- * @param {string} exponent - The exponent number
21
- * @memberof Crypto
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 {string} message - The message to encrypt
45
- * @param {string} publicKey - The public key
46
- * @memberof Crypto
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
- const b = [];
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
- b.push(this._modularExponentiation(a, publicKey));
66
+ encryptedMessage.push(this._modularExponentiation(a, publicKey));
57
67
  }
58
- return b;
68
+ return encryptedMessage;
59
69
  };
60
70
  /**
61
71
  * Decrypt the message using the private key
62
- * @param {string} encryptedMessage - The ciphertext to decrypt
63
- * @param {string} privateKey - The private key
64
- * @memberof Crypto
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 {string} primeP - The prime number P
86
- * @memberof Crypto
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 {string} primeQ - The prime number Q
108
- * @memberof Crypto
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;
@@ -1 +1,2 @@
1
1
  export { default as Crypto } from './cypto';
2
+ export { default as Formatter } from './formatter';
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,16 +1,16 @@
1
1
  {
2
2
  "name": "@mhmdhammoud/meritt-utils",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
- "private":false,
6
+ "private": false,
7
7
  "repository": {
8
8
  "type": "git",
9
9
  "url": "git@github.com:Mhmdhammoud/meritt-utils.git"
10
10
  },
11
- "publishConfig": {
12
- "access": "public"
13
- },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
14
  "scripts": {
15
15
  "dev-ts": "ts-node-dev --respawn --transpile-only src/index.ts",
16
16
  "dev": "nodemon ./dist/index.js",
@@ -19,8 +19,7 @@
19
19
  "types": "tsc --noemit",
20
20
  "prepare": "husky install",
21
21
  "lint": "eslint src --fix",
22
- "prepublish": "yarn build",
23
- "postinstall": "yarn prepare"
22
+ "prepublish": "npm run build"
24
23
  },
25
24
  "dependencies": {
26
25
  "dotenv": "^10.0.0"
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export {Crypto} from './lib'
2
+ export {Formatter} from './lib'
package/src/lib/cypto.ts CHANGED
@@ -1,11 +1,9 @@
1
- /**
2
- * The Crypto class
3
- * @class Crypto
4
- * @example
5
- * ```typescript
6
- * import crypto from './lib/crypto'
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 {string} primeP - The prime number P
18
- * @memberof Crypto
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 {string} primeQ - The prime number Q
41
- * @memberof Crypto
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 {string} base - The base number
64
- * @param {string} exponent - The exponent number
65
- * @memberof Crypto
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 {string} message - The message to encrypt
90
- * @param {string} publicKey - The public key
91
- * @memberof Crypto
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 = (message: string, publicKey: number): number[] => {
98
- const b: number[] = []
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
- b.push(this._modularExponentiation(a, publicKey))
120
+ encryptedMessage.push(this._modularExponentiation(a, publicKey))
102
121
  }
103
- return b
122
+ return encryptedMessage
104
123
  }
105
124
 
106
125
  /**
107
126
  * Decrypt the message using the private key
108
- * @param {string} encryptedMessage - The ciphertext to decrypt
109
- * @param {string} privateKey - The private key
110
- * @memberof Crypto
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
@@ -1 +1,2 @@
1
1
  export {default as Crypto} from './cypto'
2
+ export {default as Formatter} from './formatter'