@better-update/cli 0.13.0 → 0.13.1

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/index.mjs CHANGED
@@ -28,7 +28,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
28
28
 
29
29
  //#endregion
30
30
  //#region package.json
31
- var version = "0.13.0";
31
+ var version = "0.13.1";
32
32
 
33
33
  //#endregion
34
34
  //#region src/lib/interactive-mode.ts
@@ -1820,6 +1820,80 @@ const promptConfirm = (message, options) => Effect.gen(function* () {
1820
1820
  })));
1821
1821
  });
1822
1822
 
1823
+ //#endregion
1824
+ //#region src/lib/apple-auth.ts
1825
+ const APPLE_PROVIDER_ID_ENV = "APPLE_PROVIDER_ID";
1826
+ const readEnv = (name) => Effect.gen(function* () {
1827
+ return yield* (yield* CliRuntime).getEnv(name);
1828
+ });
1829
+ const parseProviderId = (raw) => {
1830
+ const id = Number(raw);
1831
+ return Number.isInteger(id) ? Effect.succeed(id) : Effect.fail(new AppleAuthError$1({ message: `${APPLE_PROVIDER_ID_ENV} must be a numeric provider ID, got "${raw}".` }));
1832
+ };
1833
+ const readEnvProviderId = Effect.gen(function* () {
1834
+ const raw = yield* readEnv(APPLE_PROVIDER_ID_ENV);
1835
+ if (!raw) return;
1836
+ return yield* parseProviderId(raw);
1837
+ });
1838
+ const switchSessionProvider = (appleUtils, providerId) => Effect.tryPromise({
1839
+ try: async () => appleUtils.Session.setSessionProviderIdAsync(providerId),
1840
+ catch: (error) => new AppleAuthError$1({ message: `Failed to switch App Store Connect provider (${providerId}): ${String(error)}` })
1841
+ }).pipe(Effect.asVoid);
1842
+ /**
1843
+ * Resolve App Store Connect provider for the current session.
1844
+ *
1845
+ * Selection order: APPLE_PROVIDER_ID env → single available provider →
1846
+ * interactive prompt (always, when multi-team + interactive) → fall back to
1847
+ * apple-utils' currentProviderId (non-interactive only).
1848
+ *
1849
+ * Multi-team users are always re-prompted in interactive mode so a wrong pick
1850
+ * from a previous run can be corrected — we do NOT cache the team choice.
1851
+ *
1852
+ * `switched` flags that the apple-utils cookie jar was mutated.
1853
+ *
1854
+ * Non-interactive (CI): env or single-team paths still work; multi-team falls
1855
+ * back to whatever apple-utils auto-resolved from cookies. Fails with
1856
+ * InteractiveProhibitedError when multi-team and no signal at all.
1857
+ */
1858
+ const resolveProvider = (appleUtils, availableProviders, currentProviderId) => Effect.gen(function* () {
1859
+ let switched = false;
1860
+ const applyChoice = (picked) => Effect.gen(function* () {
1861
+ if (currentProviderId !== picked) {
1862
+ yield* switchSessionProvider(appleUtils, picked);
1863
+ switched = true;
1864
+ }
1865
+ return picked;
1866
+ });
1867
+ const envId = yield* readEnvProviderId;
1868
+ if (envId !== void 0) return {
1869
+ providerId: yield* applyChoice(envId),
1870
+ switched
1871
+ };
1872
+ if (availableProviders.length === 0) return {
1873
+ providerId: currentProviderId,
1874
+ switched
1875
+ };
1876
+ const [firstProvider] = availableProviders;
1877
+ if (availableProviders.length === 1 && firstProvider) return {
1878
+ providerId: yield* applyChoice(firstProvider.providerId),
1879
+ switched
1880
+ };
1881
+ if (!(yield* InteractiveMode).allow) {
1882
+ if (currentProviderId !== void 0) return {
1883
+ providerId: currentProviderId,
1884
+ switched
1885
+ };
1886
+ return yield* new InteractiveProhibitedError({ message: "Multiple App Store Connect providers are available but no APPLE_PROVIDER_ID is set; re-run interactively or set the env var." });
1887
+ }
1888
+ return {
1889
+ providerId: yield* applyChoice(yield* promptSelect("Select App Store Connect provider:", availableProviders.map((provider) => ({
1890
+ value: provider.providerId,
1891
+ label: `${provider.name} [${provider.subType}] (${provider.providerId})`
1892
+ })))),
1893
+ switched
1894
+ };
1895
+ });
1896
+
1823
1897
  //#endregion
