bscript-cli 1.0.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.
- package/BScript.js +233 -0
- package/Docs/BScript/BSCRIPT-REFERENCE-CLI.md +502 -0
- package/Docs/Images/BScript-baner.png +0 -0
- package/Docs/Images/BooleanType.png +0 -0
- package/Docs/Images/FuncionType.png +0 -0
- package/Docs/Images/Logo.png +0 -0
- package/Docs/Images/NumberType.png +0 -0
- package/Docs/Images/ObjectType.png +0 -0
- package/Docs/Images/PromiseType.png +0 -0
- package/Docs/Images/RawType.png +0 -0
- package/Docs/Images/RefType.png +0 -0
- package/Docs/Images/TextType.png +0 -0
- package/Docs/README.md +157 -0
- package/Docs/REFERENCE.md +602 -0
- package/Docs/TECHNICAL.md +1143 -0
- package/Docs/TUTORIAL.md +604 -0
- package/SRC/BScriptHistory.js +98 -0
- package/SRC/CMDPermissions.js +4 -0
- package/SRC/utils/utils.js +63 -0
- package/TerminalCommandController.js +193 -0
- package/bin/bscript.js +94 -0
- package/commands/.default/BScript/$arg.js +9 -0
- package/commands/.default/BScript/$val.js +19 -0
- package/commands/.default/BScript/Input.js +10 -0
- package/commands/.default/BScript/bool.js +9 -0
- package/commands/.default/BScript/delay.js +10 -0
- package/commands/.default/BScript/eval.js +9 -0
- package/commands/.default/BScript/import.js +17 -0
- package/commands/.default/BScript/js_new.js +9 -0
- package/commands/.default/BScript/js_require.js +9 -0
- package/commands/.default/BScript/jstype.js +9 -0
- package/commands/.default/BScript/num.js +9 -0
- package/commands/.default/BScript/object.js +19 -0
- package/commands/.default/BScript/print.js +9 -0
- package/commands/.default/BScript/raw.js +9 -0
- package/commands/.default/BScript/ref.js +65 -0
- package/commands/.default/BScript/run-with-await.js +13 -0
- package/commands/.default/BScript/run.js +11 -0
- package/commands/.default/BScript/script.js +13 -0
- package/commands/.default/BScript/str.js +9 -0
- package/commands/.default/DebugOnly/clear.js +8 -0
- package/commands/.default/DebugOnly/update-commands.js +8 -0
- package/commands/.default/help.js +20 -0
- package/commands/snapshot.md +421 -0
- package/index.js +8 -0
- package/package.json +12 -0
- package/postinstall.js +12 -0
package/Docs/TUTORIAL.md
ADDED
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
Practical step-by-step guide for installing, configuring, and using BScript to build interactive command-line applications.
|
|
4
|
+
|
|
5
|
+
This guide focuses on real-world usage with complete examples. Detailed API information is available in **REFERENCE.md**.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [1. Installation](#1-installation)
|
|
12
|
+
- [2. Importing the package](#2-importing-the-package)
|
|
13
|
+
- [3. Initial setup](#3-initial-setup)
|
|
14
|
+
- [4. Core usage scenarios](#4-core-usage-scenarios)
|
|
15
|
+
- [5. Useful examples](#5-useful-examples)
|
|
16
|
+
- [6. Best practices](#6-best-practices)
|
|
17
|
+
- [See also](#see-also)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<a id="1-installation"></a>
|
|
22
|
+
|
|
23
|
+
## 1. Installation
|
|
24
|
+
|
|
25
|
+
### npm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install bscript
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### pnpm
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm add bscript
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### yarn
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
yarn add bscript
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
<a id="2-importing-the-package"></a>
|
|
46
|
+
|
|
47
|
+
## 2. Importing the package
|
|
48
|
+
|
|
49
|
+
### CommonJS
|
|
50
|
+
|
|
51
|
+
```javascript
|
|
52
|
+
const BScript = require("bscript");
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### ES Modules
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
import BScript from "bscript";
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
or
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
import { BScript } from "bscript";
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
<a id="3-initial-setup"></a>
|
|
70
|
+
|
|
71
|
+
## 3. Initial setup
|
|
72
|
+
|
|
73
|
+
### Basic Initialization
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
const BScript = require("bscript");
|
|
77
|
+
|
|
78
|
+
const cmd = new BScript({
|
|
79
|
+
commandsPaths: ["./commands"],
|
|
80
|
+
cmdRootPermissions: [0] // default permission level
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
cmd.updateCommands();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Description
|
|
87
|
+
|
|
88
|
+
When you create a new BScript instance, you're initializing an interactive command-line environment. The constructor accepts:
|
|
89
|
+
|
|
90
|
+
- **commandsPaths**: Array of directories to scan for command files
|
|
91
|
+
- **cmdRootPermissions**: Permission levels that determine which commands are available
|
|
92
|
+
- **cmdPermissionsHistory**: Initial permission stack for nested contexts
|
|
93
|
+
|
|
94
|
+
After configuration, call `updateCommands()` to load all command files from specified directories. BScript scans recursively and filters commands based on your permission settings.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
<a id="4-core-usage-scenarios"></a>
|
|
99
|
+
|
|
100
|
+
## 4. Core usage scenarios
|
|
101
|
+
|
|
102
|
+
### 4.1 Starting Interactive Mode
|
|
103
|
+
|
|
104
|
+
Start a fully-featured interactive command-line interface.
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const BScript = require("bscript");
|
|
108
|
+
|
|
109
|
+
const cmd = new BScript();
|
|
110
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.default];
|
|
111
|
+
cmd.updateCommands();
|
|
112
|
+
|
|
113
|
+
// Begin interactive mode with prompt
|
|
114
|
+
cmd.Start();
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Output
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
<help>? echo "Welcome to BScript"
|
|
121
|
+
> Welcome to BScript
|
|
122
|
+
<help>? help
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### 4.2 Executing Scripts from Code
|
|
128
|
+
|
|
129
|
+
Execute BScript code programmatically without interactive mode.
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
const BScript = require("bscript");
|
|
133
|
+
|
|
134
|
+
const cmd = new BScript();
|
|
135
|
+
cmd.cmdRootPermissions = [
|
|
136
|
+
cmd.perrmissionsKeys.default,
|
|
137
|
+
cmd.perrmissionsKeys.script
|
|
138
|
+
];
|
|
139
|
+
cmd.updateCommands();
|
|
140
|
+
|
|
141
|
+
// Execute inline script
|
|
142
|
+
const scriptFn = cmd.bscript('echo "Hello from script"');
|
|
143
|
+
scriptFn();
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### 4.3 Working with Permissions
|
|
149
|
+
|
|
150
|
+
Create different access levels for different users or contexts.
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
const BScript = require("bscript");
|
|
154
|
+
|
|
155
|
+
const cmd = new BScript({
|
|
156
|
+
perrmissionsKeys: {
|
|
157
|
+
default: 0,
|
|
158
|
+
admin: 100,
|
|
159
|
+
script: 999
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// User mode - only default commands available
|
|
164
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.default];
|
|
165
|
+
cmd.updateCommands();
|
|
166
|
+
cmd.Start();
|
|
167
|
+
|
|
168
|
+
// Later: switch to admin mode
|
|
169
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.admin];
|
|
170
|
+
cmd.updateCommands();
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### 4.4 Loading Commands from Multiple Directories
|
|
176
|
+
|
|
177
|
+
Organize commands in separate folders and load them all.
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
const BScript = require("bscript");
|
|
181
|
+
|
|
182
|
+
const cmd = new BScript({
|
|
183
|
+
commandsPaths: [
|
|
184
|
+
"./built-in-commands",
|
|
185
|
+
"./user-commands",
|
|
186
|
+
"./admin-commands"
|
|
187
|
+
]
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.default];
|
|
191
|
+
cmd.updateCommands();
|
|
192
|
+
cmd.Start();
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 4.5 Adding Commands Programmatically
|
|
198
|
+
|
|
199
|
+
Register commands without creating files.
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
const BScript = require("bscript");
|
|
203
|
+
|
|
204
|
+
const cmd = new BScript();
|
|
205
|
+
|
|
206
|
+
// Add a simple echo command
|
|
207
|
+
cmd.createCommand({
|
|
208
|
+
name: "echo",
|
|
209
|
+
description: "Echo text to console",
|
|
210
|
+
syntax: "echo [text...]",
|
|
211
|
+
execute: (args) => {
|
|
212
|
+
console.log(args.join(" "));
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Add a math command
|
|
217
|
+
cmd.createCommand({
|
|
218
|
+
name: "add",
|
|
219
|
+
description: "Add numbers",
|
|
220
|
+
syntax: "add [number1] [number2] ...",
|
|
221
|
+
execute: (args) => {
|
|
222
|
+
const sum = args.reduce((a, b) => a + parseFloat(b), 0);
|
|
223
|
+
console.log("Result:", sum);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
cmd.Start();
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Expected output
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
<help>? add 5 10 15
|
|
234
|
+
Result: 30
|
|
235
|
+
<help>? echo Hello World
|
|
236
|
+
Hello World
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
### 4.6 Using the Loader Animation
|
|
242
|
+
|
|
243
|
+
Display loading animation while executing async operations.
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
const BScript = require("bscript");
|
|
247
|
+
|
|
248
|
+
const cmd = new BScript();
|
|
249
|
+
|
|
250
|
+
cmd.createCommand({
|
|
251
|
+
name: "fetch-data",
|
|
252
|
+
description: "Fetch data with loading animation",
|
|
253
|
+
execute: () => {
|
|
254
|
+
cmd.loader(async (done, waitForPromise, startAnimation) => {
|
|
255
|
+
// Perform async work
|
|
256
|
+
const result = await waitForPromise(async () => {
|
|
257
|
+
return new Promise(resolve => {
|
|
258
|
+
setTimeout(() => {
|
|
259
|
+
resolve("Data loaded successfully!");
|
|
260
|
+
}, 3000);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
console.log(result);
|
|
265
|
+
done();
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
cmd.Start();
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Output
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
<help>? fetch-data
|
|
277
|
+
Loading...
|
|
278
|
+
Data loaded successfully!
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
<a id="5-useful-examples"></a>
|
|
284
|
+
|
|
285
|
+
## 5. Useful Examples
|
|
286
|
+
|
|
287
|
+
### Example 1 — Complete CLI Application
|
|
288
|
+
|
|
289
|
+
Build a complete calculator CLI with multiple commands and permissions.
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
const BScript = require("bscript");
|
|
293
|
+
|
|
294
|
+
const cmd = new BScript({
|
|
295
|
+
perrmissionsKeys: {
|
|
296
|
+
default: 0,
|
|
297
|
+
admin: 100
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.default];
|
|
302
|
+
|
|
303
|
+
// Basic math commands
|
|
304
|
+
cmd.createCommand({
|
|
305
|
+
name: "add",
|
|
306
|
+
description: "Add numbers: add 2 3 4",
|
|
307
|
+
execute: (args) => {
|
|
308
|
+
const result = args.reduce((a, b) => a + parseFloat(b), 0);
|
|
309
|
+
console.log(`Result: ${result}`);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
cmd.createCommand({
|
|
314
|
+
name: "multiply",
|
|
315
|
+
description: "Multiply numbers: multiply 2 3 4",
|
|
316
|
+
execute: (args) => {
|
|
317
|
+
const result = args.reduce((a, b) => a * parseFloat(b), 1);
|
|
318
|
+
console.log(`Result: ${result}`);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// Admin-only command
|
|
323
|
+
cmd.createCommand({
|
|
324
|
+
name: "admin-reset",
|
|
325
|
+
description: "Reset calculator",
|
|
326
|
+
perms: [cmd.perrmissionsKeys.admin],
|
|
327
|
+
execute: () => {
|
|
328
|
+
console.log("Calculator reset");
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
cmd.updateCommands();
|
|
333
|
+
cmd.Start();
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### Expected output
|
|
337
|
+
|
|
338
|
+
```
|
|
339
|
+
<help>? add 10 20 30
|
|
340
|
+
Result: 60
|
|
341
|
+
<help>? multiply 2 5 3
|
|
342
|
+
Result: 30
|
|
343
|
+
<help>? admin-reset
|
|
344
|
+
[command not found - permissions required]
|
|
345
|
+
<help>?
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### Example 2 — Multi-Role Access Control
|
|
351
|
+
|
|
352
|
+
Create an application with different user roles and permissions.
|
|
353
|
+
|
|
354
|
+
```javascript
|
|
355
|
+
const BScript = require("bscript");
|
|
356
|
+
|
|
357
|
+
const cmd = new BScript({
|
|
358
|
+
perrmissionsKeys: {
|
|
359
|
+
guest: 0,
|
|
360
|
+
user: 50,
|
|
361
|
+
moderator: 100,
|
|
362
|
+
admin: 999
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Set initial role
|
|
367
|
+
let currentRole = "guest";
|
|
368
|
+
|
|
369
|
+
cmd.createCommand({
|
|
370
|
+
name: "status",
|
|
371
|
+
description: "Show current role",
|
|
372
|
+
perms: [cmd.perrmissionsKeys.guest], // Available to all
|
|
373
|
+
execute: () => {
|
|
374
|
+
console.log(`Current role: ${currentRole}`);
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
cmd.createCommand({
|
|
379
|
+
name: "upload",
|
|
380
|
+
description: "Upload a file",
|
|
381
|
+
perms: [cmd.perrmissionsKeys.user], // User and above
|
|
382
|
+
execute: (args) => {
|
|
383
|
+
console.log(`Uploading file: ${args[0]}`);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
cmd.createCommand({
|
|
388
|
+
name: "ban-user",
|
|
389
|
+
description: "Ban a user",
|
|
390
|
+
perms: [cmd.perrmissionsKeys.moderator], // Moderator and above
|
|
391
|
+
execute: (args) => {
|
|
392
|
+
console.log(`Banned user: ${args[0]}`);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
cmd.createCommand({
|
|
397
|
+
name: "login",
|
|
398
|
+
description: "Login as user",
|
|
399
|
+
perms: [cmd.perrmissionsKeys.guest],
|
|
400
|
+
execute: (args) => {
|
|
401
|
+
if (args[0] === "admin" && args[1] === "password") {
|
|
402
|
+
currentRole = "admin";
|
|
403
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.admin];
|
|
404
|
+
console.log("Logged in as admin");
|
|
405
|
+
} else {
|
|
406
|
+
currentRole = "user";
|
|
407
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.user];
|
|
408
|
+
console.log("Logged in as user");
|
|
409
|
+
}
|
|
410
|
+
cmd.updateCommands();
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.guest];
|
|
415
|
+
cmd.updateCommands();
|
|
416
|
+
cmd.Start();
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
### Example 3 — Script File Execution
|
|
422
|
+
|
|
423
|
+
Execute a BScript file from the command line.
|
|
424
|
+
|
|
425
|
+
**my-script.js:**
|
|
426
|
+
```javascript
|
|
427
|
+
echo "Script execution started"
|
|
428
|
+
echo "Running calculations..."
|
|
429
|
+
add 5 10
|
|
430
|
+
echo "Done!"
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
**main.js:**
|
|
434
|
+
```javascript
|
|
435
|
+
const BScript = require("bscript");
|
|
436
|
+
|
|
437
|
+
const cmd = new BScript();
|
|
438
|
+
cmd.cmdRootPermissions = [
|
|
439
|
+
cmd.perrmissionsKeys.default,
|
|
440
|
+
cmd.perrmissionsKeys.script
|
|
441
|
+
];
|
|
442
|
+
cmd.updateCommands();
|
|
443
|
+
|
|
444
|
+
// Execute script file
|
|
445
|
+
const scriptFn = cmd.bscript("script my-script.js");
|
|
446
|
+
scriptFn();
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Run from terminal:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
node main.js
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Expected output:
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
Script execution started
|
|
459
|
+
Running calculations...
|
|
460
|
+
[result of add 5 10]
|
|
461
|
+
Done!
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
<a id="6-best-practices"></a>
|
|
467
|
+
|
|
468
|
+
## 6. Best practices
|
|
469
|
+
|
|
470
|
+
### 1. Organize Commands in Separate Files
|
|
471
|
+
|
|
472
|
+
Instead of creating commands in code, create `.js` files in a commands directory:
|
|
473
|
+
|
|
474
|
+
**commands/echo.js:**
|
|
475
|
+
```javascript
|
|
476
|
+
module.exports = {
|
|
477
|
+
name: "echo",
|
|
478
|
+
description: "Echo text",
|
|
479
|
+
syntax: "echo [text...]",
|
|
480
|
+
execute: (args) => {
|
|
481
|
+
console.log(args.join(" "));
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
**commands/math/add.js:**
|
|
487
|
+
```javascript
|
|
488
|
+
module.exports = {
|
|
489
|
+
name: "add",
|
|
490
|
+
description: "Add numbers",
|
|
491
|
+
syntax: "add [num1] [num2] ...",
|
|
492
|
+
execute: (args) => {
|
|
493
|
+
const sum = args.reduce((a, b) => a + parseFloat(b), 0);
|
|
494
|
+
console.log(sum);
|
|
495
|
+
},
|
|
496
|
+
perms: [0] // Available to default permission level
|
|
497
|
+
};
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### 2. Use Permissions Consistently
|
|
501
|
+
|
|
502
|
+
Define permission levels early and use them consistently:
|
|
503
|
+
|
|
504
|
+
```javascript
|
|
505
|
+
const cmd = new BScript({
|
|
506
|
+
perrmissionsKeys: {
|
|
507
|
+
public: 0,
|
|
508
|
+
authenticated: 50,
|
|
509
|
+
admin: 100
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### 3. Handle Errors Gracefully
|
|
515
|
+
|
|
516
|
+
Always validate arguments and provide helpful error messages:
|
|
517
|
+
|
|
518
|
+
```javascript
|
|
519
|
+
cmd.createCommand({
|
|
520
|
+
name: "divide",
|
|
521
|
+
execute: (args) => {
|
|
522
|
+
if (args.length < 2) {
|
|
523
|
+
console.error("divide: requires 2 arguments");
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
const [a, b] = args.map(parseFloat);
|
|
527
|
+
if (b === 0) {
|
|
528
|
+
console.error("divide: cannot divide by zero");
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
console.log(a / b);
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### 4. Use Command Metadata
|
|
537
|
+
|
|
538
|
+
Provide description and syntax for every command:
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
cmd.createCommand({
|
|
542
|
+
name: "user-info",
|
|
543
|
+
description: "Display user information",
|
|
544
|
+
syntax: "user-info [username]",
|
|
545
|
+
execute: (args) => {
|
|
546
|
+
// Implementation
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 5. Leverage async/await with Loader
|
|
552
|
+
|
|
553
|
+
Provide visual feedback for long-running operations:
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
cmd.createCommand({
|
|
557
|
+
name: "process-data",
|
|
558
|
+
execute: () => {
|
|
559
|
+
cmd.loader(async (done) => {
|
|
560
|
+
const result = await processLargeDataset();
|
|
561
|
+
console.log("Processing complete:", result);
|
|
562
|
+
done();
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### 6. Keep Command Loading Idempotent
|
|
569
|
+
|
|
570
|
+
Ensure `updateCommands()` can be called multiple times safely:
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
// Safe to call after permission changes
|
|
574
|
+
cmd.cmdRootPermissions = [cmd.perrmissionsKeys.admin];
|
|
575
|
+
cmd.updateCommands(); // Re-loads commands with new permissions
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### 7. Use Command Aliases for Common Commands
|
|
579
|
+
|
|
580
|
+
Support multiple names for a single command:
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
module.exports = {
|
|
584
|
+
name: ["exit", "quit", "q"], // Multiple aliases
|
|
585
|
+
description: "Exit the application",
|
|
586
|
+
execute: () => {
|
|
587
|
+
process.exit(0);
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
<a id="see-also"></a>
|
|
595
|
+
|
|
596
|
+
## See also
|
|
597
|
+
|
|
598
|
+
- **[REFERENCE.md](./REFERENCE.md)** — Complete API documentation
|
|
599
|
+
- **[TECHNICAL.md](./TECHNICAL.md)** — Internal architecture
|
|
600
|
+
- **[README.md](./README.md)** — Project overview
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
**Made with ❤️ for the Node.js ecosystem**
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const os = require("os");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
module.exports = class BScriptHistory {
|
|
6
|
+
constructor(filePath = path.join(os.homedir(), ".bscript_history")) {
|
|
7
|
+
this.filePath = filePath;
|
|
8
|
+
this.history = [];
|
|
9
|
+
this.index = 0;
|
|
10
|
+
|
|
11
|
+
this.load();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
load() {
|
|
15
|
+
if (!fs.existsSync(this.filePath)) {
|
|
16
|
+
fs.writeFileSync(this.filePath, "", "utf8");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const content = fs.readFileSync(this.filePath, "utf8");
|
|
21
|
+
|
|
22
|
+
this.history = content
|
|
23
|
+
.split("\n")
|
|
24
|
+
.map(x => x.trim())
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
|
|
27
|
+
this.index = this.history.length;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
save() {
|
|
31
|
+
fs.writeFileSync(
|
|
32
|
+
this.filePath,
|
|
33
|
+
this.history.join("\n"),
|
|
34
|
+
"utf8"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
add(command) {
|
|
39
|
+
if (!command?.trim())
|
|
40
|
+
return;
|
|
41
|
+
|
|
42
|
+
if (this.history[this.history.length - 1] === command) {
|
|
43
|
+
this.index = this.history.length;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.history.push(command);
|
|
48
|
+
this.index = this.history.length;
|
|
49
|
+
|
|
50
|
+
this.save();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
previous() {
|
|
54
|
+
if (this.index > 0)
|
|
55
|
+
this.index--;
|
|
56
|
+
|
|
57
|
+
return this.history[this.index] ?? "";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
next() {
|
|
61
|
+
if (this.index < this.history.length)
|
|
62
|
+
this.index++;
|
|
63
|
+
|
|
64
|
+
return this.history[this.index] ?? "";
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
clear() {
|
|
68
|
+
this.history = [];
|
|
69
|
+
this.index = 0;
|
|
70
|
+
|
|
71
|
+
this.save();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
remove(command) {
|
|
75
|
+
this.history = this.history.filter(x => x !== command);
|
|
76
|
+
|
|
77
|
+
if (this.index > this.history.length)
|
|
78
|
+
this.index = this.history.length;
|
|
79
|
+
|
|
80
|
+
this.save();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
contains(command) {
|
|
84
|
+
return this.history.includes(command);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get(index) {
|
|
88
|
+
return this.history[index] ?? null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getAll() {
|
|
92
|
+
return [...this.history];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get length() {
|
|
96
|
+
return this.history.length;
|
|
97
|
+
}
|
|
98
|
+
}
|