repo-cloak-cli 1.2.4 → 1.3.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.
@@ -1,128 +1,128 @@
1
- /**
2
- * Anonymizer
3
- * Handles keyword replacement for anonymizing content
4
- */
5
-
6
- /**
7
- * Create a replacement function for a list of replacements
8
- * @param {Array<{original: string, replacement: string}>} replacements
9
- * @param {Object} options
10
- * @returns {Function} Transform function
11
- */
12
- export function createAnonymizer(replacements, options = {}) {
13
- const { caseSensitive = false } = options;
14
-
15
- if (!replacements || replacements.length === 0) {
16
- return (content) => content;
17
- }
18
-
19
- return (content) => {
20
- let result = content;
21
-
22
- for (const { original, replacement } of replacements) {
23
- if (caseSensitive) {
24
- // Case-sensitive replacement
25
- result = result.split(original).join(replacement);
26
- } else {
27
- // Case-insensitive replacement using regex
28
- const regex = new RegExp(escapeRegex(original), 'gi');
29
- result = result.replace(regex, (match) => {
30
- // Preserve case pattern
31
- return matchCase(match, replacement);
32
- });
33
- }
34
- }
35
-
36
- return result;
37
- };
38
- }
39
-
40
- /**
41
- * Create reverse anonymizer (for push operation)
42
- * @param {Array<{original: string, replacement: string}>} replacements
43
- * @returns {Function} Transform function
44
- */
45
- export function createDeanonymizer(replacements, options = {}) {
46
- const { caseSensitive = false } = options;
47
-
48
- if (!replacements || replacements.length === 0) {
49
- return (content) => content;
50
- }
51
-
52
- // Reverse the replacements
53
- const reversed = replacements.map(r => ({
54
- original: r.replacement,
55
- replacement: r.original
56
- }));
57
-
58
- return createAnonymizer(reversed, options);
59
- }
60
-
61
- /**
62
- * Escape special regex characters
63
- */
64
- function escapeRegex(string) {
65
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
66
- }
67
-
68
- /**
69
- * Match the case pattern of the original to the replacement
70
- */
71
- function matchCase(original, replacement) {
72
- // If original is all uppercase, make replacement uppercase
73
- if (original === original.toUpperCase()) {
74
- return replacement.toUpperCase();
75
- }
76
-
77
- // If original is all lowercase, make replacement lowercase
78
- if (original === original.toLowerCase()) {
79
- return replacement.toLowerCase();
80
- }
81
-
82
- // If original is Title Case, make replacement Title Case
83
- if (original[0] === original[0].toUpperCase()) {
84
- return replacement.charAt(0).toUpperCase() + replacement.slice(1).toLowerCase();
85
- }
86
-
87
- // Default: return replacement as-is
88
- return replacement;
89
- }
90
-
91
- /**
92
- * Apply replacements to a file path (for renaming files/folders)
93
- */
94
- export function anonymizePath(filePath, replacements) {
95
- if (!replacements || replacements.length === 0) {
96
- return filePath;
97
- }
98
-
99
- let result = filePath;
100
-
101
- for (const { original, replacement } of replacements) {
102
- const regex = new RegExp(escapeRegex(original), 'gi');
103
- result = result.replace(regex, replacement);
104
- }
105
-
106
- return result;
107
- }
108
-
109
- /**
110
- * Count replacements in content
111
- */
112
- export function countReplacements(content, replacements) {
113
- if (!replacements || replacements.length === 0) {
114
- return 0;
115
- }
116
-
117
- let count = 0;
118
-
119
- for (const { original } of replacements) {
120
- const regex = new RegExp(escapeRegex(original), 'gi');
121
- const matches = content.match(regex);
122
- if (matches) {
123
- count += matches.length;
124
- }
125
- }
126
-
127
- return count;
128
- }
1
+ /**
2
+ * Anonymizer
3
+ * Handles keyword replacement for anonymizing content
4
+ */
5
+
6
+ /**
7
+ * Create a replacement function for a list of replacements
8
+ * @param {Array<{original: string, replacement: string}>} replacements
9
+ * @param {Object} options
10
+ * @returns {Function} Transform function
11
+ */
12
+ export function createAnonymizer(replacements, options = {}) {
13
+ const { caseSensitive = false } = options;
14
+
15
+ if (!replacements || replacements.length === 0) {
16
+ return (content) => content;
17
+ }
18
+
19
+ return (content) => {
20
+ let result = content;
21
+
22
+ for (const { original, replacement } of replacements) {
23
+ if (caseSensitive) {
24
+ // Case-sensitive replacement
25
+ result = result.split(original).join(replacement);
26
+ } else {
27
+ // Case-insensitive replacement using regex
28
+ const regex = new RegExp(escapeRegex(original), 'gi');
29
+ result = result.replace(regex, (match) => {
30
+ // Preserve case pattern
31
+ return matchCase(match, replacement);
32
+ });
33
+ }
34
+ }
35
+
36
+ return result;
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Create reverse anonymizer (for push operation)
42
+ * @param {Array<{original: string, replacement: string}>} replacements
43
+ * @returns {Function} Transform function
44
+ */
45
+ export function createDeanonymizer(replacements, options = {}) {
46
+ const { caseSensitive = false } = options;
47
+
48
+ if (!replacements || replacements.length === 0) {
49
+ return (content) => content;
50
+ }
51
+
52
+ // Reverse the replacements
53
+ const reversed = replacements.map(r => ({
54
+ original: r.replacement,
55
+ replacement: r.original
56
+ }));
57
+
58
+ return createAnonymizer(reversed, options);
59
+ }
60
+
61
+ /**
62
+ * Escape special regex characters
63
+ */
64
+ function escapeRegex(string) {
65
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
66
+ }
67
+
68
+ /**
69
+ * Match the case pattern of the original to the replacement
70
+ */
71
+ function matchCase(original, replacement) {
72
+ // If original is all uppercase, make replacement uppercase
73
+ if (original === original.toUpperCase()) {
74
+ return replacement.toUpperCase();
75
+ }
76
+
77
+ // If original is all lowercase, make replacement lowercase
78
+ if (original === original.toLowerCase()) {
79
+ return replacement.toLowerCase();
80
+ }
81
+
82
+ // If original is Title Case, make replacement Title Case
83
+ if (original[0] === original[0].toUpperCase()) {
84
+ return replacement.charAt(0).toUpperCase() + replacement.slice(1).toLowerCase();
85
+ }
86
+
87
+ // Default: return replacement as-is
88
+ return replacement;
89
+ }
90
+
91
+ /**
92
+ * Apply replacements to a file path (for renaming files/folders)
93
+ */
94
+ export function anonymizePath(filePath, replacements) {
95
+ if (!replacements || replacements.length === 0) {
96
+ return filePath;
97
+ }
98
+
99
+ let result = filePath;
100
+
101
+ for (const { original, replacement } of replacements) {
102
+ const regex = new RegExp(escapeRegex(original), 'gi');
103
+ result = result.replace(regex, replacement);
104
+ }
105
+
106
+ return result;
107
+ }
108
+
109
+ /**
110
+ * Count replacements in content
111
+ */
112
+ export function countReplacements(content, replacements) {
113
+ if (!replacements || replacements.length === 0) {
114
+ return 0;
115
+ }
116
+
117
+ let count = 0;
118
+
119
+ for (const { original } of replacements) {
120
+ const regex = new RegExp(escapeRegex(original), 'gi');
121
+ const matches = content.match(regex);
122
+ if (matches) {
123
+ count += matches.length;
124
+ }
125
+ }
126
+
127
+ return count;
128
+ }
@@ -1,139 +1,139 @@
1
- /**
2
- * File Copier
3
- * Copies files while preserving directory structure
4
- * Now also anonymizes folder/file names!
5
- */
6
-
7
- import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
8
- import { dirname, join, relative, basename } from 'path';
9
- import { isBinaryFile } from './scanner.js';
10
-
11
- /**
12
- * Apply replacements to a path (file/folder names)
13
- */
14
- function anonymizePath(relativePath, replacements) {
15
- if (!replacements || replacements.length === 0) {
16
- return relativePath;
17
- }
18
-
19
- let result = relativePath;
20
- for (const { original, replacement } of replacements) {
21
- // Case-insensitive replacement
22
- const regex = new RegExp(escapeRegex(original), 'gi');
23
- result = result.replace(regex, (match) => matchCase(match, replacement));
24
- }
25
- return result;
26
- }
27
-
28
- /**
29
- * Escape special regex characters
30
- */
31
- function escapeRegex(string) {
32
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
33
- }
34
-
35
- /**
36
- * Match case pattern
37
- */
38
- function matchCase(original, replacement) {
39
- if (original === original.toUpperCase()) {
40
- return replacement.toUpperCase();
41
- }
42
- if (original === original.toLowerCase()) {
43
- return replacement.toLowerCase();
44
- }
45
- if (original[0] === original[0].toUpperCase()) {
46
- return replacement.charAt(0).toUpperCase() + replacement.slice(1);
47
- }
48
- return replacement;
49
- }
50
-
51
- /**
52
- * Copy a single file, creating directories as needed
53
- */
54
- export function copyFile(sourcePath, destPath) {
55
- const destDir = dirname(destPath);
56
- mkdirSync(destDir, { recursive: true });
57
- copyFileSync(sourcePath, destPath);
58
- }
59
-
60
- /**
61
- * Copy a file with content transformation
62
- */
63
- export function copyFileWithTransform(sourcePath, destPath, transformFn) {
64
- const destDir = dirname(destPath);
65
- mkdirSync(destDir, { recursive: true });
66
-
67
- if (isBinaryFile(sourcePath)) {
68
- copyFileSync(sourcePath, destPath);
69
- return { transformed: false };
70
- }
71
-
72
- try {
73
- let content = readFileSync(sourcePath, 'utf-8');
74
- const originalContent = content;
75
- content = transformFn(content);
76
- writeFileSync(destPath, content, 'utf-8');
77
- return {
78
- transformed: content !== originalContent,
79
- originalLength: originalContent.length,
80
- newLength: content.length
81
- };
82
- } catch (error) {
83
- copyFileSync(sourcePath, destPath);
84
- return { transformed: false, error: error.message };
85
- }
86
- }
87
-
88
- /**
89
- * Copy multiple files with progress callback
90
- * Now also renames folders/files based on replacements!
91
- */
92
- export async function copyFiles(files, sourceBase, destBase, transformFn, onProgress, replacements = []) {
93
- const results = {
94
- total: files.length,
95
- copied: 0,
96
- transformed: 0,
97
- pathsRenamed: 0,
98
- errors: []
99
- };
100
-
101
- for (let i = 0; i < files.length; i++) {
102
- const file = files[i];
103
- const originalRelativePath = typeof file === 'string'
104
- ? relative(sourceBase, file)
105
- : file.relativePath;
106
- const sourcePath = typeof file === 'string' ? file : file.absolutePath;
107
-
108
- // Anonymize the path (folder and file names)
109
- const anonymizedPath = anonymizePath(originalRelativePath, replacements);
110
- const destPath = join(destBase, anonymizedPath);
111
-
112
- if (anonymizedPath !== originalRelativePath) {
113
- results.pathsRenamed++;
114
- }
115
-
116
- try {
117
- if (transformFn) {
118
- const result = copyFileWithTransform(sourcePath, destPath, transformFn);
119
- if (result.transformed) {
120
- results.transformed++;
121
- }
122
- } else {
123
- copyFile(sourcePath, destPath);
124
- }
125
- results.copied++;
126
- } catch (error) {
127
- results.errors.push({
128
- file: originalRelativePath,
129
- error: error.message
130
- });
131
- }
132
-
133
- if (onProgress) {
134
- onProgress(i + 1, files.length, anonymizedPath);
135
- }
136
- }
137
-
138
- return results;
139
- }
1
+ /**
2
+ * File Copier
3
+ * Copies files while preserving directory structure
4
+ * Now also anonymizes folder/file names!
5
+ */
6
+
7
+ import { copyFileSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
8
+ import { dirname, join, relative, basename } from 'path';
9
+ import { isBinaryFile } from './scanner.js';
10
+
11
+ /**
12
+ * Apply replacements to a path (file/folder names)
13
+ */
14
+ function anonymizePath(relativePath, replacements) {
15
+ if (!replacements || replacements.length === 0) {
16
+ return relativePath;
17
+ }
18
+
19
+ let result = relativePath;
20
+ for (const { original, replacement } of replacements) {
21
+ // Case-insensitive replacement
22
+ const regex = new RegExp(escapeRegex(original), 'gi');
23
+ result = result.replace(regex, (match) => matchCase(match, replacement));
24
+ }
25
+ return result;
26
+ }
27
+
28
+ /**
29
+ * Escape special regex characters
30
+ */
31
+ function escapeRegex(string) {
32
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
33
+ }
34
+
35
+ /**
36
+ * Match case pattern
37
+ */
38
+ function matchCase(original, replacement) {
39
+ if (original === original.toUpperCase()) {
40
+ return replacement.toUpperCase();
41
+ }
42
+ if (original === original.toLowerCase()) {
43
+ return replacement.toLowerCase();
44
+ }
45
+ if (original[0] === original[0].toUpperCase()) {
46
+ return replacement.charAt(0).toUpperCase() + replacement.slice(1);
47
+ }
48
+ return replacement;
49
+ }
50
+
51
+ /**
52
+ * Copy a single file, creating directories as needed
53
+ */
54
+ export function copyFile(sourcePath, destPath) {
55
+ const destDir = dirname(destPath);
56
+ mkdirSync(destDir, { recursive: true });
57
+ copyFileSync(sourcePath, destPath);
58
+ }
59
+
60
+ /**
61
+ * Copy a file with content transformation
62
+ */
63
+ export function copyFileWithTransform(sourcePath, destPath, transformFn) {
64
+ const destDir = dirname(destPath);
65
+ mkdirSync(destDir, { recursive: true });
66
+
67
+ if (isBinaryFile(sourcePath)) {
68
+ copyFileSync(sourcePath, destPath);
69
+ return { transformed: false };
70
+ }
71
+
72
+ try {
73
+ let content = readFileSync(sourcePath, 'utf-8');
74
+ const originalContent = content;
75
+ content = transformFn(content);
76
+ writeFileSync(destPath, content, 'utf-8');
77
+ return {
78
+ transformed: content !== originalContent,
79
+ originalLength: originalContent.length,
80
+ newLength: content.length
81
+ };
82
+ } catch (error) {
83
+ copyFileSync(sourcePath, destPath);
84
+ return { transformed: false, error: error.message };
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Copy multiple files with progress callback
90
+ * Now also renames folders/files based on replacements!
91
+ */
92
+ export async function copyFiles(files, sourceBase, destBase, transformFn, onProgress, replacements = []) {
93
+ const results = {
94
+ total: files.length,
95
+ copied: 0,
96
+ transformed: 0,
97
+ pathsRenamed: 0,
98
+ errors: []
99
+ };
100
+
101
+ for (let i = 0; i < files.length; i++) {
102
+ const file = files[i];
103
+ const originalRelativePath = typeof file === 'string'
104
+ ? relative(sourceBase, file)
105
+ : file.relativePath;
106
+ const sourcePath = typeof file === 'string' ? file : file.absolutePath;
107
+
108
+ // Anonymize the path (folder and file names)
109
+ const anonymizedPath = anonymizePath(originalRelativePath, replacements);
110
+ const destPath = join(destBase, anonymizedPath);
111
+
112
+ if (anonymizedPath !== originalRelativePath) {
113
+ results.pathsRenamed++;
114
+ }
115
+
116
+ try {
117
+ if (transformFn) {
118
+ const result = copyFileWithTransform(sourcePath, destPath, transformFn);
119
+ if (result.transformed) {
120
+ results.transformed++;
121
+ }
122
+ } else {
123
+ copyFile(sourcePath, destPath);
124
+ }
125
+ results.copied++;
126
+ } catch (error) {
127
+ results.errors.push({
128
+ file: originalRelativePath,
129
+ error: error.message
130
+ });
131
+ }
132
+
133
+ if (onProgress) {
134
+ onProgress(i + 1, files.length, anonymizedPath);
135
+ }
136
+ }
137
+
138
+ return results;
139
+ }