seabox 0.1.1 → 0.2.0

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,203 +1,203 @@
1
- /**
2
- * native-scanner.mjs
3
- * Deep scanning of node_modules for native modules and automatic detection.
4
- */
5
-
6
- import fs from 'fs/promises';
7
- import fsSync from 'fs';
8
- import path from 'path';
9
- import * as diag from './diagnostics.mjs';
10
-
11
- /**
12
- * @typedef {Object} NativeModuleMetadata
13
- * @property {string} name - Module name
14
- * @property {string} path - Absolute path to module root
15
- * @property {string} version - Module version
16
- * @property {boolean} hasBindingGyp - Whether binding.gyp exists
17
- * @property {string[]} binaryFiles - Detected .node files
18
- */
19
-
20
- /**
21
- * Scan node_modules directory for native modules
22
- * @param {string} projectRoot - Project root directory
23
- * @param {boolean} verbose - Enable verbose logging
24
- * @returns {Promise<NativeModuleMetadata[]>}
25
- */
26
- export async function scanDependenciesForNativeModules(projectRoot, verbose = false) {
27
- const nativeModules = [];
28
- const nodeModulesPath = path.join(projectRoot, 'node_modules');
29
-
30
- if (!fsSync.existsSync(nodeModulesPath)) {
31
- diag.verbose('No node_modules directory found');
32
- return [];
33
- }
34
-
35
- diag.verbose('Scanning node_modules for native modules');
36
-
37
- /**
38
- * Recursively scan a directory for packages
39
- */
40
- async function scanDir(dir, isScoped = false) {
41
- try {
42
- const entries = await fs.readdir(dir, { withFileTypes: true });
43
-
44
- for (const entry of entries) {
45
- // Skip hidden directories and bin
46
- if (entry.name.startsWith('.') || entry.name === '.bin') {
47
- continue;
48
- }
49
-
50
- const fullPath = path.join(dir, entry.name);
51
-
52
- if (entry.isDirectory()) {
53
- const pkgPath = path.join(fullPath, 'package.json');
54
-
55
- // Check if this is a scoped package directory
56
- if (entry.name.startsWith('@')) {
57
- await scanDir(fullPath, true);
58
- continue;
59
- }
60
-
61
- // Check if package.json exists
62
- if (fsSync.existsSync(pkgPath)) {
63
- const moduleInfo = await analyzePackage(fullPath, pkgPath);
64
- if (moduleInfo) {
65
- nativeModules.push(moduleInfo);
66
- }
67
- }
68
- }
69
- }
70
- } catch (err) {
71
- diag.verbose(`Error scanning directory: ${dir} - ${err.message}`);
72
- }
73
- }
74
-
75
- /**
76
- * Analyze a package to determine if it's a native module
77
- */
78
- async function analyzePackage(modulePath, pkgPath) {
79
- try {
80
- const pkgContent = await fs.readFile(pkgPath, 'utf8');
81
- const pkg = JSON.parse(pkgContent);
82
-
83
- // Check for native module indicators
84
- const hasBindingGyp = fsSync.existsSync(path.join(modulePath, 'binding.gyp'));
85
- const hasGypfile = pkg.gypfile === true;
86
- const hasBinaryField = pkg.binary != null;
87
-
88
- if (!hasBindingGyp && !hasGypfile && !hasBinaryField) {
89
- return null;
90
- }
91
-
92
- // Find .node files
93
- const binaryFiles = await findNodeFiles(modulePath);
94
-
95
- if (hasBindingGyp || hasGypfile || binaryFiles.length > 0) {
96
- return {
97
- name: pkg.name,
98
- path: modulePath,
99
- version: pkg.version,
100
- hasBindingGyp: hasBindingGyp,
101
- binaryFiles: binaryFiles
102
- };
103
- }
104
-
105
- return null;
106
- } catch (err) {
107
- // Ignore packages with invalid package.json
108
- return null;
109
- }
110
- }
111
-
112
- /**
113
- * Find all .node files in a directory tree
114
- */
115
- async function findNodeFiles(dir, maxDepth = 5, currentDepth = 0) {
116
- const nodeFiles = [];
117
-
118
- if (currentDepth > maxDepth) {
119
- return nodeFiles;
120
- }
121
-
122
- try {
123
- const entries = await fs.readdir(dir, { withFileTypes: true });
124
-
125
- for (const entry of entries) {
126
- const fullPath = path.join(dir, entry.name);
127
-
128
- if (entry.isDirectory()) {
129
- // Skip node_modules subdirectories
130
- if (entry.name === 'node_modules') {
131
- continue;
132
- }
133
-
134
- // Recurse into subdirectories
135
- const subFiles = await findNodeFiles(fullPath, maxDepth, currentDepth + 1);
136
- nodeFiles.push(...subFiles);
137
- } else if (entry.name.endsWith('.node')) {
138
- nodeFiles.push(fullPath);
139
- }
140
- }
141
- } catch (err) {
142
- // Ignore read errors
143
- }
144
-
145
- return nodeFiles;
146
- }
147
-
148
- await scanDir(nodeModulesPath);
149
-
150
- diag.verbose(`Found ${nativeModules.length} native modules`);
151
- for (const mod of nativeModules) {
152
- diag.verbose(`- ${mod.name}@${mod.version} (${mod.binaryFiles.length} binaries)`, 1);
153
- }
154
-
155
- return nativeModules;
156
- }
157
-
158
- /**
159
- * Find the build output path for a native module
160
- * @param {string} moduleRoot - Root directory of the native module
161
- * @param {string} target - Build target (e.g., node24.11.0-win32-x64)
162
- * @returns {Promise<string|null>}
163
- */
164
- export async function findNativeModuleBuildPath(moduleRoot, target) {
165
- const { platform, arch } = parseTarget(target);
166
-
167
- // Common build output locations
168
- const searchPaths = [
169
- path.join(moduleRoot, 'build/Release'),
170
- path.join(moduleRoot, 'build/Debug'),
171
- path.join(moduleRoot, 'lib/binding', `${platform}-${arch}`),
172
- path.join(moduleRoot, 'prebuilds', `${platform}-${arch}`)
173
- ];
174
-
175
- for (const searchPath of searchPaths) {
176
- if (fsSync.existsSync(searchPath)) {
177
- // Look for .node files
178
- const files = await fs.readdir(searchPath);
179
- const nodeFile = files.find(f => f.endsWith('.node'));
180
-
181
- if (nodeFile) {
182
- return path.join(searchPath, nodeFile);
183
- }
184
- }
185
- }
186
-
187
- return null;
188
- }
189
-
190
- /**
191
- * Parse a target string into components
192
- */
193
- function parseTarget(target) {
194
- const match = target.match(/^node(\d+\.\d+\.\d+)-(\w+)-(\w+)$/);
195
- if (!match) {
196
- throw new Error(`Cannot parse target: ${target}`);
197
- }
198
- return {
199
- nodeVersion: match[1],
200
- platform: match[2],
201
- arch: match[3]
202
- };
203
- }
1
+ /**
2
+ * native-scanner.mjs
3
+ * Deep scanning of node_modules for native modules and automatic detection.
4
+ */
5
+
6
+ import fs from 'fs/promises';
7
+ import fsSync from 'fs';
8
+ import path from 'path';
9
+ import * as diag from './diagnostics.mjs';
10
+
11
+ /**
12
+ * @typedef {Object} NativeModuleMetadata
13
+ * @property {string} name - Module name
14
+ * @property {string} path - Absolute path to module root
15
+ * @property {string} version - Module version
16
+ * @property {boolean} hasBindingGyp - Whether binding.gyp exists
17
+ * @property {string[]} binaryFiles - Detected .node files
18
+ */
19
+
20
+ /**
21
+ * Scan node_modules directory for native modules
22
+ * @param {string} projectRoot - Project root directory
23
+ * @param {boolean} verbose - Enable verbose logging
24
+ * @returns {Promise<NativeModuleMetadata[]>}
25
+ */
26
+ export async function scanDependenciesForNativeModules(projectRoot, verbose = false) {
27
+ const nativeModules = [];
28
+ const nodeModulesPath = path.join(projectRoot, 'node_modules');
29
+
30
+ if (!fsSync.existsSync(nodeModulesPath)) {
31
+ diag.verbose('No node_modules directory found');
32
+ return [];
33
+ }
34
+
35
+ diag.verbose('Scanning node_modules for native modules');
36
+
37
+ /**
38
+ * Recursively scan a directory for packages
39
+ */
40
+ async function scanDir(dir, isScoped = false) {
41
+ try {
42
+ const entries = await fs.readdir(dir, { withFileTypes: true });
43
+
44
+ for (const entry of entries) {
45
+ // Skip hidden directories and bin
46
+ if (entry.name.startsWith('.') || entry.name === '.bin') {
47
+ continue;
48
+ }
49
+
50
+ const fullPath = path.join(dir, entry.name);
51
+
52
+ if (entry.isDirectory()) {
53
+ const pkgPath = path.join(fullPath, 'package.json');
54
+
55
+ // Check if this is a scoped package directory
56
+ if (entry.name.startsWith('@')) {
57
+ await scanDir(fullPath, true);
58
+ continue;
59
+ }
60
+
61
+ // Check if package.json exists
62
+ if (fsSync.existsSync(pkgPath)) {
63
+ const moduleInfo = await analyzePackage(fullPath, pkgPath);
64
+ if (moduleInfo) {
65
+ nativeModules.push(moduleInfo);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ } catch (err) {
71
+ diag.verbose(`Error scanning directory: ${dir} - ${err.message}`);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Analyze a package to determine if it's a native module
77
+ */
78
+ async function analyzePackage(modulePath, pkgPath) {
79
+ try {
80
+ const pkgContent = await fs.readFile(pkgPath, 'utf8');
81
+ const pkg = JSON.parse(pkgContent);
82
+
83
+ // Check for native module indicators
84
+ const hasBindingGyp = fsSync.existsSync(path.join(modulePath, 'binding.gyp'));
85
+ const hasGypfile = pkg.gypfile === true;
86
+ const hasBinaryField = pkg.binary != null;
87
+
88
+ if (!hasBindingGyp && !hasGypfile && !hasBinaryField) {
89
+ return null;
90
+ }
91
+
92
+ // Find .node files
93
+ const binaryFiles = await findNodeFiles(modulePath);
94
+
95
+ if (hasBindingGyp || hasGypfile || binaryFiles.length > 0) {
96
+ return {
97
+ name: pkg.name,
98
+ path: modulePath,
99
+ version: pkg.version,
100
+ hasBindingGyp: hasBindingGyp,
101
+ binaryFiles: binaryFiles
102
+ };
103
+ }
104
+
105
+ return null;
106
+ } catch (err) {
107
+ // Ignore packages with invalid package.json
108
+ return null;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Find all .node files in a directory tree
114
+ */
115
+ async function findNodeFiles(dir, maxDepth = 5, currentDepth = 0) {
116
+ const nodeFiles = [];
117
+
118
+ if (currentDepth > maxDepth) {
119
+ return nodeFiles;
120
+ }
121
+
122
+ try {
123
+ const entries = await fs.readdir(dir, { withFileTypes: true });
124
+
125
+ for (const entry of entries) {
126
+ const fullPath = path.join(dir, entry.name);
127
+
128
+ if (entry.isDirectory()) {
129
+ // Skip node_modules subdirectories
130
+ if (entry.name === 'node_modules') {
131
+ continue;
132
+ }
133
+
134
+ // Recurse into subdirectories
135
+ const subFiles = await findNodeFiles(fullPath, maxDepth, currentDepth + 1);
136
+ nodeFiles.push(...subFiles);
137
+ } else if (entry.name.endsWith('.node')) {
138
+ nodeFiles.push(fullPath);
139
+ }
140
+ }
141
+ } catch (err) {
142
+ // Ignore read errors
143
+ }
144
+
145
+ return nodeFiles;
146
+ }
147
+
148
+ await scanDir(nodeModulesPath);
149
+
150
+ diag.verbose(`Found ${nativeModules.length} native modules`);
151
+ for (const mod of nativeModules) {
152
+ diag.verbose(`- ${mod.name}@${mod.version} (${mod.binaryFiles.length} binaries)`, 1);
153
+ }
154
+
155
+ return nativeModules;
156
+ }
157
+
158
+ /**
159
+ * Find the build output path for a native module
160
+ * @param {string} moduleRoot - Root directory of the native module
161
+ * @param {string} target - Build target (e.g., node24.11.0-win32-x64)
162
+ * @returns {Promise<string|null>}
163
+ */
164
+ export async function findNativeModuleBuildPath(moduleRoot, target) {
165
+ const { platform, arch } = parseTarget(target);
166
+
167
+ // Common build output locations
168
+ const searchPaths = [
169
+ path.join(moduleRoot, 'build/Release'),
170
+ path.join(moduleRoot, 'build/Debug'),
171
+ path.join(moduleRoot, 'lib/binding', `${platform}-${arch}`),
172
+ path.join(moduleRoot, 'prebuilds', `${platform}-${arch}`)
173
+ ];
174
+
175
+ for (const searchPath of searchPaths) {
176
+ if (fsSync.existsSync(searchPath)) {
177
+ // Look for .node files
178
+ const files = await fs.readdir(searchPath);
179
+ const nodeFile = files.find(f => f.endsWith('.node'));
180
+
181
+ if (nodeFile) {
182
+ return path.join(searchPath, nodeFile);
183
+ }
184
+ }
185
+ }
186
+
187
+ return null;
188
+ }
189
+
190
+ /**
191
+ * Parse a target string into components
192
+ */
193
+ function parseTarget(target) {
194
+ const match = target.match(/^node(\d+\.\d+\.\d+)-(\w+)-(\w+)$/);
195
+ if (!match) {
196
+ throw new Error(`Cannot parse target: ${target}`);
197
+ }
198
+ return {
199
+ nodeVersion: match[1],
200
+ platform: match[2],
201
+ arch: match[3]
202
+ };
203
+ }
package/lib/obfuscate.mjs CHANGED
@@ -1,51 +1,51 @@
1
- /**
2
- * obfuscate.mjs
3
- * Obfuscate bootstrap code to protect encryption keys and decryption logic
4
- */
5
-
6
- import Module from 'module';
7
-
8
- const require = Module.createRequire(import.meta.url);
9
- const JavaScriptObfuscator = require('javascript-obfuscator');
10
-
11
- /**
12
- * Obfuscate bootstrap code with maximum protection settings
13
- *
14
- * @param {string} bootstrapCode - The bootstrap JavaScript code to obfuscate
15
- * @returns {string} Obfuscated JavaScript code
16
- */
17
- export function obfuscateBootstrap(bootstrapCode) {
18
- const obfuscationResult = JavaScriptObfuscator.obfuscate(bootstrapCode, {
19
- // Maximum protection settings for encryption key and decryption logic
20
- stringArray: true,
21
- stringArrayThreshold: 1,
22
- stringArrayEncoding: ['rc4'],
23
- stringArrayIndexShift: true,
24
- stringArrayRotate: true,
25
- stringArrayShuffle: true,
26
- stringArrayWrappersCount: 5,
27
- stringArrayWrappersChainedCalls: true,
28
- stringArrayWrappersParametersMaxCount: 5,
29
- stringArrayWrappersType: 'function',
30
- controlFlowFlattening: true,
31
- controlFlowFlatteningThreshold: 1,
32
- deadCodeInjection: true,
33
- deadCodeInjectionThreshold: 0.4,
34
- transformObjectKeys: true,
35
- splitStrings: true,
36
- splitStringsChunkLength: 10,
37
- identifierNamesGenerator: 'hexadecimal',
38
- identifiersPrefix: '',
39
- renameGlobals: false,
40
- renameProperties: false,
41
- selfDefending: true,
42
- compact: true,
43
- numbersToExpressions: true,
44
- simplify: true,
45
- target: 'node',
46
- ignoreImports: true,
47
- sourceMap: false
48
- });
49
-
50
- return obfuscationResult.getObfuscatedCode();
51
- }
1
+ /**
2
+ * obfuscate.mjs
3
+ * Obfuscate bootstrap code to protect encryption keys and decryption logic
4
+ */
5
+
6
+ import Module from 'module';
7
+
8
+ const require = Module.createRequire(import.meta.url);
9
+ const JavaScriptObfuscator = require('javascript-obfuscator');
10
+
11
+ /**
12
+ * Obfuscate bootstrap code with maximum protection settings
13
+ *
14
+ * @param {string} bootstrapCode - The bootstrap JavaScript code to obfuscate
15
+ * @returns {string} Obfuscated JavaScript code
16
+ */
17
+ export function obfuscateBootstrap(bootstrapCode) {
18
+ const obfuscationResult = JavaScriptObfuscator.obfuscate(bootstrapCode, {
19
+ // Maximum protection settings for encryption key and decryption logic
20
+ stringArray: true,
21
+ stringArrayThreshold: 1,
22
+ stringArrayEncoding: ['rc4'],
23
+ stringArrayIndexShift: true,
24
+ stringArrayRotate: true,
25
+ stringArrayShuffle: true,
26
+ stringArrayWrappersCount: 5,
27
+ stringArrayWrappersChainedCalls: true,
28
+ stringArrayWrappersParametersMaxCount: 5,
29
+ stringArrayWrappersType: 'function',
30
+ controlFlowFlattening: true,
31
+ controlFlowFlatteningThreshold: 1,
32
+ deadCodeInjection: true,
33
+ deadCodeInjectionThreshold: 0.4,
34
+ transformObjectKeys: true,
35
+ splitStrings: true,
36
+ splitStringsChunkLength: 10,
37
+ identifierNamesGenerator: 'hexadecimal',
38
+ identifiersPrefix: '',
39
+ renameGlobals: false,
40
+ renameProperties: false,
41
+ selfDefending: true,
42
+ compact: true,
43
+ numbersToExpressions: true,
44
+ simplify: true,
45
+ target: 'node',
46
+ ignoreImports: true,
47
+ sourceMap: false
48
+ });
49
+
50
+ return obfuscationResult.getObfuscatedCode();
51
+ }