mac-helper 0.3.1 → 0.5.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/lib/app.js CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isAppRunning = isAppRunning;
4
- const child_process_1 = require("child_process");
4
+ const node_child_process_1 = require("node:child_process");
5
5
  /**
6
6
  * file path based process running detect.
7
7
  * for vscode, process name = `Code`, file is `Visual Studio Code.app`, the `Visual Studio Code` should be passed
8
8
  */
9
- async function isAppRunning(appName) {
9
+ function isAppRunning(appName) {
10
10
  return new Promise((resolve, reject) => {
11
- (0, child_process_1.exec)(`ps -ax -o command`, (err, stdout, stderr) => {
11
+ (0, node_child_process_1.exec)(`ps -ax -o command`, (err, stdout, stderr) => {
12
12
  if (err)
13
13
  return reject(err);
14
14
  const lines = stdout
package/lib/chrome.js CHANGED
@@ -12,8 +12,8 @@ async function getChromeActiveTab() {
12
12
  return await (0, run_1.run)(() => {
13
13
  const app = Application('Google Chrome');
14
14
  app.includeStandardAdditions = true;
15
- const wins = (app.windows() || []).filter((w) => !w.minimized());
16
- const tab = wins[0]?.activeTab();
15
+ const win = (app.windows() || []).find((w) => !w.minimized());
16
+ const tab = win?.activeTab();
17
17
  return {
18
18
  url: tab?.url(),
19
19
  title: tab?.title(),
package/lib/finder.d.ts CHANGED
@@ -15,16 +15,14 @@ export declare const QSpace: {
15
15
  allSelected(): Promise<string[]>;
16
16
  singleSelected(): Promise<string | undefined>;
17
17
  };
18
- /**
19
- * impls
20
- */
21
- export declare function getPathFinderSelected(): Promise<string[]>;
22
- export declare function setPathFinderSelected(filePaths: string[]): Promise<void>;
23
- export declare function getFinderSelected(): Promise<string[]>;
24
- export declare function setFinderSelected(filePaths: string[]): Promise<void>;
25
18
  export type QSpaceFileItem = {
26
19
  id: () => string;
27
20
  name: () => string;
28
21
  urlstr: () => string;
29
22
  };
30
- export declare function getQSpaceSelected(): Promise<string[]>;
23
+ export declare function isRepresentPF(file: string): boolean;
24
+ export declare function isRepresentQS(file: string): boolean;
25
+ /**
26
+ * 处理 $PF $QS, ignore case
27
+ */
28
+ export declare function normalizeInputFileList(fileList: string[]): Promise<string[]>;
package/lib/finder.js CHANGED
@@ -1,51 +1,57 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.QSpace = exports.Finder = exports.PathFinder = void 0;
4
- exports.getPathFinderSelected = getPathFinderSelected;
5
- exports.setPathFinderSelected = setPathFinderSelected;
6
- exports.getFinderSelected = getFinderSelected;
7
- exports.setFinderSelected = setFinderSelected;
8
- exports.getQSpaceSelected = getQSpaceSelected;
7
+ exports.isRepresentPF = isRepresentPF;
8
+ exports.isRepresentQS = isRepresentQS;
9
+ exports.normalizeInputFileList = normalizeInputFileList;
10
+ const node_os_1 = require("node:os");
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const node_url_1 = require("node:url");
9
13
  const run_1 = require("@jxa/run");
10
- const url_1 = require("url");
14
+ const es_toolkit_1 = require("es-toolkit");
15
+ const promise_map_1 = __importDefault(require("promise.map"));
11
16
  const app_1 = require("./app");
12
17
  /**
13
18
  * `App` named epxorts
14
19
  */
15
20
  exports.PathFinder = {
16
- async allSelected() {
17
- return getPathFinderSelected();
21
+ allSelected() {
22
+ return PathFinder_allSelected();
18
23
  },
19
- async singleSelected() {
20
- return (await getPathFinderSelected())[0];
24
+ singleSelected() {
25
+ return PathFinder_singleSelected();
21
26
  },
22
- async setSelected(filePaths) {
23
- await setPathFinderSelected(filePaths);
27
+ setSelected(filePaths) {
28
+ return PathFinder_setSelected(filePaths);
24
29
  },
25
30
  };
26
31
  exports.Finder = {
27
- async allSelected() {
28
- return getFinderSelected();
32
+ allSelected() {
33
+ return Finder_allSelected();
29
34
  },
30
35
  async singleSelected() {
31
- return (await getFinderSelected())[0];
36
+ return (await Finder_allSelected())[0];
32
37
  },
33
- async setSelected(filePaths) {
34
- await setFinderSelected(filePaths);
38
+ setSelected(filePaths) {
39
+ return Finder_setSelected(filePaths);
35
40
  },
36
41
  };
37
42
  exports.QSpace = {
38
- async allSelected() {
39
- return getQSpaceSelected();
43
+ allSelected() {
44
+ return QSpace_allSelected();
40
45
  },
41
46
  async singleSelected() {
42
- return (await getQSpaceSelected())[0];
47
+ return (await QSpace_allSelected())[0];
43
48
  },
44
49
  };
45
50
  /**
46
51
  * impls
47
52
  */
48
- async function getPathFinderSelected() {
53
+ /* #region PathFinder */
54
+ async function PathFinder_allSelected() {
49
55
  if (!(await (0, app_1.isAppRunning)('Path Finder'))) {
50
56
  return [];
51
57
  }
@@ -55,28 +61,41 @@ async function getPathFinderSelected() {
55
61
  });
56
62
  return filePaths;
57
63
  }
58
- async function setPathFinderSelected(filePaths) {
64
+ async function PathFinder_singleSelected() {
65
+ if (!(await (0, app_1.isAppRunning)('Path Finder'))) {
66
+ return;
67
+ }
68
+ const firstFilePath = await (0, run_1.run)(() => {
69
+ const app = Application('Path Finder');
70
+ const arr = (app.selection() || []).map((x) => x.posixPath());
71
+ return arr[0];
72
+ });
73
+ return firstFilePath;
74
+ }
75
+ async function PathFinder_setSelected(filePaths) {
59
76
  await (0, run_1.run)((filePaths) => {
60
77
  const app = Application('Path Finder');
61
78
  app.select(filePaths);
62
79
  }, filePaths);
63
80
  }
64
- async function getFinderSelected() {
81
+ /* #endregion */
82
+ /* #region Finder */
83
+ async function Finder_allSelected() {
65
84
  const urls = await (0, run_1.run)(() => {
66
85
  const app = Application('Finder');
67
86
  const selection = app.selection();
68
87
  return (selection || []).map((x) => x.url());
69
88
  });
70
- return urls.map((u) => (0, url_1.fileURLToPath)(u));
89
+ return urls.map((u) => (0, node_url_1.fileURLToPath)(u));
71
90
  }
72
- async function setFinderSelected(filePaths) {
91
+ async function Finder_setSelected(filePaths) {
73
92
  await (0, run_1.run)((filePaths) => {
74
93
  const app = Application('Finder');
75
94
  app.select(filePaths.map((f) => Path(f)));
76
95
  app.activate();
77
96
  }, filePaths);
78
97
  }
79
- async function getQSpaceSelected() {
98
+ async function QSpace_allSelected() {
80
99
  if (!(await (0, app_1.isAppRunning)('QSpace Pro'))) {
81
100
  return [];
82
101
  }
@@ -85,8 +104,29 @@ async function getQSpaceSelected() {
85
104
  const selection = (app.selectedItems() || []).map((x) => x.urlstr());
86
105
  return selection;
87
106
  });
88
- return urls.map((u) => (0, url_1.fileURLToPath)(u));
107
+ return urls.map((u) => (0, node_url_1.fileURLToPath)(u));
108
+ }
109
+ /* #endregion */
110
+ /* #region Top Level Helper */
111
+ function isRepresentPF(file) {
112
+ return /^\$?pf$/i.test(file);
113
+ }
114
+ function isRepresentQS(file) {
115
+ return /^\$?qs$/i.test(file);
116
+ }
117
+ /**
118
+ * 处理 $PF $QS, ignore case
119
+ */
120
+ async function normalizeInputFileList(fileList) {
121
+ return (0, es_toolkit_1.uniq)((await (0, promise_map_1.default)(fileList, async (f) => {
122
+ if (isRepresentPF(f))
123
+ return await exports.PathFinder.allSelected();
124
+ if (isRepresentQS(f))
125
+ return await exports.QSpace.allSelected();
126
+ return node_path_1.default.resolve(f);
127
+ }, (0, node_os_1.availableParallelism)())).flat());
89
128
  }
129
+ /* #endregion */
90
130
  // ;(async () => {
91
131
  // console.log(await getQSpaceSelected())
92
132
  // })()
@@ -8,9 +8,7 @@ async function isAppRunning(appName) {
8
8
  return await (0, run_1.run)((appName) => {
9
9
  const app = Application('System Events');
10
10
  app.includeStandardAdditions = true;
11
- const runningAppNames = app
12
- .processes()
13
- .map((p) => p.name());
11
+ const runningAppNames = app.processes().map((p) => p.name());
14
12
  return runningAppNames.includes(appName);
15
13
  }, appName);
16
14
  }
@@ -18,9 +16,7 @@ async function getRunningAppNames() {
18
16
  return await (0, run_1.run)(() => {
19
17
  const app = Application('System Events');
20
18
  app.includeStandardAdditions = true;
21
- const runningAppNames = app
22
- .processes()
23
- .map((p) => p.name());
19
+ const runningAppNames = app.processes().map((p) => p.name());
24
20
  return runningAppNames;
25
21
  });
26
22
  }
package/package.json CHANGED
@@ -1,13 +1,32 @@
1
1
  {
2
2
  "name": "mac-helper",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
+ "packageManager": "pnpm@10.25.0+sha512.5e82639027af37cf832061bcc6d639c219634488e0f2baebe785028a793de7b525ffcd3f7ff574f5e9860654e098fe852ba8ac5dd5cefe1767d23a020a92f501",
4
5
  "description": "useful helper for macOS",
5
- "main": "lib/index.js",
6
- "types": "lib/index.d.ts",
6
+ "keywords": [
7
+ "mac",
8
+ "helper",
9
+ "mac-helper"
10
+ ],
11
+ "license": "MIT",
12
+ "homepage": "https://github.com/magicdawn/mac-helper#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/magicdawn/mac-helper/issues"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+ssh://git@github.com/magicdawn/mac-helper.git"
19
+ },
20
+ "author": "magicdawn",
7
21
  "files": [
8
22
  "lib/",
9
23
  "src/"
10
24
  ],
25
+ "main": "lib/index.js",
26
+ "types": "lib/index.d.ts",
27
+ "publishConfig": {
28
+ "registry": "https://registry.npmjs.org"
29
+ },
11
30
  "scripts": {
12
31
  "prepare": "husky",
13
32
  "test": "vitest run --globals --testTimeout=30000",
@@ -15,66 +34,47 @@
15
34
  "test-cover": "vitest run --globals --coverage --testTimeout=30000",
16
35
  "dev": "tsc -w --incremental",
17
36
  "typecheck": "tsc --noEmit",
18
- "build": "rm -rf lib; rm tsconfig.tsbuildinfo; tsc",
37
+ "build": "rm -rf lib; rm *.tsbuildinfo; tsc",
19
38
  "prepublishOnly": "pnpm test && pnpm build"
20
39
  },
21
- "repository": {
22
- "type": "git",
23
- "url": "git+ssh://git@github.com/magicdawn/mac-helper.git"
24
- },
25
- "keywords": [
26
- "mac",
27
- "helper",
28
- "mac-helper"
29
- ],
30
- "author": "magicdawn",
31
- "license": "MIT",
32
- "bugs": {
33
- "url": "https://github.com/magicdawn/mac-helper/issues"
34
- },
35
- "homepage": "https://github.com/magicdawn/mac-helper#readme",
36
40
  "dependencies": {
37
- "@jxa/run": "^1.4.0"
41
+ "@jxa/run": "^1.4.0",
42
+ "es-toolkit": "^1.43.0",
43
+ "promise.map": "^1.1.3"
38
44
  },
39
45
  "devDependencies": {
40
46
  "@jxa/global-type": "^1.4.0",
41
47
  "@jxa/sdef-to-dts": "^1.4.0",
42
48
  "@jxa/types": "^1.4.0",
49
+ "@magicdawn/eslint-config": "^1.5.14",
43
50
  "@magicdawn/prettier-config": "^0.1.0",
44
- "@swc/core": "1.11.24",
45
51
  "@types/fs-extra": "^11.0.4",
46
- "@types/mocha": "^10.0.10",
47
- "@types/node": "^22.15.17",
48
- "@typescript-eslint/eslint-plugin": "^8.32.0",
49
- "@typescript-eslint/parser": "^8.32.0",
50
- "@vitest/coverage-v8": "^3.1.3",
51
- "delay": "^6.0.0",
52
- "eslint": "^9.26.0",
53
- "eslint-config-prettier": "^10.1.5",
54
- "fs-extra": "^11.3.0",
52
+ "@types/node": "^25.0.2",
53
+ "@vitest/coverage-v8": "^4.0.15",
54
+ "delay": "^7.0.0",
55
+ "eslint": "^9.39.2",
56
+ "eslint-config-prettier": "^10.1.8",
57
+ "fs-extra": "^11.3.2",
55
58
  "husky": "^9.1.7",
56
59
  "jxa-common-used": "^0.0.3",
57
- "lint-staged": "^16.0.0",
58
- "prettier": "^3.5.3",
60
+ "lint-staged": "^16.2.7",
61
+ "prettier": "^3.7.4",
59
62
  "should": "^13.2.3",
60
- "typescript": "^5.8.3",
61
- "vitest": "^3.1.3"
63
+ "typescript": "^5.9.3",
64
+ "vitest": "^4.0.15"
62
65
  },
63
- "publishConfig": {
64
- "registry": "https://registry.npmjs.org"
65
- },
66
- "lint-staged": {
67
- "*.{js,jsx,ts,tsx,less,md}": [
68
- "prettier --write"
69
- ]
70
- },
71
- "packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39",
72
66
  "pnpm": {
73
67
  "onlyBuiltDependencies": [
74
68
  "@swc/core",
75
69
  "core-js",
76
70
  "es5-ext",
77
- "esbuild"
71
+ "esbuild",
72
+ "unrs-resolver"
73
+ ]
74
+ },
75
+ "lint-staged": {
76
+ "*.{js,jsx,ts,tsx,less,md}": [
77
+ "prettier --write"
78
78
  ]
79
79
  }
80
80
  }
package/src/app.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { exec } from 'child_process'
1
+ import { exec } from 'node:child_process'
2
2
 
3
3
  /**
4
4
  * file path based process running detect.
5
5
  * for vscode, process name = `Code`, file is `Visual Studio Code.app`, the `Visual Studio Code` should be passed
6
6
  */
7
7
 
8
- export async function isAppRunning(appName: string): Promise<boolean> {
8
+ export function isAppRunning(appName: string): Promise<boolean> {
9
9
  return new Promise((resolve, reject) => {
10
10
  exec(`ps -ax -o command`, (err, stdout, stderr) => {
11
11
  if (err) return reject(err)
package/src/chrome.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { run } from '@jxa/run'
2
- import { type GoogleChrome } from 'jxa-common-used'
2
+ import type { GoogleChrome } from 'jxa-common-used'
3
3
 
4
4
  export type ActiveTab = { url: string; title: string }
5
5
 
@@ -14,8 +14,8 @@ export async function getChromeActiveTab(): Promise<ActiveTab> {
14
14
  const app = Application<GoogleChrome>('Google Chrome')
15
15
  app.includeStandardAdditions = true
16
16
 
17
- const wins = (app.windows() || []).filter((w) => !w.minimized())
18
- const tab = wins[0]?.activeTab()
17
+ const win = (app.windows() || []).find((w) => !w.minimized())
18
+ const tab = win?.activeTab()
19
19
  return {
20
20
  url: tab?.url(),
21
21
  title: tab?.title(),
package/src/finder.ts CHANGED
@@ -1,47 +1,51 @@
1
+ import { availableParallelism } from 'node:os'
2
+ import path from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
1
4
  import { run as jxaRun } from '@jxa/run'
2
- import { type PathFinder as PathFinderType } from 'jxa-common-used'
3
- import { fileURLToPath } from 'url'
5
+ import { uniq } from 'es-toolkit'
6
+ import pmap from 'promise.map'
4
7
  import { isAppRunning } from './app'
8
+ import type { PathFinder as PathFinderType } from 'jxa-common-used'
5
9
 
6
10
  /**
7
11
  * `App` named epxorts
8
12
  */
9
13
  export const PathFinder = {
10
- async allSelected() {
11
- return getPathFinderSelected()
14
+ allSelected() {
15
+ return PathFinder_allSelected()
12
16
  },
13
- async singleSelected(): Promise<string | undefined> {
14
- return (await getPathFinderSelected())[0]
17
+ singleSelected() {
18
+ return PathFinder_singleSelected()
15
19
  },
16
- async setSelected(filePaths: string[]) {
17
- await setPathFinderSelected(filePaths)
20
+ setSelected(filePaths: string[]) {
21
+ return PathFinder_setSelected(filePaths)
18
22
  },
19
23
  }
20
24
  export const Finder = {
21
- async allSelected() {
22
- return getFinderSelected()
25
+ allSelected() {
26
+ return Finder_allSelected()
23
27
  },
24
28
  async singleSelected(): Promise<string | undefined> {
25
- return (await getFinderSelected())[0]
29
+ return (await Finder_allSelected())[0]
26
30
  },
27
- async setSelected(filePaths: string[]) {
28
- await setFinderSelected(filePaths)
31
+ setSelected(filePaths: string[]) {
32
+ return Finder_setSelected(filePaths)
29
33
  },
30
34
  }
31
35
  export const QSpace = {
32
- async allSelected() {
33
- return getQSpaceSelected()
36
+ allSelected() {
37
+ return QSpace_allSelected()
34
38
  },
35
39
  async singleSelected(): Promise<string | undefined> {
36
- return (await getQSpaceSelected())[0]
40
+ return (await QSpace_allSelected())[0]
37
41
  },
38
42
  }
39
43
 
40
44
  /**
41
45
  * impls
42
46
  */
43
-
44
- export async function getPathFinderSelected() {
47
+ /* #region PathFinder */
48
+ async function PathFinder_allSelected() {
45
49
  if (!(await isAppRunning('Path Finder'))) {
46
50
  return []
47
51
  }
@@ -52,14 +56,28 @@ export async function getPathFinderSelected() {
52
56
  return filePaths
53
57
  }
54
58
 
55
- export async function setPathFinderSelected(filePaths: string[]) {
59
+ async function PathFinder_singleSelected(): Promise<string | undefined> {
60
+ if (!(await isAppRunning('Path Finder'))) {
61
+ return
62
+ }
63
+ const firstFilePath: string | undefined = await jxaRun(() => {
64
+ const app = Application<PathFinderType>('Path Finder')
65
+ const arr = (app.selection() || []).map((x) => x.posixPath())
66
+ return arr[0]
67
+ })
68
+ return firstFilePath
69
+ }
70
+
71
+ async function PathFinder_setSelected(filePaths: string[]) {
56
72
  await jxaRun((filePaths: string[]) => {
57
73
  const app = Application<PathFinderType>('Path Finder')
58
74
  app.select(filePaths)
59
75
  }, filePaths)
60
76
  }
77
+ /* #endregion */
61
78
 
62
- export async function getFinderSelected() {
79
+ /* #region Finder */
80
+ async function Finder_allSelected() {
63
81
  const urls: string[] = await jxaRun(() => {
64
82
  const app = Application('Finder')
65
83
  const selection = app.selection()
@@ -67,16 +85,17 @@ export async function getFinderSelected() {
67
85
  })
68
86
  return urls.map((u) => fileURLToPath(u))
69
87
  }
70
-
71
- export async function setFinderSelected(filePaths: string[]) {
88
+ async function Finder_setSelected(filePaths: string[]) {
72
89
  await jxaRun((filePaths: string[]) => {
73
90
  const app = Application('Finder')
74
91
  app.select(filePaths.map((f) => Path(f)))
75
92
  app.activate()
76
93
  }, filePaths)
77
94
  }
95
+ /* #endregion */
78
96
 
79
- // file item n [inh. item] : A file item.
97
+ /* #region QSpace */
98
+ // file item n [inh. item] : A file item.
80
99
  // properties
81
100
  // - id (text, r/o) : The unique identifier of the item.
82
101
  // - name (text, r/o) : The name of the file.
@@ -90,7 +109,7 @@ export type QSpaceFileItem = {
90
109
  urlstr: () => string
91
110
  }
92
111
 
93
- export async function getQSpaceSelected() {
112
+ async function QSpace_allSelected() {
94
113
  if (!(await isAppRunning('QSpace Pro'))) {
95
114
  return []
96
115
  }
@@ -101,6 +120,36 @@ export async function getQSpaceSelected() {
101
120
  })
102
121
  return urls.map((u) => fileURLToPath(u))
103
122
  }
123
+ /* #endregion */
124
+
125
+ /* #region Top Level Helper */
126
+ export function isRepresentPF(file: string) {
127
+ return /^\$?pf$/i.test(file)
128
+ }
129
+
130
+ export function isRepresentQS(file: string) {
131
+ return /^\$?qs$/i.test(file)
132
+ }
133
+
134
+ /**
135
+ * 处理 $PF $QS, ignore case
136
+ */
137
+ export async function normalizeInputFileList(fileList: string[]) {
138
+ return uniq(
139
+ (
140
+ await pmap(
141
+ fileList,
142
+ async (f) => {
143
+ if (isRepresentPF(f)) return await PathFinder.allSelected()
144
+ if (isRepresentQS(f)) return await QSpace.allSelected()
145
+ return path.resolve(f)
146
+ },
147
+ availableParallelism(),
148
+ )
149
+ ).flat(),
150
+ )
151
+ }
152
+ /* #endregion */
104
153
 
105
154
  // ;(async () => {
106
155
  // console.log(await getQSpaceSelected())
package/src/iterm.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { run } from '@jxa/run'
2
- import { iTerm2 } from 'jxa-common-used'
2
+ import type { iTerm2 } from 'jxa-common-used'
3
3
 
4
4
  export async function runInIterm(command: string, reuse = true) {
5
5
  await run(
@@ -9,9 +9,7 @@ async function isAppRunning(appName: string): Promise<boolean> {
9
9
  return await run((appName) => {
10
10
  const app = Application<SystemEvents.SystemEvents.Application>('System Events')
11
11
  app.includeStandardAdditions = true
12
- const runningAppNames: string[] = app
13
- .processes()
14
- .map((p: SystemEvents.SystemEvents.Process) => p.name())
12
+ const runningAppNames: string[] = app.processes().map((p: SystemEvents.SystemEvents.Process) => p.name())
15
13
  return runningAppNames.includes(appName)
16
14
  }, appName)
17
15
  }
@@ -20,9 +18,7 @@ async function getRunningAppNames(): Promise<string[]> {
20
18
  return await run(() => {
21
19
  const app = Application<SystemEvents.SystemEvents.Application>('System Events')
22
20
  app.includeStandardAdditions = true
23
- const runningAppNames: string[] = app
24
- .processes()
25
- .map((p: SystemEvents.SystemEvents.Process) => p.name())
21
+ const runningAppNames: string[] = app.processes().map((p: SystemEvents.SystemEvents.Process) => p.name())
26
22
  return runningAppNames
27
23
  })
28
24
  }