calendit 1.20260426.1 → 1.20260426.4
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/commands/macos.js +64 -4
- package/dist/core/calenditInstallRoot.d.ts +5 -0
- package/dist/core/calenditInstallRoot.js +31 -0
- package/dist/core/eventkitBridgeFetch.js +1 -1
- package/dist/core/eventkitHelper.d.ts +1 -1
- package/dist/core/eventkitHelper.js +9 -1
- package/dist/core/macosBridgeApp.d.ts +19 -7
- package/dist/core/macosBridgeApp.js +69 -32
- package/dist/generated/locale-keys.d.ts +1 -1
- package/dist/generated/locale-keys.js +8 -0
- package/dist/locales/en.json +11 -1
- package/dist/locales/ja.json +11 -1
- package/package.json +1 -1
package/dist/commands/macos.js
CHANGED
|
@@ -7,9 +7,9 @@ import { writeStdoutLine } from "../core/logger.js";
|
|
|
7
7
|
import { logger } from "../core/logger.js";
|
|
8
8
|
import { ValidationError } from "../core/errors.js";
|
|
9
9
|
import { t } from "../core/i18n.js";
|
|
10
|
-
import { eventkitDoctorJson, eventkitListCalendarsJson, hasEventkitTransport, resolveEventkitHelperPath, } from "../core/eventkitHelper.js";
|
|
10
|
+
import { eventkitDoctorJson, eventkitListCalendarsJson, hasEventkitTransport, resolveBridgeSocketPathForRun, resolveEventkitHelperPath, } from "../core/eventkitHelper.js";
|
|
11
11
|
import { getDefaultEventkitFetchUrlFromEnv, getFetchedEventkitBridgePath, materializeEventkitBridgeFromNetwork, formatMebibytes, probeHttpArchiveSizeBytes, } from "../core/eventkitBridgeFetch.js";
|
|
12
|
-
import { resolveEventkitBridgeAppBundlePath, resolveEventkitBridgeRepoPath, } from "../core/macosBridgeApp.js";
|
|
12
|
+
import { installBuiltBridgeAppToSystemApplications, installBuiltBridgeAppToUserApplications, recordLastOpenedBridgeAppBundle, resolveEventkitBridgeAppBundlePath, resolveEventkitBridgeRepoPath, } from "../core/macosBridgeApp.js";
|
|
13
13
|
import { loadConfigIfExists } from "./shared.js";
|
|
14
14
|
import { buildMacosExternalShellLine, buildMacosTerminalSessionLine, openTerminalAndRunShellLine, } from "../core/macosTerminalRelay.js";
|
|
15
15
|
const execFileAsync = promisify(execFile);
|
|
@@ -39,6 +39,47 @@ function isConnectFailure(msg) {
|
|
|
39
39
|
function isInteractiveTty() {
|
|
40
40
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
41
41
|
}
|
|
42
|
+
/** ビルド済み `.app` を `~/Applications` と `/Applications` にコピー(失敗はログのみ)。`CALENDIT_BRIDGE_BUILD_SKIP_INSTALL=1` で無効化。 */
|
|
43
|
+
async function finalizeBridgeInstallCopies(bridgeRoot) {
|
|
44
|
+
const bundlePath = path.join(bridgeRoot, ".build", "CalenditEventKitBridge.app");
|
|
45
|
+
if (!fs.existsSync(path.join(bundlePath, "Contents", "Info.plist"))) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (process.env.CALENDIT_BRIDGE_BUILD_SKIP_INSTALL?.trim() === "1") {
|
|
49
|
+
logger.info(t("macos.bridge.buildCopySkipped"));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const user = await installBuiltBridgeAppToUserApplications(bundlePath);
|
|
53
|
+
if (user.ok) {
|
|
54
|
+
logger.info(t("macos.bridge.buildCopyUserOk", { path: user.dest }));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
logger.warn(t("macos.bridge.buildCopyUserWarn", { message: user.message ?? "" }));
|
|
58
|
+
}
|
|
59
|
+
if (process.env.CALENDIT_BRIDGE_BUILD_SKIP_SYSTEM_APP?.trim() === "1") {
|
|
60
|
+
if (user.ok) {
|
|
61
|
+
recordLastOpenedBridgeAppBundle(user.dest);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
recordLastOpenedBridgeAppBundle(bundlePath);
|
|
65
|
+
}
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const sys = await installBuiltBridgeAppToSystemApplications(bundlePath);
|
|
69
|
+
if (sys.ok) {
|
|
70
|
+
logger.info(t("macos.bridge.buildCopySystemOk", { path: sys.dest }));
|
|
71
|
+
recordLastOpenedBridgeAppBundle(sys.dest);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
logger.warn(t("macos.bridge.buildCopySystemSkipped", { message: sys.message ?? "" }));
|
|
75
|
+
if (user.ok) {
|
|
76
|
+
recordLastOpenedBridgeAppBundle(user.dest);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
recordLastOpenedBridgeAppBundle(bundlePath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
42
83
|
/** Run `scripts/build-app-bundle.sh` in `bridgeRoot` and log success. */
|
|
43
84
|
function runBridgeBuildFromRoot(bridgeRoot) {
|
|
44
85
|
const script = path.join(bridgeRoot, "scripts/build-app-bundle.sh");
|
|
@@ -155,6 +196,7 @@ export function registerMacosCommands(program, deps) {
|
|
|
155
196
|
await runBridgeBuildFromRoot(bridgeRoot);
|
|
156
197
|
const outApp = path.join(bridgeRoot, ".build/CalenditEventKitBridge.app");
|
|
157
198
|
logger.info(t("macos.bridge.buildOk", { path: outApp }));
|
|
199
|
+
await finalizeBridgeInstallCopies(bridgeRoot);
|
|
158
200
|
}
|
|
159
201
|
catch (e) {
|
|
160
202
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -181,6 +223,7 @@ export function registerMacosCommands(program, deps) {
|
|
|
181
223
|
await runBridgeBuildFromRoot(bridgeRoot);
|
|
182
224
|
const outApp = path.join(bridgeRoot, ".build/CalenditEventKitBridge.app");
|
|
183
225
|
logger.info(t("macos.bridge.buildOk", { path: outApp }));
|
|
226
|
+
await finalizeBridgeInstallCopies(bridgeRoot);
|
|
184
227
|
}
|
|
185
228
|
catch (e) {
|
|
186
229
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -205,6 +248,7 @@ export function registerMacosCommands(program, deps) {
|
|
|
205
248
|
}
|
|
206
249
|
try {
|
|
207
250
|
await execFileAsync("/usr/bin/open", [p], { shell: false });
|
|
251
|
+
recordLastOpenedBridgeAppBundle(p);
|
|
208
252
|
logger.info(t("macos.bridge.opened", { path: p }));
|
|
209
253
|
}
|
|
210
254
|
catch (e) {
|
|
@@ -317,8 +361,19 @@ export function registerMacosCommands(program, deps) {
|
|
|
317
361
|
writeStdoutLine("macOS のみ対応です。現在の OS では EventKit ヘルパーを使用できません。");
|
|
318
362
|
return;
|
|
319
363
|
}
|
|
364
|
+
const socketPath = resolveBridgeSocketPathForRun();
|
|
320
365
|
const p = resolveEventkitHelperPath();
|
|
321
|
-
|
|
366
|
+
if (socketPath) {
|
|
367
|
+
writeStdoutLine(`EventKit bridge socket: ${socketPath}`);
|
|
368
|
+
const appPath = resolveEventkitBridgeAppBundlePath();
|
|
369
|
+
if (appPath) {
|
|
370
|
+
writeStdoutLine(t("macos.doctor.bridgeAppResolved", { path: appPath }));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
writeStdoutLine(t("macos.doctor.bridgeAppUnresolved"));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
writeStdoutLine(`eventkit-helper: ${p ?? (socketPath ? "(not used — doctor uses the bridge above)" : "(not found — build from repo or set CALENDIT_EVENTKIT_HELPER)")}`);
|
|
322
377
|
if (!hasEventkitTransport()) {
|
|
323
378
|
writeStdoutLine("EventKit: no helper and no local bridge. Build helper or start CalenditEventKitBridge.app.");
|
|
324
379
|
return;
|
|
@@ -328,7 +383,12 @@ export function registerMacosCommands(program, deps) {
|
|
|
328
383
|
writeStdoutLine(JSON.stringify(j, null, 2));
|
|
329
384
|
if (j.calendarAccess === "denied" && isLikelyIdeIntegratedTerminal()) {
|
|
330
385
|
writeStdoutLine("");
|
|
331
|
-
|
|
386
|
+
if (j.transport === "bridge") {
|
|
387
|
+
writeStdoutLine(t("macos.doctor.bridgeDeniedHint"));
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
writeStdoutLine(t("macos.external.suggestionWhenDenied"));
|
|
391
|
+
}
|
|
332
392
|
}
|
|
333
393
|
}
|
|
334
394
|
catch (e) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
/**
|
|
5
|
+
* 実行中の `calendit` が属する npm パッケージのルート(`package.json` の `name` が `calendit` のディレクトリ)。
|
|
6
|
+
* `dist/` から親を辿って解決する。フル git クローンでは `native/` がこの下に付く。
|
|
7
|
+
*/
|
|
8
|
+
export function resolveCalenditPackageRootFromModule() {
|
|
9
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
for (let i = 0; i < 20; i++) {
|
|
11
|
+
const pkg = path.join(dir, "package.json");
|
|
12
|
+
if (fs.existsSync(pkg)) {
|
|
13
|
+
try {
|
|
14
|
+
const raw = fs.readFileSync(pkg, "utf8");
|
|
15
|
+
const j = JSON.parse(raw);
|
|
16
|
+
if (j.name === "calendit") {
|
|
17
|
+
return dir;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// ignore
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const parent = path.dirname(dir);
|
|
25
|
+
if (parent === dir) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
dir = parent;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
@@ -4,7 +4,7 @@ import { promisify } from "util";
|
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import { defaultCalenditDataDir } from "./eventkitHelper.js";
|
|
7
|
-
import { resolveCalenditPackageRootFromModule } from "./
|
|
7
|
+
import { resolveCalenditPackageRootFromModule } from "./calenditInstallRoot.js";
|
|
8
8
|
const execFileAsync = promisify(execFile);
|
|
9
9
|
const fsp = fs.promises;
|
|
10
10
|
/** Same `CALENDIT_CONFIG_DIR` rules as the bridge: fetched sources live under defaultCalenditDataDir. */
|
|
@@ -20,7 +20,7 @@ export declare function resolveBridgeSocketPathForRun(): string | null;
|
|
|
20
20
|
export declare function resolveBridgeSocketPath(): string | null;
|
|
21
21
|
/** true if a helper binary exists, or a bridge socket path is in use (explicit or auto). */
|
|
22
22
|
export declare function hasEventkitTransport(): boolean;
|
|
23
|
-
/** 優先: CALENDIT_EVENTKIT_HELPER →
|
|
23
|
+
/** 優先: CALENDIT_EVENTKIT_HELPER → cwd 配下の release → calendit パッケージルート配下(cwd が fetch 先などでもリポジトリ版を拾える) */
|
|
24
24
|
export declare function resolveEventkitHelperPath(): string | null;
|
|
25
25
|
/**
|
|
26
26
|
* Run EventKit helper: **bridge** when a socket is resolved, else spawn `eventkit-helper`.
|
|
@@ -3,6 +3,7 @@ import * as fs from "fs";
|
|
|
3
3
|
import * as net from "net";
|
|
4
4
|
import * as os from "os";
|
|
5
5
|
import * as path from "path";
|
|
6
|
+
import { resolveCalenditPackageRootFromModule } from "./calenditInstallRoot.js";
|
|
6
7
|
import { t } from "./i18n.js";
|
|
7
8
|
/** Same directory layout as native/eventkit-bridge (Swift). */
|
|
8
9
|
export function defaultCalenditDataDir() {
|
|
@@ -298,7 +299,7 @@ async function runEventkitHelperSpawn(args, options) {
|
|
|
298
299
|
});
|
|
299
300
|
});
|
|
300
301
|
}
|
|
301
|
-
/** 優先: CALENDIT_EVENTKIT_HELPER →
|
|
302
|
+
/** 優先: CALENDIT_EVENTKIT_HELPER → cwd 配下の release → calendit パッケージルート配下(cwd が fetch 先などでもリポジトリ版を拾える) */
|
|
302
303
|
export function resolveEventkitHelperPath() {
|
|
303
304
|
const fromEnv = process.env.CALENDIT_EVENTKIT_HELPER?.trim();
|
|
304
305
|
if (fromEnv && fs.existsSync(fromEnv)) {
|
|
@@ -308,6 +309,13 @@ export function resolveEventkitHelperPath() {
|
|
|
308
309
|
if (fs.existsSync(rel)) {
|
|
309
310
|
return rel;
|
|
310
311
|
}
|
|
312
|
+
const pkgRoot = resolveCalenditPackageRootFromModule();
|
|
313
|
+
if (pkgRoot) {
|
|
314
|
+
const fromPkg = path.join(pkgRoot, "native", "eventkit-helper", ".build", "release", "eventkit-helper");
|
|
315
|
+
if (fs.existsSync(fromPkg)) {
|
|
316
|
+
return fromPkg;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
311
319
|
return null;
|
|
312
320
|
}
|
|
313
321
|
/**
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
export declare function resolveCalenditPackageRootFromModule(): string | null;
|
|
1
|
+
/** Persist which `.app` calendit last opened or installed (helps doctor after cwd / helper path changes). */
|
|
2
|
+
export declare function recordLastOpenedBridgeAppBundle(appPath: string): void;
|
|
3
|
+
export { resolveCalenditPackageRootFromModule } from "./calenditInstallRoot.js";
|
|
6
4
|
/** `native/eventkit-bridge` with `Package.swift` (source tree), or null. */
|
|
7
5
|
export declare function resolveEventkitBridgeRepoPath(): string | null;
|
|
8
6
|
/**
|
|
9
|
-
* Resolve the CalenditEventKitBridge .app path for `calendit macos bridge start
|
|
10
|
-
* Order: CALENDIT_EVENTKIT_BRIDGE_APP
|
|
7
|
+
* Resolve the CalenditEventKitBridge .app path for `calendit macos bridge start` / doctor.
|
|
8
|
+
* Order: `CALENDIT_EVENTKIT_BRIDGE_APP`, then `/Applications` and `~/Applications` (stable TCC targets),
|
|
9
|
+
* then `Package.swift` 隣の `.build/`(fetch / clone / `CALENDIT_EVENTKIT_BRIDGE_ROOT`),
|
|
10
|
+
* then cwd 配下の開発用 `.build/`, finally the path last recorded by `recordLastOpenedBridgeAppBundle` if still present.
|
|
11
11
|
*/
|
|
12
12
|
export declare function resolveEventkitBridgeAppBundlePath(): string | null;
|
|
13
|
+
/** `~/Applications/CalenditEventKitBridge.app` へ上書きコピー(TCC 用の安定パス向け)。 */
|
|
14
|
+
export declare function installBuiltBridgeAppToUserApplications(sourceApp: string): Promise<{
|
|
15
|
+
ok: boolean;
|
|
16
|
+
dest: string;
|
|
17
|
+
message?: string;
|
|
18
|
+
}>;
|
|
19
|
+
/** `/Applications/CalenditEventKitBridge.app` へ上書きコピー(権限が無い場合は失敗し得る)。 */
|
|
20
|
+
export declare function installBuiltBridgeAppToSystemApplications(sourceApp: string): Promise<{
|
|
21
|
+
ok: boolean;
|
|
22
|
+
dest: string;
|
|
23
|
+
message?: string;
|
|
24
|
+
}>;
|
|
@@ -1,39 +1,42 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
+
import * as fsp from "fs/promises";
|
|
2
3
|
import * as os from "os";
|
|
3
4
|
import * as path from "path";
|
|
4
|
-
import {
|
|
5
|
+
import { resolveCalenditPackageRootFromModule } from "./calenditInstallRoot.js";
|
|
5
6
|
import { defaultCalenditDataDir } from "./eventkitHelper.js";
|
|
6
7
|
function isAppBundle(p) {
|
|
7
8
|
return p.endsWith(".app") && fs.existsSync(path.join(p, "Contents/Info.plist"));
|
|
8
9
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (fs.existsSync(pkg)) {
|
|
18
|
-
try {
|
|
19
|
-
const raw = fs.readFileSync(pkg, "utf8");
|
|
20
|
-
const j = JSON.parse(raw);
|
|
21
|
-
if (j.name === "calendit") {
|
|
22
|
-
return dir;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// ignore
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
const parent = path.dirname(dir);
|
|
30
|
-
if (parent === dir) {
|
|
31
|
-
return null;
|
|
10
|
+
/** Last bundle opened or installed by calendit (fallback when search paths miss). */
|
|
11
|
+
const BRIDGE_BUNDLE_PATH_CACHE = "eventkit-bridge-bundle-path.txt";
|
|
12
|
+
function readCachedBridgeAppBundlePath() {
|
|
13
|
+
const f = path.join(defaultCalenditDataDir(), BRIDGE_BUNDLE_PATH_CACHE);
|
|
14
|
+
try {
|
|
15
|
+
const raw = fs.readFileSync(f, "utf8").trim();
|
|
16
|
+
if (raw && isAppBundle(raw)) {
|
|
17
|
+
return raw;
|
|
32
18
|
}
|
|
33
|
-
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
/* missing or unreadable */
|
|
34
22
|
}
|
|
35
23
|
return null;
|
|
36
24
|
}
|
|
25
|
+
/** Persist which `.app` calendit last opened or installed (helps doctor after cwd / helper path changes). */
|
|
26
|
+
export function recordLastOpenedBridgeAppBundle(appPath) {
|
|
27
|
+
const resolved = path.resolve(appPath);
|
|
28
|
+
if (!isAppBundle(resolved)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
fs.mkdirSync(defaultCalenditDataDir(), { recursive: true });
|
|
33
|
+
fs.writeFileSync(path.join(defaultCalenditDataDir(), BRIDGE_BUNDLE_PATH_CACHE), `${resolved}\n`, "utf8");
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
/* best-effort */
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export { resolveCalenditPackageRootFromModule } from "./calenditInstallRoot.js";
|
|
37
40
|
/** `native/eventkit-bridge` with `Package.swift` (source tree), or null. */
|
|
38
41
|
export function resolveEventkitBridgeRepoPath() {
|
|
39
42
|
const override = process.env.CALENDIT_EVENTKIT_BRIDGE_ROOT?.trim();
|
|
@@ -59,25 +62,59 @@ export function resolveEventkitBridgeRepoPath() {
|
|
|
59
62
|
return null;
|
|
60
63
|
}
|
|
61
64
|
/**
|
|
62
|
-
* Resolve the CalenditEventKitBridge .app path for `calendit macos bridge start
|
|
63
|
-
* Order: CALENDIT_EVENTKIT_BRIDGE_APP
|
|
65
|
+
* Resolve the CalenditEventKitBridge .app path for `calendit macos bridge start` / doctor.
|
|
66
|
+
* Order: `CALENDIT_EVENTKIT_BRIDGE_APP`, then `/Applications` and `~/Applications` (stable TCC targets),
|
|
67
|
+
* then `Package.swift` 隣の `.build/`(fetch / clone / `CALENDIT_EVENTKIT_BRIDGE_ROOT`),
|
|
68
|
+
* then cwd 配下の開発用 `.build/`, finally the path last recorded by `recordLastOpenedBridgeAppBundle` if still present.
|
|
64
69
|
*/
|
|
65
70
|
export function resolveEventkitBridgeAppBundlePath() {
|
|
66
71
|
const fromEnv = process.env.CALENDIT_EVENTKIT_BRIDGE_APP?.trim();
|
|
67
72
|
if (fromEnv && isAppBundle(fromEnv)) {
|
|
68
|
-
return fromEnv;
|
|
73
|
+
return path.resolve(fromEnv);
|
|
74
|
+
}
|
|
75
|
+
const global = "/Applications/CalenditEventKitBridge.app";
|
|
76
|
+
if (isAppBundle(global)) {
|
|
77
|
+
return global;
|
|
69
78
|
}
|
|
70
79
|
const homeApps = path.join(os.homedir(), "Applications/CalenditEventKitBridge.app");
|
|
71
80
|
if (isAppBundle(homeApps)) {
|
|
72
81
|
return homeApps;
|
|
73
82
|
}
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
|
|
83
|
+
const bridgeRoot = resolveEventkitBridgeRepoPath();
|
|
84
|
+
if (bridgeRoot) {
|
|
85
|
+
const fromRepoBuild = path.join(bridgeRoot, ".build", "CalenditEventKitBridge.app");
|
|
86
|
+
if (isAppBundle(fromRepoBuild)) {
|
|
87
|
+
return fromRepoBuild;
|
|
88
|
+
}
|
|
77
89
|
}
|
|
78
90
|
const dev = path.join(process.cwd(), "native/eventkit-bridge/.build/CalenditEventKitBridge.app");
|
|
79
91
|
if (isAppBundle(dev)) {
|
|
80
92
|
return dev;
|
|
81
93
|
}
|
|
82
|
-
return
|
|
94
|
+
return readCachedBridgeAppBundlePath();
|
|
95
|
+
}
|
|
96
|
+
/** `~/Applications/CalenditEventKitBridge.app` へ上書きコピー(TCC 用の安定パス向け)。 */
|
|
97
|
+
export async function installBuiltBridgeAppToUserApplications(sourceApp) {
|
|
98
|
+
const dest = path.join(os.homedir(), "Applications", "CalenditEventKitBridge.app");
|
|
99
|
+
try {
|
|
100
|
+
await fsp.mkdir(path.dirname(dest), { recursive: true });
|
|
101
|
+
await fsp.rm(dest, { recursive: true, force: true });
|
|
102
|
+
await fsp.cp(sourceApp, dest, { recursive: true, force: true });
|
|
103
|
+
return { ok: true, dest };
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
return { ok: false, dest, message: e instanceof Error ? e.message : String(e) };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** `/Applications/CalenditEventKitBridge.app` へ上書きコピー(権限が無い場合は失敗し得る)。 */
|
|
110
|
+
export async function installBuiltBridgeAppToSystemApplications(sourceApp) {
|
|
111
|
+
const dest = "/Applications/CalenditEventKitBridge.app";
|
|
112
|
+
try {
|
|
113
|
+
await fsp.rm(dest, { recursive: true, force: true });
|
|
114
|
+
await fsp.cp(sourceApp, dest, { recursive: true, force: true });
|
|
115
|
+
return { ok: true, dest };
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
return { ok: false, dest, message: e instanceof Error ? e.message : String(e) };
|
|
119
|
+
}
|
|
83
120
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** Generated by scripts/gen-locale-keys.mjs — do not edit by hand */
|
|
2
|
-
export type LocaleKey = "common.hint" | "config.check.contexts" | "config.check.contextsNone" | "config.check.fileLine" | "config.check.googleNotSet" | "config.check.googleOk" | "config.check.header" | "config.check.outlookNotSet" | "config.check.outlookOk" | "config.check.uiLocale" | "config.cmd.contextDeleted" | "config.cmd.contextSaved" | "config.cmd.googleSaved" | "config.cmd.localeSet" | "config.cmd.macosTransportSet" | "config.cmd.outlookSaved" | "errors.api.prefix" | "errors.apiWithStatus" | "errors.auth.googleLoginHint" | "errors.auth.prefix" | "errors.config.fileNotFound" | "errors.config.fileNotFoundHint" | "errors.config.invalidFormat" | "errors.config.invalidFormatDetails" | "errors.config.prefix" | "errors.config.readFailed" | "errors.config.readFailedHint" | "errors.context.loadFailed" | "errors.context.loadFailedHint" | "errors.context.missing" | "errors.context.missingHint" | "errors.datetime.invalidFormat" | "errors.datetime.invalidParse" | "errors.datetime.invalidParseHint" | "errors.service.googleCredsNotSet" | "errors.service.googleCredsNotSetHint" | "errors.service.outlookAccountMismatch" | "errors.service.outlookAccountMismatchHint" | "errors.service.outlookCredsNotSet" | "errors.service.outlookCredsNotSetHint" | "errors.service.outlookNoMsalAccounts" | "errors.service.outlookNoMsalAccountsHint" | "errors.unknown" | "errors.validation.prefix" | "eventkit.bridge.bridgeError" | "eventkit.bridge.closedWithoutResponse" | "eventkit.bridge.connectFailed" | "eventkit.bridge.hintStartBridge" | "eventkit.bridge.invalidJson" | "eventkit.bridge.timeout" | "eventkit.bridge.tokenMissing" | "eventkit.helper.exitCode" | "eventkit.helper.hintBuild" | "eventkit.helper.missing" | "eventkit.helper.timeout" | "locale.bootstrap.choiceEn" | "locale.bootstrap.choiceJa" | "locale.bootstrap.prompt" | "macos.bridge.buildFailed" | "macos.bridge.buildNoSource" | "macos.bridge.buildOk" | "macos.bridge.fetchBuildPrompt" | "macos.bridge.fetchCancel" | "macos.bridge.fetchConfirm" | "macos.bridge.fetchFailed" | "macos.bridge.fetchIntro" | "macos.bridge.fetchNoTty" | "macos.bridge.fetchOk" | "macos.bridge.fetchPlan" | "macos.bridge.fetchSizeKnown" | "macos.bridge.fetchSizeUnknown" | "macos.bridge.fetchSkipsExisting" | "macos.bridge.notFound" | "macos.bridge.openFailed" | "macos.bridge.opened" | "macos.external.badSub" | "macos.external.badSubHint" | "macos.external.jsonOnlyForList" | "macos.external.onlyDarwin" | "macos.external.opened" | "macos.external.osascriptFailed" | "macos.external.suggestionWhenDenied" | "macos.setup.canceled" | "macos.setup.contextName" | "macos.setup.contextNameRequired" | "macos.setup.noCalendars" | "macos.setup.noTransport" | "macos.setup.notDarwin" | "macos.setup.pickCalendar" | "macos.setup.saved" | "macos.setup.startBridgePrompt" | "macos.setup.tcc";
|
|
2
|
+
export type LocaleKey = "common.hint" | "config.check.contexts" | "config.check.contextsNone" | "config.check.fileLine" | "config.check.googleNotSet" | "config.check.googleOk" | "config.check.header" | "config.check.outlookNotSet" | "config.check.outlookOk" | "config.check.uiLocale" | "config.cmd.contextDeleted" | "config.cmd.contextSaved" | "config.cmd.googleSaved" | "config.cmd.localeSet" | "config.cmd.macosTransportSet" | "config.cmd.outlookSaved" | "errors.api.prefix" | "errors.apiWithStatus" | "errors.auth.googleLoginHint" | "errors.auth.prefix" | "errors.config.fileNotFound" | "errors.config.fileNotFoundHint" | "errors.config.invalidFormat" | "errors.config.invalidFormatDetails" | "errors.config.prefix" | "errors.config.readFailed" | "errors.config.readFailedHint" | "errors.context.loadFailed" | "errors.context.loadFailedHint" | "errors.context.missing" | "errors.context.missingHint" | "errors.datetime.invalidFormat" | "errors.datetime.invalidParse" | "errors.datetime.invalidParseHint" | "errors.service.googleCredsNotSet" | "errors.service.googleCredsNotSetHint" | "errors.service.outlookAccountMismatch" | "errors.service.outlookAccountMismatchHint" | "errors.service.outlookCredsNotSet" | "errors.service.outlookCredsNotSetHint" | "errors.service.outlookNoMsalAccounts" | "errors.service.outlookNoMsalAccountsHint" | "errors.unknown" | "errors.validation.prefix" | "eventkit.bridge.bridgeError" | "eventkit.bridge.closedWithoutResponse" | "eventkit.bridge.connectFailed" | "eventkit.bridge.hintStartBridge" | "eventkit.bridge.invalidJson" | "eventkit.bridge.timeout" | "eventkit.bridge.tokenMissing" | "eventkit.helper.exitCode" | "eventkit.helper.hintBuild" | "eventkit.helper.missing" | "eventkit.helper.timeout" | "locale.bootstrap.choiceEn" | "locale.bootstrap.choiceJa" | "locale.bootstrap.prompt" | "macos.bridge.buildCopySkipped" | "macos.bridge.buildCopySystemOk" | "macos.bridge.buildCopySystemSkipped" | "macos.bridge.buildCopyUserOk" | "macos.bridge.buildCopyUserWarn" | "macos.bridge.buildFailed" | "macos.bridge.buildNoSource" | "macos.bridge.buildOk" | "macos.bridge.fetchBuildPrompt" | "macos.bridge.fetchCancel" | "macos.bridge.fetchConfirm" | "macos.bridge.fetchFailed" | "macos.bridge.fetchIntro" | "macos.bridge.fetchNoTty" | "macos.bridge.fetchOk" | "macos.bridge.fetchPlan" | "macos.bridge.fetchSizeKnown" | "macos.bridge.fetchSizeUnknown" | "macos.bridge.fetchSkipsExisting" | "macos.bridge.notFound" | "macos.bridge.openFailed" | "macos.bridge.opened" | "macos.doctor.bridgeAppResolved" | "macos.doctor.bridgeAppUnresolved" | "macos.doctor.bridgeDeniedHint" | "macos.external.badSub" | "macos.external.badSubHint" | "macos.external.jsonOnlyForList" | "macos.external.onlyDarwin" | "macos.external.opened" | "macos.external.osascriptFailed" | "macos.external.suggestionWhenDenied" | "macos.setup.canceled" | "macos.setup.contextName" | "macos.setup.contextNameRequired" | "macos.setup.noCalendars" | "macos.setup.noTransport" | "macos.setup.notDarwin" | "macos.setup.pickCalendar" | "macos.setup.saved" | "macos.setup.startBridgePrompt" | "macos.setup.tcc";
|
|
3
3
|
export declare const LOCALE_KEYS: readonly LocaleKey[];
|
|
@@ -57,6 +57,11 @@ export const LOCALE_KEYS = [
|
|
|
57
57
|
"locale.bootstrap.choiceEn",
|
|
58
58
|
"locale.bootstrap.choiceJa",
|
|
59
59
|
"locale.bootstrap.prompt",
|
|
60
|
+
"macos.bridge.buildCopySkipped",
|
|
61
|
+
"macos.bridge.buildCopySystemOk",
|
|
62
|
+
"macos.bridge.buildCopySystemSkipped",
|
|
63
|
+
"macos.bridge.buildCopyUserOk",
|
|
64
|
+
"macos.bridge.buildCopyUserWarn",
|
|
60
65
|
"macos.bridge.buildFailed",
|
|
61
66
|
"macos.bridge.buildNoSource",
|
|
62
67
|
"macos.bridge.buildOk",
|
|
@@ -74,6 +79,9 @@ export const LOCALE_KEYS = [
|
|
|
74
79
|
"macos.bridge.notFound",
|
|
75
80
|
"macos.bridge.openFailed",
|
|
76
81
|
"macos.bridge.opened",
|
|
82
|
+
"macos.doctor.bridgeAppResolved",
|
|
83
|
+
"macos.doctor.bridgeAppUnresolved",
|
|
84
|
+
"macos.doctor.bridgeDeniedHint",
|
|
77
85
|
"macos.external.badSub",
|
|
78
86
|
"macos.external.badSubHint",
|
|
79
87
|
"macos.external.jsonOnlyForList",
|
package/dist/locales/en.json
CHANGED
|
@@ -91,9 +91,14 @@
|
|
|
91
91
|
"bridge": {
|
|
92
92
|
"openFailed": "Could not open the bridge app: {message}.",
|
|
93
93
|
"opened": "Launched {path}. Wait a few seconds, then run: calendit macos doctor",
|
|
94
|
-
"notFound": "CalenditEventKitBridge.app not found.
|
|
94
|
+
"notFound": "CalenditEventKitBridge.app not found. After `calendit macos bridge fetch` + `bridge build`, `.build` under the bridge root and ~/Applications are searched automatically. Otherwise install a release, use Homebrew when available, or run `bridge build` then `macos bridge start`.",
|
|
95
95
|
"buildNoSource": "EventKit bridge sources are not available next to this install. Use a full git clone, or set CALENDIT_EVENTKIT_BRIDGE_ROOT to your native/eventkit-bridge directory.",
|
|
96
96
|
"buildOk": "Build finished. App bundle: {path}",
|
|
97
|
+
"buildCopySkipped": "Skipping post-build copy to Applications (CALENDIT_BRIDGE_BUILD_SKIP_INSTALL=1).",
|
|
98
|
+
"buildCopyUserOk": "Copied bridge .app to {path} (usable from `calendit macos bridge start`).",
|
|
99
|
+
"buildCopyUserWarn": "Could not copy to ~/Applications: {message}",
|
|
100
|
+
"buildCopySystemOk": "Copied bridge .app to {path}",
|
|
101
|
+
"buildCopySystemSkipped": "Skipped copy to /Applications ({message}). Copy manually or use sudo if you need it there.",
|
|
97
102
|
"buildFailed": "EventKit bridge build failed: {message}",
|
|
98
103
|
"fetchIntro": "Download the calendit repository snapshot from GitHub, extract only native/eventkit-bridge, and place it under your calendit data directory (next to the bridge token when using the default location). A Swift build (see next step) will compile CalenditEventKitBridge.app.",
|
|
99
104
|
"fetchPlan": "• Source archive: {url}\n• Approx. download size: {sizeLine}\n• Extract to: {dest}\n• Then (optional) run the Swift build to create the .app under .build/ in that folder.",
|
|
@@ -119,6 +124,11 @@
|
|
|
119
124
|
"startBridgePrompt": "The bridge does not seem to be running. Open CalenditEventKitBridge.app now?",
|
|
120
125
|
"canceled": "Setup canceled."
|
|
121
126
|
},
|
|
127
|
+
"doctor": {
|
|
128
|
+
"bridgeDeniedHint": "Using the bridge, but calendar access is denied. Check System Settings → Privacy & Security → Calendars and grant **CalenditEventKitBridge** full access (TCC applies to the .app, not this terminal).",
|
|
129
|
+
"bridgeAppResolved": "CalenditEventKitBridge.app (same resolution as `macos bridge start`): {path}",
|
|
130
|
+
"bridgeAppUnresolved": "CalenditEventKitBridge.app: could not resolve a bundle path (run `macos bridge build` / `bridge start`, or set CALENDIT_EVENTKIT_BRIDGE_APP)."
|
|
131
|
+
},
|
|
122
132
|
"external": {
|
|
123
133
|
"onlyDarwin": "macOS only.",
|
|
124
134
|
"badSub": "Subcommand must be `doctor`, `list-calendars`, or `shell`.",
|
package/dist/locales/ja.json
CHANGED
|
@@ -91,9 +91,14 @@
|
|
|
91
91
|
"bridge": {
|
|
92
92
|
"openFailed": "ブリッジ app を起動できません: {message}",
|
|
93
93
|
"opened": "起動しました: {path}。数秒待ってから: calendit macos doctor",
|
|
94
|
-
"notFound": "CalenditEventKitBridge.app
|
|
94
|
+
"notFound": "CalenditEventKitBridge.app が見つかりません。`calendit macos bridge fetch` + `bridge build` 後は `.build` や ~/Applications を自動検出します。未ビルドなら配布 / Homebrew、またはクローンで `bridge build` のうえ `macos bridge start` を。",
|
|
95
95
|
"buildNoSource": "EventKit ブリッジのソースがこのインストール近くにありません。git クローン一式を使うか、CALENDIT_EVENTKIT_BRIDGE_ROOT に native/eventkit-bridge を指定するか、**calendit macos bridge fetch** で取得できます。",
|
|
96
96
|
"buildOk": "ビルドが完了しました。{path}",
|
|
97
|
+
"buildCopySkipped": "環境変数により、ビルド後の Applications へのコピーをスキップしました。",
|
|
98
|
+
"buildCopyUserOk": "ブリッジ .app をコピーしました: {path}(`calendit macos bridge start` から利用できます)。",
|
|
99
|
+
"buildCopyUserWarn": "~/Applications へのコピーに失敗しました: {message}",
|
|
100
|
+
"buildCopySystemOk": "ブリッジ .app をコピーしました: {path}",
|
|
101
|
+
"buildCopySystemSkipped": "/Applications へのコピーをスキップしました(権限など: {message})。必要なら手動でコピーするか、`sudo` で同パスへ配置してください。",
|
|
97
102
|
"buildFailed": "EventKit ブリッジのビルドに失敗しました: {message}",
|
|
98
103
|
"fetchIntro": "GitHub 上の calendit リポジトリのスナップショットを取り、**native/eventkit-bridge だけ**を、既定の calendit データ領域(通常は `~/Library/Application Support/calendit/` 配下)に展開します。次のステップで Swift により CalenditEventKitBridge.app をビルドします。",
|
|
99
104
|
"fetchPlan": "• 取得元: {url}\n• おおよそのダウンロード量: {sizeLine}\n• 展開先: {dest}\n• その後(任意)同フォルダで Swift ビルドを実行し、`.build/CalenditEventKitBridge.app` を作ります。",
|
|
@@ -119,6 +124,11 @@
|
|
|
119
124
|
"startBridgePrompt": "ブリッジが起動していない可能性があります。CalenditEventKitBridge.app を開きますか?",
|
|
120
125
|
"canceled": "セットアップを中止しました。"
|
|
121
126
|
},
|
|
127
|
+
"doctor": {
|
|
128
|
+
"bridgeDeniedHint": "ブリッジ経由ですがカレンダーが拒否されています。システム設定 → プライバシーとセキュリティ → カレンダー で **CalenditEventKitBridge** のフルアクセスを確認してください(このターミナルではなく .app 側の許可です)。",
|
|
129
|
+
"bridgeAppResolved": "CalenditEventKitBridge.app(`macos bridge start` と同じ候補解決): {path}",
|
|
130
|
+
"bridgeAppUnresolved": "CalenditEventKitBridge.app: 候補を解決できませんでした(`macos bridge build` / `bridge start`、または CALENDIT_EVENTKIT_BRIDGE_APP を設定してください)。"
|
|
131
|
+
},
|
|
122
132
|
"external": {
|
|
123
133
|
"onlyDarwin": "macOS のみ対応です。",
|
|
124
134
|
"badSub": "サブコマンドは `doctor` / `list-calendars` / `shell` です。",
|
package/package.json
CHANGED