@robinpath/cli 1.73.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.
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Native child process module for RobinPath.
3
+ * Execute system commands and spawn processes.
4
+ */
5
+ import { exec as _exec, execSync as _execSync, spawn as _spawn } from 'node:child_process';
6
+ import { toStr, toNum, requireArgs } from './_helpers.js';
7
+
8
+ const _processes = new Map();
9
+ let _nextId = 1;
10
+
11
+ export const ChildFunctions = {
12
+
13
+ exec: (args) => {
14
+ requireArgs('child.exec', args, 1);
15
+ const command = toStr(args[0]);
16
+ const opts = {};
17
+ if (args[1] && typeof args[1] === 'object') {
18
+ if (args[1].cwd) opts.cwd = toStr(args[1].cwd);
19
+ if (args[1].timeout) opts.timeout = toNum(args[1].timeout);
20
+ if (args[1].encoding) opts.encoding = toStr(args[1].encoding);
21
+ if (args[1].env) opts.env = { ...process.env, ...args[1].env };
22
+ if (args[1].maxBuffer) opts.maxBuffer = toNum(args[1].maxBuffer);
23
+ if (args[1].shell) opts.shell = toStr(args[1].shell);
24
+ }
25
+ opts.encoding = opts.encoding || 'utf-8';
26
+
27
+ return new Promise((resolve, reject) => {
28
+ _exec(command, opts, (error, stdout, stderr) => {
29
+ resolve({
30
+ stdout: stdout || '',
31
+ stderr: stderr || '',
32
+ code: error ? error.code ?? 1 : 0,
33
+ error: error ? error.message : null
34
+ });
35
+ });
36
+ });
37
+ },
38
+
39
+ execSync: (args) => {
40
+ requireArgs('child.execSync', args, 1);
41
+ const command = toStr(args[0]);
42
+ const opts = { encoding: 'utf-8' };
43
+ if (args[1] && typeof args[1] === 'object') {
44
+ if (args[1].cwd) opts.cwd = toStr(args[1].cwd);
45
+ if (args[1].timeout) opts.timeout = toNum(args[1].timeout);
46
+ if (args[1].shell) opts.shell = toStr(args[1].shell);
47
+ }
48
+ try {
49
+ return _execSync(command, opts);
50
+ } catch (err) {
51
+ return {
52
+ stdout: err.stdout || '',
53
+ stderr: err.stderr || '',
54
+ code: err.status ?? 1,
55
+ error: err.message
56
+ };
57
+ }
58
+ },
59
+
60
+ spawn: (args) => {
61
+ requireArgs('child.spawn', args, 1);
62
+ const command = toStr(args[0]);
63
+ const spawnArgs = Array.isArray(args[1]) ? args[1].map(a => toStr(a)) : [];
64
+ const opts = { shell: true };
65
+ if (args[2] && typeof args[2] === 'object') {
66
+ if (args[2].cwd) opts.cwd = toStr(args[2].cwd);
67
+ if (args[2].env) opts.env = { ...process.env, ...args[2].env };
68
+ if (args[2].shell !== undefined) opts.shell = args[2].shell;
69
+ if (args[2].detached) opts.detached = true;
70
+ }
71
+
72
+ const child = _spawn(command, spawnArgs, opts);
73
+ const id = `proc_${_nextId++}`;
74
+ let stdout = '';
75
+ let stderr = '';
76
+
77
+ if (child.stdout) child.stdout.on('data', (d) => { stdout += d; });
78
+ if (child.stderr) child.stderr.on('data', (d) => { stderr += d; });
79
+
80
+ const resultPromise = new Promise((resolve) => {
81
+ child.on('close', (code) => {
82
+ _processes.delete(id);
83
+ resolve({ id, stdout, stderr, code: code ?? 0 });
84
+ });
85
+ child.on('error', (err) => {
86
+ _processes.delete(id);
87
+ resolve({ id, stdout, stderr, code: 1, error: err.message });
88
+ });
89
+ });
90
+
91
+ _processes.set(id, { child, resultPromise });
92
+ return id;
93
+ },
94
+
95
+ wait: async (args) => {
96
+ requireArgs('child.wait', args, 1);
97
+ const id = toStr(args[0]);
98
+ const proc = _processes.get(id);
99
+ if (!proc) return { error: `Process ${id} not found` };
100
+ return await proc.resultPromise;
101
+ },
102
+
103
+ kill: (args) => {
104
+ requireArgs('child.kill', args, 1);
105
+ const id = toStr(args[0]);
106
+ const signal = toStr(args[1], 'SIGTERM');
107
+ const proc = _processes.get(id);
108
+ if (!proc) return false;
109
+ proc.child.kill(signal);
110
+ _processes.delete(id);
111
+ return true;
112
+ },
113
+
114
+ running: () => {
115
+ return Array.from(_processes.keys());
116
+ }
117
+ };
118
+
119
+ export const ChildFunctionMetadata = {
120
+ exec: {
121
+ description: 'Execute a shell command and return output',
122
+ parameters: [
123
+ { name: 'command', dataType: 'string', description: 'Shell command to execute', formInputType: 'text', required: true },
124
+ { name: 'options', dataType: 'object', description: 'Options: cwd, timeout, encoding, env, maxBuffer, shell', formInputType: 'json', required: false }
125
+ ],
126
+ returnType: 'object', returnDescription: 'Object with stdout, stderr, code, error', example: 'child.exec "ls -la"'
127
+ },
128
+ execSync: {
129
+ description: 'Execute a shell command synchronously',
130
+ parameters: [
131
+ { name: 'command', dataType: 'string', description: 'Shell command', formInputType: 'text', required: true },
132
+ { name: 'options', dataType: 'object', description: 'Options: cwd, timeout, shell', formInputType: 'json', required: false }
133
+ ],
134
+ returnType: 'string', returnDescription: 'Command output string', example: 'child.execSync "echo hello"'
135
+ },
136
+ spawn: {
137
+ description: 'Spawn a child process (non-blocking)',
138
+ parameters: [
139
+ { name: 'command', dataType: 'string', description: 'Command to run', formInputType: 'text', required: true },
140
+ { name: 'args', dataType: 'array', description: 'Command arguments', formInputType: 'json', required: false },
141
+ { name: 'options', dataType: 'object', description: 'Options: cwd, env, shell, detached', formInputType: 'json', required: false }
142
+ ],
143
+ returnType: 'string', returnDescription: 'Process handle ID', example: 'child.spawn "node" ["server.js"]'
144
+ },
145
+ wait: {
146
+ description: 'Wait for a spawned process to finish',
147
+ parameters: [{ name: 'processId', dataType: 'string', description: 'Process handle ID from spawn', formInputType: 'text', required: true }],
148
+ returnType: 'object', returnDescription: 'Object with stdout, stderr, code', example: 'child.wait $pid'
149
+ },
150
+ kill: {
151
+ description: 'Kill a spawned process',
152
+ parameters: [
153
+ { name: 'processId', dataType: 'string', description: 'Process handle ID', formInputType: 'text', required: true },
154
+ { name: 'signal', dataType: 'string', description: 'Signal (default: SIGTERM)', formInputType: 'text', required: false, defaultValue: 'SIGTERM' }
155
+ ],
156
+ returnType: 'boolean', returnDescription: 'true if killed', example: 'child.kill $pid'
157
+ },
158
+ running: {
159
+ description: 'List all running spawned processes',
160
+ parameters: [],
161
+ returnType: 'array', returnDescription: 'Array of process handle IDs', example: 'child.running'
162
+ }
163
+ };
164
+
165
+ export const ChildModuleMetadata = {
166
+ description: 'Child process execution: exec, execSync, spawn, kill, and process management',
167
+ methods: Object.keys(ChildFunctions)
168
+ };
169
+
170
+ export default {
171
+ name: 'child',
172
+ functions: ChildFunctions,
173
+ functionMetadata: ChildFunctionMetadata,
174
+ moduleMetadata: ChildModuleMetadata,
175
+ global: false
176
+ };
@@ -0,0 +1,352 @@
1
+ /**
2
+ * Native crypto module for RobinPath.
3
+ * Full cryptographic operations powered by Node.js crypto.
4
+ */
5
+ import {
6
+ createHash, createHmac, createCipheriv, createDecipheriv,
7
+ randomBytes, randomUUID, randomInt, pbkdf2 as _pbkdf2, scrypt as _scrypt,
8
+ getCiphers, getHashes
9
+ } from 'node:crypto';
10
+ import { toStr, toNum, requireArgs } from './_helpers.js';
11
+
12
+ export const CryptoNativeFunctions = {
13
+
14
+ // --- Hashing ---
15
+
16
+ hash: async (args) => {
17
+ requireArgs('crypto.hash', args, 2);
18
+ const algo = toStr(args[0]);
19
+ const data = toStr(args[1]);
20
+ const encoding = toStr(args[2], 'hex');
21
+ return createHash(algo).update(data).digest(encoding);
22
+ },
23
+
24
+ md5: async (args) => {
25
+ requireArgs('crypto.md5', args, 1);
26
+ return createHash('md5').update(toStr(args[0])).digest('hex');
27
+ },
28
+
29
+ sha1: async (args) => {
30
+ requireArgs('crypto.sha1', args, 1);
31
+ return createHash('sha1').update(toStr(args[0])).digest('hex');
32
+ },
33
+
34
+ sha256: async (args) => {
35
+ requireArgs('crypto.sha256', args, 1);
36
+ return createHash('sha256').update(toStr(args[0])).digest('hex');
37
+ },
38
+
39
+ sha512: async (args) => {
40
+ requireArgs('crypto.sha512', args, 1);
41
+ return createHash('sha512').update(toStr(args[0])).digest('hex');
42
+ },
43
+
44
+ // --- HMAC ---
45
+
46
+ hmac: async (args) => {
47
+ requireArgs('crypto.hmac', args, 3);
48
+ const algo = toStr(args[0]);
49
+ const key = toStr(args[1]);
50
+ const data = toStr(args[2]);
51
+ const encoding = toStr(args[3], 'hex');
52
+ return createHmac(algo, key).update(data).digest(encoding);
53
+ },
54
+
55
+ hmacSha256: async (args) => {
56
+ requireArgs('crypto.hmacSha256', args, 2);
57
+ return createHmac('sha256', toStr(args[0])).update(toStr(args[1])).digest('hex');
58
+ },
59
+
60
+ hmacSha512: async (args) => {
61
+ requireArgs('crypto.hmacSha512', args, 2);
62
+ return createHmac('sha512', toStr(args[0])).update(toStr(args[1])).digest('hex');
63
+ },
64
+
65
+ // --- Encryption ---
66
+
67
+ encrypt: async (args) => {
68
+ requireArgs('crypto.encrypt', args, 3);
69
+ const algo = toStr(args[0], 'aes-256-cbc');
70
+ const key = toStr(args[1]);
71
+ const data = toStr(args[2]);
72
+ // Derive a 32-byte key from the input key
73
+ const keyBuf = createHash('sha256').update(key).digest();
74
+ // Generate random IV
75
+ const iv = randomBytes(16);
76
+ const cipher = createCipheriv(algo, keyBuf, iv);
77
+ let encrypted = cipher.update(data, 'utf-8', 'hex');
78
+ encrypted += cipher.final('hex');
79
+ // Return IV + encrypted data separated by ':'
80
+ return iv.toString('hex') + ':' + encrypted;
81
+ },
82
+
83
+ decrypt: async (args) => {
84
+ requireArgs('crypto.decrypt', args, 3);
85
+ const algo = toStr(args[0], 'aes-256-cbc');
86
+ const key = toStr(args[1]);
87
+ const encryptedStr = toStr(args[2]);
88
+ const keyBuf = createHash('sha256').update(key).digest();
89
+ const parts = encryptedStr.split(':');
90
+ if (parts.length !== 2) throw new Error('crypto.decrypt: invalid encrypted data format (expected iv:data)');
91
+ const iv = Buffer.from(parts[0], 'hex');
92
+ const encrypted = parts[1];
93
+ const decipher = createDecipheriv(algo, keyBuf, iv);
94
+ let decrypted = decipher.update(encrypted, 'hex', 'utf-8');
95
+ decrypted += decipher.final('utf-8');
96
+ return decrypted;
97
+ },
98
+
99
+ // --- Random ---
100
+
101
+ randomBytes: async (args) => {
102
+ const size = toNum(args[0], 32);
103
+ const encoding = toStr(args[1], 'hex');
104
+ return randomBytes(size).toString(encoding);
105
+ },
106
+
107
+ randomUUID: () => randomUUID(),
108
+
109
+ randomInt: (args) => {
110
+ const min = args.length >= 2 ? toNum(args[0], 0) : 0;
111
+ const max = args.length >= 2 ? toNum(args[1], 100) : toNum(args[0], 100);
112
+ return randomInt(min, max);
113
+ },
114
+
115
+ // --- Key Derivation ---
116
+
117
+ pbkdf2: (args) => {
118
+ requireArgs('crypto.pbkdf2', args, 2);
119
+ const password = toStr(args[0]);
120
+ const salt = toStr(args[1], 'salt');
121
+ const iterations = toNum(args[2], 100000);
122
+ const keylen = toNum(args[3], 64);
123
+ const digest = toStr(args[4], 'sha512');
124
+ return new Promise((resolve, reject) => {
125
+ _pbkdf2(password, salt, iterations, keylen, digest, (err, key) => {
126
+ if (err) reject(err);
127
+ else resolve(key.toString('hex'));
128
+ });
129
+ });
130
+ },
131
+
132
+ scrypt: (args) => {
133
+ requireArgs('crypto.scrypt', args, 2);
134
+ const password = toStr(args[0]);
135
+ const salt = toStr(args[1]);
136
+ const keylen = toNum(args[2], 64);
137
+ return new Promise((resolve, reject) => {
138
+ _scrypt(password, salt, keylen, (err, key) => {
139
+ if (err) reject(err);
140
+ else resolve(key.toString('hex'));
141
+ });
142
+ });
143
+ },
144
+
145
+ // --- Encoding ---
146
+
147
+ base64Encode: (args) => {
148
+ requireArgs('crypto.base64Encode', args, 1);
149
+ return Buffer.from(toStr(args[0])).toString('base64');
150
+ },
151
+
152
+ base64Decode: (args) => {
153
+ requireArgs('crypto.base64Decode', args, 1);
154
+ return Buffer.from(toStr(args[0]), 'base64').toString('utf-8');
155
+ },
156
+
157
+ base64UrlEncode: (args) => {
158
+ requireArgs('crypto.base64UrlEncode', args, 1);
159
+ return Buffer.from(toStr(args[0])).toString('base64url');
160
+ },
161
+
162
+ base64UrlDecode: (args) => {
163
+ requireArgs('crypto.base64UrlDecode', args, 1);
164
+ return Buffer.from(toStr(args[0]), 'base64url').toString('utf-8');
165
+ },
166
+
167
+ hexEncode: (args) => {
168
+ requireArgs('crypto.hexEncode', args, 1);
169
+ return Buffer.from(toStr(args[0])).toString('hex');
170
+ },
171
+
172
+ hexDecode: (args) => {
173
+ requireArgs('crypto.hexDecode', args, 1);
174
+ return Buffer.from(toStr(args[0]), 'hex').toString('utf-8');
175
+ },
176
+
177
+ // --- Info ---
178
+
179
+ ciphers: () => getCiphers(),
180
+
181
+ hashes: () => getHashes()
182
+ };
183
+
184
+ export const CryptoNativeFunctionMetadata = {
185
+ hash: {
186
+ description: 'Hash data with any supported algorithm',
187
+ parameters: [
188
+ { name: 'algorithm', dataType: 'string', description: 'Hash algorithm (md5, sha256, sha512, etc.)', formInputType: 'text', required: true },
189
+ { name: 'data', dataType: 'string', description: 'Data to hash', formInputType: 'text', required: true },
190
+ { name: 'encoding', dataType: 'string', description: 'Output encoding (hex, base64)', formInputType: 'text', required: false, defaultValue: 'hex' }
191
+ ],
192
+ returnType: 'string', returnDescription: 'Hash digest', example: 'crypto.hash "sha256" "hello"'
193
+ },
194
+ md5: {
195
+ description: 'MD5 hash',
196
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to hash', formInputType: 'text', required: true }],
197
+ returnType: 'string', returnDescription: 'MD5 hex digest', example: 'crypto.md5 "hello"'
198
+ },
199
+ sha1: {
200
+ description: 'SHA-1 hash',
201
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to hash', formInputType: 'text', required: true }],
202
+ returnType: 'string', returnDescription: 'SHA-1 hex digest', example: 'crypto.sha1 "hello"'
203
+ },
204
+ sha256: {
205
+ description: 'SHA-256 hash',
206
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to hash', formInputType: 'text', required: true }],
207
+ returnType: 'string', returnDescription: 'SHA-256 hex digest', example: 'crypto.sha256 "hello"'
208
+ },
209
+ sha512: {
210
+ description: 'SHA-512 hash',
211
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to hash', formInputType: 'text', required: true }],
212
+ returnType: 'string', returnDescription: 'SHA-512 hex digest', example: 'crypto.sha512 "hello"'
213
+ },
214
+ hmac: {
215
+ description: 'HMAC with any algorithm',
216
+ parameters: [
217
+ { name: 'algorithm', dataType: 'string', description: 'Hash algorithm', formInputType: 'text', required: true },
218
+ { name: 'key', dataType: 'string', description: 'Secret key', formInputType: 'text', required: true },
219
+ { name: 'data', dataType: 'string', description: 'Data to sign', formInputType: 'text', required: true },
220
+ { name: 'encoding', dataType: 'string', description: 'Output encoding', formInputType: 'text', required: false, defaultValue: 'hex' }
221
+ ],
222
+ returnType: 'string', returnDescription: 'HMAC digest', example: 'crypto.hmac "sha256" "secret" "data"'
223
+ },
224
+ hmacSha256: {
225
+ description: 'HMAC-SHA256',
226
+ parameters: [
227
+ { name: 'key', dataType: 'string', description: 'Secret key', formInputType: 'text', required: true },
228
+ { name: 'data', dataType: 'string', description: 'Data to sign', formInputType: 'text', required: true }
229
+ ],
230
+ returnType: 'string', returnDescription: 'HMAC-SHA256 hex digest', example: 'crypto.hmacSha256 "secret" "data"'
231
+ },
232
+ hmacSha512: {
233
+ description: 'HMAC-SHA512',
234
+ parameters: [
235
+ { name: 'key', dataType: 'string', description: 'Secret key', formInputType: 'text', required: true },
236
+ { name: 'data', dataType: 'string', description: 'Data to sign', formInputType: 'text', required: true }
237
+ ],
238
+ returnType: 'string', returnDescription: 'HMAC-SHA512 hex digest', example: 'crypto.hmacSha512 "secret" "data"'
239
+ },
240
+ encrypt: {
241
+ description: 'Encrypt data with AES (returns iv:ciphertext)',
242
+ parameters: [
243
+ { name: 'algorithm', dataType: 'string', description: 'Cipher algorithm (default: aes-256-cbc)', formInputType: 'text', required: false, defaultValue: 'aes-256-cbc' },
244
+ { name: 'key', dataType: 'string', description: 'Encryption key (hashed to 32 bytes)', formInputType: 'text', required: true },
245
+ { name: 'data', dataType: 'string', description: 'Data to encrypt', formInputType: 'text', required: true }
246
+ ],
247
+ returnType: 'string', returnDescription: 'iv:encryptedHex string', example: 'crypto.encrypt "aes-256-cbc" "mykey" "secret data"'
248
+ },
249
+ decrypt: {
250
+ description: 'Decrypt data from encrypt() output',
251
+ parameters: [
252
+ { name: 'algorithm', dataType: 'string', description: 'Cipher algorithm', formInputType: 'text', required: false, defaultValue: 'aes-256-cbc' },
253
+ { name: 'key', dataType: 'string', description: 'Encryption key', formInputType: 'text', required: true },
254
+ { name: 'encryptedData', dataType: 'string', description: 'iv:ciphertext from encrypt()', formInputType: 'text', required: true }
255
+ ],
256
+ returnType: 'string', returnDescription: 'Decrypted string', example: 'crypto.decrypt "aes-256-cbc" "mykey" $encrypted'
257
+ },
258
+ randomBytes: {
259
+ description: 'Generate random bytes',
260
+ parameters: [
261
+ { name: 'size', dataType: 'number', description: 'Number of bytes (default: 32)', formInputType: 'number', required: false, defaultValue: 32 },
262
+ { name: 'encoding', dataType: 'string', description: 'Output encoding (hex, base64)', formInputType: 'text', required: false, defaultValue: 'hex' }
263
+ ],
264
+ returnType: 'string', returnDescription: 'Random bytes as encoded string', example: 'crypto.randomBytes 16'
265
+ },
266
+ randomUUID: {
267
+ description: 'Generate a random UUID v4',
268
+ parameters: [],
269
+ returnType: 'string', returnDescription: 'UUID v4 string', example: 'crypto.randomUUID'
270
+ },
271
+ randomInt: {
272
+ description: 'Generate a random integer',
273
+ parameters: [
274
+ { name: 'min', dataType: 'number', description: 'Minimum (or max if single arg)', formInputType: 'number', required: false, defaultValue: 0 },
275
+ { name: 'max', dataType: 'number', description: 'Maximum (exclusive)', formInputType: 'number', required: false, defaultValue: 100 }
276
+ ],
277
+ returnType: 'number', returnDescription: 'Random integer', example: 'crypto.randomInt 1 100'
278
+ },
279
+ pbkdf2: {
280
+ description: 'Derive key using PBKDF2',
281
+ parameters: [
282
+ { name: 'password', dataType: 'string', description: 'Password', formInputType: 'text', required: true },
283
+ { name: 'salt', dataType: 'string', description: 'Salt', formInputType: 'text', required: true },
284
+ { name: 'iterations', dataType: 'number', description: 'Iterations (default: 100000)', formInputType: 'number', required: false, defaultValue: 100000 },
285
+ { name: 'keylen', dataType: 'number', description: 'Key length (default: 64)', formInputType: 'number', required: false, defaultValue: 64 },
286
+ { name: 'digest', dataType: 'string', description: 'Digest algorithm (default: sha512)', formInputType: 'text', required: false, defaultValue: 'sha512' }
287
+ ],
288
+ returnType: 'string', returnDescription: 'Derived key as hex', example: 'crypto.pbkdf2 "password" "salt"'
289
+ },
290
+ scrypt: {
291
+ description: 'Derive key using scrypt',
292
+ parameters: [
293
+ { name: 'password', dataType: 'string', description: 'Password', formInputType: 'text', required: true },
294
+ { name: 'salt', dataType: 'string', description: 'Salt', formInputType: 'text', required: true },
295
+ { name: 'keylen', dataType: 'number', description: 'Key length (default: 64)', formInputType: 'number', required: false, defaultValue: 64 }
296
+ ],
297
+ returnType: 'string', returnDescription: 'Derived key as hex', example: 'crypto.scrypt "password" "salt"'
298
+ },
299
+ base64Encode: {
300
+ description: 'Encode string to Base64',
301
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to encode', formInputType: 'text', required: true }],
302
+ returnType: 'string', returnDescription: 'Base64 encoded string', example: 'crypto.base64Encode "hello"'
303
+ },
304
+ base64Decode: {
305
+ description: 'Decode Base64 to string',
306
+ parameters: [{ name: 'data', dataType: 'string', description: 'Base64 data', formInputType: 'text', required: true }],
307
+ returnType: 'string', returnDescription: 'Decoded string', example: 'crypto.base64Decode "aGVsbG8="'
308
+ },
309
+ base64UrlEncode: {
310
+ description: 'Encode string to URL-safe Base64',
311
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to encode', formInputType: 'text', required: true }],
312
+ returnType: 'string', returnDescription: 'Base64url encoded string', example: 'crypto.base64UrlEncode "hello"'
313
+ },
314
+ base64UrlDecode: {
315
+ description: 'Decode URL-safe Base64 to string',
316
+ parameters: [{ name: 'data', dataType: 'string', description: 'Base64url data', formInputType: 'text', required: true }],
317
+ returnType: 'string', returnDescription: 'Decoded string', example: 'crypto.base64UrlDecode "aGVsbG8"'
318
+ },
319
+ hexEncode: {
320
+ description: 'Encode string to hex',
321
+ parameters: [{ name: 'data', dataType: 'string', description: 'Data to encode', formInputType: 'text', required: true }],
322
+ returnType: 'string', returnDescription: 'Hex encoded string', example: 'crypto.hexEncode "hello"'
323
+ },
324
+ hexDecode: {
325
+ description: 'Decode hex to string',
326
+ parameters: [{ name: 'data', dataType: 'string', description: 'Hex data', formInputType: 'text', required: true }],
327
+ returnType: 'string', returnDescription: 'Decoded string', example: 'crypto.hexDecode "68656c6c6f"'
328
+ },
329
+ ciphers: {
330
+ description: 'List all supported cipher algorithms',
331
+ parameters: [],
332
+ returnType: 'array', returnDescription: 'Array of cipher names', example: 'crypto.ciphers'
333
+ },
334
+ hashes: {
335
+ description: 'List all supported hash algorithms',
336
+ parameters: [],
337
+ returnType: 'array', returnDescription: 'Array of hash names', example: 'crypto.hashes'
338
+ }
339
+ };
340
+
341
+ export const CryptoNativeModuleMetadata = {
342
+ description: 'Cryptographic operations: hashing, HMAC, encryption, key derivation, random generation, and encoding',
343
+ methods: Object.keys(CryptoNativeFunctions)
344
+ };
345
+
346
+ export default {
347
+ name: 'crypto',
348
+ functions: CryptoNativeFunctions,
349
+ functionMetadata: CryptoNativeFunctionMetadata,
350
+ moduleMetadata: CryptoNativeModuleMetadata,
351
+ global: false
352
+ };
package/modules/dns.js ADDED
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Native DNS module for RobinPath.
3
+ * DNS resolution and lookup.
4
+ */
5
+ import { promises as dns } from 'node:dns';
6
+ import { toStr, requireArgs } from './_helpers.js';
7
+
8
+ export const DnsFunctions = {
9
+
10
+ lookup: async (args) => {
11
+ requireArgs('dns.lookup', args, 1);
12
+ const hostname = toStr(args[0]);
13
+ const result = await dns.lookup(hostname, { all: true });
14
+ if (Array.isArray(result)) {
15
+ return result.map(r => ({ address: r.address, family: r.family }));
16
+ }
17
+ return { address: result.address, family: result.family };
18
+ },
19
+
20
+ resolve: async (args) => {
21
+ requireArgs('dns.resolve', args, 1);
22
+ const hostname = toStr(args[0]);
23
+ const rrtype = toStr(args[1], 'A');
24
+ return await dns.resolve(hostname, rrtype);
25
+ },
26
+
27
+ resolve4: async (args) => {
28
+ requireArgs('dns.resolve4', args, 1);
29
+ return await dns.resolve4(toStr(args[0]));
30
+ },
31
+
32
+ resolve6: async (args) => {
33
+ requireArgs('dns.resolve6', args, 1);
34
+ return await dns.resolve6(toStr(args[0]));
35
+ },
36
+
37
+ resolveMx: async (args) => {
38
+ requireArgs('dns.resolveMx', args, 1);
39
+ return await dns.resolveMx(toStr(args[0]));
40
+ },
41
+
42
+ resolveTxt: async (args) => {
43
+ requireArgs('dns.resolveTxt', args, 1);
44
+ const records = await dns.resolveTxt(toStr(args[0]));
45
+ return records.map(r => r.join(''));
46
+ },
47
+
48
+ resolveNs: async (args) => {
49
+ requireArgs('dns.resolveNs', args, 1);
50
+ return await dns.resolveNs(toStr(args[0]));
51
+ },
52
+
53
+ resolveCname: async (args) => {
54
+ requireArgs('dns.resolveCname', args, 1);
55
+ return await dns.resolveCname(toStr(args[0]));
56
+ },
57
+
58
+ resolveSrv: async (args) => {
59
+ requireArgs('dns.resolveSrv', args, 1);
60
+ return await dns.resolveSrv(toStr(args[0]));
61
+ },
62
+
63
+ resolveSoa: async (args) => {
64
+ requireArgs('dns.resolveSoa', args, 1);
65
+ return await dns.resolveSoa(toStr(args[0]));
66
+ },
67
+
68
+ reverse: async (args) => {
69
+ requireArgs('dns.reverse', args, 1);
70
+ return await dns.reverse(toStr(args[0]));
71
+ }
72
+ };
73
+
74
+ export const DnsFunctionMetadata = {
75
+ lookup: {
76
+ description: 'Resolve hostname to IP address(es)',
77
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Hostname to resolve', formInputType: 'text', required: true }],
78
+ returnType: 'array', returnDescription: 'Array of {address, family}', example: 'dns.lookup "google.com"'
79
+ },
80
+ resolve: {
81
+ description: 'Resolve DNS records by type',
82
+ parameters: [
83
+ { name: 'hostname', dataType: 'string', description: 'Hostname', formInputType: 'text', required: true },
84
+ { name: 'rrtype', dataType: 'string', description: 'Record type (A, AAAA, MX, TXT, etc.)', formInputType: 'text', required: false, defaultValue: 'A' }
85
+ ],
86
+ returnType: 'array', returnDescription: 'Array of DNS records', example: 'dns.resolve "example.com" "MX"'
87
+ },
88
+ resolve4: {
89
+ description: 'Resolve IPv4 addresses',
90
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Hostname', formInputType: 'text', required: true }],
91
+ returnType: 'array', returnDescription: 'Array of IPv4 addresses', example: 'dns.resolve4 "google.com"'
92
+ },
93
+ resolve6: {
94
+ description: 'Resolve IPv6 addresses',
95
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Hostname', formInputType: 'text', required: true }],
96
+ returnType: 'array', returnDescription: 'Array of IPv6 addresses', example: 'dns.resolve6 "google.com"'
97
+ },
98
+ resolveMx: {
99
+ description: 'Resolve MX (mail) records',
100
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Domain', formInputType: 'text', required: true }],
101
+ returnType: 'array', returnDescription: 'Array of {exchange, priority}', example: 'dns.resolveMx "gmail.com"'
102
+ },
103
+ resolveTxt: {
104
+ description: 'Resolve TXT records',
105
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Domain', formInputType: 'text', required: true }],
106
+ returnType: 'array', returnDescription: 'Array of TXT record strings', example: 'dns.resolveTxt "example.com"'
107
+ },
108
+ resolveNs: {
109
+ description: 'Resolve NS (nameserver) records',
110
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Domain', formInputType: 'text', required: true }],
111
+ returnType: 'array', returnDescription: 'Array of nameserver hostnames', example: 'dns.resolveNs "example.com"'
112
+ },
113
+ resolveCname: {
114
+ description: 'Resolve CNAME records',
115
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Hostname', formInputType: 'text', required: true }],
116
+ returnType: 'array', returnDescription: 'Array of CNAME records', example: 'dns.resolveCname "www.example.com"'
117
+ },
118
+ resolveSrv: {
119
+ description: 'Resolve SRV records',
120
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Hostname', formInputType: 'text', required: true }],
121
+ returnType: 'array', returnDescription: 'Array of SRV records', example: 'dns.resolveSrv "_http._tcp.example.com"'
122
+ },
123
+ resolveSoa: {
124
+ description: 'Resolve SOA (Start of Authority) record',
125
+ parameters: [{ name: 'hostname', dataType: 'string', description: 'Domain', formInputType: 'text', required: true }],
126
+ returnType: 'object', returnDescription: 'SOA record object', example: 'dns.resolveSoa "example.com"'
127
+ },
128
+ reverse: {
129
+ description: 'Reverse DNS lookup (IP to hostname)',
130
+ parameters: [{ name: 'ip', dataType: 'string', description: 'IP address', formInputType: 'text', required: true }],
131
+ returnType: 'array', returnDescription: 'Array of hostnames', example: 'dns.reverse "8.8.8.8"'
132
+ }
133
+ };
134
+
135
+ export const DnsModuleMetadata = {
136
+ description: 'DNS resolution: lookup, resolve A/AAAA/MX/TXT/NS/SRV/SOA records, reverse lookup',
137
+ methods: Object.keys(DnsFunctions)
138
+ };
139
+
140
+ export default {
141
+ name: 'dns',
142
+ functions: DnsFunctions,
143
+ functionMetadata: DnsFunctionMetadata,
144
+ moduleMetadata: DnsModuleMetadata,
145
+ global: false
146
+ };