mac-helper 0.10.0 → 0.11.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
@@ -19,4 +19,3 @@ export function isAppRunning(appName) {
19
19
  });
20
20
  });
21
21
  }
22
- // isAppRunning('Visual Studio Code').then(console.log)
package/lib/dialog.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { runJxa } from 'run-jxa';
2
+ import { runOnCurrentApp } from './utils.js';
2
3
  export const dialog = {
3
4
  prompt,
4
5
  chooseFromList,
@@ -18,14 +19,6 @@ async function prompt(label, defaultValue = '', signal) {
18
19
  return defaultValue;
19
20
  }
20
21
  }
21
- async function runOnCurrentApp(method, args, signal) {
22
- return await runJxa((method, ...args) => {
23
- const app = Application.currentApplication();
24
- app.includeStandardAdditions = true;
25
- // @ts-ignore
26
- return app[method]?.(...args);
27
- }, [method, ...(args || [])], { signal });
28
- }
29
22
  async function chooseFromList(list, options = {}, signal) {
30
23
  let usingOption = false;
31
24
  let showList = [];
@@ -69,32 +62,3 @@ async function chooseMultipleFromList(list, options = {}, signal) {
69
62
  return valArr;
70
63
  }
71
64
  }
72
- // dialog.chooseFromList(['hello', 'world']).then((selected) => {
73
- // console.log(selected)
74
- // })
75
- // dialog
76
- // .chooseFromList([
77
- // { value: 'yes', label: '是吧~~~' },
78
- // { value: 'halo', label: 'Halo 啊洒洒' },
79
- // ])
80
- // .then((selected) => {
81
- // console.log(selected)
82
- // })
83
- // dialog
84
- // .chooseMultipleFromList(
85
- // [
86
- // { value: 'yes', label: '是吧~~~' },
87
- // { value: 'halo', label: 'Halo 啊洒洒' },
88
- // ],
89
- // {
90
- // withTitle: 'title',
91
- // withPrompt: 'prompt',
92
- // cancelButtonName: '取消!',
93
- // // @ts-ignore
94
- // okButtonName: '酱紫吧~',
95
- // }
96
- // )
97
- // .then((selected) => {
98
- // console.log(selected)
99
- // })
100
- // dialog.prompt('hello', 'world').then(console.log)
package/lib/index.d.ts CHANGED
@@ -3,3 +3,5 @@ export * from './chrome.js';
3
3
  export * from './dialog.js';
4
4
  export * from './finder.js';
5
5
  export * from './iterm.js';
6
+ export * from './notification.js';
7
+ export * from './system-events.js';
package/lib/index.js CHANGED
@@ -5,3 +5,5 @@ export * from './chrome.js';
5
5
  export * from './dialog.js';
6
6
  export * from './finder.js';
7
7
  export * from './iterm.js';
8
+ export * from './notification.js';
9
+ export * from './system-events.js';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html#//apple_ref/doc/uid/TP40016239-CH61-SW1
3
+ */
4
+ /**
5
+ * 视觉从上到下 title-subtitle-message
6
+ */
7
+ export type NotificationOptions = {
8
+ /** fallback 到 "脚本编辑器" */
9
+ title?: string;
10
+ /** 通常来说很少见, 写上很诡异 */
11
+ subtitle?: string;
12
+ /** 提示:这些声音文件物理存放在 Mac 系统的 /System/Library/Sounds/ 目录下 */
13
+ soundName?: 'Basso' | 'Blow' | 'Bottle' | 'Frog' | 'Funk' | 'Glass' | 'Hero' | 'Morse' | 'Ping' | 'Pop' | 'Purr' | 'Sosumi' | 'Submarine' | 'Tink' | (string & {});
14
+ };
15
+ export declare function displayNotification(message: string, options?: NotificationOptions): Promise<void>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html#//apple_ref/doc/uid/TP40016239-CH61-SW1
3
+ */
4
+ import { runJxa } from 'run-jxa';
5
+ export async function displayNotification(message, options) {
6
+ // jxa 直接传 options 报错: execution error: Error: Error: 不能转换类型。 (-1700)
7
+ // 只能拆开喽
8
+ // undefined 更好, 但 jxa 更期望 null 或 空字符串
9
+ const title = options?.title || ''; // null 会变成 msgr
10
+ const subtitle = options?.subtitle || '';
11
+ const soundName = options?.soundName || '';
12
+ await runJxa((message, title, subtitle, soundName) => {
13
+ const app = Application.currentApplication();
14
+ app.includeStandardAdditions = true;
15
+ app.displayNotification(message, { withTitle: title, subtitle, soundName });
16
+ return null;
17
+ }, [message, title, subtitle, soundName]);
18
+ }
@@ -1 +1,11 @@
1
- export {};
1
+ export type AppInfo = {
2
+ name: string;
3
+ bundleId: string;
4
+ path?: string;
5
+ };
6
+ export declare function getRunningAppInfos(signal?: AbortSignal): Promise<AppInfo[]>;
7
+ export declare function getForegroundAppInfo(signal?: AbortSignal): Promise<{
8
+ foregroundAppName: string | undefined;
9
+ foregroundAppBundleId: string | undefined;
10
+ foregroundAppPath: string | undefined;
11
+ }>;
@@ -10,11 +10,29 @@ async function isAppRunning(appName, signal) {
10
10
  return runningAppNames.includes(appName);
11
11
  }, [appName], { signal });
12
12
  }
