@przeprogramowani/10x-cli 1.3.0 → 1.3.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 +54 -5
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -2271,7 +2271,7 @@ var cac = (name = "") => new CAC(name);
2271
2271
  // package.json
2272
2272
  var package_default = {
2273
2273
  name: "@przeprogramowani/10x-cli",
2274
- version: "1.3.0",
2274
+ version: "1.3.2",
2275
2275
  description: "Open-source CLI for 10xDevs course content",
2276
2276
  repository: {
2277
2277
  type: "git",
@@ -3034,6 +3034,37 @@ function resolveApiBase() {
3034
3034
  throw new Error(`API_BASE_URL must be ${DEFAULT_API_BASE} or http://localhost[:port] (got ${JSON.stringify(override)})`);
3035
3035
  }
3036
3036
  var DEFAULT_TIMEOUT_MS = 30000;
3037
+ var UNKNOWN_API_ERROR_MESSAGE = "An unknown error occurred. Please contact 10xDevs mentors and share the command that caused this. Sorry for the issue!";
3038
+ var ERROR_CODE_MESSAGES = {
3039
+ course_not_found: "Course not found.",
3040
+ lesson_not_found: "Lesson not found.",
3041
+ module_not_found: "Module not found.",
3042
+ artifact_not_found: "Artifact not found.",
3043
+ bundle_not_found: "Bundle not found.",
3044
+ module_locked: "This module is not available yet.",
3045
+ signing_failed: "Could not sign the download URL. Try again in a moment.",
3046
+ invalid_json: "The server received a malformed request.",
3047
+ unauthorized: "You are not signed in. Run `10x auth` first.",
3048
+ no_membership: "No active course membership was found for this email.",
3049
+ invalid_refresh_token: "Your session has expired. Run `10x auth` again.",
3050
+ membership_revoked: "Your course membership has been revoked.",
3051
+ rate_limited: "Too many requests. Please slow down and try again shortly.",
3052
+ email_send_failed: "Could not send the login email. Try again in a moment.",
3053
+ admin_access_required: "This action requires admin access.",
3054
+ circle_api_error: "The membership service is temporarily unavailable.",
3055
+ internal_error: "The server hit an unexpected error."
3056
+ };
3057
+ function messageForApiError(payload) {
3058
+ if (!payload)
3059
+ return;
3060
+ if (typeof payload.message === "string" && payload.message.length > 0) {
3061
+ return payload.message;
3062
+ }
3063
+ if (typeof payload.error === "string" && payload.error.length > 0) {
3064
+ return ERROR_CODE_MESSAGES[payload.error];
3065
+ }
3066
+ return;
3067
+ }
3037
3068
  async function request(method, path, body, options = {}) {
3038
3069
  const base = resolveApiBase();
3039
3070
  const url = path.startsWith("http") ? path : `${base}${path}`;
@@ -3077,11 +3108,22 @@ async function request(method, path, body, options = {}) {
3077
3108
  }
3078
3109
  if (!response.ok) {
3079
3110
  const payload = parsed && typeof parsed === "object" ? parsed : undefined;
3111
+ const mapped = messageForApiError(payload);
3112
+ let errorMessage;
3113
+ if (mapped) {
3114
+ errorMessage = mapped;
3115
+ } else if (payload) {
3116
+ errorMessage = UNKNOWN_API_ERROR_MESSAGE;
3117
+ } else if (response.statusText.length > 0) {
3118
+ errorMessage = response.statusText;
3119
+ } else {
3120
+ errorMessage = UNKNOWN_API_ERROR_MESSAGE;
3121
+ }
3080
3122
  return {
3081
3123
  ok: false,
3082
3124
  status: response.status,
3083
- code: payload?.code ?? `http_${response.status}`,
3084
- error: payload?.error ?? payload?.message ?? response.statusText,
3125
+ code: typeof payload?.code === "string" ? payload.code : `http_${response.status}`,
3126
+ error: errorMessage,
3085
3127
  payload
3086
3128
  };
3087
3129
  }
@@ -5232,13 +5274,14 @@ function formatModuleRow(m3, lessonCount) {
5232
5274
  return ` ${icon} ${label} — ${lessonCount} lesson${lessonCount === 1 ? "" : "s"} [${state}]`;
5233
5275
  }
5234
5276
  function renderModuleDetail(ctx, module) {
5277
+ const isLocked = module.effectiveState === "locked";
5235
5278
  if (ctx.json) {
5236
5279
  output(ctx, "", {
5237
5280
  module: module.module,
5238
5281
  title: module.title,
5239
5282
  state: module.effectiveState,
5240
5283
  releaseAt: module.releaseAt,
5241
- lessons: module.lessons.map((l2) => ({
5284
+ lessons: isLocked ? [] : module.lessons.map((l2) => ({
5242
5285
  lessonId: l2.lessonId,
5243
5286
  lesson: l2.lesson,
5244
5287
  title: l2.title,
@@ -5248,10 +5291,16 @@ function renderModuleDetail(ctx, module) {
5248
5291
  });
5249
5292
  return;
5250
5293
  }
5251
- const stateLabel = module.effectiveState === "unlocked" ? "unlocked" : `locked — unlocks ${formatReleaseAt(module.releaseAt)}`;
5294
+ const stateLabel = isLocked ? `locked — unlocks ${formatReleaseAt(module.releaseAt)}` : "unlocked";
5252
5295
  const lines = [];
5253
5296
  lines.push(`Module ${module.module}: ${module.title} [${stateLabel}]`);
5254
5297
  lines.push("");
5298
+ if (isLocked) {
5299
+ lines.push(` Lessons will be available after this module unlocks on ${formatReleaseAt(module.releaseAt)}.`);
5300
+ output(ctx, lines.join(`
5301
+ `), undefined);
5302
+ return;
5303
+ }
5255
5304
  if (module.lessons.length === 0) {
5256
5305
  lines.push(" (no lessons in this module)");
5257
5306
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@przeprogramowani/10x-cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Open-source CLI for 10xDevs course content",
5
5
  "repository": {
6
6
  "type": "git",