hacktheandes-cli 0.1.203 → 0.1.206

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 (3) hide show
  1. package/README.md +8 -2
  2. package/dist/index.js +423 -290
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -74,8 +74,12 @@ version; legacy attempts do not count toward admission.
74
74
 
75
75
  The public ranking is read-only at `https://hacktheandes.com/challenges`.
76
76
 
77
- Run `andes` for a compact retro welcome screen with a pixel Sacred Valley and
78
- the main commands. Run `andes --help` for the full command reference. The
77
+ Run `andes` to see your current progress and the next command to run.
78
+ `andes challenge` also checks your application before showing the challenge guide.
79
+ Repeating `andes register` after submission shows your next step without submitting again.
80
+ After acceptance, run `andes confirm`; after confirmation, run `andes badge`.
81
+ Confirmation generates the badge automatically. Repeat `andes badge` if it is still processing.
82
+ Run `andes --help` for the full command reference. The welcome screen's
79
83
  landscape uses colored terminal cells, with readable text that works with your
80
84
  terminal's line spacing. It adapts to the terminal width and has a plain ASCII
81
85
  fallback when color is disabled with `NO_COLOR`. JSON output and individual
@@ -93,6 +97,8 @@ Validation does not contact the API, and a successful result does not echo input
93
97
  values. Local validation errors include `acceptedFields` in JSON mode. The
94
98
  `status` response already includes both the registration and its requirements;
95
99
  use `requirements` only when requirements-only human output is preferred.
100
+ The CLI adds `data.nextStep` with `kind`, `message`, and `command` to registration
101
+ results and to home and challenge guidance. JSON output remains one versioned envelope.
96
102
 
97
103
  Run `andes login` to authenticate. For automation, provide an OAuth access
98
104
  token with `CHOFEX_TOKEN`.
package/dist/index.js CHANGED
@@ -59988,7 +59988,7 @@ var challengeListText = (catalog) => {
59988
59988
  if (hasOpenChallenge) {
59989
59989
  lines2.push("Empieza el challenge abierto: andes challenge");
59990
59990
  } else {
59991
- lines2.push("No hay un challenge abierto. Los rankings finales siguen visibles.");
59991
+ lines2.push("No hay un challenge abierto. Los rankings finales siguen visibles.", "Siguiente comando para consultar tu postulación: andes status");
59992
59992
  }
59993
59993
  return lines2.join(`
59994
59994
  `);
@@ -60023,7 +60023,11 @@ var challengeShowText = (attempt) => {
60023
60023
  if (progress.shareCode)
60024
60024
  lines3.push(`Código #${progress.shareCode}`);
60025
60025
  }
60026
- lines3.push("", "SIGUIENTE PASO", "Lee el contrato. Antes de editar, discute tres trazas de falla y elige cuál investigar primero.", " cd broken-agent && npm test", " andes challenge test --challenge broken-agent --source ./scheduler.js");
60026
+ if (attempt.latestEvaluation || challenge.closed || evaluationsRemaining <= 0) {
60027
+ lines3.push("", "Consulta el estado de tu postulación y tu siguiente paso:", " andes status");
60028
+ } else {
60029
+ lines3.push("", "SIGUIENTE PASO", "Desde la carpeta broken-agent, lee el contrato, repara scheduler.js y ejecuta los tests públicos:", " andes challenge test --challenge broken-agent --source ./scheduler.js", "Después prepara review.json con tu revisión y envía una evaluación oficial:", " andes challenge evaluate --challenge broken-agent --source ./scheduler.js --review ./review.json", "Abre personalmente el enlace de aprobación y repite el mismo comando. Los tests públicos por sí solos no completan el challenge.");
60030
+ }
60027
60031
  return lines3.join(`
60028
60032
  `);
60029
60033
  }
@@ -60209,7 +60213,7 @@ var challengeTestText = (result3) => {
60209
60213
  lines3.push(` ${String(mismatch.actual)}`);
60210
60214
  }
60211
60215
  }
60212
- lines3.push("", "Corrige las regresiones públicas antes de usar una evaluación oficial.");
60216
+ lines3.push("", "Corrige las regresiones públicas antes de usar una evaluación oficial.", "Siguiente comando: andes challenge test --challenge broken-agent --source ./scheduler.js");
60213
60217
  return lines3.join(`
60214
60218
  `);
60215
60219
  }
@@ -60274,13 +60278,13 @@ var challengeRankingText = (ranking, now3 = new Date) => {
60274
60278
  const lines2 = [`${ranking.challenge.theme} — ${ranking.challenge.title}`];
60275
60279
  const { rankingVisibleAt } = ranking.challenge;
60276
60280
  if (rankingVisibleAt && !isChallengeRankingVisibleAt(ranking.challenge, now3)) {
60277
- lines2.push("", `Ranking disponible ${formatChallengeOpeningInPeru(rankingVisibleAt)}.`);
60281
+ lines2.push("", `Ranking disponible ${formatChallengeOpeningInPeru(rankingVisibleAt)}.`, "Siguiente comando para consultar tu postulación: andes status");
60278
60282
  return lines2.join(`
60279
60283
  `);
60280
60284
  }
60281
60285
  lines2.push("");
60282
60286
  if (ranking.entries.length === 0) {
60283
- lines2.push("Todavía no hay evaluaciones oficiales.");
60287
+ lines2.push("Todavía no hay evaluaciones oficiales.", "Siguiente comando: andes");
60284
60288
  return lines2.join(`
60285
60289
  `);
60286
60290
  }
@@ -60294,6 +60298,7 @@ var challengeRankingText = (ranking, now3 = new Date) => {
60294
60298
  const participant = [entry.displayName, ...profileLinks].join(" ");
60295
60299
  lines2.push(`${rank} ${accuracy} ${points} ${participant}`);
60296
60300
  }
60301
+ lines2.push("", "El ranking no confirma tu aceptación. Consulta tu siguiente paso:", " andes status");
60297
60302
  return lines2.join(`
60298
60303
  `);
60299
60304
  }
@@ -60307,6 +60312,7 @@ var challengeRankingText = (ranking, now3 = new Date) => {
60307
60312
  const participant = [entry.displayName, ...profileLinks].join(" ");
60308
60313
  lines2.push(`${rank} ${accuracy} ${exact} ${queries} ${participant}`);
60309
60314
  }
60315
+ lines2.push("", "El ranking no confirma tu aceptación. Consulta tu siguiente paso:", " andes status");
60310
60316
  return lines2.join(`
60311
60317
  `);
60312
60318
  };
@@ -60865,6 +60871,108 @@ var root = exports_Command.make(cliCommandName).pipe(exports_Command.withSharedF
60865
60871
  token: exports_Flag.string(rootValueFlagNames.token).pipe(exports_Flag.optional, exports_Flag.withDescription("Clerk OAuth token (prefer CHOFEX_TOKEN to avoid shell history)"))
60866
60872
  }), exports_Command.withDescription(`Apply to ${eventName} and compete for a seat through the mandatory technical challenges`));
