1import * as Effect from "effect/Effect";
2import * as FileSystem from "effect/FileSystem";
3import { safariAccessGranted } from "./SafariCookies.ts";
4import {
5 BROWSER_IMPORT_SOURCES,
6 resolveCookieDatabase,
7 listSourceProfiles,
8 sourcePathContext,
9} from "./Sources.ts";
10
11export const safariPermissionCheck = Effect.gen(function* () {
12 const context = yield* sourcePathContext;
13 const services = yield* Effect.context<FileSystem.FileSystem>();
14 const runPromise = Effect.runPromiseWith(services);
15 const safari = BROWSER_IMPORT_SOURCES.find((source) => source.engine === "safari");
16 const check = Effect.gen(function* () {
17 if (!safari || context.platform !== "darwin") return false;
18 const defaultJar = yield* resolveCookieDatabase(safari, context, ".");
19 if (defaultJar !== undefined) return yield* safariAccessGranted(defaultJar);
20 // A Safari installation can have cookies only in a named profile. Rediscover
21 // those stores after a grant, since TCC may have hidden their metadata before.
22 const profiles = yield* listSourceProfiles(safari, context);
23 for (const profile of profiles) {
24 const jar = yield* resolveCookieDatabase(safari, context, profile.directory);
25 if (jar !== undefined && (yield* safariAccessGranted(jar))) return true;
26 }
27 return false;
28 });
29 // Open and close the jar without reading cookies or attempting an import.
30 return () => runPromise(check);
31});