@aspiresys/visor 1.1.9 → 1.1.11

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/dist/app.d.ts CHANGED
@@ -43,3 +43,5 @@ export declare function openApp(target: string): Promise<void>;
43
43
  * await closeApp("ms-teams.exe");
44
44
  */
45
45
  export declare function closeApp(processName: string): Promise<void>;
46
+ export declare function execCommand(command: string): Promise<string>;
47
+ export declare function execDetached(command: string): Promise<void>;
package/dist/app.js CHANGED
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.openApp = openApp;
4
4
  exports.closeApp = closeApp;
5
+ exports.execCommand = execCommand;
6
+ exports.execDetached = execDetached;
5
7
  const child_process_1 = require("child_process");
6
8
  const logger_1 = require("./logger");
7
9
  function execAsync(command) {
@@ -98,3 +100,23 @@ async function closeApp(processName) {
98
100
  });
99
101
  });
100
102
  }
103
+ async function execCommand(command) {
104
+ (0, logger_1.log)(`[CMD] Executing: ${command}`);
105
+ return new Promise((resolve, reject) => {
106
+ (0, child_process_1.exec)(command, (error, stdout, stderr) => {
107
+ if (error) {
108
+ reject(new Error(stderr || error.message));
109
+ return;
110
+ }
111
+ resolve(stdout.trim());
112
+ });
113
+ });
114
+ }
115
+ async function execDetached(command) {
116
+ (0, logger_1.log)(`[CMD] Starting detached: ${command}`);
117
+ (0, child_process_1.spawn)(command, [], {
118
+ detached: true,
119
+ shell: true,
120
+ stdio: "ignore",
121
+ }).unref();
122
+ }
package/dist/config.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export declare const visorConfig: {
2
+ initialized: boolean;
2
3
  scaleFactor: number;
3
4
  debug: boolean;
4
5
  imagePath: string;
package/dist/config.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.visorConfig = void 0;
4
4
  exports.visorConfig = {
5
+ initialized: false,
5
6
  scaleFactor: 1,
6
7
  debug: true,
7
8
  imagePath: "",
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export declare class Visor {
4
4
  keyboard: import("@nut-tree-fork/nut-js").KeyboardClass;
5
5
  Key: typeof Key;
6
6
  Button: typeof Button;
7
+ private configWarningShown;
8
+ private checkConfig;
7
9
  /**
8
10
  * Finds an image on screen using OpenCV
9
11
  * and performs a left mouse click
@@ -903,5 +905,32 @@ export declare class Visor {
903
905
  * await visor.terminateOCR();
904
906
  */
905
907
  terminateOCR(): Promise<void>;
908
+ /**
909
+ * Executes a command and returns output.
910
+ *
911
+ * @example
912
+ * const output =
913
+ * await visor.exec("ipconfig");
914
+ */
915
+ exec(command: string): Promise<string>;
916
+ /**
917
+ * Starts a command without waiting
918
+ * for completion.
919
+ *
920
+ * @example
921
+ * await visor.execDetached(
922
+ * "notepad"
923
+ * );
924
+ */
925
+ execDetached(command: string): Promise<void>;
926
+ /**
927
+ * Pastes text using keyboard automation.
928
+ *
929
+ * @param text Text to paste.
930
+ *
931
+ * @example
932
+ * await visor.paste("Hello World");
933
+ */
934
+ paste(text: string): Promise<void>;
906
935
  }
907
936
  export declare const visor: Visor;
package/dist/index.js CHANGED
@@ -12,12 +12,40 @@ const nut_js_1 = require("@nut-tree-fork/nut-js");
12
12
  const path_1 = require("./path");
13
13
  const display_1 = require("./display");
14
14
  const logger_1 = require("./logger");
15
+ const console_1 = require("console");
15
16
  class Visor {
16
17
  constructor() {
17
18
  this.mouse = nut_js_1.mouse;
18
19
  this.keyboard = nut_js_1.keyboard;
19
20
  this.Key = nut_js_1.Key;
20
21
  this.Button = nut_js_1.Button;
22
+ this.configWarningShown = false;
23
+ }
24
+ checkConfig() {
25
+ if (this.configWarningShown) {
26
+ return;
27
+ }
28
+ const missing = [];
29
+ if (!config_1.visorConfig.imagePath) {
30
+ missing.push("imagePath");
31
+ }
32
+ if (!config_1.visorConfig.outputPath) {
33
+ missing.push("outputPath");
34
+ }
35
+ if (missing.length > 0) {
36
+ (0, console_1.warn)(`[VISOR] Configuration incomplete.\n` +
37
+ `Missing: ${missing.join(", ")}\n\n` +
38
+ `Relative paths may not work correctly.\n` +
39
+ `Use visor.loadConfig(...) or provide absolute paths directly to functions.`);
40
+ }
41
+ if (!config_1.visorConfig.initialized) {
42
+ config_1.visorConfig.scaleFactor = (0, display_1.getWindowsScaleFactor)();
43
+ (0, console_1.warn)(`[VISOR] Configuration not loaded.\n` +
44
+ `Auto-detected scaleFactor=${config_1.visorConfig.scaleFactor}.\n`);
45
+ }
46
+ if (missing.length > 0 || !config_1.visorConfig.initialized) {
47
+ this.configWarningShown = true;
48
+ }
21
49
  }
22
50
  /**
23
51
  * Finds an image on screen using OpenCV
@@ -50,6 +78,7 @@ class Visor {
50
78
  * await visor.click("./images/save.png", 0.9);
51
79
  */
52
80
  async click(image, confidence = 0.8) {
81
+ this.checkConfig();
53
82
  if (!image) {
54
83
  await this.mouse.click(this.Button.LEFT);
55
84
  (0, logger_1.log)("[MOUSE] Left click completed");
@@ -87,6 +116,7 @@ class Visor {
87
116
  * await visor.rightClick();
88
117
  */
89
118
  async rightClick(image, confidence = 0.8) {
119
+ this.checkConfig();
90
120
  if (image) {
91
121
  const region = await this.find(image, confidence);
92
122
  if (!region) {
@@ -123,6 +153,7 @@ class Visor {
123
153
  * await visor.doubleClick();
124
154
  */
125
155
  async doubleClick(image, confidence = 0.8) {
156
+ this.checkConfig();
126
157
  if (image) {
127
158
  const region = await this.find(image, confidence);
128
159
  if (!region) {
@@ -163,6 +194,7 @@ class Visor {
163
194
  * await visor.find("save.png");
164
195
  */
165
196
  async find(image, confidence = 0.8) {
197
+ this.checkConfig();
166
198
  const start = Date.now();
167
199
  const screen = await (0, screen_1.captureScreen)();
168
200
  const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
@@ -196,6 +228,7 @@ class Visor {
196
228
  * await visor.exists("login.png");
197
229
  */
198
230
  async exists(image, confidence = 0.8) {
231
+ this.checkConfig();
199
232
  return (await this.find(image, confidence)) !== null;
200
233
  }
201
234
  /**
@@ -221,6 +254,7 @@ class Visor {
221
254
  * await visor.findAll("icon.png");
222
255
  */
223
256
  async findAll(image, confidence = 0.8) {
257
+ this.checkConfig();
224
258
  const screen = await (0, screen_1.captureScreen)();
225
259
  const template = await (0, matcher_1.loadTemplate)((0, path_1.resolveImagePath)(image));
226
260
  try {
@@ -254,6 +288,7 @@ class Visor {
254
288
  * await visor.previewMatches("button.png");
255
289
  */
256
290
  async previewMatches(image, confidence = 0.8) {
291
+ this.checkConfig();
257
292
  const matches = await this.findAll(image, confidence);
258
293
  (0, logger_1.log)("\n=== MATCH PREVIEW ===\n");
259
294
  matches.forEach((m, i) => {
@@ -301,6 +336,7 @@ CONF:${m.confidence.toFixed(3)}
301
336
  * await visor.wait("loading-done.png");
302
337
  */
303
338
  async wait(image, { confidence = 0.8, timeout = 5000 } = {}) {
339
+ this.checkConfig();
304
340
  const interval = 300;
305
341
  const attempts = Math.ceil(timeout / interval);
306
342
  for (let i = 0; i < attempts; i++) {
@@ -337,6 +373,7 @@ CONF:${m.confidence.toFixed(3)}
337
373
  * await visor.waitToVanish("spinner.png");
338
374
  */
339
375
  async waitToVanish(image, { confidence = 0.8, timeout = 5000 } = {}) {
376
+ this.checkConfig();
340
377
  const start = Date.now();
341
378
  while (Date.now() - start < timeout) {
342
379
  if (!(await this.exists(image, confidence))) {
@@ -372,6 +409,7 @@ CONF:${m.confidence.toFixed(3)}
372
409
  * await visor.waitText("Success");
373
410
  */
374
411
  async waitText(text, timeout = 5000) {
412
+ this.checkConfig();
375
413
  const start = Date.now();
376
414
  while (Date.now() - start < timeout) {
377
415
  if (await this.existsText(text)) {
@@ -405,6 +443,7 @@ CONF:${m.confidence.toFixed(3)}
405
443
  * await visor.waitTextToVanish("Loading");
406
444
  */
407
445
  async waitTextToVanish(text, timeout = 5000) {
446
+ this.checkConfig();
408
447
  const start = Date.now();
409
448
  while (Date.now() - start < timeout) {
410
449
  if (!(await this.existsText(text))) {
@@ -428,6 +467,7 @@ CONF:${m.confidence.toFixed(3)}
428
467
  * await visor.clickText("Login");
429
468
  */
430
469
  async clickText(text, index = 0) {
470
+ this.checkConfig();
431
471
  const region = await (0, text_1.findText)(text, index);
432
472
  if (!region) {
433
473
  throw new Error(`Text not found: ${text}`);
@@ -449,6 +489,7 @@ CONF:${m.confidence.toFixed(3)}
449
489
  * await visor.findText("Submit");
450
490
  */
451
491
  async findText(text, index = 0, region) {
492
+ this.checkConfig();
452
493
  return await (0, text_1.findText)(text, index, region);
453
494
  }
454
495
  /**
@@ -465,6 +506,7 @@ CONF:${m.confidence.toFixed(3)}
465
506
  * await visor.existsText("Teams");
466
507
  */
467
508
  async existsText(text, region) {
509
+ this.checkConfig();
468
510
  return await (0, text_1.existsText)(text, region);
469
511
  }
470
512
  /**
@@ -485,6 +527,7 @@ CONF:${m.confidence.toFixed(3)}
485
527
  * });
486
528
  */
487
529
  async readRegion(region) {
530
+ this.checkConfig();
488
531
  return await (0, ocr_1.extractTextFromRegion)(region);
489
532
  }
490
533
  /**
@@ -519,6 +562,7 @@ CONF:${m.confidence.toFixed(3)}
519
562
  * log(result.text);
520
563
  */
521
564
  async readScreen() {
565
+ this.checkConfig();
522
566
  return await (0, ocr_1.extractTextFromRegion)();
523
567
  }
524
568
  /**
@@ -537,6 +581,7 @@ CONF:${m.confidence.toFixed(3)}
537
581
  * );
538
582
  */
539
583
  async captureScreenshot(path) {
584
+ this.checkConfig();
540
585
  path = config_1.visorConfig.outputPath + "/" + path;
541
586
  (0, logger_1.log)(`[VISOR] Saving screenshot: ${path}`);
542
587
  await (0, screen_1.saveScreenshot)(path);
@@ -597,6 +642,7 @@ CONF:${m.confidence.toFixed(3)}
597
642
  * );
598
643
  */
599
644
  async dragDrop(source, target, confidence = 0.8) {
645
+ this.checkConfig();
600
646
  const src = await this.find(source, confidence);
601
647
  const dst = await this.find(target, confidence);
602
648
  if (!src || !dst) {
@@ -628,6 +674,7 @@ CONF:${m.confidence.toFixed(3)}
628
674
  * await visor.hover("menu.png");
629
675
  */
630
676
  async hover(image, confidence = 0.8) {
677
+ this.checkConfig();
631
678
  const region = await this.find(image, confidence);
632
679
  if (!region) {
633
680
  throw new Error(`Image not found: ${image}`);
@@ -650,6 +697,7 @@ CONF:${m.confidence.toFixed(3)}
650
697
  * await visor.scrollDown(1000);
651
698
  */
652
699
  async scrollDown(amount = 500) {
700
+ this.checkConfig();
653
701
  await this.mouse.scrollDown(amount);
654
702
  }
655
703
  /**
@@ -667,6 +715,7 @@ CONF:${m.confidence.toFixed(3)}
667
715
  * await visor.scrollUp(1000);
668
716
  */
669
717
  async scrollUp(amount = 500) {
718
+ this.checkConfig();
670
719
  await this.mouse.scrollUp(amount);
671
720
  }
672
721
  /**
@@ -744,6 +793,7 @@ CONF:${m.confidence.toFixed(3)}
744
793
  * await visor.moveMouse(500, 300);
745
794
  */
746
795
  async moveMouse(x, y) {
796
+ this.checkConfig();
747
797
  await this.mouse.move((0, nut_js_1.straightTo)(new nut_js_1.Point(x, y)));
748
798
  }
749
799
  /**
@@ -757,6 +807,7 @@ CONF:${m.confidence.toFixed(3)}
757
807
  * await visor.getMousePosition();
758
808
  */
759
809
  async getMousePosition() {
810
+ this.checkConfig();
760
811
  return await this.mouse.getPosition();
761
812
  }
762
813
  /**
@@ -923,6 +974,7 @@ CONF:${m.confidence.toFixed(3)}
923
974
  if (config.debug !== undefined) {
924
975
  this.setDebug(config.debug);
925
976
  }
977
+ config_1.visorConfig.initialized = true;
926
978
  (0, logger_1.log)("[VISOR] Config loaded");
927
979
  }
928
980
  /**
@@ -954,6 +1006,7 @@ CONF:${m.confidence.toFixed(3)}
954
1006
  * ]);
955
1007
  */
956
1008
  async findAny(images, confidence = 0.8) {
1009
+ this.checkConfig();
957
1010
  const screen = await (0, screen_1.captureScreen)();
958
1011
  try {
959
1012
  for (const image of images) {
@@ -1005,6 +1058,7 @@ CONF:${m.confidence.toFixed(3)}
1005
1058
  * ]);
1006
1059
  */
1007
1060
  async existsAny(images, confidence = 0.8) {
1061
+ this.checkConfig();
1008
1062
  return (await this.findAny(images, confidence)) !== null;
1009
1063
  }
1010
1064
  /**
@@ -1047,6 +1101,7 @@ CONF:${m.confidence.toFixed(3)}
1047
1101
  * ]);
1048
1102
  */
1049
1103
  async clickAny(images, confidence = 0.8) {
1104
+ this.checkConfig();
1050
1105
  const result = await this.findAny(images, confidence);
1051
1106
  if (!result) {
1052
1107
  throw new Error(`None of the images were found`);
@@ -1101,6 +1156,7 @@ CONF:${m.confidence.toFixed(3)}
1101
1156
  * ]);
1102
1157
  */
1103
1158
  async waitAny(images, { confidence = 0.8, timeout = 5000 } = {}) {
1159
+ this.checkConfig();
1104
1160
  const interval = 300;
1105
1161
  const attempts = Math.ceil(timeout / interval);
1106
1162
  for (let i = 0; i < attempts; i++) {
@@ -1133,6 +1189,41 @@ CONF:${m.confidence.toFixed(3)}
1133
1189
  async terminateOCR() {
1134
1190
  await (0, ocr_1.terminateOCR)();
1135
1191
  }
1192
+ /**
1193
+ * Executes a command and returns output.
1194
+ *
1195
+ * @example
1196
+ * const output =
1197
+ * await visor.exec("ipconfig");
1198
+ */
1199
+ async exec(command) {
1200
+ return await (0, app_1.execCommand)(command);
1201
+ }
1202
+ /**
1203
+ * Starts a command without waiting
1204
+ * for completion.
1205
+ *
1206
+ * @example
1207
+ * await visor.execDetached(
1208
+ * "notepad"
1209
+ * );
1210
+ */
1211
+ async execDetached(command) {
1212
+ await (0, app_1.execDetached)(command);
1213
+ }
1214
+ /**
1215
+ * Pastes text using keyboard automation.
1216
+ *
1217
+ * @param text Text to paste.
1218
+ *
1219
+ * @example
1220
+ * await visor.paste("Hello World");
1221
+ */
1222
+ async paste(text) {
1223
+ await nut_js_1.clipboard.setContent(text);
1224
+ await this.sleep(100);
1225
+ await this.press(nut_js_1.Key.LeftControl, nut_js_1.Key.V);
1226
+ }
1136
1227
  }
1137
1228
  exports.Visor = Visor;
1138
1229
  exports.visor = new Visor();
package/dist/ocr.js CHANGED
@@ -76,5 +76,5 @@ async function extractTextFromRegion(region) {
76
76
  });
77
77
  (0, logger_1.log)("[OCR] Extracted Text:");
78
78
  (0, logger_1.log)(result.data.text);
79
- return result.data.text;
79
+ return result.data;
80
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspiresys/visor",
3
- "version": "1.1.9",
3
+ "version": "1.1.11",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {