@awesomeness-js/utils 1.0.24 → 1.0.25

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.
Files changed (75) hide show
  1. package/build/build.js +11 -11
  2. package/build/postBuild.js +8 -8
  3. package/eslint.config.js +90 -0
  4. package/index.js +77 -74
  5. package/package.json +25 -25
  6. package/schemas/schema1.js +5 -1
  7. package/schemas/schema2.js +5 -1
  8. package/schemas.js +2 -2
  9. package/src/build.js +12 -8
  10. package/src/clean/boolean.js +27 -17
  11. package/src/clean/integer.js +85 -69
  12. package/src/clean/number.js +103 -86
  13. package/src/clean/string.js +91 -67
  14. package/src/clean/timestamp.js +61 -45
  15. package/src/clean/uuid.js +38 -25
  16. package/src/collectImports.js +195 -0
  17. package/src/combineFiles.js +45 -36
  18. package/src/convertBytes.js +12 -7
  19. package/src/decrypt.js +17 -9
  20. package/src/each.js +26 -4
  21. package/src/eachAsync.js +35 -19
  22. package/src/encrypt.js +22 -17
  23. package/src/getAllFiles.js +55 -41
  24. package/src/ignoreFolder/ignoreMe.js +6 -2
  25. package/src/ignoreMe.js +4 -2
  26. package/src/isUUID.js +4 -0
  27. package/src/md5.js +5 -1
  28. package/src/password/check.js +7 -3
  29. package/src/password/hash.js +12 -7
  30. package/src/setLocalEnvs.js +16 -3
  31. package/src/thingType.js +62 -24
  32. package/src/toPennies.js +23 -5
  33. package/src/utils/buildExportsTree.js +45 -17
  34. package/src/utils/buildFileDataList.js +32 -17
  35. package/src/utils/clean.js +205 -120
  36. package/src/utils/extractJSDocComment.js +14 -7
  37. package/src/utils/generateFile.js +20 -18
  38. package/src/utils/generateFlatExportLines.js +34 -17
  39. package/src/utils/generateImportStatements.js +15 -7
  40. package/src/utils/generateNamedExports.js +20 -9
  41. package/src/utils/generateNamespaceCode.js +45 -24
  42. package/src/utils/generateNamespaceExportLines.js +16 -7
  43. package/src/utils/shouldIgnore.js +57 -37
  44. package/src/uuid.js +9 -7
  45. package/src/validateSchema.js +95 -77
  46. package/test/collectImports.js +8 -0
  47. package/test/css/some.css +3 -0
  48. package/test/css/some.js +5 -0
  49. package/test/ignoreFolder/ignoreMe.js +3 -1
  50. package/test/ignoreFolder/ignoreMe2.js +3 -1
  51. package/test/ignoreFolder2/ignoreMe.js +6 -2
  52. package/test/js/abc.test.js +7 -3
  53. package/test/js/some.js +5 -0
  54. package/test/secret.test.js +1 -1
  55. package/tests/clean/array.test.js +122 -74
  56. package/tests/clean/boolean.test.js +18 -6
  57. package/tests/clean/integer.test.js +25 -9
  58. package/tests/clean/number.test.js +49 -13
  59. package/tests/clean/object.test.js +190 -119
  60. package/tests/clean/string.test.js +48 -17
  61. package/tests/clean/timestamp.test.js +12 -5
  62. package/tests/clean/uuid.test.js +13 -6
  63. package/tests/collectImports.test.js +66 -0
  64. package/tests/combineFiles.test.js +28 -26
  65. package/tests/convertBytes.test.js +8 -3
  66. package/tests/env.test.js +9 -3
  67. package/tests/example.test.js +7 -3
  68. package/tests/fileList.test.js +16 -12
  69. package/tests/hash-and-encrypt.test.js +13 -4
  70. package/tests/md5.test.js +7 -2
  71. package/tests/uuid.test.js +10 -4
  72. package/tests/validateSchema.test.js +21 -9
  73. package/tsconfig.json +20 -16
  74. package/types/collectImports.d.ts +6 -0
  75. package/types/index.d.ts +3 -0
