@better-update/cli 0.21.0 → 0.22.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/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
3
3
  import { execFile, spawn, spawnSync } from "node:child_process";
4
4
  import { defineCommand, runMain } from "citty";
5
5
  import { Console, Context, Data, Deferred, Duration, Effect, Either, Layer, Match, Option, ParseResult, Schedule, Schema } from "effect";
6
- import { Command, FetchHttpClient, FileSystem, HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpClient, HttpClientRequest, OpenApi, Path } from "@effect/platform";
6
+ import { Command, FetchHttpClient, FileSystem, Headers as Headers$1, HttpApi, HttpApiClient, HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, HttpApiSecurity, HttpClient, HttpClientRequest, OpenApi, Path } from "@effect/platform";
7
7
  import { NodeContext } from "@effect/platform-node";
8
8
  import path, { join } from "node:path";
9
9
  import process$1 from "node:process";
@@ -33,7 +33,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
33
33
 
34
34
  //#endregion
35
35
  //#region package.json
36
- var version = "0.21.0";
36
+ var version = "0.22.0";
37
37
 
38
38
  //#endregion
39
39
  //#region src/lib/interactive-mode.ts
@@ -1621,7 +1621,7 @@ const MeOrganization = Schema.Struct({
1621
1621
  const Me = Schema.Struct({
1622
1622
  user: Schema.NullOr(MeUser),
1623
1623
  activeOrganization: Schema.NullOr(MeOrganization),
1624
- /** Authentication source — "session" for browser cookie, "api-key" for CLI bearer tokens. */
1624
+ /** Authentication source — "session" for browser + CLI sessions, "api-key" for API-key (CI) bearer tokens. */
1625
1625
  source: Schema.Literal("session", "api-key"),
1626
1626
  /** Email or descriptor identifying the actor — useful when `user` is null (api-key auth). */
1627
1627
  actorEmail: Schema.String
@@ -2011,17 +2011,10 @@ var ProtocolApi = class extends HttpApi.make("protocol-api").add(ManifestGroup).
2011
2011
  description: "Expo Updates protocol endpoints (unauthenticated)"
2012
2012
  })) {};
2013
2013
 
2014
- //#endregion
2015
- //#region ../../packages/type-guards/src/index.ts
2016
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2017
- const asRecord = (value) => isRecord(value) ? value : void 0;
2018
- const toOptional = (value) => value ?? void 0;
2019
- const toDbNull = (value) => value ?? null;
2020
- const compact = (obj) => Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== void 0));
2021
-
2022
2014
  //#endregion
2023
2015
  //#region src/lib/exit-codes.ts
2024
2016
  var AuthRequiredError = class extends Data.TaggedError("AuthRequiredError") {};
2017
+ var LoginError = class extends Data.TaggedError("LoginError") {};
2025
2018
  var ProjectNotLinkedError = class extends Data.TaggedError("ProjectNotLinkedError") {};
2026
2019
  var UploadFailedError = class extends Data.TaggedError("UploadFailedError") {};
2027
2020
  var BuildProfileError = class extends Data.TaggedError("BuildProfileError") {};
@@ -2048,6 +2041,14 @@ var CredentialsJsonError = class extends Data.TaggedError("CredentialsJsonError"
2048
2041
  var DirtyRepoError = class extends Data.TaggedError("DirtyRepoError") {};
2049
2042
  var StagingError = class extends Data.TaggedError("StagingError") {};
2050
2043
 
2044
+ //#endregion
2045
+ //#region ../../packages/type-guards/src/index.ts
2046
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2047
+ const asRecord = (value) => isRecord(value) ? value : void 0;
2048
+ const toOptional = (value) => value ?? void 0;
2049
+ const toDbNull = (value) => value ?? null;
2050
+ const compact = (obj) => Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== void 0));
2051
+
2051
2052
  //#endregion
2052
2053
  //#region src/lib/format-error.ts
