Jelajahi Sumber

Add per-service refresh entry points; write creds on completion

refresh-airbnb and refresh-booking are now top-level uv commands,
mirroring the existing npm scripts. refresh-all now uses
Promise.allSettled so each service writes its credentials as soon as it
finishes rather than waiting for all to complete, and a single failure
no longer blocks the other service's output.
ZiB 4 bulan lalu
induk
melakukan
b9ed98f056

+ 2 - 0
pyproject.toml

@@ -15,6 +15,8 @@ dependencies = [
 
 
 [project.scripts]
 [project.scripts]
 refresh-creds = "room_cal.service_api._scripts:refresh_cookies"
 refresh-creds = "room_cal.service_api._scripts:refresh_cookies"
+refresh-airbnb = "room_cal.service_api._scripts:refresh_airbnb_cli"
+refresh-booking = "room_cal.service_api._scripts:refresh_booking_cli"
 refresh-homestay = "room_cal.service_api._scripts:refresh_homestay_cookies"
 refresh-homestay = "room_cal.service_api._scripts:refresh_homestay_cookies"
 booking-2fa = "room_cal.service_api._scripts:_trigger_booking_chat_auth_cli"
 booking-2fa = "room_cal.service_api._scripts:_trigger_booking_chat_auth_cli"
 room-cal = "room_cal.actions._cli:main"
 room-cal = "room_cal.actions._cli:main"

+ 16 - 0
room_cal/service_api/_scripts.py

@@ -106,6 +106,22 @@ def refresh_service(key: str) -> None:
   fn()
   fn()
 
 
 
 
+def refresh_airbnb_cli() -> None:
+  """CLI entry point for `uv run refresh-airbnb`."""
+  ts_dir = _ts_dir()
+  _ensure_installed(ts_dir)
+  result = subprocess.run(['npm', 'run', 'refresh-airbnb', '--'] + sys.argv[1:], cwd=ts_dir, env=_npm_env())
+  sys.exit(result.returncode)
+
+
+def refresh_booking_cli() -> None:
+  """CLI entry point for `uv run refresh-booking`."""
+  ts_dir = _ts_dir()
+  _ensure_installed(ts_dir)
+  result = subprocess.run(['npm', 'run', 'refresh-booking', '--'] + sys.argv[1:], cwd=ts_dir, env=_npm_env())
+  sys.exit(result.returncode)
+
+
 def refresh_cookies() -> None:
 def refresh_cookies() -> None:
   ts_dir = _ts_dir()
   ts_dir = _ts_dir()
   _ensure_installed(ts_dir)
   _ensure_installed(ts_dir)

+ 19 - 8
room_cal/service_api/typescript/scripts/refresh-all.ts

@@ -2,22 +2,33 @@ import { refresh as refreshAirbnb } from '../airbnb/refresh-cookies';
 import { refresh as refreshBooking } from '../booking/refresh-cookies';
 import { refresh as refreshBooking } from '../booking/refresh-cookies';
 import { handleOutput } from '../shared/api-client';
 import { handleOutput } from '../shared/api-client';
 import { parseOutputMode } from '../shared/cookie-utils';
 import { parseOutputMode } from '../shared/cookie-utils';
+import type { CredentialsPayload } from '../shared/types';
 import * as path from 'path';
 import * as path from 'path';
 import * as os from 'os';
 import * as os from 'os';
 
 
 const DATA_HOME = process.env.ROOM_CAL_DATA_HOME ?? path.join(os.homedir(), '.local', 'room_cal');
 const DATA_HOME = process.env.ROOM_CAL_DATA_HOME ?? path.join(os.homedir(), '.local', 'room_cal');
 const mode = parseOutputMode(process.argv);
 const mode = parseOutputMode(process.argv);
 
 
+async function refreshService(
+  name: string,
+  refreshFn: () => Promise<CredentialsPayload>,
+  envPath: string,
+): Promise<void> {
+  const creds = await refreshFn();
+  await handleOutput(name, creds, mode, envPath);
+}
+
 async function main(): Promise<void> {
 async function main(): Promise<void> {
-  const [airbnbCreds, bookingCreds] = await Promise.all([
-    refreshAirbnb(mode),
-    refreshBooking(mode),
-  ]);
-  await Promise.all([
-    handleOutput('airbnb',  airbnbCreds,  mode, path.join(DATA_HOME, 'airbnb.env')),
-    handleOutput('booking', bookingCreds, mode, path.join(DATA_HOME, 'booking.env')),
+  const results = await Promise.allSettled([
+    refreshService('airbnb', () => refreshAirbnb(mode), path.join(DATA_HOME, 'airbnb.env')),
+    refreshService('booking', () => refreshBooking(mode), path.join(DATA_HOME, 'booking.env')),
   ]);
   ]);
-  if (mode !== 'stdout') console.error('\nAll credentials refreshed.');
+  const failures = results.filter((r): r is PromiseRejectedResult => r.status === 'rejected');
+  if (mode !== 'stdout') {
+    if (failures.length === 0) console.error('\nAll credentials refreshed.');
+    else console.error(`\n${failures.length} service(s) failed to refresh.`);
+  }
+  if (failures.length > 0) process.exit(1);
 }
 }
 
 
 main().catch(err => { console.error(err.message); process.exit(1); });
 main().catch(err => { console.error(err.message); process.exit(1); });