@@ -0,0 +1,195 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import md5 from './md5.js';
4
+ import each from './each.js';
5
+
6
+
7
+ function collectImports(filePath, seen = new Set(), collected = []) {
8
+
9
+ const fullPath = path.resolve(filePath);
10
+
11
+ if (seen.has(fullPath)) return;
12
+ seen.add(fullPath);
13
+
14
+ const code = fs.readFileSync(fullPath, 'utf-8');
15
+ const hash = md5(code);
16
+
17
+ collected.push({
18
+ fullPath,
19
+ hash,
20
+ code,
21
+ });
22
+
23
+ const importRegex = /import\s+.*?['"](.+?)['"];?/g;
24
+ let match;
25
+
26
+ while ((match = importRegex.exec(code)) !== null) {
27
+
28
+ const importPath = match[1];
29
+
30
+ // Skip package imports (non-relative paths)
31
+ if (!importPath.startsWith('.')) continue;
32
+
33
+ const resolved = resolveImport(path.dirname(fullPath), importPath);
34
+
35
+ if (resolved) collectImports(resolved, seen, collected);
36
+
37
+ }
38
+
39
+ return collected;
40
+
41
+ }
42
+
43
+ function findProjectRoot(from = process.cwd()) {
44
+
45
+ let currentPath = from;
46
+
47
+ while (true) {
48
+
49
+ if (fs.existsSync(path.join(currentPath, 'package.json'))) {
50
+
51
+ return currentPath;
52
+
53
+ }
54
+
55
+ const parent = path.dirname(currentPath);
56
+
57
+
58
+ if (parent === currentPath) {
59
+
60
+ throw new Error('Project root not found (no package.json)');
61
+
62
+ }
63
+
64
+ currentPath = parent;
65
+
66
+ }
67
+
68
+ }
69
+
70
+
71
+ function resolveImport(baseDir, importPath) {
72
+
73
+ const candidates = [
74
+ importPath,
75
+ `${importPath}.js`,
76
+ `${importPath}.css`,
77
+ path.join(importPath, 'index.js'),
78
+ path.join(importPath, 'index.css'),
79
+ ];
80
+
81
+ for (const candidate of candidates) {
82
+
83
+ const full = path.resolve(baseDir, candidate);
84
+
85
+
86
+ if (fs.existsSync(full) && fs.statSync(full).isFile()) {
87
+
88
+ return full;
89
+
90
+ }
91
+
92
+ }
93
+
94
+ return null;
95
+
96
+ }
97
+
98
+ function jsName( file ){
99
+
100
+ return file.rootPath
101
+ .replace('.'+file.type, '')
102
+ .replaceAll('/', '.');
103
+
104
+ }
105
+
106
+ function cssName( file ){
107
+
108
+ return file.rootPath
109
+ .replace('.'+file.type, '')
110
+ .replaceAll('/', '_');
111
+
112
+ }
113
+
114
+ function run(filePath, {
115
+ returnCode = true,
116
+ jsMaps = {},
117
+ cssMaps = {}
118
+ } = {}){
119
+
120
+ const root = findProjectRoot(__dirname);
121
+
122
+ const imports = collectImports(filePath);
123
+
124
+ imports.forEach((file) => {
125
+
126
+ const rootPath = path.relative(root, file.fullPath).replace(/\\/g, '/');
127
+
128
+ file.rootPath = rootPath;
129
+
130
+ // strip file type
131
+ const fileType = rootPath.split('.').pop();
132
+
133
+ file.type = fileType;
134
+
135
+ if(fileType === 'js'){
136
+
137
+ file.name = jsName(file);
138
+
139
+ if(Object.keys(jsMaps).length){
140
+
141
+ each(jsMaps,( v, k ) => {
142
+
143
+ file.name = file.name.replace(k.replace(/\.\//g, ''),v);
144
+
145
+ });
146
+
147
+ }
148
+
149
+ if(returnCode){
150
+
151
+ file.code = file.code.replace(/import\s+.*?['"](.+?)['"];?/g, '').replace('export default', `${file.name} =`);
152
+
153
+ } else {
154
+
155
+ delete file.code;
156
+
157
+ }
158
+
159
+
160
+ }
161
+
162
+ if(fileType === 'css'){
163
+
164
+ file.name = cssName(file);
165
+
166
+ if(Object.keys(cssMaps).length){
167
+
168
+ each(cssMaps,( v, k ) => {
169
+
170
+ file.name = file.name.replace(k.replace(/\.\//g, ''),v);
171
+
172
+ });
173
+
174
+ }
175
+
176
+ if(returnCode){
177
+
178
+ file.code = file.code.replace(/import\s+.*?['"](.+?)['"];?/g, '');
179
+
180
+ } else {
181
+
182
+ delete file.code;
183
+
184
+ }
185
+
186
+
187
+ }
188
+
189
+ });
190
+
191
+ return imports;
192
+
193
+ }
194
+
195
+ export default run;
@@ -1,66 +1,75 @@
1
1
  // main-module/index.js
2
- import { readdirSync, statSync, readFileSync } from 'fs';
2
+ import {
3
+ readdirSync, statSync, readFileSync
4
+ } from 'fs';
3
5
 
4
6
  function combineFiles(dir, fileType, {
5
7
  minify = false,
6
- processContent = ({ content, path }) => { return content; },
8
+ processContent = ({
9
+ content, path
10
+ }) => {
11
+
12
+ return content;
13
+
14
+ },
7
15
  } = {}) {
8
16
 
9
- var returnString = "";
17
+ var returnString = "";
10
18
 
11
- let stuff = readdirSync(dir);
19
+ let stuff = readdirSync(dir);
12
20
 
13
- // sort it
14
- stuff = stuff.sort();
21
+ // sort it
22
+ stuff = stuff.sort();
15
23
 
16
24
 
17
- stuff.forEach(stuff => {
25
+ stuff.forEach((stuff) => {
18
26
 
19
- const isDir = statSync(`${dir}/${stuff}`).isDirectory();
27
+ const isDir = statSync(`${dir}/${stuff}`).isDirectory();
20
28
 
21
- if(isDir){
29
+ if(isDir){
22
30
 
23
- returnString += combineFiles(`${dir}/${stuff}`, fileType, {
24
- minify,
25
- processContent,
26
- });
31
+ returnString += combineFiles(`${dir}/${stuff}`, fileType, {
32
+ minify,
33
+ processContent,
34
+ });
27
35
 
28
- } else {
36
+ } else {
29
37
 
30
- // is file
38
+ // is file
31
39
 
32
- // get file and extension from stuff
33
- let file = stuff.split('.');
34
- let ext = file[file.length - 1];
40
+ // get file and extension from stuff
41
+ let file = stuff.split('.');
42
+ let ext = file[file.length - 1];
35
43
 
36
44
 
37
- if(ext === fileType){
45
+ if(ext === fileType){
38
46
 
39
- let thisData = readFileSync(`${dir}/${stuff}`, 'utf8');
40
-
41
- if(typeof processContent === 'function'){
42
-
43
- thisData = processContent({
44
- path: `${dir}/${stuff}`,
45
- content: thisData,
46
- });
47
+ let thisData = readFileSync(`${dir}/${stuff}`, 'utf8');
47
48
 
48
- }
49
+ if(typeof processContent === 'function'){
49
50
 
50
- if(minify){
51
- // todo
52
- }
51
+ thisData = processContent({
52
+ path: `${dir}/${stuff}`,
53
+ content: thisData,
54
+ });
53
55
 
54
- returnString += thisData + " \n ";
56
+ }
55
57
 
58
+ if(minify){
59
+ // todo
56
60
  }
57
61
 
62
+ returnString += thisData + " \n ";
63
+
58
64
  }
59
65
 
60
- });
66
+ }
67
+
68
+ });
69
+
70
+ return returnString;
61
71
 
62
- return returnString;
72
+ }
63
73
 
64
- };
65
74
 
66
- export default combineFiles;
75
+ export default combineFiles;
@@ -7,10 +7,15 @@
7
7
  * @returns {string} The converted bytes in a string format with appropriate units.
8
8
  */
9
9
  export default function convertBytes(bytes, precision = 2) {
10
- const units = ['B', 'KB', 'MB', 'GB', 'TB'];
11
- bytes = Math.max(bytes, 0);
12
- const pow = Math.floor((bytes ? Math.log(bytes) : 0) / Math.log(1024));
13
- const index = Math.min(pow, units.length - 1);
14
- bytes /= 2 ** (10 * pow);
15
- return `${bytes.toFixed(precision)} ${units[index]}`;
16
- };
10
+
11
+ const units = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
12
+
13
+ bytes = Math.max(bytes, 0);
14
+ const pow = Math.floor((bytes ? Math.log(bytes) : 0) / Math.log(1024));
15
+ const index = Math.min(pow, units.length - 1);
16
+
17
+ bytes /= 2 ** (10 * pow);
18
+
19
+ return `${bytes.toFixed(precision)} ${units[index]}`;
20
+
21
+ }
package/src/decrypt.js CHANGED
@@ -2,18 +2,26 @@ import { createDecipheriv } from 'crypto';
2
2
 
3
3
  export default function decrypt(encryptedData, key = process.env.AWESOMENESS_ENCRYPTION_KEY) {
4
4
 
5
- if(!key){
6
- throw new Error('Encryption key is not set. Please set the AWESOMENESS_ENCRYPTION_KEY environment variable.');
7
- }
5
+ if(!key){
8
6
 
9
- const { iv, authTag, cipherText } = encryptedData;
7
+ throw new Error('Encryption key is not set. Please set the AWESOMENESS_ENCRYPTION_KEY environment variable.');
8
+
9
+ }
10
+
11
+ const {
12
+ iv,
13
+ authTag,
14
+ cipherText
15
+ } = encryptedData;
10
16
 
11
- const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(iv, 'hex'));
12
- decipher.setAuthTag(Buffer.from(authTag, 'hex'));
17
+ const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(iv, 'hex'));
18
+
19
+ decipher.setAuthTag(Buffer.from(authTag, 'hex'));
13
20
 
14
- let decrypted = decipher.update(cipherText, 'hex', 'utf8');
15
- decrypted += decipher.final('utf8');
21
+ let decrypted = decipher.update(cipherText, 'hex', 'utf8');
22
+
23
+ decrypted += decipher.final('utf8');
16
24
 
17
- return decrypted;
25
+ return decrypted;
18
26
 
19
27
  }
package/src/each.js CHANGED
@@ -13,15 +13,37 @@ export default function each(objectOrArray, callback) {
13
13
  if(Array.isArray(objectOrArray)){
14
14
 
15
15
  objectOrArray.every( (v, k) => {
16
- if(callback( v, k ) === false){ return false; } else { return true; }
16
+
17
+ if(callback( v, k ) === false){
18
+
19
+ return false;
20
+
21
+ } else {
22
+
23
+ return true;
24
+
25
+ }
26
+
17
27
  });
18
28
 
19
29
  } else {
20
30
 
21
- Object.entries(objectOrArray).every(entry => {
22
- if(callback( entry[1], entry[0] ) === false){ return false; } else { return true; }
31
+ Object.entries(objectOrArray).every((entry) => {
32
+
33
+ if(callback( entry[1], entry[0] ) === false){
34
+
35
+ return false;
36
+
37
+ } else {
38
+
39
+ return true;
40
+
41
+ }
42
+
23
43
  });
24
44
 
25
45
  }
26
46
 
27
- };
47
+ }
48
+
49
+ ;
package/src/eachAsync.js CHANGED
@@ -1,21 +1,37 @@
1
1
  export default async function eachAsync(objectOrArray, callback) {
2
- if (Array.isArray(objectOrArray)) {
3
- // Use a for...of loop for arrays
4
- for (const [k, v] of objectOrArray.entries()) {
5
- // Await the callback
6
- if (await callback(v, k) === false) {
7
- break;
8
- }
9
- }
10
- } else {
11
- // Use a for...in loop for objects
12
- for (const k in objectOrArray) {
13
- if (objectOrArray.hasOwnProperty(k)) {
14
- // Await the callback
15
- if (await callback(objectOrArray[k], k) === false) {
16
- break;
17
- }
18
- }
19
- }
20
- }
2
+
3
+ if (Array.isArray(objectOrArray)) {
4
+
5
+ // Use a for...of loop for arrays
6
+ for (const [ k, v ] of objectOrArray.entries()) {
7
+
8
+ // Await the callback
9
+ if (await callback(v, k) === false) {
10
+
11
+ break;
12
+
13
+ }
14
+
15
+ }
16
+
17
+ } else {
18
+
19
+ // Use a for...in loop for objects
20
+ for (const k in objectOrArray) {
21
+
22
+ if (objectOrArray.hasOwnProperty(k)) {
23
+
24
+ // Await the callback
25
+ if (await callback(objectOrArray[k], k) === false) {
26
+
27
+ break;
28
+
29
+ }
30
+
31
+ }
32
+
33
+ }
34
+
35
+ }
36
+
21
37
  }
package/src/encrypt.js CHANGED
@@ -1,29 +1,34 @@
1
- import { randomBytes, createCipheriv } from 'crypto';
1
+ import {
2
+ randomBytes, createCipheriv
3
+ } from 'crypto';
2
4
 
3
5
 
4
6
  // Encrypt plaintext using AES-256-GCM
5
7
  export default function encrypt(plainText, key = process.env.AWESOMENESS_ENCRYPTION_KEY) {
6
8
 
7
- if(!key){
8
- throw new Error('Encryption key is not set. Please set the AWESOMENESS_ENCRYPTION_KEY environment variable.');
9
- }
9
+ if(!key){
10
10
 
11
- // GCM typically uses a 12- or 16-byte IV/nonce
12
- const iv = randomBytes(12);
11
+ throw new Error('Encryption key is not set. Please set the AWESOMENESS_ENCRYPTION_KEY environment variable.');
12
+
13
+ }
13
14
 
14
- const cipher = createCipheriv('aes-256-gcm', key, iv);
15
- let encrypted = cipher.update(plainText, 'utf8', 'hex');
16
- encrypted += cipher.final('hex');
15
+ // GCM typically uses a 12- or 16-byte IV/nonce
16
+ const iv = randomBytes(12);
17
17
 
18
- // GCM provides an auth tag, which is required for decryption
19
- const authTag = cipher.getAuthTag().toString('hex');
18
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
19
+ let encrypted = cipher.update(plainText, 'utf8', 'hex');
20
20
 
21
- // Return all parts needed for safe decryption
22
- return {
23
- iv: iv.toString('hex'),
24
- authTag,
25
- cipherText: encrypted
26
- };
21
+ encrypted += cipher.final('hex');
22
+
23
+ // GCM provides an auth tag, which is required for decryption
24
+ const authTag = cipher.getAuthTag().toString('hex');
25
+
26
+ // Return all parts needed for safe decryption
27
+ return {
28
+ iv: iv.toString('hex'),
29
+ authTag,
30
+ cipherText: encrypted
31
+ };
27
32
 
28
33
  }
29
34
 
@@ -1,48 +1,62 @@
1
- import { readdirSync, statSync } from 'fs';
1
+ import {
2
+ readdirSync, statSync
3
+ } from 'fs';
2
4
  import { join } from 'path';
3
5
  import shouldIgnore from './utils/shouldIgnore.js';
4
6
 
5
7
  export default function getAllFiles(base, {
6
- dir = '.',
7
- files = [],
8
- ignore = [],
9
- fileTypes = []
8
+ dir = '.',
9
+ files = [],
10
+ ignore = [],
11
+ fileTypes = []
10
12
  } = {}) {
11
13
 
12
- const directory = join(base, dir);
13
-
14
- const sortedFiles = readdirSync(directory).sort();
15
-
16
- sortedFiles.forEach(file => {
17
- const fullPath = join(directory, file);
18
- // 1) Generate the original "relative path"
19
- const relativePath = join(dir, file).replace(/\\/g, '/');
20
-
21
- // 2) Prepend a slash so patterns like "/css/*.js" will match "/css/some.js"
22
- const pathForIgnore = '/' + relativePath.replace(/^\/*/, '');
23
-
24
- // 3) Check with the leading slash path
25
- if (shouldIgnore(pathForIgnore, ignore)) {
26
- return;
27
- }
28
-
29
- // Recurse if it's a directory
30
- if (statSync(fullPath).isDirectory()) {
31
- getAllFiles(base, {
32
- dir: join(dir, file),
33
- files,
34
- ignore,
35
- fileTypes
36
- });
37
- } else {
38
- // Filter by file types if specified
39
- if (fileTypes.length > 0 && !fileTypes.some(ext => file.endsWith(ext))) {
40
- return;
41
- }
42
- // 4) Store the original relative path (without leading slash) in `files` if you prefer
43
- files.push(relativePath);
44
- }
45
- });
46
-
47
- return files;
14
+ const directory = join(base, dir);
15
+
16
+ const sortedFiles = readdirSync(directory).sort();
17
+
18
+ sortedFiles.forEach((file) => {
19
+
20
+ const fullPath = join(directory, file);
21
+ // 1) Generate the original "relative path"
22
+ const relativePath = join(dir, file).replace(/\\/g, '/');
23
+
24
+ // 2) Prepend a slash so patterns like "/css/*.js" will match "/css/some.js"
25
+ const pathForIgnore = '/' + relativePath.replace(/^\/*/, '');
26
+
27
+ // 3) Check with the leading slash path
28
+ if (shouldIgnore(pathForIgnore, ignore)) {
29
+
30
+ return;
31
+
32
+ }
33
+
34
+ // Recurse if it's a directory
35
+ if (statSync(fullPath).isDirectory()) {
36
+
37
+ getAllFiles(base, {
38
+ dir: join(dir, file),
39
+ files,
40
+ ignore,
41
+ fileTypes
42
+ });
43
+
44
+ } else {
45
+
46
+ // Filter by file types if specified
47
+ if (fileTypes.length > 0 && !fileTypes.some((ext) => file.endsWith(ext))) {
48
+
49
+ return;
50
+
51
+ }
52
+
53
+ // 4) Store the original relative path (without leading slash) in `files` if you prefer
54
+ files.push(relativePath);
55
+
56
+ }
57
+
58
+ });
59
+
60
+ return files;
61
+
48
62
  }
@@ -1,3 +1,7 @@
1
1
  export default function ignoreMeTest() {
2
- console.log('I should not be in the build!');
3
- };
2
+
3
+ console.log('I should not be in the build!');
4
+
5
+ }
6
+
7
+ ;
package/src/ignoreMe.js CHANGED
@@ -1,3 +1,5 @@
1
1
  export default function ignoreMeTest() {
2
- console.log('I should not be in the build!');
3
- };
2
+
3
+ console.log('I should not be in the build!');
4
+
5
+ }
package/src/isUUID.js CHANGED
@@ -1,4 +1,8 @@
1
1
  export default function isUUID(uuid) {
2
+
2
3
  const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4
+
5
+
3
6
  return uuidV4Regex.test(uuid);
7
+
4
8
  }
package/src/md5.js CHANGED
@@ -1,5 +1,9 @@
1
1
  import { createHash } from 'crypto';
2
+
2
3
  function md5(data) {
3
- return createHash('md5').update(data).digest('hex');
4
+
5
+ return createHash('md5').update(data).digest('hex');
6
+
4
7
  }
8
+
5
9
  export default md5;
@@ -2,8 +2,12 @@ import { pbkdf2Sync } from 'crypto';
2
2
 
3
3
  // Compare a plain-text password to a stored salt+hash
4
4
  export default function validatePassword(password, storedHash) {
5
- const [salt, originalHash] = storedHash.split('::');
6
- const derivedKey = pbkdf2Sync(password, salt, 100000, 64, 'sha512');
7
- return derivedKey.toString('hex') === originalHash;
5
+
6
+ const [ salt, originalHash ] = storedHash.split('::');
7
+ const derivedKey = pbkdf2Sync(password, salt, 100000, 64, 'sha512');
8
+
9
+
10
+ return derivedKey.toString('hex') === originalHash;
11
+
8
12
  }
9
13