2053
2054
  const formatCause = (cause) => {
@@ -2168,14 +2169,25 @@ const ApiClientLive = Layer.effect(ApiClientService, Effect.gen(function* () {
2168
2169
  const authStore = yield* AuthStore;
2169
2170
  const configStore = yield* ConfigStore;
2170
2171
  const retryingClient = HttpClient.retryTransient(clientService, RETRY_TRANSIENT_OPTIONS);
2171
- return { get: Effect.gen(function* () {
2172
- const token = yield* authStore.getToken;
2173
- const baseUrl = yield* configStore.getBaseUrl;
2174
- return yield* HttpApiClient.make(ManagementApi, {
2175
- transformClient: HttpClient.mapRequest(HttpClientRequest.bearerToken(token)),
2176
- baseUrl
2177
- }).pipe(Effect.provideService(HttpClient.HttpClient, retryingClient));
2178
- }) };
2172
+ return {
2173
+ get: Effect.gen(function* () {
2174
+ const token = yield* authStore.getToken;
2175
+ const baseUrl = yield* configStore.getBaseUrl;
2176
+ return yield* HttpApiClient.make(ManagementApi, {
2177
+ transformClient: HttpClient.mapRequest(HttpClientRequest.bearerToken(token)),
2178
+ baseUrl
2179
+ }).pipe(Effect.provideService(HttpClient.HttpClient, retryingClient));
2180
+ }),
2181
+ exchangeOneTimeToken: (oneTimeToken) => Effect.gen(function* () {
2182
+ const baseUrl = yield* configStore.getBaseUrl;
2183
+ const request = yield* HttpClientRequest.post(`${baseUrl}/api/auth/one-time-token/verify`).pipe(HttpClientRequest.bodyJson({ token: oneTimeToken }), Effect.mapError(() => new LoginError({ message: "Could not encode the login request." })));
2184
+ const response = yield* retryingClient.execute(request).pipe(Effect.mapError((cause) => new LoginError({ message: `Could not reach the login server: ${String(cause)}` })));
2185
+ if (response.status < 200 || response.status >= 300) return yield* new LoginError({ message: `Login token exchange failed (HTTP ${response.status}). Run \`better-update login\` again.` });
2186
+ const sessionToken = Headers$1.get(response.headers, "set-auth-token");
2187
+ if (Option.isNone(sessionToken)) return yield* new LoginError({ message: "The login server did not return a session token (missing set-auth-token header)." });
2188
+ return sessionToken.value;
2189
+ })
2190
+ };
2179
2191
  }));
2180
2192
 
2181
2193
  //#endregion
@@ -2789,8 +2801,9 @@ const browserLogin = Effect.scoped(Effect.gen(function* () {
2789
2801
  yield* Console.log("Opening browser for better-update login...");
2790
2802
  yield* Console.log("");
2791
2803
  yield* openBrowser(loginUrl);
2792
- const token = yield* loginServer.waitForToken;
2793
- yield* authStore.saveToken(token);
2804
+ const oneTimeToken = yield* loginServer.waitForToken;
2805
+ const sessionToken = yield* (yield* ApiClientService).exchangeOneTimeToken(oneTimeToken);
2806
+ yield* authStore.saveToken(sessionToken);
2794
2807
  yield* Console.log("");
2795
2808
  yield* Console.log("Logged in successfully. Token saved to ~/.better-update/auth.json");
2796
2809
  }));
@@ -2821,6 +2834,7 @@ const exitWith = (code, message) => Console.error(message).pipe(Effect.zipRight(
2821
2834
  //#region src/lib/command-errors.ts
2822
2835
  const BASE_TAG_MAP = {
2823
2836
  AuthRequiredError: 3,
2837
+ LoginError: 3,
2824
2838
  ProjectNotLinkedError: 4,
2825
2839
  NotFound: 1,
2826
2840
  Conflict: 1,