60867
60873
 
60874
+ // src/participant-guidance.ts
60875
+ var nextStepFor = (result3) => {
60876
+ if (!result3) {
60877
+ return {
60878
+ kind: "register",
60879
+ message: "Completa y envía tu postulación. Después deberás completar un challenge con una evaluación oficial.",
60880
+ command: "andes register"
60881
+ };
60882
+ }
60883
+ const { registration, requirements } = result3;
60884
+ if (registration.status === "rejected" || registration.status === "withdrawn") {
60885
+ return {
60886
+ kind: "register",
60887
+ message: "Puedes enviar una nueva postulación.",
60888
+ command: "andes register"
60889
+ };
60890
+ }
60891
+ if (registration.status === "accepted") {
60892
+ if (requirements.stage === "complete") {
60893
+ return {
60894
+ kind: "badge",
60895
+ message: "Tu asistencia está confirmada. Generaremos tu carnet automáticamente. Consulta el resultado y comparte tu carnet.",
60896
+ command: "andes badge"
60897
+ };
60898
+ }
60899
+ return {
60900
+ kind: "confirm",
60901
+ message: "Tu postulación fue aceptada. Falta confirmar tu asistencia y completar tus datos de ingreso. Al terminar generaremos tu carnet automáticamente.",
60902
+ command: "andes confirm"
60903
+ };
60904
+ }
60905
+ if (requirements.stage === "draft") {
60906
+ return {
60907
+ kind: "register",
60908
+ message: "Tu postulación todavía es un borrador. Completa los datos y envíala.",
60909
+ command: "andes register"
60910
+ };
60911
+ }
60912
+ const evaluated = registration.challenges.find((challenge2) => challenge2.playable && challenge2.status === "evaluated");
60913
+ if (evaluated) {
60914
+ let message = "Tu evaluación oficial está registrada. Todavía falta la decisión sobre tu postulación. Te avisaremos por correo; también puedes consultar tu estado aquí.";
60915
+ if (registration.status === "waitlisted") {
60916
+ message = "Tu evaluación oficial está registrada y estás en lista de espera. Te avisaremos por correo si se libera un cupo.";
60917
+ }
60918
+ return { kind: "decision", message, command: "andes status" };
60919
+ }
60920
+ const available = registration.challenges.filter((challenge2) => challenge2.playable && challenge2.open && !challenge2.closed && challenge2.evaluationsUsed < challenge2.evaluationsLimit);
60921
+ const challenge = available.find((item) => item.status === "in_progress") ?? available[0];
60922
+ if (challenge) {
60923
+ if (challenge.status === "in_progress") {
60924
+ return {
60925
+ kind: "challenge_continue",
60926
+ challengeSlug: challenge.slug,
60927
+ message: `Tu postulación está enviada, pero falta completar ${challenge.theme} con una evaluación oficial. Revisa tu progreso y prepara el envío. Los tests públicos no completan este paso.`,
60928
+ command: `andes challenge show --challenge ${challenge.slug}`
60929
+ };
60930
+ }
60931
+ return {
60932
+ kind: "challenge_start",
60933
+ challengeSlug: challenge.slug,
60934
+ message: `Tu postulación está enviada, pero falta el challenge obligatorio. Empieza ${challenge.theme}, resuélvelo y envía una evaluación oficial para competir por un cupo.`,
60935
+ command: `andes challenge init --challenge ${challenge.slug}`
60936
+ };
60937
+ }
60938
+ return {
60939
+ kind: "challenge_unavailable",
60940
+ message: "Todavía necesitas una evaluación oficial para competir por un cupo, pero no hay un challenge abierto con evaluaciones disponibles. Consulta las fechas y los challenges disponibles.",
60941
+ command: "andes challenge list"
60942
+ };
60943
+ };
60944
+ var nextStepText = (step) => ["SIGUIENTE PASO", step.message, `Siguiente comando: ${step.command}`].join(`
60945
+ `);
60946
+ var withRegistrationNextStep = (operation) => operation.pipe(exports_Effect.map((response) => ({
60947
+ ...response,
60948
+ data: { ...response.data, nextStep: nextStepFor(response.data) }
60949
+ })));
60950
+ var loadParticipantGuidance = (client) => getRegistration(client).pipe(exports_Effect.map((response) => ({
60951
+ ...response,
60952
+ data: {
60953
+ registration: response.data,
60954
+ nextStep: nextStepFor(response.data)
60955
+ }
60956
+ })), exports_Effect.catch((error2) => {
60957
+ if (error2.code !== "REGISTRATION_NOT_FOUND" && error2.code !== "AUTHENTICATION_REQUIRED") {
60958
+ return exports_Effect.fail(error2);
60959
+ }
60960
+ let nextStep = nextStepFor();
60961
+ if (error2.code === "AUTHENTICATION_REQUIRED") {
60962
+ nextStep = {
60963
+ kind: "login",
60964
+ message: "Inicia sesión para consultar tu avance y continuar tu postulación.",
60965
+ command: "andes login"
60966
+ };
60967
+ }
60968
+ return exports_Effect.succeed({
60969
+ version: 1,
60970
+ ok: true,
60971
+ requestId: error2.requestId,
60972
+ data: { nextStep }
60973
+ });
60974
+ }));
60975
+
60868
60976
  // src/output.ts