1824
1898
  //#region ../../packages/safe-json/src/index.ts
1825
1899
  const parseJsonResult = (text) => {
@@ -1852,14 +1926,10 @@ const AppleSessionStoreLive = Layer.effect(AppleSessionStore, Effect.gen(functio
1852
1926
  if (!content) return null;
1853
1927
  const parsed = safeJsonParse(content);
1854
1928
  if (!isRecord(parsed)) return null;
1855
- if (typeof parsed["teamId"] !== "string" || typeof parsed["username"] !== "string" || !parsed["cookies"]) return null;
1856
- const providerIdRaw = parsed["providerId"];
1857
- const hasProviderId = typeof providerIdRaw === "number" && Number.isInteger(providerIdRaw);
1929
+ if (typeof parsed["username"] !== "string" || !parsed["cookies"]) return null;
1858
1930
  return {
1859
1931
  cookies: parsed["cookies"],
1860
- teamId: parsed["teamId"],
1861
- username: parsed["username"],
1862
- ...hasProviderId ? { providerId: providerIdRaw } : {}
1932
+ username: parsed["username"]
1863
1933
  };
1864
1934
  }),
1865
1935
  saveSession: (session) => Effect.gen(function* () {
@@ -1905,17 +1975,30 @@ const sessionFromInfo = (username, info) => ({
1905
1975
  teamName: info.provider.name,
1906
1976
  providerId: info.provider.providerId
1907
1977
  });
1908
- const restoreFromCookies = (appleUtils, cookies, providerId, teamId) => Effect.tryPromise({
1909
- try: async () => {
1910
- const input = {
1911
- cookies,
1912
- ...providerId === void 0 ? {} : { providerId },
1913
- ...teamId === void 0 ? {} : { teamId }
1914
- };
1915
- return appleUtils.Auth.loginWithCookiesAsync(input);
1916
- },
1978
+ const sessionFromProvider = (username, provider) => ({
1979
+ username,
1980
+ teamId: provider.publicProviderId,
1981
+ teamName: provider.name,
1982
+ providerId: provider.providerId
1983
+ });
1984
+ const restoreFromCookies = (appleUtils, cookies) => Effect.tryPromise({
1985
+ try: async () => appleUtils.Auth.loginWithCookiesAsync({ cookies }),
1917
1986
  catch: (cause) => new AppleAuthError$1({ message: `Failed to restore Apple session: ${formatCause(cause)}` })
1918
1987
  });
1988
+ /**
1989
+ * After a cookie restore or fresh credentials login, re-resolve the team via
1990
+ * {@link resolveProvider}. The cookies are accepted as-is (auth state) but the
1991
+ * team is treated as a per-run choice — we never trust a previously-cached team,
1992
+ * so a wrong pick can always be corrected on the next run.
1993
+ */
1994
+ const resolveSessionTeam = (appleUtils, state) => Effect.gen(function* () {
1995
+ const { availableProviders } = state.session;
1996
+ const resolution = yield* resolveProvider(appleUtils, availableProviders, state.context.providerId ?? state.session.provider.providerId);
1997
+ if (!resolution.switched || resolution.providerId === void 0) return sessionFromAuthState(state);
1998
+ const picked = availableProviders.find((provider) => provider.providerId === resolution.providerId);
1999
+ if (picked === void 0) return yield* new AppleAuthError$1({ message: `Selected provider ${String(resolution.providerId)} not in available providers list.` });
2000
+ return sessionFromProvider(state.username, picked);
2001
+ });
1919
2002
  const loginWithCredentials = (appleUtils, credentials) => Effect.tryPromise({
1920
2003
  try: async () => appleUtils.Auth.loginWithUserCredentialsAsync(credentials, { autoResolveProvider: true }),
1921
2004
  catch: (cause) => new AppleAuthError$1({ message: `Apple login failed: ${formatCause(cause)}` })
@@ -1942,12 +2025,10 @@ const interactiveLogin = (appleUtils, options, cachedUsername) => Effect.gen(fun
1942
2025
  password
1943
2026
  });
1944
2027
  if (state === null) return yield* new AppleAuthError$1({ message: "Apple login returned no session (unexpected)." });
1945
- const session = sessionFromAuthState(state);
2028
+ const session = yield* resolveSessionTeam(appleUtils, state);
1946
2029
  yield* store.saveSession({
1947
2030
  cookies: readJarCookies(appleUtils),
1948
- username: session.username,
1949
- teamId: session.teamId,
1950
- ...session.providerId === void 0 ? {} : { providerId: session.providerId }
2031
+ username: session.username
1951
2032
  });
1952
2033
  yield* store.saveLastUsername(session.username);
1953
2034
  return session;
@@ -1955,15 +2036,15 @@ const interactiveLogin = (appleUtils, options, cachedUsername) => Effect.gen(fun
1955
2036
  const tryRestore = (appleUtils, store) => Effect.gen(function* () {
1956
2037
  const stored = yield* store.loadSession;
1957
2038
  if (stored === null) return null;
1958
- const restored = yield* restoreFromCookies(appleUtils, stored.cookies, stored.providerId, stored.teamId);
2039
+ const restored = yield* restoreFromCookies(appleUtils, stored.cookies).pipe(Effect.catchAll(() => Effect.succeed(null)));
1959
2040
  if (restored === null) return null;
1960
- return sessionFromAuthState(restored);
2041
+ return yield* resolveSessionTeam(appleUtils, restored);
1961
2042
  });
1962
2043
  const makeAppleAuthLive = (appleUtils = defaultAppleUtils) => Layer.effect(AppleAuth, Effect.gen(function* () {
1963
2044
  const store = yield* AppleSessionStore;
1964
2045
  return {
1965
2046
  ensureLoggedIn: (options = {}) => Effect.gen(function* () {
1966
- const restored = yield* tryRestore(appleUtils, store).pipe(Effect.catchAll(() => Effect.succeed(null)));
2047
+ const restored = yield* tryRestore(appleUtils, store);
1967
2048
  if (restored !== null) return restored;
1968
2049
  return yield* interactiveLogin(appleUtils, options, yield* store.loadLastUsername).pipe(Effect.provideService(AppleSessionStore, store));
1969
2050
  }),
@@ -1974,15 +2055,10 @@ const makeAppleAuthLive = (appleUtils = defaultAppleUtils) => Layer.effect(Apple
1974
2055
  whoami: Effect.gen(function* () {
1975
2056
  const stored = yield* store.loadSession;
1976
2057
  if (stored === null) return null;
1977
- const restored = yield* restoreFromCookies(appleUtils, stored.cookies, stored.providerId, stored.teamId).pipe(Effect.catchAll(() => Effect.succeed(null)));
2058
+ const restored = yield* restoreFromCookies(appleUtils, stored.cookies).pipe(Effect.catchAll(() => Effect.succeed(null)));
1978
2059
  if (restored !== null) return sessionFromAuthState(restored);
1979
2060
  const info = appleUtils.Session.getAnySessionInfo();
1980
- return info === null ? {
1981
- username: stored.username,
1982
- teamId: stored.teamId,
1983
- teamName: null,
1984
- providerId: stored.providerId
1985
- } : sessionFromInfo(stored.username, info);
2061
+ return info === null ? null : sessionFromInfo(stored.username, info);
1986
2062
  }),
1987
2063
  buildRequestContext: (session) => ({
1988
2064
  teamId: session.teamId,