13
- async function getRunningAppNames(signal) {
13
+ export async function getRunningAppInfos(signal) {
14
14
  return await runJxa(() => {
15
15
  const app = Application('System Events');
16
16
  app.includeStandardAdditions = true;
17
- const runningAppNames = app.processes().map((p) => p.name());
17
+ const runningAppNames = app.applicationProcesses().map((p) => {
18
+ return {
19
+ name: p.name(),
20
+ bundleId: p.bundleIdentifier(),
21
+ path: p.applicationFile()?.posixPath(),
22
+ };
23
+ });
18
24
  return runningAppNames;
19
25
  }, undefined, { signal });
20
26
  }
27
+ export async function getForegroundAppInfo(signal) {
28
+ return await runJxa(function () {
29
+ const app = Application('System Events');
30
+ app.includeStandardAdditions = true;
31
+ const foregroundApp = app.applicationProcesses.whose({ frontmost: true })?.[0];
32
+ return {
33
+ foregroundAppName: foregroundApp?.name(),
34
+ foregroundAppBundleId: foregroundApp?.bundleIdentifier(),
35
+ foregroundAppPath: foregroundApp?.applicationFile()?.posixPath(),
36
+ };
37
+ }, undefined, { signal });
38
+ }
package/lib/utils.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export type AppMethod = 'chooseFromList';
2
+ export declare function runOnCurrentApp(method: AppMethod, args: any[] | undefined, signal?: AbortSignal): Promise<any>;
package/lib/utils.js ADDED
@@ -0,0 +1,9 @@
1
+ import { runJxa } from 'run-jxa';
2
+ export async function runOnCurrentApp(method, args, signal) {
3
+ return await runJxa((method, ...args) => {
4
+ const app = Application.currentApplication();
5
+ app.includeStandardAdditions = true;
6
+ // @ts-ignore
7
+ return app[method]?.(...args);
8
+ }, [method, ...(args || [])], { signal });
9
+ }
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "mac-helper",
3
3
  "type": "module",
4
- "version": "0.10.0",
5
- "packageManager": "pnpm@11.8.0+sha512.c1f5e7c4cb241c8f174b743851d82f42b802324afc8b0f116b96adb15aa06664948dde36960a3ba1079ba5b4b29dd0140135b94b5b5f5263592249d68e555f26",
4
+ "version": "0.11.0",
6
5
  "description": "useful helper for macOS",
7
6
  "author": "magicdawn",
8
7
  "license": "MIT",
@@ -31,19 +30,9 @@
31
30
  "publishConfig": {
32
31
  "registry": "https://registry.npmjs.org"
33
32
  },
34
- "scripts": {
35
- "prepare": "husky",
36
- "test": "vitest run --globals --testTimeout=30000",
37
- "test:dev": "vitest --globals --testTimeout=30000",
38
- "test-cover": "vitest run --globals --coverage --testTimeout=30000",
39
- "dev": "tsgo -w --incremental",
40
- "typecheck": "tsgo --noEmit",
41
- "build": "rm -rf lib; tsgo",
42
- "prepublishOnly": "pnpm test && pnpm build"
43
- },
44
33
  "dependencies": {
45
34
  "dedent": "^1.7.2",
46
- "es-toolkit": "^1.47.1",
35
+ "es-toolkit": "^1.52.0",
47
36
  "promise.map": "^1.2.0",
48
37
  "run-applescript": "^7.1.0",
49
38
  "run-jxa": "^4.0.0"
@@ -52,23 +41,24 @@
52
41
  "@jxa/global-type": "^1.4.0",
53
42
  "@jxa/sdef-to-dts": "^1.4.0",
54
43
  "@jxa/types": "^1.4.0",
55
- "@magicdawn/eslint-config": "^1.6.8",
44
+ "@magicdawn/eslint-config": "^1.6.18",
56
45
  "@magicdawn/prettier-config": "^0.1.0",
57
46
  "@types/fs-extra": "^11.0.4",
58
- "@types/node": "^25.9.4",
59
- "@typescript/native-preview": "7.0.0-dev.20260620.1",
60
- "@vitest/coverage-v8": "^4.1.9",
47
+ "@types/node": "^26.6.3",
48
+ "@typescript/native-preview": "7.0.0-dev.20260707.2",
49
+ "@vitest/coverage-v8": "^5.0.3",
61
50
  "delay": "^7.0.0",
62
- "eslint": "^10.5.0",
51
+ "eslint": "^10.11.0",
63
52
  "eslint-config-prettier": "^10.1.8",
64
- "fs-extra": "^11.3.5",
53
+ "fs-extra": "^11.4.1",
65
54
  "husky": "^9.1.7",
66
55
  "jxa-common-used": "^0.0.3",
67
- "lint-staged": "^17.0.7",
68
- "prettier": "^3.8.4",
56
+ "lint-staged": "^17.6.0",
57
+ "prettier": "^3.9.9",
69
58
  "should": "^13.2.3",
70
59
  "typescript": "^6.0.3",
71
- "vitest": "^4.1.9"
60
+ "vite": "^8.3.1",
61
+ "vitest": "^5.0.3"
72
62
  },
73
63
  "lint-staged": {
74
64
  "*.{?(c|m)(j|t)s?(x),json,y?(a)ml}": [
@@ -78,5 +68,13 @@
78
68
  "!*.{?(c|m)(j|t)s?(x),json,y?(a)ml}": [
79
69
  "prettier --write --ignore-unknown"
80
70
  ]
71
+ },
72
+ "scripts": {
73
+ "test": "vitest run --globals --testTimeout=30000",
74
+ "test:dev": "vitest --globals --testTimeout=30000",
75
+ "test-cover": "vitest run --globals --coverage --testTimeout=30000",
76
+ "dev": "tsgo -w --incremental",
77
+ "typecheck": "tsgo --noEmit",
78
+ "build": "rm -rf lib; tsgo"
81
79
  }
82
- }
80
+ }