60869
60977
  var printJson = (value3) => exports_Effect.sync(() => {
60870
60978
  process.stdout.write(`${JSON.stringify(value3)}
@@ -60929,74 +61037,69 @@ Request ID: ${error2.requestId}`);
60929
61037
  var registrationLookupErrorText = (error2) => {
60930
61038
  if (error2.code !== "REGISTRATION_NOT_FOUND")
60931
61039
  return;
60932
- return `No registration found.
60933
- Next command: andes register`;
61040
+ return `Todavía no tienes una postulación.
61041
+ ${nextStepText(nextStepFor())}`;
60934
61042
  };
60935
61043
  var requirementsText = (result3) => {
60936
61044
  const { registration, requirements } = result3;
60937
- if (registration.status === "withdrawn") {
60938
- return "Application withdrawn. You may submit a new application.";
60939
- }
60940
- if (requirements.stage === "complete")
60941
- return "Attendance details: complete";
60942
- if (requirements.stage === "draft") {
60943
- return `Application draft in progress.${registrationPartsText(result3)}`;
60944
- }
60945
- if (requirements.stage === "review") {
60946
- return [
60947
- "Application received. A seat has not been assigned.",
60948
- result3.admission?.notice ?? challengeAdmissionNotice,
60949
- "Next command: andes challenge"
60950
- ].join(`
60951
- `);
60952
- }
60953
- let feedback = "";
61045
+ const lines2 = [];
61046
+ if (requirements.stage === "draft")
61047
+ lines2.push(registrationPartsText(result3));
60954
61048
  const rejectionReason = requirements.rejectionReason ?? registration.rejectionReason;
60955
- if (rejectionReason) {
60956
- feedback = `
60957
- Review feedback: ${rejectionReason}`;
60958
- }
60959
- let nextCommand = "";
60960
- if (requirements.stage === "accepted") {
60961
- nextCommand = `
60962
- Next command: andes confirm`;
60963
- }
60964
- let missing2 = "";
61049
+ if (rejectionReason)
61050
+ lines2.push(`Comentario del equipo: ${rejectionReason}`);
60965
61051
  if (requirements.missing.length > 0) {
60966
61052
  const items = requirements.missing.map((item) => ` - ${item.field}: ${item.reason}`).join(`
60967
61053
  `);
60968
- missing2 = `
60969
- Still required:
60970
- ${items}`;
61054
+ lines2.push(`Datos pendientes:
61055
+ ${items}`);
60971
61056
  }
60972
- return `Next stage: ${requirements.stage}${feedback}${missing2}${nextCommand}`;
61057
+ lines2.push(nextStepText(nextStepFor(result3)));
61058
+ return lines2.join(`
61059
+
61060
+ `);
61061
+ };
61062
+ var statusLabels = {
61063
+ draft: "Borrador",
61064
+ submitted: "Postulación enviada",
61065
+ under_review: "En revisión",
61066
+ waitlisted: "En lista de espera",
61067
+ accepted: "Aceptada",
61068
+ rejected: "No aceptada",
61069
+ withdrawn: "Retirada"
60973
61070
  };
60974
61071
  var registrationText = (result3) => [
60975
- `Registration: ${result3.registration.id}`,
60976
- `Participant: ${result3.registration.firstName} ${result3.registration.lastName}`,
60977
- `Status: ${result3.registration.status}`,
61072
+ `Postulación: ${result3.registration.id}`,
61073
+ `Participante: ${result3.registration.firstName} ${result3.registration.lastName}`,
61074
+ `Estado: ${statusLabels[result3.registration.status]}`,
60978
61075
  requirementsText(result3)
60979
61076
  ].join(`
60980
61077
  `);
60981
61078
  var createdText = (result3) => {
60982
- if (result3.registration.status !== "submitted") {
60983
- return ["Application draft saved.", registrationText(result3)].join(`
61079
+ if (result3.registration.status === "draft") {
61080
+ return ["Borrador guardado.", registrationText(result3)].join(`
60984
61081
  `);
60985
61082
  }
60986
- return ["Application submitted successfully.", registrationText(result3)].join(`
61083
+ return ["Postulación enviada.", registrationText(result3)].join(`
60987
61084
  `);
60988
61085
  };
60989
61086
  var requirementsOnlyText = (result3) => requirementsText(result3);
60990
61087
  var badgeText = (result3) => {
60991
- if (result3.url)
60992
- return result3.url;
61088
+ if (result3.status === "completed" && result3.url)
61089
+ return `Tu carnet está listo:
61090
+ ${result3.url}
61091
+
61092
+ Compártelo en LinkedIn o Instagram.
61093
+ Para personalizarlo: andes badge regenerate`;
60993
61094
  if (result3.status === "pending" || result3.status === "running") {
60994
- return "Tu carnet se está generando.";
61095
+ return `Tu carnet se está generando. Espera unos minutos y consulta de nuevo.
61096
+ Siguiente comando: andes badge`;
60995
61097
  }
60996
61098
  if (result3.status === "failed") {
60997
61099
  return "No se pudo generar tu carnet. Ejecuta `andes badge regenerate` para intentarlo de nuevo.";
60998
61100
  }
60999
- return "Todavía no tienes un carnet.";
61101
+ return `Todavía no tienes un carnet. Consulta qué paso te falta completar.
61102
+ Siguiente comando: andes status`;
61000
61103
  };
61001
61104
 
61002
61105
  // src/challenge-commands.ts
@@ -61369,9 +61472,18 @@ var evaluateCommand = exports_Command.make("evaluate", { challenge: challengeFla
61369
61472
  const token = exports_Option.getOrUndefined(options.token);
61370
61473
  const operation = exports_Effect.gen(function* () {
61371
61474
  const solution = yield* challengeEvaluationInput(exports_Option.getOrUndefined(source), exports_Option.getOrUndefined(review), challenge);
61372
- return yield* evaluateChallenge({ apiUrl: options.apiUrl, token }, challenge, solution);
61475
+ const client = { apiUrl: options.apiUrl, token };
61476
+ const evaluated = yield* evaluateChallenge(client, challenge, solution);
61477
+ const nextStep = yield* loadParticipantGuidance(client).pipe(exports_Effect.map((response) => response.data.nextStep), exports_Effect.catch(() => exports_Effect.succeed({
61478
+ kind: "decision",
61479
+ message: "Tu evaluación oficial se guardó. Consulta el estado de tu postulación para continuar.",
61480
+ command: "andes status"
61481
+ })));
61482
+ return { ...evaluated, data: { ...evaluated.data, nextStep } };
61373
61483
  });
61374
- yield* execute(options.output, operation, challengeEvaluateText, evaluationErrorText);
61484
+ yield* execute(options.output, operation, (result3) => `${challengeEvaluateText(result3)}
61485
+
61486
+ ${nextStepText(result3.nextStep)}`, evaluationErrorText);
61375
61487
  })).pipe(exports_Command.withDescription("Score a solution on hidden cases. Broken Agent requires participant browser approval before a limited evaluation is consumed."), exports_Command.withExamples([
61376
61488
  {
61377
61489
  command: "andes challenge evaluate --challenge broken-agent --source ./scheduler.js --review ./review.json",
@@ -61389,50 +61501,25 @@ var rankingCommand = exports_Command.make("ranking", { challenge: challengeFlag
61389
61501
  ]));
61390
61502
  var challengeCommand = exports_Command.make("challenge", {}, exports_Effect.fn("challengeQuickstartCommand")(function* () {
61391
61503
  const options = yield* root;
61392
- const participationState = participationStateFor(defaultChallengeSlug);
61393
- const participationOpen = participationState === "open";
61394
- const launchNotice = launchNoticeFor(defaultChallengeSlug);
61395
- if (options.output === "json") {
61396
- let workflow = challengeQuickstart.workflow;
61397
- let helpCommand = challengeQuickstart.helpCommand;
61398
- let story = challengeQuickstart.story;
61399
- let mission = challengeQuickstart.mission;
61400
- let rules = challengeQuickstart.rules;
61401
- if (participationState === "closed") {
61402
- const rankingStep = challengeQuickstart.workflow.at(-1);
61403
- workflow = rankingStep ? [rankingStep] : [];
61404
- helpCommand = "andes challenge ranking --help";
61405
- story = [];
61406
- mission = "El Challenge 2 terminó. El ranking final sigue disponible.";
61407
- rules = [];
61408
- } else if (participationState === "scheduled") {
61409
- workflow = [];
61410
- helpCommand = "andes challenge list --help";
61411
- story = [];
61412
- mission = "El challenge todavía no está disponible.";
61413
- rules = [];
61414
- }
61415
- const data = {
61416
- ...challengeQuickstart,
61417
- story,
61418
- mission,
61419
- rules,
61420
- workflow,
61421
- helpCommand,
61422
- open: participationOpen,
61423
- state: participationState
61424
- };
61425
- if (launchNotice)
61426
- data.notice = launchNotice;
61427
- yield* printJson({
61428
- version: 1,
61429
- ok: true,
61430
- requestId: crypto.randomUUID(),
61431
- data
61432
- });
61433
- return;
61434
- }
61435
- yield* exports_Console.log(challengeQuickstartText(participationState, launchNotice));
61504
+ const client = {
61505
+ apiUrl: options.apiUrl,
61506
+ token: exports_Option.getOrUndefined(options.token)
61507
+ };
61508
+ const operation = loadParticipantGuidance(client).pipe(exports_Effect.map((response) => {
61509
+ const { nextStep } = response.data;
61510
+ let guide;
61511
+ if ((nextStep.kind === "challenge_start" || nextStep.kind === "challenge_continue") && nextStep.challengeSlug === "broken-agent") {
61512
+ guide = challengeQuickstart;
61513
+ }
61514
+ return { ...response, data: { ...response.data, guide } };
61515
+ }));
61516
+ yield* execute(options.output, operation, (result3) => {
61517
+ if (!result3.guide)
61518
+ return nextStepText(result3.nextStep);
61519
+ return `${challengeQuickstartText("open")}
61520
+
61521
+ ${nextStepText(result3.nextStep)}`;
61522
+ });
61436
61523
  })).pipe(exports_Command.withDescription("Compite en challenges técnicos obligatorios por un cupo. Ejecuta el comando sin subcomandos para abrir la guía del challenge actual."), exports_Command.withExamples([
61437
61524
  {
61438
61525
  command: "andes challenge",
@@ -63785,6 +63872,149 @@ var runUpdatedCli = () => new Promise((resolve4, reject) => {
63785
63872
  child.on("close", (exitCode) => resolve4(exitCode ?? 1));
63786
63873
  });
63787
63874
 
63875
+ // src/welcome.ts
63876
+ var valley = [
63877
+ " 11 55 ",
63878
+ " 11 1111 5555 11 ",
63879
+ " 1111 111111 11 55 1111 ",
63880
+ " 11112222111111 111111 111111 ",
63881
+ "111222222211111111111111111122221111",
63882
+ "112223333222111111111111112223332222",
63883
+ "222333333322211114411111222333333333",
63884
+ "333333333332222144442222233333333333",
63885
+ "333333333333322244422223333333333333"
63886
+ ];
63887
+ var palette = {
63888
+ sky: "12;24;24",
63889
+ distant: "28;62;61",
63890
+ ridge: "44;101;85",
63891
+ terrace: "84;143;111",
63892
+ river: "141;200;190",
63893
+ sun: "234;183;108",
63894
+ border: "66;101;85",
63895
+ text: "243;241;217",
63896
+ muted: "183;201;181",
63897
+ accent: "214;255;0"
63898
+ };
63899
+ var pixels = {
63900
+ " ": { color: palette.sky, character: " " },
63901
+ "1": { color: palette.distant, character: "." },
63902
+ "2": { color: palette.ridge, character: ":" },
63903
+ "3": { color: palette.terrace, character: "#" },
63904
+ "4": { color: palette.river, character: "~" },
63905
+ "5": { color: palette.sun, character: "o" }
63906
+ };
63907
+ var wrap = (text2, width) => {
63908
+ const lines2 = [];
63909
+ let line = "";
63910
+ for (const word of text2.split(" ")) {
63911
+ if (line && line.length + word.length + 1 > width) {
63912
+ lines2.push(line);
63913
+ line = "";
63914
+ }
63915
+ line = line ? `${line} ${word}` : word;
63916
+ while (line.length > width) {
63917
+ lines2.push(line.slice(0, width));
63918
+ line = line.slice(width);
63919
+ }
63920
+ }
63921
+ if (line)
63922
+ lines2.push(line);
63923
+ return lines2;
63924
+ };
63925
+ var center = (text2, width) => (" ".repeat(Math.max(0, Math.floor((width - text2.length) / 2))) + text2).padEnd(width);
63926
+ var renderWelcome = ({
63927
+ columns = 80,
63928
+ colors: colors2 = false
63929
+ } = {}) => {
63930
+ const width = Math.max(1, Math.min(Math.floor(columns), 72));
63931
+ if (width < 24) {
63932
+ return [
63933
+ eventName,
63934
+ "by Chofex",
63935
+ "S/8,000 in prizes",
63936
+ "Only for the best engineers from Peru."
63937
+ ].flatMap((line) => wrap(line, width)).join(`
63938
+ `);
63939
+ }
63940
+ const innerWidth = width - 4;
63941
+ const paint = (text2, foreground = palette.text, background = palette.sky, bold2 = false) => {
63942
+ if (!colors2)
63943
+ return text2;
63944
+ const weight = bold2 ? "1;" : "";
63945
+ return `\x1B[${weight}38;2;${foreground};48;2;${background}m${text2}\x1B[0m`;
63946
+ };
63947
+ let horizontal = "-";
63948
+ let vertical = "|";
63949
+ let corners = ["+", "+", "+", "+"];
63950
+ if (colors2) {
63951
+ horizontal = "─";
63952
+ vertical = "│";
63953
+ corners = ["╭", "╮", "╰", "╯"];
63954
+ }
63955
+ const frame = (content) => ` ${paint(vertical, palette.border)}${content}${paint(vertical, palette.border)}`;
63956
+ const rule = (left, right) => ` ${paint(left + horizontal.repeat(innerWidth) + right, palette.border)}`;
63957
+ const label = (text2, foreground, bold2 = false) => frame(paint(center(text2, innerWidth), foreground, palette.sky, bold2));
63958
+ const sourceWidth = Math.max(...valley.map((row) => row.length));
63959
+ const scene = valley.map((row, y) => {
63960
+ const cells = Array.from({ length: innerWidth }, (_, x) => {
63961
+ const sourceX = Math.floor(x / innerWidth * sourceWidth);
63962
+ return row[sourceX] ?? " ";
63963
+ });
63964
+ let heading = "";
63965
+ let foreground = palette.text;
63966
+ if (y === 3)
63967
+ heading = eventName;
63968
+ if (y === 4) {
63969
+ heading = "by Chofex";
63970
+ foreground = palette.sun;
63971
+ }
63972
+ const headingStart = Math.floor((innerWidth - heading.length) / 2);
63973
+ let rendered = "";
63974
+ for (let x = 0;x < cells.length; x += 1) {
63975
+ if (heading && x >= headingStart - 1 && x <= headingStart + heading.length) {
63976
+ const character = heading[x - headingStart] ?? " ";
63977
+ rendered += paint(character, foreground, palette.sky, y === 3);
63978
+ continue;
63979
+ }
63980
+ const pixel = pixels[cells[x] ?? " "] ?? pixels[" "];
63981
+ if (!pixel)
63982
+ continue;
63983
+ if (colors2) {
63984
+ rendered += paint(" ", pixel.color, pixel.color);
63985
+ } else {
63986
+ rendered += pixel.character;
63987
+ }
63988
+ }
63989
+ return frame(rendered);
63990
+ });
63991
+ return [
63992
+ "",
63993
+ rule(corners[0] ?? "+", corners[1] ?? "+"),
63994
+ ...scene,
63995
+ label("", palette.text),
63996
+ label("S/8,000 in prizes", palette.accent, true),
63997
+ ...wrap("Only for the best engineers from Peru.", innerWidth - 2).map((line) => label(line, palette.muted)),
63998
+ rule(corners[2] ?? "+", corners[3] ?? "+"),
63999
+ ""
64000
+ ].join(`
64001
+ `);
64002
+ };
64003
+ var welcomeFormatter = (options) => {
64004
+ const formatter = exports_CliOutput.defaultFormatter({ colors: options.colors });
64005
+ return {
64006
+ ...formatter,
64007
+ formatHelpDoc: (doc) => {
64008
+ const help = formatter.formatHelpDoc(doc);
64009
+ if (!doc.subcommands?.length)
64010
+ return help;
64011
+ const welcome = renderWelcome(options);
64012
+ return `${welcome}
64013
+ ${help}`;
64014
+ }
64015
+ };
64016
+ };
64017
+
63788
64018
  // src/commands.ts
63789
64019
  var inputFlag2 = exports_Flag.string("input").pipe(exports_Flag.optional, exports_Flag.withDescription("Read JSON from a file, or use - for stdin"));
63790
64020
  var stageFlag = exports_Flag.choice("stage", ["application", "acceptance"]).pipe(exports_Flag.withDefault("application"));
@@ -63794,42 +64024,32 @@ var currentRegistration = (client) => getRegistration(client).pipe(exports_Effec
63794
64024
  }
63795
64025
  return exports_Effect.fail(error2);
63796
64026
  }));
63797
- var rejectIfApplicationLocked = exports_Effect.fn("rejectIfApplicationLocked")(function* (current) {
63798
- if (exports_Option.isNone(current))
63799
- return;
63800
- const { registration, requirements } = current.value.data;
63801
- const { status } = registration;
63802
- const registrationAlreadyExists = status === "submitted" || status === "under_review" || status === "waitlisted" || status === "accepted";
63803
- if (!registrationAlreadyExists)
63804
- return;
63805
- let message = "Already registered. Wait for approval.";
63806
- if (status === "accepted") {
63807
- message = "Already accepted. Your registration is complete.";
63808
- if (requirements.stage === "accepted") {
63809
- message = "Already accepted. Run `andes confirm` to complete your registration.";
63810
- }
63811
- }
63812
- return yield* cliError("ACTIVE_APPLICATION_EXISTS", message, false, {
63813
- currentStatus: status
63814
- });
63815
- });
63816
64027
  var registerCommand = exports_Command.make("register", { input: inputFlag2 }, exports_Effect.fn("registerCommand")(function* ({ input }) {
63817
64028
  const options = yield* root;
64029
+ let existing = false;
63818
64030
  const operation = exports_Effect.gen(function* () {
63819
64031
  const token = exports_Option.getOrUndefined(options.token);
63820
64032
  const client = { apiUrl: options.apiUrl, token };
63821
64033
  const current = yield* currentRegistration(client);
63822
- yield* rejectIfApplicationLocked(current);
64034
+ if (exports_Option.isSome(current) && !current.value.data.requirements.canSubmitNewApplication && !current.value.data.requirements.canSaveDraft) {
64035
+ existing = true;
64036
+ return current.value;
64037
+ }
63823
64038
  if (exports_Option.isSome(input)) {
63824
64039
  const body = yield* applicationInput(input.value, config.publicSiteUrl);
63825
64040
  return yield* register(client, body);
63826
64041
  }
63827
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
64042
+ if (options.output === "json" || !process.stdin.isTTY || !process.stdout.isTTY) {
63828
64043
  return yield* cliError("INPUT_REQUIRED", "Non-interactive use requires --input <file>, or --input - for stdin");
63829
64044
  }
63830
64045
  return yield* interactiveRegister(client, current);
63831
64046
  });
63832
- yield* execute(options.output, operation, createdText);
64047
+ yield* execute(options.output, withRegistrationNextStep(operation), (result3) => {
64048
+ if (existing)
64049
+ return `Tu postulación ya estaba enviada.
64050
+ ${registrationText(result3)}`;
64051
+ return createdText(result3);
64052
+ }, registrationLookupErrorText);
63833
64053
  })).pipe(exports_Command.withDescription("Complete and submit an application for review"), exports_Command.withExamples([
63834
64054
  {
63835
64055
  command: "andes register",
@@ -63860,7 +64080,7 @@ var statusCommand = exports_Command.make("status", {}, exports_Effect.fn("status
63860
64080
  const token = exports_Option.getOrUndefined(options.token);
63861
64081
  return yield* getRegistration({ apiUrl: options.apiUrl, token });
63862
64082
  });
63863
- yield* execute(options.output, operation, registrationText, registrationLookupErrorText);
64083
+ yield* execute(options.output, withRegistrationNextStep(operation), registrationText, registrationLookupErrorText);
63864
64084
  })).pipe(exports_Command.withDescription("Show your latest application and next steps"));
63865
64085
  var requirementsCommand = exports_Command.make("requirements", {}, exports_Effect.fn("requirementsCommand")(function* () {
63866
64086
  const options = yield* root;
@@ -63868,7 +64088,7 @@ var requirementsCommand = exports_Command.make("requirements", {}, exports_Effec
63868
64088
  const token = exports_Option.getOrUndefined(options.token);
63869
64089
  return yield* getRegistration({ apiUrl: options.apiUrl, token });
63870
64090
  });
63871
- yield* execute(options.output, operation, requirementsOnlyText, registrationLookupErrorText);
64091
+ yield* execute(options.output, withRegistrationNextStep(operation), requirementsOnlyText, registrationLookupErrorText);
63872
64092
  })).pipe(exports_Command.withDescription("Show information you still need to provide"));
63873
64093
  var badgeRegenerateCommand = exports_Command.make("regenerate", {
63874
64094
  input: inputFlag2,
@@ -63882,14 +64102,15 @@ var badgeRegenerateCommand = exports_Command.make("regenerate", {
63882
64102
  }
63883
64103
  const token = exports_Option.getOrUndefined(options.token);
63884
64104
  const client = { apiUrl: options.apiUrl, token };
64105
+ const current = yield* getRegistration(client);
64106
+ if (current.data.requirements.stage !== "complete") {
64107
+ return yield* cliError("INVALID_APPLICATION_STATE", nextStepText(nextStepFor(current.data)));
64108
+ }
63885
64109
  const badge = yield* getBadge(client);
63886
64110
  if (!badge.data.profile) {
63887
64111
  return yield* exports_Effect.fail(cliError("INVALID_APPLICATION_STATE", "Confirma tu asistencia antes de regenerar tu carnet"));
63888
64112
  }
63889
- const [current, currentUser] = yield* exports_Effect.all([
63890
- getRegistration(client),
63891
- getCurrentUser(client)
63892
- ]);
64113
+ const currentUser = yield* getCurrentUser(client);
63893
64114
  const body = yield* badgeProfileInput(inputPath, badge.data.profile, {
63894
64115
  clerkPictureUrl: currentUser.data.clerkPictureUrl,
63895
64116
  githubUrl: current.data.registration.githubUrl
@@ -63911,8 +64132,26 @@ var badgeRegenerateCommand = exports_Command.make("regenerate", {
63911
64132
  var badgeCommand = exports_Command.make("badge", {}, exports_Effect.fn("badgeCommand")(function* () {
63912
64133
  const options = yield* root;
63913
64134
  const token = exports_Option.getOrUndefined(options.token);
63914
- const operation = getBadge({ apiUrl: options.apiUrl, token });
63915
- yield* execute(options.output, operation, badgeText);
64135
+ const client = { apiUrl: options.apiUrl, token };
64136
+ const operation = exports_Effect.gen(function* () {
64137
+ const current = yield* getRegistration(client);
64138
+ if (current.data.registration.status !== "accepted") {
64139
+ return yield* cliError("INVALID_APPLICATION_STATE", nextStepText(nextStepFor(current.data)));
64140
+ }
64141
+ const badge = yield* getBadge(client);
64142
+ return {
64143
+ ...badge,
64144
+ data: { ...badge.data, nextStep: nextStepFor(current.data) }
64145
+ };
64146
+ });
64147
+ yield* execute(options.output, operation, (result3) => {
64148
+ if (result3.nextStep.kind === "confirm")
64149
+ return `Tu carnet predeterminado no confirma tu asistencia.
64150
+ ${result3.url ?? "El carnet todavía se está preparando."}
64151
+
64152
+ ${nextStepText(result3.nextStep)}`;
64153
+ return badgeText(result3);
64154
+ }, registrationLookupErrorText);
63916
64155
  })).pipe(exports_Command.withDescription("Muestra o regenera tu carnet de participante"), exports_Command.withSubcommands([badgeRegenerateCommand]));
63917
64156
  var confirmCommand = exports_Command.make("confirm", {
63918
64157
  input: inputFlag2,
@@ -63923,8 +64162,13 @@ var confirmCommand = exports_Command.make("confirm", {
63923
64162
  const token = exports_Option.getOrUndefined(options.token);
63924
64163
  const client = { apiUrl: options.apiUrl, token };
63925
64164
  const current = yield* getRegistration(client);
64165
+ if (current.data.requirements.stage === "complete" && exports_Option.isNone(input) && exports_Option.isNone(picture))
64166
+ return current;
63926
64167
  if (!current.data.requirements.canSubmitAcceptedDetails) {
63927
- return yield* exports_Effect.fail(cliError("INVALID_APPLICATION_STATE", "Acceptance details can only be submitted after acceptance"));
64168
+ return yield* exports_Effect.fail(cliError("INVALID_APPLICATION_STATE", nextStepText(nextStepFor(current.data))));
64169
+ }
64170
+ if (options.output === "json" && exports_Option.isNone(input)) {
64171
+ return yield* cliError("INPUT_REQUIRED", "El modo JSON requiere --input <archivo> o --input -");
63928
64172
  }
63929
64173
  const currentUser = yield* getCurrentUser(client);
63930
64174
  const currentBadge = yield* getBadge(client);
@@ -63938,6 +64182,9 @@ var confirmCommand = exports_Command.make("confirm", {
63938
64182
  });
63939
64183
  const picturePath = exports_Option.getOrUndefined(picture);
63940
64184
  if (body.pictureSource === "upload") {
64185
+ if (options.output === "json" && picturePath === undefined) {
64186
+ return yield* cliError("PICTURE_PATH_REQUIRED", "Usa --picture <ruta> cuando pictureSource es upload");
64187
+ }
63941
64188
  const path4 = yield* picturePathInput(picturePath);
63942
64189
  yield* uploadPicture(client, path4);
63943
64190
  } else if (picturePath) {
@@ -63945,7 +64192,7 @@ var confirmCommand = exports_Command.make("confirm", {
63945
64192
  }
63946
64193
  return yield* confirmAttendance(client, body);
63947
64194
  });
63948
- yield* execute(options.output, operation, registrationText);
64195
+ yield* execute(options.output, withRegistrationNextStep(operation), registrationText, registrationLookupErrorText);
63949
64196
  })).pipe(exports_Command.withDescription("Provide private attendance details after acceptance"), exports_Command.withExamples([
63950
64197
  {
63951
64198
  command: "andes confirm",
@@ -63968,21 +64215,33 @@ var loginCommand = exports_Command.make("login", {}, exports_Effect.fn("loginCom
63968
64215
  token
63969
64216
  });
63970
64217
  const environmentTokenActive = Boolean(process.env.CHOFEX_TOKEN);
64218
+ const nextStep = yield* loadParticipantGuidance({
64219
+ apiUrl: options.apiUrl,
64220
+ token
64221
+ }).pipe(exports_Effect.map((response) => response.data.nextStep), exports_Effect.catch(() => exports_Effect.succeed({
64222
+ kind: "status",
64223
+ message: "Consulta tu avance para continuar con tu siguiente paso.",
64224
+ command: "andes"
64225
+ })));
63971
64226
  return {
63972
64227
  version: 1,
63973
64228
  ok: true,
63974
64229
  requestId: currentUser.requestId,
63975
64230
  data: {
63976
64231
  authenticated: true,
63977
- environmentTokenActive
64232
+ environmentTokenActive,
64233
+ nextStep
63978
64234
  }
63979
64235
  };
63980
64236
  });
63981
64237
  yield* execute(options.output, operation, (result3) => {
63982
64238
  if (result3.environmentTokenActive) {
63983
- return "Signed in successfully. CHOFEX_TOKEN is set and will override the stored session; unset it before running other commands.";
64239
+ return `Sesión iniciada. CHOFEX_TOKEN está configurado y tiene prioridad sobre la sesión guardada; elimínalo del entorno para usar esta sesión.
64240
+ Siguiente comando: andes`;
63984
64241
  }
63985
- return "Signed in successfully.";
64242
+ return `Sesión iniciada.
64243
+ ${result3.nextStep.message}
64244
+ Siguiente comando: ${result3.nextStep.command}`;
63986
64245
  });
63987
64246
  })).pipe(exports_Command.withDescription("Sign in through Clerk OAuth in your browser"));
63988
64247
  var logoutCommand = exports_Command.make("logout", {}, exports_Effect.fn("logoutCommand")(function* () {
@@ -64007,14 +64266,16 @@ var logoutCommand = exports_Command.make("logout", {}, exports_Effect.fn("logout
64007
64266
  if (result3.environmentTokenActive) {
64008
64267
  return "Stored credentials removed. CHOFEX_TOKEN remains active; unset it to stop using that token.";
64009
64268
  }
64010
- return "Signed out successfully.";
64269
+ return `Sesión cerrada. Para volver a continuar tu postulación:
64270
+ Siguiente comando: andes login`;
64011
64271
  });
64012
64272
  })).pipe(exports_Command.withDescription("Revoke and remove locally stored credentials"));
64013
64273
  var whoamiCommand = exports_Command.make("whoami", {}, exports_Effect.fn("whoamiCommand")(function* () {
64014
64274
  const options = yield* root;
64015
64275
  const token = exports_Option.getOrUndefined(options.token);
64016
64276
  const operation = getCurrentUser({ apiUrl: options.apiUrl, token });
64017
- yield* execute(options.output, operation, (result3) => `Authenticated as ${result3.email} (${result3.userId}, ${result3.tokenType}).`);
64277
+ yield* execute(options.output, operation, (result3) => `Sesión iniciada como ${result3.email} (${result3.userId}, ${result3.tokenType}).
64278
+ Consulta tu siguiente paso: andes`);
64018
64279
  })).pipe(exports_Command.withDescription("Verify the current Clerk authentication"));
64019
64280
  var makeUpgradeCommand = (name) => exports_Command.make(name, {}, exports_Effect.fn("upgradeCommand")(function* () {
64020
64281
  const options = yield* root;
@@ -64034,7 +64295,8 @@ var makeUpgradeCommand = (name) => exports_Command.make(name, {}, exports_Effect
64034
64295
  },
64035
64296
  catch: (error2) => cliError("UPGRADE_FAILED", `No se pudieron actualizar ${cliPackageName} y ${skillName}`, false, String(error2))
64036
64297
  });
64037
- yield* execute(options.output, operation, () => `Se actualizó ${cliPackageName} a la versión ${upgradeVersion} y se refrescó ${skillName}.`);
64298
+ yield* execute(options.output, operation, () => `Se actualizó ${cliPackageName} a la versión ${upgradeVersion} y se refrescó ${skillName}.
64299
+ Siguiente comando: andes`);
64038
64300
  })).pipe(exports_Command.withDescription(`Actualiza ${cliPackageName} y su skill de agente a la última versión`));
64039
64301
  var updateCommand = makeUpgradeCommand("update");
64040
64302
  var upgradeCommand = makeUpgradeCommand("upgrade");
@@ -64046,13 +64308,24 @@ var inputValidation = (stage, path4) => {
64046
64308
  };
64047
64309
  var validateCommand = exports_Command.make("validate", { input: inputFlag2, stage: stageFlag }, exports_Effect.fn("validateCommand")(function* ({ input, stage }) {
64048
64310
  const options = yield* root;
64311
+ if (options.output === "json" && exports_Option.isNone(input)) {
64312
+ yield* execute(options.output, exports_Effect.fail(cliError("INPUT_REQUIRED", "El modo JSON requiere --input <archivo> o --input -")), () => "");
64313
+ return;
64314
+ }
64049
64315
  const operation = inputValidation(stage, exports_Option.getOrUndefined(input)).pipe(exports_Effect.map(() => ({
64050
64316
  version: 1,
64051
64317
  ok: true,
64052
64318
  requestId: crypto.randomUUID(),
64053
64319
  data: { valid: true, stage }
64054
64320
  })));
64055
- yield* execute(options.output, operation, (result3) => `${result3.stage} input is valid.`);
64321
+ yield* execute(options.output, operation, (result3) => {
64322
+ const command = result3.stage === "application" ? "andes register" : "andes confirm";
64323
+ let nextCommand = command;
64324
+ if (exports_Option.isSome(input))
64325
+ nextCommand += ` --input ${JSON.stringify(input.value)}`;
64326
+ return `Datos válidos. Todavía no se enviaron.
64327
+ Siguiente comando: ${nextCommand}`;
64328
+ });
64056
64329
  })).pipe(exports_Command.withDescription("Validate input without submitting it"), exports_Command.withExamples([
64057
64330
  {
64058
64331
  command: "andes --output json validate --stage application --input application.json",
@@ -64098,7 +64371,23 @@ var schemaCommand = exports_Command.make("schema", { stage: stageFlag }, exports
64098
64371
  description: "Print the post-acceptance input template"
64099
64372
  }
64100
64373
  ]));
64101
- var command = root.pipe(exports_Command.withSubcommands([
64374
+ var command = root.pipe(exports_Command.withHandler((options) => exports_Effect.gen(function* () {
64375
+ const client = {
64376
+ apiUrl: options.apiUrl,
64377
+ token: exports_Option.getOrUndefined(options.token)
64378
+ };
64379
+ yield* execute(options.output, loadParticipantGuidance(client), (result3) => {
64380
+ const welcome = renderWelcome({
64381
+ columns: process.stdout.columns ?? 80,
64382
+ colors: process.stdout.isTTY === true && process.env.NO_COLOR === undefined
64383
+ });
64384
+ const guidance = result3.registration ? registrationText(result3.registration) : nextStepText(result3.nextStep);
64385
+ return `${welcome}
64386
+ ${guidance}
64387
+
64388
+ Todos los comandos: andes --help`;
64389
+ });
64390
+ })), exports_Command.withSubcommands([
64102
64391
  loginCommand,
64103
64392
  logoutCommand,
64104
64393
  whoamiCommand,
@@ -64114,161 +64403,6 @@ var command = root.pipe(exports_Command.withSubcommands([
64114
64403
  challengeCommand
64115
64404
  ]));
64116
64405
 
64117
- // src/welcome.ts
64118
- var valley = [
64119
- " 11 55 ",
64120
- " 11 1111 5555 11 ",
64121
- " 1111 111111 11 55 1111 ",
64122
- " 11112222111111 111111 111111 ",
64123
- "111222222211111111111111111122221111",
64124
- "112223333222111111111111112223332222",
64125
- "222333333322211114411111222333333333",
64126
- "333333333332222144442222233333333333",
64127
- "333333333333322244422223333333333333"
64128
- ];
64129
- var palette = {
64130
- sky: "12;24;24",
64131
- distant: "28;62;61",
64132
- ridge: "44;101;85",
64133
- terrace: "84;143;111",
64134
- river: "141;200;190",
64135
- sun: "234;183;108",
64136
- border: "66;101;85",
64137
- text: "243;241;217",
64138
- muted: "183;201;181",
64139
- accent: "214;255;0"
64140
- };
64141
- var pixels = {
64142
- " ": { color: palette.sky, character: " " },
64143
- "1": { color: palette.distant, character: "." },
64144
- "2": { color: palette.ridge, character: ":" },
64145
- "3": { color: palette.terrace, character: "#" },
64146
- "4": { color: palette.river, character: "~" },
64147
- "5": { color: palette.sun, character: "o" }
64148
- };
64149
- var wrap = (text2, width) => {
64150
- const lines2 = [];
64151
- let line = "";
64152
- for (const word of text2.split(" ")) {
64153
- if (line && line.length + word.length + 1 > width) {
64154
- lines2.push(line);
64155
- line = "";
64156
- }
64157
- line = line ? `${line} ${word}` : word;
64158
- while (line.length > width) {
64159
- lines2.push(line.slice(0, width));
64160
- line = line.slice(width);
64161
- }
64162
- }
64163
- if (line)
64164
- lines2.push(line);
64165
- return lines2;
64166
- };
64167
- var center = (text2, width) => (" ".repeat(Math.max(0, Math.floor((width - text2.length) / 2))) + text2).padEnd(width);
64168
- var renderWelcome = ({
64169
- columns = 80,
64170
- colors: colors2 = false
64171
- } = {}) => {
64172
- const width = Math.max(1, Math.min(Math.floor(columns), 72));
64173
- if (width < 24) {
64174
- return [
64175
- eventName,
64176
- "by Chofex",
64177
- "S/8,000 in prizes",
64178
- "Only for the best engineers from Peru."
64179
- ].flatMap((line) => wrap(line, width)).join(`
64180
- `);
64181
- }
64182
- const innerWidth = width - 4;
64183
- const paint = (text2, foreground = palette.text, background = palette.sky, bold2 = false) => {
64184
- if (!colors2)
64185
- return text2;
64186
- const weight = bold2 ? "1;" : "";
64187
- return `\x1B[${weight}38;2;${foreground};48;2;${background}m${text2}\x1B[0m`;
64188
- };
64189
- let horizontal = "-";
64190
- let vertical = "|";
64191
- let corners = ["+", "+", "+", "+"];
64192
- if (colors2) {
64193
- horizontal = "─";
64194
- vertical = "│";
64195
- corners = ["╭", "╮", "╰", "╯"];
64196
- }
64197
- const frame = (content) => ` ${paint(vertical, palette.border)}${content}${paint(vertical, palette.border)}`;
64198
- const rule = (left, right) => ` ${paint(left + horizontal.repeat(innerWidth) + right, palette.border)}`;
64199
- const label = (text2, foreground, bold2 = false) => frame(paint(center(text2, innerWidth), foreground, palette.sky, bold2));
64200
- const sourceWidth = Math.max(...valley.map((row) => row.length));
64201
- const scene = valley.map((row, y) => {
64202
- const cells = Array.from({ length: innerWidth }, (_, x) => {
64203
- const sourceX = Math.floor(x / innerWidth * sourceWidth);
64204
- return row[sourceX] ?? " ";
64205
- });
64206
- let heading = "";
64207
- let foreground = palette.text;
64208
- if (y === 3)
64209
- heading = eventName;
64210
- if (y === 4) {
64211
- heading = "by Chofex";
64212
- foreground = palette.sun;
64213
- }
64214
- const headingStart = Math.floor((innerWidth - heading.length) / 2);
64215
- let rendered = "";
64216
- for (let x = 0;x < cells.length; x += 1) {
64217
- if (heading && x >= headingStart - 1 && x <= headingStart + heading.length) {
64218
- const character = heading[x - headingStart] ?? " ";
64219
- rendered += paint(character, foreground, palette.sky, y === 3);
64220
- continue;
64221
- }
64222
- const pixel = pixels[cells[x] ?? " "] ?? pixels[" "];
64223
- if (!pixel)
64224
- continue;
64225
- if (colors2) {
64226
- rendered += paint(" ", pixel.color, pixel.color);
64227
- } else {
64228
- rendered += pixel.character;
64229
- }
64230
- }
64231
- return frame(rendered);
64232
- });
64233
- return [
64234
- "",
64235
- rule(corners[0] ?? "+", corners[1] ?? "+"),
64236
- ...scene,
64237
- label("", palette.text),
64238
- label("S/8,000 in prizes", palette.accent, true),
64239
- ...wrap("Only for the best engineers from Peru.", innerWidth - 2).map((line) => label(line, palette.muted)),
64240
- rule(corners[2] ?? "+", corners[3] ?? "+"),
64241
- ""
64242
- ].join(`
64243
- `);
64244
- };
64245
- var welcomeFormatter = (options) => {
64246
- const formatter = exports_CliOutput.defaultFormatter({ colors: options.colors });
64247
- return {
64248
- ...formatter,
64249
- formatHelpDoc: (doc) => {
64250
- const help = formatter.formatHelpDoc(doc);
64251
- if (!doc.subcommands?.length)
64252
- return help;
64253
- const welcome = renderWelcome(options);
64254
- if (!options.home)
64255
- return `${welcome}
64256
- ${help}`;
64257
- const width = Math.max(1, Math.min(options.columns ?? 80, 72));
64258
- const shortcuts = [
64259
- "andes login Sign in",
64260
- "andes register Apply",
64261
- "andes status Check your application",
64262
- "andes --help All commands"
64263
- ];
64264
- return `${welcome}
64265
- ${shortcuts.flatMap((line) => wrap(line, width)).join(`
64266
- `)}
64267
- `;
64268
- }
64269
- };
64270
- };
64271
-
64272
64406
  // src/index.ts
64273
64407
  var arguments_ = process.argv.slice(2);
64274
64408
  var jsonOutputRequested = (arguments_2) => {
@@ -64289,7 +64423,6 @@ var quietConsole = Object.assign(Object.create(console), {
64289
64423
  }
64290
64424
  });
64291
64425
  var commandProgram = command.pipe(exports_Command.run({ version: cliVersion, renderErrors: !jsonMode }), exports_Effect.provide(exports_CliOutput.layer(welcomeFormatter({
64292
- home: arguments_.length === 0,
64293
64426
  columns: process.stdout.columns ?? 80,
64294
64427
  colors: process.stdout.isTTY === true && process.env.NO_COLOR === undefined && process.env.TERM !== "dumb"
64295
64428
  }))), exports_Effect.catch((error2) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hacktheandes-cli",
3
- "version": "0.1.203",
3
+ "version": "0.1.206",
4
4
  "description": "Command-line client for Hack the Andes",
5
5
  "type": "module",
6
6
  "bin": {