chofex-cli 0.1.8 → 0.1.10

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.js +189 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31422,6 +31422,142 @@ var confirmAttendance = (options, input) => request3(options, "/api/v1/registrat
31422
31422
 
31423
31423
  // src/input.ts
31424
31424
  import { readFile as readFile3 } from "node:fs/promises";
31425
+
31426
+ // src/profile-username-prompt.ts
31427
+ var ansi = {
31428
+ bold: "\x1B[1m",
31429
+ underlined: "\x1B[4m",
31430
+ italicized: "\x1B[3m",
31431
+ reset: "\x1B[0m",
31432
+ eraseLine: "\x1B[2K",
31433
+ cursorStart: "\x1B[G",
31434
+ cursorSave: "\x1B[s",
31435
+ cursorRestore: "\x1B[u",
31436
+ cursorUp: "\x1B[1A",
31437
+ cursorDown: "\x1B[1B",
31438
+ beep: "\x07"
31439
+ };
31440
+ var annotate5 = (text2, ...styles) => {
31441
+ if (text2 === "")
31442
+ return "";
31443
+ return `${styles.join("")}${text2}${ansi.reset}`;
31444
+ };
31445
+ var nextFrame = (state) => ({
31446
+ _tag: "NextFrame",
31447
+ state
31448
+ });
31449
+ var beep2 = () => ({
31450
+ _tag: "Beep"
31451
+ });
31452
+ var renderProfileUsername = (state, message, profilePrefix, submitted) => {
31453
+ const theme = exports_Prompt.makeTheme();
31454
+ const leadingSymbol = submitted ? theme.tick : theme.prefix;
31455
+ const trailingSymbol = submitted ? theme.ellipsis : theme.pointerSmall;
31456
+ const leadingColor = submitted ? theme.successColor : theme.primaryColor;
31457
+ let valueColor = `${ansi.underlined}${theme.primaryColor}`;
31458
+ if (submitted)
31459
+ valueColor = theme.submittedColor;
31460
+ if (state.error !== undefined)
31461
+ valueColor = theme.errorColor;
31462
+ const line = [
31463
+ annotate5(leadingSymbol, leadingColor),
31464
+ annotate5(message, ansi.bold),
31465
+ annotate5(trailingSymbol, theme.mutedColor),
31466
+ `${annotate5(profilePrefix, theme.mutedColor)}${annotate5(state.value, valueColor)}`
31467
+ ].join(" ");
31468
+ const cursorOffset = state.cursor - state.value.length;
31469
+ let output = line;
31470
+ if (cursorOffset < 0)
31471
+ output += `\x1B[${-cursorOffset}D`;
31472
+ if (state.error !== undefined && !submitted) {
31473
+ const error2 = `${annotate5(theme.pointerSmall, theme.errorColor)} ${annotate5(state.error, ansi.italicized, theme.errorColor)}`;
31474
+ output += `${ansi.cursorSave}
31475
+ ${error2}${ansi.cursorRestore}`;
31476
+ }
31477
+ if (submitted)
31478
+ output += `
31479
+ `;
31480
+ return output;
31481
+ };
31482
+ var clearProfileUsername = (state) => {
31483
+ if (state.error === undefined) {
31484
+ return ansi.eraseLine + ansi.cursorStart;
31485
+ }
31486
+ return ansi.cursorDown + ansi.eraseLine + ansi.cursorUp + ansi.eraseLine + ansi.cursorStart;
31487
+ };
31488
+ var insertInput = (state, input) => {
31489
+ const beforeCursor = state.value.slice(0, state.cursor);
31490
+ const afterCursor = state.value.slice(state.cursor);
31491
+ return nextFrame({
31492
+ cursor: state.cursor + input.length,
31493
+ value: `${beforeCursor}${input}${afterCursor}`
31494
+ });
31495
+ };
31496
+ var processProfileUsername = (input, state) => {
31497
+ if (input.key.ctrl) {
31498
+ if (input.key.name === "u") {
31499
+ return exports_Effect.succeed(nextFrame({ cursor: 0, value: "" }));
31500
+ }
31501
+ if (input.key.name === "a") {
31502
+ return exports_Effect.succeed(nextFrame({ ...state, cursor: 0 }));
31503
+ }
31504
+ if (input.key.name === "e") {
31505
+ return exports_Effect.succeed(nextFrame({ ...state, cursor: state.value.length }));
31506
+ }
31507
+ return exports_Effect.succeed(beep2());
31508
+ }
31509
+ if (input.key.name === "backspace") {
31510
+ if (state.cursor === 0)
31511
+ return exports_Effect.succeed(beep2());
31512
+ return exports_Effect.succeed(nextFrame({
31513
+ cursor: state.cursor - 1,
31514
+ value: state.value.slice(0, state.cursor - 1) + state.value.slice(state.cursor)
31515
+ }));
31516
+ }
31517
+ if (input.key.name === "left") {
31518
+ if (state.cursor === 0)
31519
+ return exports_Effect.succeed(beep2());
31520
+ return exports_Effect.succeed(nextFrame({ ...state, cursor: state.cursor - 1, error: undefined }));
31521
+ }
31522
+ if (input.key.name === "right") {
31523
+ if (state.cursor === state.value.length)
31524
+ return exports_Effect.succeed(beep2());
31525
+ return exports_Effect.succeed(nextFrame({ ...state, cursor: state.cursor + 1, error: undefined }));
31526
+ }
31527
+ if (input.key.name === "home") {
31528
+ return exports_Effect.succeed(nextFrame({ ...state, cursor: 0, error: undefined }));
31529
+ }
31530
+ if (input.key.name === "end") {
31531
+ return exports_Effect.succeed(nextFrame({
31532
+ ...state,
31533
+ cursor: state.value.length,
31534
+ error: undefined
31535
+ }));
31536
+ }
31537
+ if (input.key.name === "enter" || input.key.name === "return") {
31538
+ if (state.value === "" || /^[A-Za-z0-9._-]+$/.test(state.value)) {
31539
+ return exports_Effect.succeed({ _tag: "Submit", value: state.value });
31540
+ }
31541
+ return exports_Effect.succeed(nextFrame({ ...state, error: "Enter only your username" }));
31542
+ }
31543
+ if (input.key.meta)
31544
+ return exports_Effect.succeed(beep2());
31545
+ return exports_Effect.succeed(exports_Option.match(input.input, {
31546
+ onNone: beep2,
31547
+ onSome: (value3) => insertInput(state, value3)
31548
+ }));
31549
+ };
31550
+ var profileUsernamePrompt = (message, profilePrefix) => exports_Prompt.custom({ cursor: 0, value: "" }, {
31551
+ render: (state, action2) => {
31552
+ if (action2._tag === "Beep")
31553
+ return exports_Effect.succeed(ansi.beep);
31554
+ return exports_Effect.succeed(renderProfileUsername(state, message, profilePrefix, action2._tag === "Submit"));
31555
+ },
31556
+ process: processProfileUsername,
31557
+ clear: (state) => exports_Effect.succeed(clearProfileUsername(state))
31558
+ });
31559
+
31560
+ // src/input.ts
31425
31561
  var requiredText = (message) => exports_Prompt.text({
31426
31562
  message,
31427
31563
  validate: (value3) => {
@@ -31431,6 +31567,8 @@ var requiredText = (message) => exports_Prompt.text({
31431
31567
  }
31432
31568
  });
31433
31569
  var optionalText2 = (message) => exports_Prompt.text({ message, default: "" });
31570
+ var githubProfilePrefix = "github.com/";
31571
+ var linkedInProfilePrefix = "linkedin.com/in/";
31434
31572
  var withoutEmptyStrings = (input) => Object.fromEntries(Object.entries(input).filter(([, value3]) => value3 !== "" && value3 !== undefined));
31435
31573
  var readStdin = async () => {
31436
31574
  const chunks = [];
@@ -31480,8 +31618,8 @@ var applicationDetailsPrompts = exports_Prompt.all({
31480
31618
  }),
31481
31619
  skills: exports_Prompt.list({ message: "Skills (comma-separated)", delimiter: "," }),
31482
31620
  bio: requiredText("Short bio"),
31483
- githubUrl: optionalText2("GitHub URL (optional)"),
31484
- linkedInUrl: optionalText2("LinkedIn URL (optional)"),
31621
+ githubUsername: profileUsernamePrompt("GitHub username (optional)", githubProfilePrefix),
31622
+ linkedInUsername: profileUsernamePrompt("LinkedIn username (optional)", linkedInProfilePrefix),
31485
31623
  portfolioUrl: optionalText2("Portfolio URL (optional)")
31486
31624
  });
31487
31625
  var teamPreferencePrompt = exports_Prompt.select({
@@ -31492,31 +31630,59 @@ var teamPreferencePrompt = exports_Prompt.select({
31492
31630
  { title: "I will participate solo", value: "solo" }
31493
31631
  ]
31494
31632
  });
31495
- var applicationConsentPrompts = exports_Prompt.all({
31496
- codeOfConductAccepted: exports_Prompt.confirm({
31497
- message: "Do you accept the code of conduct?"
31498
- }),
31499
- privacyPolicyAccepted: exports_Prompt.confirm({
31500
- message: "Do you accept the privacy policy?"
31501
- }),
31502
- mediaConsent: exports_Prompt.confirm({
31503
- message: "Do you consent to appearing in event media?"
31504
- })
31633
+ var publicDocumentUrl = (baseUrl, path4) => `${baseUrl.replace(/\/$/, "")}${path4}`;
31634
+ var requiredAgreement = exports_Effect.fn("requiredAgreement")(function* (name, url2) {
31635
+ const accepted = yield* exports_Prompt.run(exports_Prompt.confirm({
31636
+ message: `Do you accept the ${name}? Read it at ${url2}`
31637
+ }));
31638
+ if (accepted)
31639
+ return true;
31640
+ const nextStep = yield* exports_Prompt.run(exports_Prompt.select({
31641
+ message: `You must accept the ${name} to register. What would you like to do?`,
31642
+ choices: [
31643
+ {
31644
+ title: "I accept and want to continue",
31645
+ value: "accept"
31646
+ },
31647
+ { title: "Cancel registration", value: "cancel" }
31648
+ ]
31649
+ }));
31650
+ if (nextStep === "accept")
31651
+ return true;
31652
+ return yield* cliError("REGISTRATION_CANCELLED", "Registration cancelled. Your answers were not submitted.");
31505
31653
  });
31506
- var interactiveApplication = exports_Effect.gen(function* () {
31654
+ var interactiveApplication = (publicBaseUrl) => exports_Effect.gen(function* () {
31507
31655
  const details = yield* exports_Prompt.run(applicationDetailsPrompts);
31508
31656
  const teamPreference = yield* exports_Prompt.run(teamPreferencePrompt);
31509
31657
  let teamName;
31510
31658
  if (teamPreference === "have_team") {
31511
31659
  teamName = yield* exports_Prompt.run(requiredText("Team name"));
31512
31660
  }
31513
- const consents = yield* exports_Prompt.run(applicationConsentPrompts);
31514
- return { ...details, teamPreference, teamName, ...consents };
31661
+ const codeOfConductAccepted = yield* requiredAgreement("Terms and Code of Conduct", publicDocumentUrl(publicBaseUrl, "/terms"));
31662
+ const privacyPolicyAccepted = yield* requiredAgreement("Privacy Policy", publicDocumentUrl(publicBaseUrl, "/privacy"));
31663
+ const mediaConsent = yield* exports_Prompt.run(exports_Prompt.confirm({
31664
+ message: "Do you consent to appearing in event media? (optional)"
31665
+ }));
31666
+ return {
31667
+ ...details,
31668
+ teamPreference,
31669
+ teamName,
31670
+ codeOfConductAccepted,
31671
+ privacyPolicyAccepted,
31672
+ mediaConsent
31673
+ };
31515
31674
  }).pipe(exports_Effect.map((input) => {
31516
- const normalized = withoutEmptyStrings(input);
31675
+ const { githubUsername, linkedInUsername, ...application } = input;
31676
+ const normalized = withoutEmptyStrings(application);
31517
31677
  if (input.graduationYear !== "") {
31518
31678
  normalized.graduationYear = Number(input.graduationYear);
31519
31679
  }
31680
+ if (githubUsername !== "") {
31681
+ normalized.githubUrl = `${githubProfilePrefix}${githubUsername}`;
31682
+ }
31683
+ if (linkedInUsername !== "") {
31684
+ normalized.linkedInUrl = `${linkedInProfilePrefix}${linkedInUsername}`;
31685
+ }
31520
31686
  return normalized;
31521
31687
  }));
31522
31688
  var shirtSizePrompt = (participationMode) => {
@@ -31546,9 +31712,13 @@ var inputOrInteractive = (path4, interactive) => {
31546
31712
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
31547
31713
  return exports_Effect.fail(cliError("INPUT_REQUIRED", "Non-interactive use requires --input <file>, or --input - for stdin"));
31548
31714
  }
31549
- return interactive.pipe(exports_Effect.mapError(() => cliError("PROMPT_CANCELLED", "Interactive input was cancelled")));
31715
+ return interactive.pipe(exports_Effect.mapError((error2) => {
31716
+ if (error2 instanceof CliError2)
31717
+ return error2;
31718
+ return cliError("PROMPT_CANCELLED", "Interactive input was cancelled");
31719
+ }));
31550
31720
  };
31551
- var applicationInput = (path4) => inputOrInteractive(path4, interactiveApplication).pipe(exports_Effect.flatMap((input) => decode2(ApplicationInput, input)), exports_Effect.flatMap((input) => validateSemantics(input, applicationSemanticRequirements(input))));
31721
+ var applicationInput = (path4, publicBaseUrl) => inputOrInteractive(path4, interactiveApplication(publicBaseUrl)).pipe(exports_Effect.flatMap((input) => decode2(ApplicationInput, input)), exports_Effect.flatMap((input) => validateSemantics(input, applicationSemanticRequirements(input))));
31552
31722
  var acceptedDetailsInput = (path4, participationMode) => inputOrInteractive(path4, interactiveAcceptedDetails(participationMode)).pipe(exports_Effect.flatMap((input) => decode2(AcceptedDetailsInput, input)), exports_Effect.flatMap((input) => validateSemantics(input, acceptedDetailsSemanticRequirements(input, participationMode))));
31553
31723
 
31554
31724
  // src/output.ts
@@ -31653,7 +31823,7 @@ var registerCommand = exports_Command.make("register", { input: inputFlag }, exp
31653
31823
  const options = yield* root;
31654
31824
  const operation = exports_Effect.gen(function* () {
31655
31825
  const token = exports_Option.getOrUndefined(options.token);
31656
- const body = yield* applicationInput(exports_Option.getOrUndefined(input));
31826
+ const body = yield* applicationInput(exports_Option.getOrUndefined(input), options.apiUrl);
31657
31827
  return yield* register({ apiUrl: options.apiUrl, token }, body);
31658
31828
  });
31659
31829
  yield* execute(options.output, operation, createdText);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chofex-cli",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Command-line client for the Chofex Hackathon",
5
5
  "type": "module",
6
6
  "bin": {