@przeprogramowani/10x-cli 1.25.1 → 1.25.2

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.
Files changed (2) hide show
  1. package/dist/index.mjs +36 -6
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -3183,7 +3183,7 @@ var cac = (name = "") => new CAC(name);
3183
3183
  // package.json
3184
3184
  var package_default = {
3185
3185
  name: "@przeprogramowani/10x-cli",
3186
- version: "1.25.1",
3186
+ version: "1.25.2",
3187
3187
  description: "Open-source CLI for 10xDevs course content",
3188
3188
  repository: {
3189
3189
  type: "git",
@@ -3359,6 +3359,7 @@ function updateToolConfig(patch) {
3359
3359
  import { hostname as osHostname, release as osRelease } from "node:os";
3360
3360
 
3361
3361
  // src/lib/api-client.ts
3362
+ var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
3362
3363
  var DEFAULT_API_BASE = "https://10x-toolkit-api.przeprogramowani.workers.dev";
3363
3364
  var PROD_HOSTNAME = "10x-toolkit-api.przeprogramowani.workers.dev";
3364
3365
  var DEV_HOSTNAMES = new Set(["localhost", "127.0.0.1"]);
@@ -3401,6 +3402,7 @@ var ERROR_CODE_MESSAGES = {
3401
3402
  module_locked: "This module is not available yet.",
3402
3403
  signing_failed: "Could not sign the download URL. Try again in a moment.",
3403
3404
  invalid_json: "The server received a malformed request.",
3405
+ email_changed: "Your email changed. Run `10x auth` to sign in again.",
3404
3406
  unauthorized: "You are not signed in. Run `10x auth` first.",
3405
3407
  no_membership: "No active course membership was found for this email.",
3406
3408
  invalid_refresh_token: "Your session has expired. Run `10x auth` again.",
@@ -3423,8 +3425,9 @@ function messageForApiError(payload) {
3423
3425
  if (typeof payload.message === "string" && payload.message.length > 0) {
3424
3426
  return payload.message;
3425
3427
  }
3426
- if (typeof payload.error === "string" && payload.error.length > 0) {
3427
- return ERROR_CODE_MESSAGES[payload.error];
3428
+ const code = payload.code ?? payload.error;
3429
+ if (typeof code === "string" && code.length > 0) {
3430
+ return ERROR_CODE_MESSAGES[code];
3428
3431
  }
3429
3432
  return;
3430
3433
  }
@@ -3471,6 +3474,21 @@ async function request(method, path, body, options = {}) {
3471
3474
  }
3472
3475
  if (!response.ok) {
3473
3476
  const payload = parsed && typeof parsed === "object" ? parsed : undefined;
3477
+ if ((payload?.code ?? payload?.error) === "email_changed" && options.token && readAuth()?.access_token === options.token) {
3478
+ try {
3479
+ const release = await import_proper_lockfile.default.lock(authFilePath(), {
3480
+ realpath: false,
3481
+ stale: 1e4,
3482
+ retries: { retries: 5, factor: 2, minTimeout: 100, maxTimeout: 1000 }
3483
+ });
3484
+ try {
3485
+ if (readAuth()?.access_token === options.token)
3486
+ deleteAuth();
3487
+ } finally {
3488
+ await release();
3489
+ }
3490
+ } catch {}
3491
+ }
3474
3492
  const mapped = messageForApiError(payload);
3475
3493
  let errorMessage;
3476
3494
  if (mapped) {
@@ -3490,7 +3508,13 @@ async function request(method, path, body, options = {}) {
3490
3508
  payload
3491
3509
  };
3492
3510
  }
3493
- return { ok: true, status: response.status, data: parsed, responseHeaders: response.headers, rawBody: text };
3511
+ return {
3512
+ ok: true,
3513
+ status: response.status,
3514
+ data: parsed,
3515
+ responseHeaders: response.headers,
3516
+ rawBody: text
3517
+ };
3494
3518
  }
3495
3519
  function apiGet(path, options = {}) {
3496
3520
  return request("GET", path, undefined, options);
@@ -3652,7 +3676,7 @@ async function pollCircleLogin(deviceCode, options = {}) {
3652
3676
  }
3653
3677
 
3654
3678
  // src/lib/auth-guard.ts
3655
- var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
3679
+ var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
3656
3680
  import { mkdirSync as mkdirSync2 } from "node:fs";
3657
3681
  import { dirname } from "node:path";
3658
3682
 
@@ -3727,7 +3751,7 @@ function isNearExpiry(auth, windowMs = DEFAULT_REFRESH_WINDOW_MS, now = new Date
3727
3751
  async function acquireRefreshLock(ctx, lockTarget) {
3728
3752
  try {
3729
3753
  mkdirSync2(dirname(lockTarget), { recursive: true });
3730
- return await import_proper_lockfile.default.lock(lockTarget, {
3754
+ return await import_proper_lockfile2.default.lock(lockTarget, {
3731
3755
  realpath: false,
3732
3756
  stale: LOCK_STALE_MS,
3733
3757
  retries: {
@@ -3785,6 +3809,12 @@ async function requireAuth(ctx, options = {}) {
3785
3809
  persist(next);
3786
3810
  return next;
3787
3811
  }
3812
+ if (refreshed.code === "email_changed") {
3813
+ try {
3814
+ (options.remove ?? deleteAuth)();
3815
+ } catch {}
3816
+ outputError(ctx, "email_changed", "Your email changed. Sign in again.", ExitCodes.AUTH_REQUIRED, "Run '10x auth' to log in.");
3817
+ }
3788
3818
  if (forced) {
3789
3819
  outputError(ctx, refreshed.code, refreshed.error, refreshed.status === 403 ? ExitCodes.FORBIDDEN : refreshed.status === 401 ? ExitCodes.AUTH_REQUIRED : ExitCodes.ERROR);
3790
3820
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@przeprogramowani/10x-cli",
3
- "version": "1.25.1",
3
+ "version": "1.25.2",
4
4
  "description": "Open-source CLI for 10xDevs course content",
5
5
  "repository": {
6
6
  "type": "git",