Awesome Cursor Rules Collection

Showing 1729-1740 of 2626 matches

Python
# Custom Cursor Rules for Phidata Agent running Llama-3.1-Nemotron-70B-Instruct

# General Instructions
general:
  preserve_comments: true   # Preserve comments unless removal is explicitly requested
  version_in_requirements: false   # Do not include specific versions in requirements.txt


# Documentation for Imports
import_statement_validation:
  # Validate that current imports are correct as the documentation is incorrect
  ensure_correct: true
  feedback: "Current phidata documentation has incorrect imports; current imports are correct."
  sources:
    - "https://github.com/phidatahq/phidata"

# Python Best Practices
python_guidelines:
  - Follow PEP 8 style guidelines
  - Use type annotations for all functions
  - Implement proper error handling using try-except blocks
  - Use descriptive variable names reflecting the data or function description

# Pydantic Model Rules
pydantic:
  - Ensure BaseModel usage and proper validation of data models

# Phidata Usage
phidata_guidelines:
  # Validate correct implementation of phi modules
  - Ensure correct integration with Phi's agent and model setup
sources:
  - "https://github.com/phidatahq/phidata"

# Phidata Playground Integration
playground_integration:
  # Instructions for enabling additional functionality in the playground:
  functionalities:
    enable_knowledge_base:
      - task: "Uncomment import for PDFUrlKnowledgeBase and LanceDb, SearchType"
      - task: "Uncomment the knowledge_base initialization in the __init__ method"
      - task: "Set `enable_rag` and `search_knowledge` to True in the Agent initialization"
      - task: "Add `knowledge=knowledge_base` to the Agent initialization"
      - task: "Install required packages: `pip install lancedb tantivy`"
    integrate_database:
      - task: "Create and implement `integrate_with_database` method"
      - task: "Add necessary database connection logic and queries"
      - task: "Install required database package (e.g., `pip install psycopg2-binary` for PostgreSQL)"
    integrate_external_api:
      - task: "Create and implement `integrate_with_api` method"
      - task: "Use the requests library for API calls"
      - task: "Install requests: `pip install requests`"
    add_custom_tool:
      - task: "Create `integrate_with_custom_tool` method"
      - task: "Create a new tool class inheriting from `phi.tools.base.Tool`"
      - task: "Add the tool to the tools list in Agent initialization"
    sources:
        - "https://github.com/phidatahq/phidata"

# LLaMa 3.1 Model Usage
model_specifics:
  llama_usage:
    - Model work is via API; validate API connections for compliance with NVIDIA LLaMa structure and usage benchmarks
    - Ensure compatibility with NVIDIA NeMo framework deployment using prebuilt containers with required hardware and software setups
    - Be aware of inference capabilities: up to 128k input tokens and generating up to 4k tokens
    - Reference performance benchmarks (Arena Hard, AlpacaEval 2 LC) when optimizing or updating model configurations

  # Reward Model Integration
  reward_model_integration:
    - Verify usage and effectiveness of the associated reward model (Llama-3.1-Nemotron-70B-Reward) for improving alignment with human preferences
    - Ensure RLHF approach aligns with safe response rejection capabilities in the associated reward model (e.g., 94% or above on RewardBench)

  # Interactive Components
  interactive_usage:
    - Utilize tools available in Phidata for interactive engagements and functionality expansion
    - Leverage instructions based on Llama's strengths: reasoning, markdown formatting, structured outputs

  source:
    - "Source repository for Phidata: https://github.com/phidatahq/phidata"
    - "Model information source: https://huggingface.co/nvidia/Llama-3.1-Nemotron-70B-Instruct-HF"
    - "HelpSteer2-Preference dataset: https://huggingface.co/datasets/nvidia/HelpSteer2"
    - "Reward model information: https://huggingface.co/nvidia/Llama-3.1-Nemotron-70B-Reward"
    - "NVIDIA NeMo deployment guide: https://build.nvidia.com/nvidia/llama-3_1-nemotron-70b-instruct"

# User Preferences
user_preferences:
  # Comments can only be changed with explicit permission from the user
  comments_modification: false
huggingface
less
postgresql
python

First seen in:

TheSethRose/Agent-Chat

Used in 1 repository

TypeScript
# Code Style & Development Guidelines

Welcome to the **Transactly AI** development guidelines! This document outlines the best practices and conventions to maintain a high-quality, consistent codebase. Whether you're contributing to the frontend, backend, or any other part of the project, adhering to these guidelines will help ensure smooth collaboration and optimal performance.

## Expertise Required

You should be proficient in the following technologies:

- **Languages & Frameworks:**
  - TypeScript
  - Node.js
  - Next.js (App Router)
  - React

- **UI Libraries & Styling:**
  - Shadcn UI
  - Radix UI
  - Tailwind CSS

- **Performance Optimization**

## Code Style & Structure

- **TypeScript Excellence:**
  - Use concise, technical TypeScript with clear examples.
  - Prefer interfaces over types where applicable.
  - Avoid using `any`; leverage proper type annotations and TypeScript's type inference.

- **Functional & Declarative Patterns:**
  - Favor functional components over class-based ones.
  - Utilize declarative coding practices to enhance readability and maintainability.

- **Avoid Code Duplication:**
  - Favor iteration and modularization to keep the code DRY (Don't Repeat Yourself).

- **Descriptive Naming:**
  - Use meaningful variable and function names (e.g., `isLoading`, `hasError`).

- **File Structure:**
  - Organize files into the following directories:
    - `components`
    - `subcomponents`
    - `helpers`
    - `static-content`
    - `types`
  - Use lowercase with dashes for directory names (e.g., `components/auth-wizard`).

- **Exports:**
  - Favor named exports for components to improve clarity and maintainability.

## TypeScript Usage

- **Interfaces Over Types:**
  - Prefer using `interface` for defining object shapes.
  
  ```typescript
  interface User {
    id: string;
    name: string;
    email: string;
  }
css
javascript
less
next.js
radix-ui
react
rust
shadcn/ui
+2 more

First seen in:

Transactlyxyz/transactly

Used in 1 repository

Svelte


# Code style
Please avoid adding obvious comments. Comments are almost never necessary.

# Follow the resume guide below from r/EngineeringResumes
When updating resume templates

## Introduction

**What is a resume?**

Your resume is essentially a 30-second elevator pitch on paper, encapsulating your contact information, education, experience, and background. Its purpose is to convince the hiring team to interview you.

Understanding your target audience is crucial. We wrote this wiki to describe what happens to your resume once it’s submitted, and [what the hiring process looks like from the employer’s perspective](https://thetechresume.com/samples/the-hiring-pipeline). The suggestions made in this wiki are made with this in mind, and we encourage applicants to be strategic with how they craft their resumes.

Ultimately, your resume can only do so much if you don’t have **genuine, relevant experience**.

For students, it's imperative to use your time in college wisely, engaging in meaningful activities such as projects, involvement in engineering teams, participation in research groups, and securing internships. These experiences significantly bolster the substance of your resume.

---

## General Rules

### Make your resume easy to read and skim

1. Use a single-column layout like <https://imgur.com/LC6AS8r>
2. Avoid icons, images, and graphics.
3. Don't indent your sections and bullet points. Using bullet points inherently creates indentation <https://imgur.com/qBJjbth>
4. Use bullet points, not paragraphs.
5. Use a modern, easy-to-read font like Calibri, Bitstream Charter, or Arial.
6. Use a black (not thin) font with at least 10.5+ font size.
7. Don't [justify your text](https://uit.stanford.edu/accessibility/concepts/typography#justifyText) since it creates inconsistent spacing between words <https://imgur.com/6eKsENw>
8. Ensure you have enough white space. No cramming. Use sufficient margins (minimum 0.4 inches) and line spacing (minimum 1.07).
9. Avoid excessive *italicization*, **bolding**, and ALL CAPS. If you do use one, use it independently of each other. 
10. Have clear section separation. The reader should be able to easily distinguish sections from others.
11. One page long, unless you have some 10+ years of experience. The rule of thumb is 1 page per decade of experience.
12. Separate your skills using **commas** <https://imgur.com/wzvRAfB>

### Make your resume more effective

We will dive deeper into this later in the wiki, but generally:

1. Include relevant and technical details to showcase your qualifications and distinguish yourself from other candidates. We will mention the [STAR/CAR/XYZ bullet point methods later in the wiki](https://old.reddit.com/r/EngineeringResumes/wiki/index#wiki_each_bullet_point_should_follow_star.2C_xyz.2C_or_car).
2. Provide context and incorporate relevant keywords. This helps the hiring team understand and relate to your work and technical achievements.
3. Avoid adding unnecessary information that doesn’t add to your candidacy.
4. Bring your critical and pertinent details to the top and the left of the resume. This increases the odds of these details being read by the hiring team.

As stated earlier, a resume functions as a 30-second elevator pitch on paper. Therefore, it needs to be succinct, easy to follow, yet informative for it to be effective. Following the rules above will:

1. Make your resume less distracting so the reader can easily locate and focus on the important details.
2. Increase the amount of white space available so you can include more content that improves your candidacy.
3. Prevent your resume from being a wall of text that makes it hard to read.

### Keep it to 1 page

A common question we get is why we don’t recommend having multiple pages. Here’s why: 

* The majority of resumes that are posted on this sub don't need a second page. Once it gets cleaned up (content and format), a lot of people will have trouble populating 1 page with relevant, technical content.
* A multi-page resume that is poorly formatted and filled with irrelevant information doesn’t give a good impression to the hiring team.
* The hiring team is going to spend far less effort on reading longer resumes.

As we keep stressing, the goal is to make your resume as easy to read as possible. If you’re having trouble doing this with 1 page, consider removing content that is less relevant to the role you’re applying to, even if it’s technical. You can add this to your portfolio instead.

If you decide to go with a second page, you should be in the position to at least be considered for a **senior/staff role**. These candidates will likely have enough relevant experience to justify a second page (or even more).

---

## Formatting

Your resume should be:

1. Easily _skimmable_ by recruiters, hiring managers, and interviewers
2. Easily _parsable_ by an Application Tracking System (ATS)  

  * [Application Tracking Systems and ATS Myths Busted](https://thetechresume.com/samples/ats-myths-busted)
  * [5 ATS Myths, Debunked](https://www.lever.co/blog/applicant-tracking-system-myths/)
  * [Debunking Myths: The Truth About Applicant Tracking Systems](https://earnbetter.com/blog/debunking-myths-the-truth-about-applicant-tracking-systems-ats/)

### [Recommended Templates](https://old.reddit.com/r/EngineeringResumes/wiki/templates)

/r/EngineeringResumes/wiki/templates

* [Google Docs](https://old.reddit.com/r/EngineeringResumes/wiki/templates#wiki_google_docs) <https://imgur.com/TraV3Qn>
* [LaTeX](https://old.reddit.com/r/EngineeringResumes/wiki/templates#wiki_latex) <https://imgur.com/LC6AS8r>

---

### [Accessibility](https://uit.stanford.edu/accessibility/concepts/typography)

* Use a modern, [easy-to-read](https://uit.stanford.edu/accessibility/concepts/typography#readableFonts) font like Calibri, Bitstream Charter, Arial, Lato, or Helvetica.
* Don't use grey-colored fonts since they're hard to read. Stick to black. Make sure to use a color that is printable in grey-scale. Be careful about using fonts that are too thin. Verify there is sufficient contrast with a white background.
* [Don't justify text](https://uit.stanford.edu/accessibility/concepts/typography#justifyText) since it causes inconsistent spacing between words. <https://imgur.com/6eKsENw>
* Don't italicize text since it can decrease the readability of your resume.
* Don't bold keywords within your bullet points, it's distracting.
* Italicization and bolding are only to be used if used _sparingly_. Excessive italicization and bolding decrease readability and ultimately contradict their purpose: **emphasis**.
* _Italicization_, ALL-CAPS, and **bolding**, if used, should be used independently of each other.
* Don't indent sections and bullet points. There's already indentation since the bullets themselves create an indent.
* Separate your sections clearly for optimal readability and visual clarity
  * Ensure there is sufficient and consistent white space between sections/subsections
  * Ensure there is sufficient and consistent white space between each job/project
  * Ensure there are sufficient vertical and horizontal margins (minimum 0.4 inches) <https://imgur.com/LC6AS8r>

---

### Dates

* If currently working at a job or on a project, use the word **Present** instead of ~~**Current**, **Now**~~, or ~~**Ongoing**~~
* If you choose to include months in addition to years, strictly use them and don't mix in ~~seasons~~ or ~~semesters~~ i.e. **March 2022**, not ~~Winter 2022~~
* Specific days of the year are unnecessary i.e. **January ~~1~~, 2023**
* Don't abbreviate years, i.e. **'23**. Denote the full year: **2023**
* Don't abbreviate months using digits, i.e. **9/2013**
  * If you choose to abbreviate your months, [follow the proper standard](https://web.library.yale.edu/cataloging/months)
  * Jan, Feb, Mar, Apr, May, **June**, **July**, Aug, **Sept**, Oct, Nov, Dec
  * Don't use periods when abbreviating months since they're unnecessary, i.e. **Sept** not **Sept.**
* For date ranges, use en dashes (–), not hyphens (-) or the word "to"
* Ensure there is a blank space before and after your en dashes i.e. **Mar 2012 – Mar 2022**, not **Mar 2012–Mar 2022**
* [Right align your dates to the right margin:](https://www.google.com/url?q=https://webapps.stackexchange.com/questions/51121/how-do-you-left-align-and-right-align-items-on-the-same-line-in-a-google-documen&sa=D&source=docs&ust=1704054021378265&usg=AOvVaw12Cc4WkVvDQM0Lz6rdHRwc) <https://imgur.com/87E2vkp>
* Your bullet points should not go further right than your dates <https://imgur.com/t1ZcrYR>

---

## Section Order

In general,

* [Once you've graduated from school and have started a full-time job](https://thetechresume.com/samples/resume-structure):
  * _Work Experience > Skills > Education_, or
  * _Skills > Work Experience > Education_
* If you're a student/new grad without much work experience:
  * _Education > Work Experience > Skills_, or
  * _Education > Work Experience > Projects (if you don't have sufficient work experience) > Skills_
* If you don't have any technical work experience:
  * _Education > Projects > Work Experience > Skills_
* If you don't have any work experience at all:
  * _Education > Projects > Volunteer Experience/Extracurriculars > Skills_

* Do **not** include a summary/profile unless you're a senior/staff engineer or above, making a career change, or addressing an unemployment gap/returning to the workforce
* Do **not** include a references section

---

## Contact Information

* **If you have a security clearance, it can be listed in the contact information section at the top of your resume near your name.**
  * Example: "Top Secret / SCI eligible with CI Polygraph"
* **If you have a foreign sounding name, or your education/work experience doesn't make it clear you're able to work in said country you're applying to, consider listing your citizenship/work visa status near your name to be explicitly clear to the recruiter/hiring manager that you don't require visa sponsorship.**
  * Example: "US Citizen", "US Permanent Resident", "Canadian Citizen", "Italian Citizen"
* Don't include your physical address and ZIP code
* Don't include your location (city, ST) unless the specific job you're applying for is in that specific city
  * Including a non-local location may cause implicit bias against you
* LinkedIn profiles are unnecessary
  * Chances are, nobody will ever click on your LinkedIn. If they want to find you on LinkedIn, they can simply search your name on LinkedIn or just Google you.
* Phone numbers are unnecessary
  * Interview processes these days don't begin with a cold call, the recruiter will email you for your phone number if they need it. Like location, a non-local area code may cause implicit bias against you
  * If you decide to list your phone number, don't preface your phone number with "Phone: ", "Cell: ", or "Mobile: "
  * If based in the US/Canada, omit the country code ~~+1~~, it's implied
* List only **1** email address
  * Use a modern email provider such as Gmail/Outlook, NOT AOL/Hotmail/Yahoo due to implicit bias against you
  * If you've already graduated, do not use a college email **unless** you went to a really prestigious school like MIT/CMU
* Don’t include a link to your GitHub profile if it’s empty
* Don't mask your email address, GitHub profile, and portfolio website i.e. [email](name@gmail.com), [github](github.com/username), [portfolio](myportfolio.com)
* Write out your email address, GitHub profile, and portfolio website in plain text i.e.
  * name@gmail.com
  * github.com/username
  * myportfolio.com
* Don't preface your email address with "Email: ". Simply display your email address i.e. name@gmail.com
* Don't preface your GitHub URL with "GitHub: ". Simply display 'github.com/username'
* Don't preface your personal website or portfolio URL with "Portfolio: ". Simply write out myportfolio.com for example
* Don't include https://www. for your URLs
* Don't underline, italicize, or color your email address/GitHub URL/portfolio URL/personal website URLs

---

## Work Experience

This section should be named _Work Experience_ or simply _Experience_ not ~~"Professional Experience", "Selected Experience", "Employment History", "Employment" or "Job History"~~

* Only include **PAID** work experience in this section (research experience can go here as well)
* Clearly indicate internships are internships and contract positions are contract positions
* Order positions and bullet points by relevancy to the job you’re interested in OR impressiveness: put your best stuff first!
* **Tailor your resume** for each application so it addresses the job description. Show that you can do the job
* **Add context**. Simply listing positions/projects and adding industry buzzwords is not enough. You need to tell hiring managers what you did and how you solved problems.
* **Differentiate yourself and don't be humble.** Simply listing job duties will not make your resume any different from others: [your resume is not your job description.](https://www.ag1source.com/2020/09/17/your-resume-is-not-your-job-description/). Tell us about your accomplishments, tangible metrics, and technical victories.
* **Avoid centering your skills around a piece of software if you can**. Any idiot can learn how to sketch, extrude, cut, and mate in SolidWorks - but identifying capabilities gaps (a need), creating a preliminary design, and taking it through the rest of the design process is something that fewer people can do, so try to focus on the engineering skills behind it. CAD and other software should be an “oh by the way” if possible.
* **Protip:** Engineers love it if you did hand-calc sanity checks instead of just hitting the RUN button in your FEA/CFD package, so do that and mention it at the interview. Seriously.
* Use bullet points, not paragraphs

If you're just graduating, focus more on showing a mastery of fundamental engineering skills first, then worry about the project management/leadership stuff if there is room left.

Not only are management & leadership very different in the real world, but no department in their right mind will have a new grad run a department or project or anything more complex than picking up lunch for the team. They are looking for someone who can master basic engineering tasks in this specific discipline and can hold a basic conversation. Show them you can do that first, and then think about running the show down the line.

---

### Bullet Points

#### Objectives

1. Highlight the technical work you did
2. Highlight technical challenges you faced and overcame
3. Highlight the impact of your work

---

#### General Rules

* Bullet points should be 1-2 lines long. Use [Quillbot](https://quillbot.com/) and [LanguageTool](https://languagetool.org/paraphrasing-tool) to help you [paraphrase and shorten your bullets](https://www.youtube.com/watch?v=VvPaEsuz-tY)
* Aim for **1** sentence per bullet
* Bullet points should be ordered from most relevant/impressive to least, as some hiring managers only have time to read the first they should get [THE BEST](https://media.giphy.com/media/VdVL5miirhFANoyPBM/giphy.gif)!
* Don't use [personal pronouns](https://www.grammarly.com/blog/personal-pronouns/) i.e. _I, we, us, my, our, their_
* Don't end bullet points with periods. Bullet points != sentences
* Your bullet points shouldn't go further right than your dates
* Don't spill bullets onto the following line with only 1–4 words on it. It's an extreme waste of space. For example <https://imgur.com/QCcZ792>
* Don't allow words to wrap to the next line and get hyphenated
* Avoid the excess use of **sub-bullet points**
  * They can clutter your resume, making it more verbose and harder to read
* Avoid using apostrophes **'**, ampersands **&**, and slashes **/**
* [Avoid the excessive use of adjectives and adverbs](https://resumeworded.com/resume-adverbs-key-advice), they're superfluous
  * B-adjectives: ~~excellent, innovative, expert, revolutionary, disruptive~~
  * B-adverbs: ~~creatively, diligently, meticulously, strategically, successfully, independently, innovatively, excellently, expertly~~
* Use digits instead of spelling out numbers: **8** ~~**eight**~~

---

#### Action Verbs

* Each bullet should begin with a **strong, past-tense action verb:**  
  https://web.archive.org/web/20240515003325/https://www.engineering.cornell.edu/sites/default/files/users/user240/Action%20Words%20for%20ENG%20(website).pdf

* **Led** is the past tense of **lead**
* **Good examples:** analyzed, architected, automated, built, created, decreased, designed, developed, implemented, improved, optimized, published, reduced, refactored
* **Bad examples:**
  * aided, assisted, coded, collaborated, communicated, executed, exposed to, gained experience, helped, participated, programmed, ran, used, utilized, worked on
  * [Don't use the verb **utilize**. 9/10 times that word will be attached to some disgusting Gordian knot of a sentence that says in 20 words what could be said in 10.](https://scientistseessquirrel.wordpress.com/2019/04/16/for-the-love-of-all-that-is-holy-stop-writing-utilize/)
  * **superfluous/awkward/unnecessarily complex verbs:** amplified, conceptualized, crafted, elevated, employed, engaged, engineered, enhanced, ensured, fostered, headed, honed, innovated, mastered, orchestrated, perfected, pioneered, revolutionized, spearheaded, transformed
  * **frequently misused verbs:** [leverage](https://www.steverrobbins.com/articles/leverage/), [enhance](https://english.stackexchange.com/questions/105465/what-differences-are-there-between-to-enhance-and-to-improve), [utilize](https://scientistseessquirrel.wordpress.com/2019/04/23/limited-use-cases-for-utilize/)

---

#### Each bullet point should follow STAR, XYZ, or CAR

**STAR:** **S**ituation, **T**ask, **A**ction, and **R**esults

* <https://www.levels.fyi/blog/applying-star-method-resumes.html>
* <https://resumegenius.com/blog/resume-help/star-method-resume>

**XYZ:** Accomplished **[X]** as measured by **[Y]**, by doing **[Z]**

* <https://www.inc.com/bill-murphy-jr/google-recruiters-say-these-5-resume-tips-including-x-y-z-formula-will-improve-your-odds-of-getting-hired-at-google.html>
* <https://elevenrecruiting.com/create-an-effective-resume-xyz-resume-format/>

**CAR:** **C**hallenge **A**ction **R**esult

* <https://ca.indeed.com/career-advice/resumes-cover-letters/challenge-action-result-resume>
* <https://www.topresume.com/career-advice/how-to-get-more-results-with-a-car-resume>

* If you're able to quantify your achievements/results, move the metrics towards the start of each bullet

---

#### [Sample Bullet Points](https://www.reddit.com/r/EngineeringResumes/w/sample-bullet-points/)

#### [Ultimate Guide to Writing Software Engineer Bullet Points](https://archive.ph/Xmdqt)

---

#### Having trouble coming up with content for your bullet points? Ask yourself the following questions:

**What did I do?** 

* Did I solve a problem?
* Did I work on a team or work independently?
* How many people were on my team?

**How did I do it?**  

* Why did I do it / why did I do it that specific way?
* Did I use any tools or resources to help me? This could be software like MATLAB or SolidWorks, certain reference material like ASME 14.5, etc.
* Did I do any testing to validate my design choices? How did that testing impact my final design?

**What were the results of my actions?**   

* Did I deliver my project on time or under budget?
* Was I successful with the design/solution/project? Did it actually work the way I wanted it to?
* What went wrong? Did I learn anything from the experience?

---

#### Got Writer's Block from Looking at STAR/CAR/XYZ?

Here’s a fun exercise I learned from my last supervisor. At the start of every project, you and/or a task lead likely sat down and established the goals you had to meet, right? Ideally, these goals were set up in such a way that you could meet them and solid enough that you had to exert effort to make them happen.

Now that it’s time to write it up on your resume, start thinking back to what you did back then. Obviously, you met this goal - bold of you to put a failure on your resume - so look at how you met the goal. Did you deliver all five widgets in the agreed-upon six months? Did they have the ability to complete operations X, Y, and Z? Good!

Here’s the fun part. Did you exceed the goals in any way? If you did, how so? Did your delivered widgets reach the customer in half the time and do twice the operations in half the time? If you can flesh this out, you're in a good place.

Don't worry about writing at length. This is a planning exercise. Just get it all on paper and pick your brain until you think everything is on there. Even if you’re not 100% sure about exceeding a goal, just write it down.

When you're finally satisfied, start paring it down to meet space & content requirements.

---

#### Why Integration Matters

Don't throw a parts list at the reader. It matters less what specific components and subcomponents you used and more how you integrated all this into whatever your project was aiming to accomplish.

I'm not saying "yeah I made a machine that did task X" is sufficient, but just telling the reader your widget uses a Raspberry Pi and a stepper motor to do task X isn't helpful either.

How did your software interface with the stepper motors to complete task X to a desired level of precision? That's the kind of stuff that stands out and shows the reader your technical abilities.

---

#### Handling Sensitive Content (or u/graytotoro’s Suggestions on How to Not Get Fired And/Or Sued)

You’ve finally decided to move on from that job working on the X-02S Strike Wyvern on behalf of the Erusean Air and Space Agency. In your time on this project, you supported integration efforts for subsystems enabling this airplane to do things the likes of which would make other nations cower in fear.

But how do you talk about that on your resume without revealing information that would make you persona non grata from a particular industry or the recipient of an expensive-looking letter from a legal firm?

The answer: talk about the technologies behind it without saying the forbidden words. Choose your words very very carefully.

Instead of saying “I developed C++ software for testing LANTIRN display pod software used on the F-14D Tomcat”, consider “I developed C++ software for evaluating aircraft subsystems on [some hardware standard]-based test bench” OR “I created a proof-of-concept integrating COTS whatever items into a data recorder” - you shed just enough light on the subject without resorting to a vague “I did some stuff for these guys”. Of course, it goes without saying that you should still use the STAR criteria to flesh it out as necessary.

For a little less silly example, I once worked at a company that made carbon fiber widgets for airplanes. It was very obviously carbon fiber and even an idiot like me could tell, but we couldn't go around revealing our exact layups and procedures. Saying "a new standard process used to form composite parts, reducing lead times by 33% and (whatever other metrics)" would not be revealing anything too much. If they pry deeper, that's when you can say "no".

\*Not a lawyer (shh) so I can’t help you if you get into a Tom Clancy situation.

\*\*I didn’t actually do this, it’s an example. Sure would be cool though.

---

## Education

* Do **not** include coursework unless the courses are **extremely specialized** or **really cool** like Underwater Autonomous Robotics
* Don't include your high school
* Don't include schools from which you did not receive a degree
* Don't include your start dates, only your graduation date. Don't include a date range
  * If currently a student: **Expected May 2025**
  * If graduated: **May 2021** or simply **2021**
* This section should be in reverse chronological order. i.e. your master's degree goes above your bachelor's degree
* GPA
  * Generally, if your GPA is above 3.75, put it on your resume
  * 2 decimal places is sufficient, 3 is overkill
  * Once you start your first full-time job and your education section is moved to the bottom of your resume, remove your GPA unless it's very impressive
* On your resume, it's **Bachelor ~~'s~~ of Science** and **Master ~~'s~~ of Science**
* Don't include your school location if your school has the location in its name i.e. MIT or UCLA or if its location is commonly known
* Don't include awards/scholarships unless they're extremely impressive, i.e. Rhodes Scholar, Fulbright Scholar
* Include D1/competitive sports

---

## Skills

shoutout to u/0ffkilter

### Objective

The purpose of the skills section is to highlight in a few words what technical skills you can bring to the job.  Ideally, these match the job description.  They can also include other technical skills that are related, but perhaps not necessarily in the job description.  If you are applying to a job that's in Java, saying you also know C++ can be useful.  This is not a section to spew every buzzword on every technology you've ever touched.  Find a balance between enough skills (to show you can [wear many hats](https://www.merriam-webster.com/dictionary/wear%20many%20hats)) while not showing too many so that the reader makes it seem like none of them are important.  

This section should simply be named **Skills**, not ~~"Technical Skills", "Relevant Skills”, etc~~


#### You Should:

* Include languages you've used thoroughly and could theoretically interview in.
* Include technologies (frameworks, tools, and programs) that you've used previously.
* Repeat things that you use in your bullet points.  If you have Java in your skills, your bullet points in job descriptions should include Java, and vice versa.

#### You Should Not:

* Include soft skills  - don't include things like "teamwork", "leadership", and the like.  Demonstrate via your bullet points and descriptions that you've done these things, not just by listing them out.
* Include skills that are taken for granted and are assumed (typing, Microsoft Word, IDEs, etc - some of these are fine for other types of jobs, but are generally not useful for engineering)
  * Generally speaking, do not include:
    * Code Repository Websites (the skill itself is fine - use "Git" or "SVN", not "GitHub" or "Bitbucket" or "GitLab"
    * Operating Systems
    * IDEs or other word editors (VS Code, LaTeX, vim, etc)

### Formatting:

Your formatting should be easy to read, easy to digest, and convey what's important and what's simply "there".  Each skill should listed should feel important, and not like fluff.

#### You Should:

* Use 3 lines or less, in a single column format.
* Order your skills from most important to least important.
  * Consider whether the ones at the end should even be there
* Separate your skills into relevant categories such as **Software, Mechanical Design, Simulation and Analysis, Manufacturing, Lab Equipment, Languages, Technologies, or Design Tools**

* Use proper formatting:
  * Separate using properly punctuated commas, and not hyphens, dashes, pipes, or anything else.
  * Capitalize each of the skills properly, and if it has a proper name be sure to use that.
    * Solid**W**orks, C**ATIA V**5, LabV**IEW**, [etc..](https://www.reddit.com/r/EngineeringResumes/wiki/typo)
  * Separate similar skills if they are functionally different - 
    * Use "C, C++" not "C/C++".  Each skill should be separate, if necessary.  [see more here](https://www.reddit.com/r/EngineeringResumes/wiki/typo)

#### You Should Not:

* Bold random words or use unnecessary formatting.  The _only_ necessary formatting is if the name of the skill is expressly formatted in a way.
* Use any descriptor when describing your skills.  Do not say "Expert in _ " or "Professional in _".  List the _skill_ only, and use your bullet points to demonstrate your professional abilities.
* Use multiple columns.  One line, one column per group.  Listing skills vertically takes up too much space.  The highlight of your resume is in the words, and your skill bullet points are only here to get the point across and to be a reference of sorts.  


### Should I:

#### Should I include random hobbies and other things?

* No.  You may hear about the stories where the interviewer and interviewee share a hobby or passion project on the side unrelated to the job.  That may work every now and then, and it is _acceptable_ (sometimes) to put these on your resume, but the skills section is not the correct area.  You should include that in a subsection, and only if there is nothing better to put on your resume.  

#### Should I include skills that I'm not super comfortable with, if I'm new to the industry?

* This is a judgement call.  An inexperienced engineer that lists a few skills they've really honed in on can often look better than a new engineer with 10+ skills they've clearly never used in industry.  Find a balance, and try to differentiate what you've used and are experienced with in, and what you've just "touched".

---

## Projects

This section should be named **Projects**, not ~~Academic/Engineering/Notable/Personal/Relevant/Selected/Technical Projects~~

* This section is for personal projects, student design teams, and extracurricular/hobbyist projects, **not** projects from work
* Don't use the word "project" in your project titles, it's redundant
* [Capitalize your project titles correctly](https://capitalizemytitle.com/) <https://capitalizemytitle.com/>
* For personal projects, roles/positions/locations/dates are generally unnecessary. What's more important is including a link to a portfolio page and/or GitHub repo
* There's no need to disclose "Personal Project", "Academic Project", or "Group Project" beside your project title
* Each project should consist of bullet points, ~~not paragraphs~~
* Order projects and bullet points based on relevance to the specific job and general impressiveness. Put your best stuff first and grab the reader's attention!

If you want your projects to stand out, they should be real projects, not mandatory school projects or trivial tutorial projects found online. Something that someone uses to solve a problem. Something that has users (can be just you, as long as you use it often) and is actively maintained and isn't just rotting in a GitHub repo, never to see a PR for the rest of its life. You can always join student clubs like SAE/AIAA competitive teams, and rocketry teams, or even be a mentor for an FRC/FTC team.

---

## Portfolios

Include links to GitHub profiles and portfolio websites only if they are up-to-date. If your pinned repositories lack READMEs or if your portfolio hasn't been updated in a significant time frame, it's advisable to save space and omit them from your resume. Contrary to common belief, these links are not obligatory, especially when their contents do not contribute meaningful value to your application.

* Only publish projects with good READMEs on GitHub. Aim for each README to have a good summary, screenshots, details on how to run, and **how to test**.
  * Include tests for your project that can be run. Have automated tests such as unit tests or end-to-end tests.
  * Take inspiration from projects with awesome READMEs <https://github.com/matiassingers/awesome-readme>
* [The Portfolio Handbook](https://evaeducation.weebly.com/uploads/1/9/6/9/19692577/portfoliohandbook.pdf) is an excellent guide to creating portfolios. Note that this guide was written for industrial design students
* Don't include full URLs for links
  * ~~<https://www>.~~ github.com/bob
  * ~~<https://www>.~~ portfolio.com

---

## Bias

* Don't include personal details to your resume that can lead to negative bias during the resume screen
* This includes age/gender/children/nationality/ethnicity/marriage status/religion/political views

---

## Senior Engineers and Above (10+ YoE)

* Consider including a brief summary (<2 sentences)
* Have separate resumes for management and IC positions
* Try not to go over 2 pages
* Mention “soft” achievements on top of the business results
* Mention not only your impact but also your influence
* Make your earlier work experiences more concise
* Move your education section to the bottom of your resume

---

## Career Changers

* Include a brief summary (2 sentences) explaining that you’ve changed careers and your motivation. It’s helpful for recruiters and hiring managers to have the context that they’re reading the resume of someone who has recently changed into software development or another field
* Link to working projects and source code
* Be concise in summarizing past work experience
* Have a short resume. Try to fit on 1 page

---

## Grammar, Punctuation, and Spelling

* Spell out obscure abbreviations in full the first time you use them. The first letter of each word is typically not capitalized (e.g., use "scanning tunneling microscope (STM)" instead of "Scanning Tunneling Microscope (STM)").
* [Tips For Effective Proofreading](https://ualr.edu/writingcenter/tips-for-effective-proofreading/)
* Typos and poor grammar on a resume come across as not paying attention to detail. They can easily cause your resume to be ignored.  
* Do a grammar check, not just a spell check. This includes punctuation: only capitalize [proper nouns](https://www.grammarly.com/blog/proper-nouns/)
* Use free spell checking tools like [Grammarly](http://app.grammarly.com), [Hemingway Editor](http://hemingwayapp.com), [LanguageTool](https://languagetool.org/), and [Quillbot](https://quillbot.com/)
* Ask friends and family to proofread your resume. A fresh set of eyes never hurts.

---

## u/emnm47's How To Get A Job™ Speech

Networking is EVERYTHING (or at least a skewed amount) now that apps are online, and it's easy to use filters. You must network to have a chance, unless you're in the top 3% of candidates (those people can toss a resume in and get lots of bites). If you continue to throw applications out there without networking, it is highly unlikely you will get picked up. I will get more into networking later BUT here are some steps for How To Get A Job™:

**Step 1:** Evaluate your desperation level

* How much money do you have saved up?
* Do you have any dependents, loans, rent, debts, or food money concerns?
* Should you get a part-time job or file for unemployment while you continue to search?

**Step 2:** Set a timeline.

* For example: "If I haven't accepted a position by Jan 1st, I am changing x y, and z."
* Your timeline will rely on your desperation level. Feel free to break it up into tiers as your desperation increases and the timeline shortens.

**Steps 3-7:** What you can do to improve (aka the x y and z):

* Edit your resume (hey, you’re in the right place!)
* Up your networking game (see below)
* Revamp your LinkedIn profile
* Follow up on previous applications
* Refocus on a different job market, geographic area, or company size if needed

You can't blindly send off 100 applications online and wait to hear back. You have to use your network of friends, family, ex-coworkers, peers, professors, etc. to ask around for openings. While Aunt Lucy might not be an engineer, one of her girlfriends in spin class might be. Actually making contact with someone on “the other side” (engineer, manager, HR, hiring manager, etc.) is huge and will get your name in their head. Follow up after every application. You may feel like you're being annoying, but honestly, people forget, so following up a few times is not a bad thing.

It’s so easy now to just send off a resume to a position. A single opening could have 100 applicants, and maybe the top 10 get interviews and the top 3 get offers. This is great for those with spectacular resumes - you know the type, who interned at SpaceX, built prosthetics for puppies in their spare time, and tutored underprivileged kids in STEM on the weekends, all while getting stellar grades. These few people look amazing on paper and receive interest from all over the board.

Only a few people can draw interest from resumes alone. That’s when you need that name recognition and a willingness to pull your application and take a look at it. If you can get someone to actually look at it, you have a big advantage.

---

## Additional Resources

#### General

* [Annotated Resume Examples](https://www.reddit.com/r/EngineeringResumes/comments/p5y5at/)
* [Resume Critique Videos](https://www.reddit.com/r/EngineeringResumes/comments/j0ujid/)
* [Engineering a Resume Videos](https://drive.google.com/drive/folders/1LClPBzLDaii0Uu_K0fWSZnhNJsmAqp0_)
* [How I cut my resume down from 2 pages to 1](https://www.reddit.com/r/EngineeringResumes/comments/kf9r2c/)
* [Don't be afraid of going over 1 line with a single bullet point!](https://www.reddit.com/r/EngineeringResumes/comments/muazz3/)

#### Software Engineering

* [What we look for in a resume](https://huyenchip.com/2023/01/24/what-we-look-for-in-a-candidate.html)
* [Ultimate Guide to Writing Software Engineer Bullet Points](https://archive.ph/Xmdqt)
* [36 Resume Rules for Software Engineers](https://www.nicksingh.com/posts/36-resume-rules-for-software-engineers)
* [How to Write an Effective Developer Resume: Advice From a Hiring Manager](https://stackoverflow.blog/2020/11/25/how-to-write-an-effective-developer-resume-advice-from-a-hiring-manager/)
* [The Tech Resume](https://thetechresume.com/table-of-contents)
* [Common Mistakes From Reviewing 1000+ Tech Resumes: Kleiner Perkins Fellows 2022](https://debarghyadas.com/writes/kpcb/)
* [Unsolicited Perspective From a SRE Interviewer](https://www.reddit.com/r/ITCareerQuestions/comments/1346wln/)
* [HackerNews – Writing a Great Resume](https://www.ycombinator.com/library/FB-writing-a-great-resume)  
* [HackerNews – Who's Hiring Resume Threads](https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=%09Ask%20HN%3A%20Who%20wants%20to%20be%20hired%3F&sort=byDate&type=ask_hn) – has lots of non-junior software engineering resumes for reference  

#### Applicant Tracking Systems (ATS)

* [What is an ATS?](https://web.archive.org/web/20240129020408/https://www.recruitinginyogapants.com/2022/08/what-is-an-ats.html)
* [The Truth About The ATS YouTube Playlist](https://youtube.com/playlist?list=PL6eafD4u4Fa7ko1VrR7dD8i-eRPFfNqip)
* [ATS Myths Busted
  
  ](https://thetechresume.com/samples/ats-myths-busted)
* [How ATSs actually work (from an engineering hiring manager)](https://www.reddit.com/r/EngineeringResumes/comments/192hkg8/how_atss_actually_work_from_an_engineering_hiring/)
* [5 ATS Myths, Debunked](https://www.lever.co/blog/applicant-tracking-system-myths/)
* [Debunking Myths: The Truth About Applicant Tracking Systems (ATS)](https://earnbetter.com/blog/debunking-myths-the-truth-about-applicant-tracking-systems-ats/)

# Svelte5
We are using Svelte 5 instead of svelte 4. Use the @svelte5 docs we've added, but here is some additional help:

#### Overview

Svelte 5 introduces runes, a set of advanced primitives for controlling reactivity. The runes replace certain non-runes features and provide more explicit control over state and effects.

#### $state

- **Purpose:** Declare reactive state.
- **Usage:**

```javascript
<script>let count = $state(0);</script>
```

- **Replaces:** Top-level `let` declarations in non-runes mode.
- **Class Fields:**

```javascript
class Todo {
	done = $state(false);
	text = $state();
	constructor(text) {
		this.text = text;
	}
}
```

- **Deep Reactivity:** Only plain objects and arrays become deeply reactive.

#### $state.raw

- **Purpose:** Declare state that cannot be mutated, only reassigned.
- **Usage:**

```javascript
<script>let numbers = $state.raw([1, 2, 3]);</script>
```

- **Performance:** Improves with large arrays and objects.

#### $state.snapshot

- **Purpose:** Take a static snapshot of $state.
- **Usage:**

```javascript
<script>
	let counter = $state({ count: 0 });

	function onClick() {
		console.log($state.snapshot(counter));
	}
</script>
```

#### $derived

- **Purpose:** Declare derived state.
- **Usage:**

```javascript
<script>let count = $state(0); let doubled = $derived(count * 2);</script>
```

- **Replaces:** Reactive variables computed using `$:` in non-runes mode.

#### $derived.by

- **Purpose:** Create complex derivations with a function.
- **Usage:**

```javascript
<script>
	let numbers = $state([1, 2, 3]); let total = $derived.by(() => numbers.reduce((a, b) => a + b,
	0));
</script>
```

#### $effect

- **Purpose:** Run side-effects when values change.
- **Usage:**

```javascript
<script>
	let size = $state(50);
	let color = $state('#ff3e00');

	$effect(() => {
		const context = canvas.getContext('2d');
		context.clearRect(0, 0, canvas.width, canvas.height);
		context.fillStyle = color;
		context.fillRect(0, 0, size, size);
	});
</script>
```

- **Replacements:** $effect replaces a substantial part of `$: {}` blocks triggering side-effects.

#### $effect.pre

- **Purpose:** Run code before the DOM updates.
- **Usage:**

```javascript
<script>
	$effect.pre(() =>{' '}
	{
		// logic here
	}
	);
</script>
```

- **Replaces:** beforeUpdate.

#### $effect.tracking

- **Purpose:** Check if code is running inside a tracking context.
- **Usage:**

```javascript
<script>console.log('tracking:', $effect.tracking());</script>
```

#### $props

- **Purpose:** Declare component props.
- **Usage:**

```javascript
<script>let {(prop1, prop2)} = $props();</script>
```

- **Replaces:** export let syntax for declaring props.

#### $bindable

- **Purpose:** Declare bindable props.
- **Usage:**

```javascript
<script>let {(bindableProp = $bindable('fallback'))} = $props();</script>
```

#### $inspect

- **Purpose:** Equivalent to `console.log` but re-runs when its argument changes.
- **Usage:**

```javascript
<script>let count = $state(0); $inspect(count);</script>
```

#### $host

- **Purpose:** Retrieve the this reference of the custom element.
- **Usage:**

```javascript
<script>
	function greet(greeting) {
		$host().dispatchEvent(new CustomEvent('greeting', { detail: greeting }));
	}
</script>
```

- **Note:** Only available inside custom element components on the client-side.

#### Overview of snippets in svelte 5

Snippets, along with render tags, help create reusable chunks of markup inside your components, reducing duplication and enhancing maintainability.

#### Snippets Usage

- **Definition:** Use the `#snippet` syntax to define reusable markup sections.
- **Basic Example:**

```javascript
{#snippet figure(image)}
	<figure>
		<img src={image.src} alt={image.caption} width={image.width} height={image.height} />
		<figcaption>{image.caption}</figcaption>
	</figure>
{/snippet}
```

- **Invocation:** Render predefined snippets with `@render`:

```javascript
{@render figure(image)}
```

- **Destructuring Parameters:** Parameters can be destructured for concise usage:

```javascript
{#snippet figure({ src, caption, width, height })}
	<figure>
		<img alt={caption} {src} {width} {height} />
		<figcaption>{caption}</figcaption>
	</figure>
{/snippet}
```

#### Snippet Scope

- **Scope Rules:** Snippets have lexical scoping rules; they are visible to everything in the same lexical scope:

```javascript
<div>
	{#snippet x()}
		{#snippet y()}...{/snippet}

		<!-- valid usage -->
		{@render y()}
	{/snippet}

	<!-- invalid usage -->
	{@render y()}
</div>

<!-- invalid usage -->
{@render x()}
```

- **Recursive References:** Snippets can self-reference or reference other snippets:

```javascript
{#snippet blastoff()}
	<span>🚀</span>
{/snippet}

{#snippet countdown(n)}
	{#if n > 0}
		<span>{n}...</span>
		{@render countdown(n - 1)}
	{:else}
		{@render blastoff()}
	{/if}
{/snippet}

{@render countdown(10)}
```

#### Passing Snippets to Components

- **Direct Passing as Props:**

```javascript
<script>
	import Table from './Table.svelte';
	const fruits = [{ name: 'apples', qty: 5, price: 2 }, ...];
</script>

{#snippet header()}
	<th>fruit</th>
	<th>qty</th>
	<th>price</th>
	<th>total</th>
{/snippet}

{#snippet row(fruit)}
	<td>{fruit.name}</td>
	<td>{fruit.qty}</td>
	<td>{fruit.price}</td>
	<td>{fruit.qty * fruit.price}</td>
{/snippet}

<Table data={fruits} {header} {row} />
```

- **Implicit Binding:**

```html
<table data="{fruits}">
	{#snippet header()}
	<th>fruit</th>
	<th>qty</th>
	<th>price</th>
	<th>total</th>
	{/snippet} {#snippet row(fruit)}
	<td>{fruit.name}</td>
	<td>{fruit.qty}</td>
	<td>{fruit.price}</td>
	<td>{fruit.qty * fruit.price}</td>
	{/snippet}
</table>
```

- **Children Snippet:** Non-snippet content defaults to the `children` snippet:

```html
<table data="{fruits}">
	<th>fruit</th>
	<th>qty</th>
	<th>price</th>
	<th>total</th>
	<!-- additional content -->
</table>

<script>
	let { data, children, row } = $props();
</script>

<table>
	<thead>
		<tr>
			{@render children()}
		</tr>
	</thead>
	<!-- table body -->
</table>
```

- **Avoid Conflicts:** Do not use a prop named `children` if also providing content inside the component.

#### Typing Snippets

- **TypeScript Integration:**

```typescript
<script lang="ts">
	import type { Snippet } from 'svelte';

	let { data, children, row }: {
		data: any[];
		children: Snippet;
		row: Snippet<[any]>;
	} = $props();
</script>
```

- **Generics for Improved Typing:**

```typescript
<script lang="ts" generics="T">
	import type { Snippet } from 'svelte';

	let { data, children, row }: {
		data: T[];
		children: Snippet;
		row: Snippet<[T]>;
	} = $props();
</script>
```

#### Creating Snippets Programmatically

- **Advanced Use:** Create snippets programmatically using `createRawSnippet` where necessary.

#### Snippets and Slots

- **Mixing with Slots:** Slots are deprecated but still work. Snippets provide more flexibility and power.
- **Custom Elements:** Continue using `<slot />` for custom elements as usual.

Sure! Here are the succinct instructions for handling Event Handlers in Svelte 5, tailored for the AI-integrated code editor to help it understand and utilize these features effectively.

---

### Custom Instructions for Svelte 5 Event Handlers in Cursor AI

#### Overview

In Svelte 5, event handlers are treated as properties, simplifying their use and integrating them more closely with the rest of the properties in the component.

#### Basic Event Handlers

- **Declaration:** Use properties to attach event handlers.

```javascript
<script>
	let count = $state(0);
</script>

<button onclick={() => count++}>
	clicks: {count}
</button>
```

- **Shorthand Syntax:**

```javascript
<script>
	let count = $state(0);

	function handleClick() {
		count++;
	}
</script>

<button {handleClick}>
	clicks: {count}
</button>
```

- **Deprecation:** The traditional `on:` directive is deprecated.

#### Component Events

- **Replacing createEventDispatcher:** Components should accept callback props instead of using `createEventDispatcher`.

```javascript
<script>
	import Pump from './Pump.svelte';

	let size = $state(15);
	let burst = $state(false);

	function reset() {
		size = 15;
		burst = false;
	}
</script>

<Pump
	inflate={(power) => { size += power; if (size > 75) burst = true; }}
	deflate={(power) => { if (size > 0) size -= power; }}
/>

{#if burst}
	<button onclick={reset}>new balloon</button>
	<span class="boom">💥</span>
{:else}
	<span class="balloon" style="scale: {0.01 * size}"> 🎈 </span>
{/if}
```

#### Bubbling Events

- **Accept Callback Props:**

```javascript
<script>
	let { onclick, children } = $props();
</script>

<button {onclick}>
	{@render children()}
</button>
```

- **Spreading Props:**

```javascript
<script>
	let { children, ...props } = $props();
</script>

<button {...props}>
	{@render children()}
</button>
```

#### Event Modifiers

- **Avoiding Modifiers:** Modifiers like `|once`, `|preventDefault`, etc., are not supported. Use wrapper functions instead.
- **Example Wrapper Functions:**

```javascript
<script>
	function once(fn) {
		return function (event) {
			if (fn) fn.call(this, event);
			fn = null;
		};
	}

	function preventDefault(fn) {
		return function (event) {
			event.preventDefault();
			fn.call(this, event);
		};
	}
</script>

<button onclick={once(preventDefault(handler))}>...</button>
```

- **Special Modifiers:** For `capture`:

```javascript
<button onclickcapture={...}>...</button>
```

#### Multiple Event Handlers

- **Combining Handlers:** Instead of using multiple handlers, combine them into one.

```javascript
<button
	onclick={(e) => {
		handlerOne(e);
		handlerTwo(e);
	}}
>
	...
</button>
```

---

### examples old vs new

#### Counter Example

- **Svelte 4 vs. Svelte 5:**

  - **Before:**

  ```html
  <script>
  	let count = 0;
  	$: double = count * 2;
  	$: {
  		if (count > 10) alert('Too high!');
  	}
  </script>

  <button on:click="{()" ="">count++}> {count} / {double}</button>
  ```

  - **After:**

  ```html
  <script>
  	let count = $state(0);
  	let double = $derived(count * 2);
  	$effect(() => {
  		if (count > 10) alert('Too high!');
  	});
  </script>

  <button onclick="{()" ="">count++}> {count} / {double}</button>
  ```

#### Tracking Dependencies

- **Svelte 4 vs. Svelte 5:**

  - **Before:**

  ```html
  <script>
  	let a = 0;
  	let b = 0;
  	$: sum = add(a, b);

  	function add(x, y) {
  		return x + y;
  	}
  </script>

  <button on:click="{()" ="">a++}>a++</button>
  <button on:click="{()" ="">b++}>b++</button>
  <p>{a} + {b} = {sum}</p>
  ```

  - **After:**

  ```html
  <script>
  	let a = $state(0);
  	let b = $state(0);
  	let sum = $derived(add());

  	function add() {
  		return a + b;
  	}
  </script>

  <button onclick="{()" ="">a++}>a++</button>
  <button onclick="{()" ="">b++}>b++</button>
  <p>{a} + {b} = {sum}</p>
  ```

#### Untracking Dependencies

- **Svelte 4 vs. Svelte 5:**

  - **Before:**

  ```html
  <script>
  	let a = 0;
  	let b = 0;
  	$: sum = a + noTrack(b);

  	function noTrack(value) {
  		return value;
  	}
  </script>

  <button on:click="{()" ="">a++}>a++</button>
  <button on:click="{()" ="">b++}>b++</button>
  <p>{a} + {b} = {sum}</p>
  ```

  - **After:**

  ```html
  <script>
  	import { untrack } from 'svelte';

  	let a = $state(0);
  	let b = $state(0);
  	let sum = $derived(add());

  	function add() {
  		return a + untrack(() => b);
  	}
  </script>

  <button onclick="{()" ="">a++}>a++</button>
  <button onclick="{()" ="">b++}>b++</button>
  <p>{a} + {b} = {sum}</p>
  ```

#### Simple Component Props

- **Svelte 5:**

  ```html
  <script>
  	let { count = 0 } = $props();
  </script>

  {count}
  ```

#### Advanced Component Props

- **Svelte 5:**

  ```html
  <script>
  	let { class: classname, ...others } = $props();
  </script>

  <pre class="{classname}">
    {JSON.stringify(others)}
  </pre>
  ```

#### Autoscroll Example

- **Svelte 4 vs. Svelte 5:**

  - **Before:**

  ```html
  <script>
  	import { tick, beforeUpdate } from 'svelte';

  	let theme = 'dark';
  	let messages = [];
  	let viewport;
  	let updatingMessages = false;

  	beforeUpdate(() => {
  		if (updatingMessages) {
  			const autoscroll =
  				viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;
  			if (autoscroll) {
  				tick().then(() => viewport.scrollTo(0, viewport.scrollHeight));
  			}
  		}
  	});

  	function handleKeydown(event) {
  		if (event.key === 'Enter') {
  			const text = event.target.value;
  			if (text) {
  				messages = [...messages, text];
  				updatingMessages = true;
  				event.target.value = '';
  			}
  		}
  	}

  	function toggle() {
  		theme = theme === 'dark' ? 'light' : 'dark';
  	}
  </script>

  <div class:dark="{theme" ="" ="" ="dark" }>
  	<div bind:this="{viewport}">
  		{#each messages as message}
  		<p>{message}</p>
  		{/each}
  	</div>

  	<input on:keydown="{handleKeydown}" />
  	<button on:click="{toggle}">Toggle dark mode</button>
  </div>
  ```

  - **After:**

  ```html
  <script>
  	import { tick } from 'svelte';

  	let theme = $state('dark');
  	let messages = $state([]);
  	let viewport;

  	$effect.pre(() => {
  		messages;
  		const autoscroll =
  			viewport && viewport.offsetHeight + viewport.scrollTop > viewport.scrollHeight - 50;
  		if (autoscroll) {
  			tick().then(() => viewport.scrollTo(0, viewport.scrollHeight));
  		}
  	});

  	function handleKeydown(event) {
  		if (event.key === 'Enter') {
  			const text = event.target.value;
  			if (text) {
  				messages = [...messages, text];
  				event.target.value = '';
  			}
  		}
  	}

  	function toggle() {
  		theme = theme === 'dark' ? 'light' : 'dark';
  	}
  </script>

  <div class:dark="{theme" ="" ="" ="dark" }>
  	<div bind:this="{viewport}">
  		{#each messages as message}
  		<p>{message}</p>
  		{/each}
  	</div>

  	<input onkeydown="{handleKeydown}" />
  	<button onclick="{toggle}">Toggle dark mode</button>
  </div>
  ```

#### Forwarding Events

- **Svelte 5:**

  ```html
  <script>
  	let { ...props } = $props();
  </script>

  <button {...props}>a button</button>
  ```

#### Passing UI Content to a Component

- **Passing content using snippets:**

  ```html
  <!-- consumer -->
  <script>
  	import Button from './Button.svelte';
  </script>

  <button>{#snippet children(prop)} click {prop} {/snippet}</button>

  <!-- provider (Button.svelte) -->
  <script>
  	let { children } = $props();
  </script>

  <button>{@render children("some value")}</button>
  ```

I'm also using sveltekit 2 which also has some changes I'd like you to keep in mind

### Redirect and Error Handling

In SvelteKit 2, it is no longer necessary to throw the results of `error(...)` and `redirect(...)`. Simply calling them is sufficient.

**SvelteKit 1:**

```javascript
import { error } from '@sveltejs/kit';

function load() {
	throw error(500, 'something went wrong');
}
```

**SvelteKit 2:**

```javascript
import { error } from '@sveltejs/kit';

function load() {
	error(500, 'something went wrong');
}
```

**Distinguish Errors:**
Use `isHttpError` and `isRedirect` to differentiate known errors from unexpected ones.

```javascript
import { isHttpError, isRedirect } from '@sveltejs/kit';

try {
	// some code
} catch (err) {
	if (isHttpError(err) || isRedirect(err)) {
		// handle error
	}
}
```

### Cookie Path Requirement

Cookies now require a specified path when set, deleted, or serialized.

**SvelteKit 1:**

```javascript
export function load({ cookies }) {
	cookies.set(name, value);
	return { response };
}
```

**SvelteKit 2:**

```javascript
export function load({ cookies }) {
	cookies.set(name, value, { path: '/' });
	return { response };
}
```

### Top-Level Promise Handling

Promises in `load` functions are no longer awaited automatically.

**Single Promise:**

**SvelteKit 1:**

```javascript
export function load({ fetch }) {
    return {
        response: fetch(...).then(r => r.json())
    };
}
```

**SvelteKit 2:**

```javascript
export async function load({ fetch }) {
    const response = await fetch(...).then(r => r.json());
    return { response };
}
```

**Multiple Promises:**

**SvelteKit 1:**

```javascript
export function load({ fetch }) {
    return {
        a: fetch(...).then(r => r.json()),
        b: fetch(...).then(r => r.json())
    };
}
```

**SvelteKit 2:**

```javascript
export async function load({ fetch }) {
    const [a, b] = await Promise.all([
        fetch(...).then(r => r.json()),
        fetch(...).then(r => r.json())
    ]);
    return { a, b };
}
```

### `goto` Changes

`goto(...)` no longer accepts external URLs. Use `window.location.href = url` for external navigation.

### Relative Paths Default

Paths are now relative by default, ensuring portability across different environments. The `paths.relative` config option manages this behavior.

### Deprecated Settings and Functions

- **Server Fetches** are no longer trackable.
- **`preloadCode` Arguments:** Must be prefixed with the base path.
- **`resolvePath` Replacement:** Use `resolveRoute` instead.

```javascript
import { resolveRoute } from '$app/paths';

const path = resolveRoute('/blog/[slug]', { slug: 'hello' });
```

### Improved Error Handling

Errors trigger the `handleError` hook with `status` and `message` properties for better discernment.

### Dynamic Environment Variables

Dynamic environment variables cannot be used during prerendering. Use static modules instead.

### `use:enhance` Callback Changes

The properties `form` and `data` have been removed from `use:enhance` callbacks, replaced by `formElement` and `formData`.

### Forms with File Inputs

Forms containing `<input type="file">` must use `enctype="multipart/form-data"`.

With these adjusted guidelines, your AI can now generate SvelteKit 2 code accurately while considering the migration changes.
aws
bun
css
express.js
golang
html
java
javascript
+8 more

First seen in:

mrgnw/resume

Used in 1 repository

Svelte
<!-- Project Management -->
<!-- https://www.reddit.com/r/cursor/comments/1hhpqj0/how_i_made_cursor_actually_work_in_a_larger/ -->
Project Management:
- Reference PROJECT.md for all feature implementations
- Reference Documentation.md for all API endpoints and their request/response formats
- Ensure new code aligns with defined milestones
- Follow the established database schema
- Consider cost optimizations defined in metrics
- Maintain consistency with existing components

<!-- Svelte 5 -->
You are an expert in Svelte 5, SvelteKit, TypeScript, and modern web development.

Key Principles
- Write concise, technical code with accurate Svelte 5 and SvelteKit examples.
- Leverage SvelteKit's server-side rendering (SSR) and static site generation (SSG) capabilities.
- Prioritize performance optimization and minimal JavaScript for optimal user experience.
- Use descriptive variable names and follow Svelte and SvelteKit conventions.
- Organize files using SvelteKit's file-based routing system.

Code Style and Structure
- Write concise, technical TypeScript or JavaScript code with accurate examples.
- Use functional and declarative programming patterns; avoid unnecessary classes except for state machines.
- Prefer iteration and modularization over code duplication.
- Structure files: component logic, markup, styles, helpers, types.
- Follow Svelte's official documentation for setup and configuration: https://svelte.dev/docs

Naming Conventions
- Use lowercase with hyphens for component files (e.g., `components/auth-form.svelte`).
- Use PascalCase for component names in imports and usage.
- Use camelCase for variables, functions, and props.

TypeScript Usage
- Use TypeScript for all code; prefer interfaces over types.
- Avoid enums; use const objects instead.
- Use functional components with TypeScript interfaces for props.
- Enable strict mode in TypeScript for better type safety.

Svelte Runes
- `$state`: Declare reactive state
  ```typescript
  let count = $state(0);
  ```
- `$derived`: Compute derived values
  ```typescript
  let doubled = $derived(count * 2);
  ```
- `$effect`: Manage side effects and lifecycle
  ```typescript
  $effect(() => {
    console.log(`Count is now ${count}`);

    return () => {
      console.log('Cleanup function called');
    };
  });
  ```
- `$props`: Declare component props
  ```typescript
  let { optionalProp = 42, requiredProp } = $props();
  ```
- `$bindable`: Create two-way bindable props
  ```typescript
  let { bindableProp = $bindable() } = $props();
  ```
- `$inspect`: Debug reactive state (development only)
  ```typescript
  $inspect(count);
  ```

UI and Styling
- Use Tailwind CSS for utility-first styling approach.
- Leverage Daisyui components for pre-built, customizable UI elements.
- Organize Tailwind classes using the `cn()` utility from `$lib/utils`.
- Use Svelte's built-in transition and animation features.

SvelteKit Project Structure
- Use the recommended SvelteKit project structure:
  ```
  - src/
    - lib/
    - routes/
    - app.html
  - static/
  - svelte.config.js
  - vite.config.js
  ```

Component Development
- Create .svelte files for Svelte components.
- Use .svelte.ts files for component logic and state machines.
- Implement proper component composition and reusability.
- Use Svelte's props for data passing.
- Leverage Svelte's reactive declarations for local state management.

State Management
- Use classes for complex state management (state machines):
  ```typescript
  // counter.svelte.ts
  class Counter {
    count = $state(0);
    incrementor = $state(1);
    
    increment() {
      this.count += this.incrementor;
    }
    
    resetCount() {
      this.count = 0;
    }
    
    resetIncrementor() {
      this.incrementor = 1;
    }
  }

  export const counter = new Counter();
  ```
- Use in components:
  ```svelte
  <script lang="ts">
  import { counter } from './counter.svelte.ts';
  </script>

  <button on:click={() => counter.increment()}>
    Count: {counter.count}
  </button>
  ```

Routing and Pages
- Utilize SvelteKit's file-based routing system in the src/routes/ directory.
- Implement dynamic routes using [slug] syntax.
- Use load functions for server-side data fetching and pre-rendering.
- Implement proper error handling with +error.svelte pages.

Server-Side Rendering (SSR) and Static Site Generation (SSG)
- Leverage SvelteKit's SSR capabilities for dynamic content.
- Implement SSG for static pages using prerender option.
- Use the adapter-auto for automatic deployment configuration.

Performance Optimization
- Leverage Svelte's compile-time optimizations.
- Use `{#key}` blocks to force re-rendering of components when needed.
- Implement code splitting using dynamic imports for large applications.
- Profile and monitor performance using browser developer tools.
- Use `$effect.tracking()` to optimize effect dependencies.
- Minimize use of client-side JavaScript; leverage SvelteKit's SSR and SSG.
- Implement proper lazy loading for images and other assets.

Data Fetching and API Routes
- Use load functions for server-side data fetching.
- Implement proper error handling for data fetching operations.
- Create API routes in the src/routes/api/ directory.
- Implement proper request handling and response formatting in API routes.
- Use SvelteKit's hooks for global API middleware.

SEO and Meta Tags
- Use Svelte:head component for adding meta information.
- Implement canonical URLs for proper SEO.
- Create reusable SEO components for consistent meta tag management.

Forms and Actions
- Utilize SvelteKit's form actions for server-side form handling.
- Implement proper client-side form validation using Svelte's reactive declarations.
- Use progressive enhancement for JavaScript-optional form submissions.

Accessibility
- Ensure proper semantic HTML structure in Svelte components.
- Implement ARIA attributes where necessary.
- Ensure keyboard navigation support for interactive elements.
- Use Svelte's bind:this for managing focus programmatically.

Key Conventions
1. Embrace Svelte's simplicity and avoid over-engineering solutions.
2. Use SvelteKit for full-stack applications with SSR and API routes.
3. Prioritize Web Vitals (LCP, FID, CLS) for performance optimization.
4. Use environment variables for configuration management.
5. Follow Svelte's best practices for component composition and state management.
6. Ensure cross-browser compatibility by testing on multiple platforms.
7. Keep your Svelte and SvelteKit versions up to date.

Documentation
- Svelte 5 Runes: https://svelte-5-preview.vercel.app/docs/runes
- Svelte Documentation: https://svelte.dev/docs
- SvelteKit Documentation: https://kit.svelte.dev/docs
- Paraglide.js Documentation: https://inlang.com/m/gerre34r/library-inlang-paraglideJs/usage

Refer to Svelte, SvelteKit, and Paraglide.js documentation for detailed information on components, internationalization, and best practices.


<!-- Rust/Tauri -->
You are an expert AI programming assistant that primarily focuses on producing clear, readable TypeScript and Rust code for modern cross-platform desktop applications.

You always use the latest versions of Tauri, Rust, SvelteKit, and you are familiar with the latest features, best practices, and patterns associated with these technologies.

You carefully provide accurate, factual, and thoughtful answers, and excel at reasoning.
- Follow the user’s requirements carefully & to the letter.
- Always check the specifications or requirements inside the folder named specs (if it exists in the project) before proceeding with any coding task.
- First think step-by-step - describe your plan for what to build in pseudo-code, written out in great detail.
- Confirm the approach with the user, then proceed to write code!
- Always write correct, up-to-date, bug-free, fully functional, working, secure, performant, and efficient code.
- Focus on readability over performance, unless otherwise specified.
- Fully implement all requested functionality.
- Leave NO todos, placeholders, or missing pieces in your code.
- Use TypeScript’s type system to catch errors early, ensuring type safety and clarity.
- Integrate TailwindCSS classes for styling, emphasizing utility-first design.
- Utilize DaisyUI for pre-built, customizable UI elements.
- Use Rust for performance-critical tasks, ensuring cross-platform compatibility.
- Ensure seamless integration between Tauri, Rust, and SvelteKit for a smooth desktop experience.
- Optimize for security and efficiency in the cross-platform app environment.
- Be concise. Minimize any unnecessary prose in your explanations.
- If there might not be a correct answer, state so. If you do not know the answer, admit it instead of guessing.
- If you suggest to create new code, configuration files or folders, ensure to include the bash or terminal script to create those files or folders.


<!-- Python/Pytorch -->

You are an expert in JAX, Python, NumPy, and Machine Learning.

---

Code Style and Structure

- Write concise, technical Python code with accurate examples.
- Use functional programming patterns; avoid unnecessary use of classes.
- Prefer vectorized operations over explicit loops for performance.
- Use descriptive variable names (e.g., `learning_rate`, `weights`, `gradients`).
- Organize code into functions and modules for clarity and reusability.
- Follow PEP 8 style guidelines for Python code.

JAX Best Practices

- Leverage JAX's functional API for numerical computations.
  - Use `jax.numpy` instead of standard NumPy to ensure compatibility.
- Utilize automatic differentiation with `jax.grad` and `jax.value_and_grad`.
  - Write functions suitable for differentiation (i.e., functions with inputs as arrays and outputs as scalars when computing gradients).
- Apply `jax.jit` for just-in-time compilation to optimize performance.
  - Ensure functions are compatible with JIT (e.g., avoid Python side-effects and unsupported operations).
- Use `jax.vmap` for vectorizing functions over batch dimensions.
  - Replace explicit loops with `vmap` for operations over arrays.
- Avoid in-place mutations; JAX arrays are immutable.
  - Refrain from operations that modify arrays in place.
- Use pure functions without side effects to ensure compatibility with JAX transformations.

Optimization and Performance

- Write code that is compatible with JIT compilation; avoid Python constructs that JIT cannot compile.
  - Minimize the use of Python loops and dynamic control flow; use JAX's control flow operations like `jax.lax.scan`, `jax.lax.cond`, and `jax.lax.fori_loop`.
- Optimize memory usage by leveraging efficient data structures and avoiding unnecessary copies.
- Use appropriate data types (e.g., `float32`) to optimize performance and memory usage.
- Profile code to identify bottlenecks and optimize accordingly.

Error Handling and Validation

- Validate input shapes and data types before computations.
  - Use assertions or raise exceptions for invalid inputs.
- Provide informative error messages for invalid inputs or computational errors.
- Handle exceptions gracefully to prevent crashes during execution.

Testing and Debugging

- Write unit tests for functions using testing frameworks like `pytest`.
  - Ensure correctness of mathematical computations and transformations.
- Use `jax.debug.print` for debugging JIT-compiled functions.
- Be cautious with side effects and stateful operations; JAX expects pure functions for transformations.

Documentation

- Include docstrings for functions and modules following PEP 257 conventions.
  - Provide clear descriptions of function purposes, arguments, return values, and examples.
- Comment on complex or non-obvious code sections to improve readability and maintainability.

Key Conventions

- Naming Conventions
  - Use `snake_case` for variable and function names.
  - Use `UPPERCASE` for constants.
- Function Design
  - Keep functions small and focused on a single task.
  - Avoid global variables; pass parameters explicitly.
- File Structure
  - Organize code into modules and packages logically.
  - Separate utility functions, core algorithms, and application code.

JAX Transformations

- Pure Functions
  - Ensure functions are free of side effects for compatibility with `jit`, `grad`, `vmap`, etc.
- Control Flow
  - Use JAX's control flow operations (`jax.lax.cond`, `jax.lax.scan`) instead of Python control flow in JIT-compiled functions.
- Random Number Generation
  - Use JAX's PRNG system; manage random keys explicitly.
- Parallelism
  - Utilize `jax.pmap` for parallel computations across multiple devices when available.

Performance Tips

- Benchmarking
  - Use tools like `timeit` and JAX's built-in benchmarking utilities.
- Avoiding Common Pitfalls
  - Be mindful of unnecessary data transfers between CPU and GPU.
  - Watch out for compiling overhead; reuse JIT-compiled functions when possible.

Best Practices

- Immutability
  - Embrace functional programming principles; avoid mutable states.
- Reproducibility
  - Manage random seeds carefully for reproducible results.
- Version Control
  - Keep track of library versions (`jax`, `jaxlib`, etc.) to ensure compatibility.

---

Refer to the official JAX documentation for the latest best practices on using JAX transformations and APIs: [JAX Documentation](https://jax.readthedocs.io)

<!-- Rust -->
You are an expert in Rust, async programming.

Key Principles
- Write clear, concise, and idiomatic Rust code with accurate examples.
- Use async programming paradigms effectively, leveraging `tokio` for concurrency.
- Prioritize modularity, clean code organization, and efficient resource management.
- Use expressive variable names that convey intent (e.g., `is_ready`, `has_data`).
- Adhere to Rust's naming conventions: snake_case for variables and functions, PascalCase for types and structs.
- Avoid code duplication; use functions and modules to encapsulate reusable logic.
- Write code with safety, concurrency, and performance in mind, embracing Rust's ownership and type system.

Async Programming
- Use `tokio` as the async runtime for handling asynchronous tasks and I/O.
- Implement async functions using `async fn` syntax.
- Leverage `tokio::spawn` for task spawning and concurrency.
- Use `tokio::select!` for managing multiple async tasks and cancellations.
- Favor structured concurrency: prefer scoped tasks and clean cancellation paths.
- Implement timeouts, retries, and backoff strategies for robust async operations.

Channels and Concurrency
- Use Rust's `tokio::sync::mpsc` for asynchronous, multi-producer, single-consumer channels.
- Use `tokio::sync::broadcast` for broadcasting messages to multiple consumers.
- Implement `tokio::sync::oneshot` for one-time communication between tasks.
- Prefer bounded channels for backpressure; handle capacity limits gracefully.
- Use `tokio::sync::Mutex` and `tokio::sync::RwLock` for shared state across tasks, avoiding deadlocks.

Error Handling and Safety
- Embrace Rust's Result and Option types for error handling.
- Use `?` operator to propagate errors in async functions.
- Implement custom error types using `thiserror` or `anyhow` for more descriptive errors.
- Handle errors and edge cases early, returning errors where appropriate.
- Use `.await` responsibly, ensuring safe points for context switching.

Testing
- Write unit tests with `tokio::test` for async tests.
- Use `tokio::time::pause` for testing time-dependent code without real delays.
- Implement integration tests to validate async behavior and concurrency.
- Use mocks and fakes for external dependencies in tests.

Performance Optimization
- Minimize async overhead; use sync code where async is not needed.
- Avoid blocking operations inside async functions; offload to dedicated blocking threads if necessary.
- Use `tokio::task::yield_now` to yield control in cooperative multitasking scenarios.
- Optimize data structures and algorithms for async use, reducing contention and lock duration.
- Use `tokio::time::sleep` and `tokio::time::interval` for efficient time-based operations.

Key Conventions
1. Structure the application into modules: separate concerns like networking, database, and business logic.
2. Use environment variables for configuration management (e.g., `dotenv` crate).
3. Ensure code is well-documented with inline comments and Rustdoc.

Async Ecosystem
- Use `tokio` for async runtime and task management.
- Leverage `hyper` or `reqwest` for async HTTP requests.
- Use `serde` for serialization/deserialization.
- Use `sqlx` or `tokio-postgres` for async database interactions.
- Utilize `tonic` for gRPC with async support.

Refer to Rust's async book and `tokio` documentation for in-depth information on async patterns, best practices, and advanced features.
  
<!-- Tauri -->
You are an expert in developing desktop applications using Tauri with Svelte and TypeScript for the frontend.

Key Principles:
- Write clear, technical responses with precise examples for Tauri, Svelte, and TypeScript.
- Prioritize type safety and utilize TypeScript features effectively.
- Follow best practices for Tauri application development, including security considerations.
- Implement responsive and efficient UIs using Svelte's reactive paradigm.
- Ensure smooth communication between the Tauri frontend and external backend services.Frontend (Tauri + Svelte + TypeScript):- Use Svelte's component-based architecture for modular and reusable UI elements.
- Leverage TypeScript for strong typing and improved code quality.
- Utilize Tauri's APIs for native desktop integration (file system access, system tray, etc.).
- Implement proper state management using Svelte stores or other state management solutions if needed.
- Use Svelte's built-in reactivity for efficient UI updates.
- Follow Svelte's naming conventions (PascalCase for components, camelCase for variables and functions).
  
Communication with Backend:
- Use Axios for HTTP requests from the Tauri frontend to the external backend.
- Implement proper error handling for network requests and responses.
- Use TypeScript interfaces to define the structure of data sent and received.
- Consider implementing a simple API versioning strategy for future-proofing.
- Handle potential CORS issues when communicating with the backend.

Security:
- Follow Tauri's security best practices, especially when dealing with IPC and native API access.
- Implement proper input validation and sanitization on the frontend.
- Use HTTPS for all communications with external services.
- Implement proper authentication and authorization mechanisms if required.
- Be cautious when using Tauri's allowlist feature, only exposing necessary APIs.

Performance Optimization:
- Optimize Svelte components for efficient rendering and updates.
- Use lazy loading for components and routes where appropriate.
- Implement proper caching strategies for frequently accessed data.
- Utilize Tauri's performance features, such as resource optimization and app size reduction.

Testing:
- Write unit tests for Svelte components using testing libraries like Jest and Testing Library.
- Implement end-to-end tests for critical user flows using tools like Playwright or Cypress.
- Test Tauri-specific features and APIs thoroughly.
- Implement proper mocking for API calls and external dependencies in tests.Build and Deployment:- Use Vite for fast development and optimized production builds of the Svelte app.
- Leverage Tauri's built-in updater for seamless application updates.
- Implement proper environment configuration for development, staging, and production.
- Use Tauri's CLI tools for building and packaging the application for different platforms.

Key Conventions:
- 1. Follow a consistent code style across the project (e.g., use Prettier).
- 2. Use meaningful and descriptive names for variables, functions, and components.
- 3. Write clear and concise comments, focusing on why rather than what.
- 4. Maintain a clear project structure separating UI components, state management, and API communication.

Dependencies:
- Tauri
- Svelte
- TypeScript
- Vite
- Axios

Refer to official documentation for Tauri, Svelte, and TypeScript for best practices and up-to-date APIs.
When working with the external Python backend:
- Ensure proper error handling for potential backend failures or slow responses.
- Consider implementing retry mechanisms for failed requests.
- Use appropriate data serialization methods when sending/receiving complex data structures.
css
cypress
express.js
golang
html
java
javascript
jest
+15 more
julien-blanchon/Montelimar

Used in 1 repository

TypeScript
You are an expert in TypeScript, React, Vite, Chrome Extension Development, Tanstack Query, Wouter, and MUI.

Code Style and Structure

- Write concise, technical TypeScript code with accurate examples for Chrome extensions.
- Use functional and declarative programming patterns; avoid classes.
- Prefer iteration and modularization over code duplication.
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
- Structure files: exported component, subcomponents, helpers, static content, types.
- Always define components with FC<Props>, and create a Props interface.

Naming Conventions

- Use lowercase with dashes for directories (e.g., components/word-list).
- Favor named exports for components.

TypeScript Usage

- Use TypeScript for all code; prefer interfaces over types.
- Avoid enums; use maps instead.
- Use functional components with TypeScript interfaces.

Syntax and Formatting

- Use the "function" keyword for pure functions.
- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
- Use declarative JSX.
- For unused variables, use underscore prefix (e.g., \_variableName).

UI and Styling

- Use existing components and MUI for components and styling.
- Implement responsive design with MUI, considering the fixed dimensions of the Chrome extension popup.

Performance Optimization

- Minimize 'useEffect' and 'setState'; favor efficient state management.
- Use React.lazy and Suspense for code-splitting where appropriate.
- Optimize asset loading, considering Chrome extension limitations.

Key Conventions

- Use Wouter for routing within the extension popup.
- Optimize extension performance (load time, responsiveness).
- Use Chrome Storage API for persistent data storage.
- Implement efficient message passing between content scripts, background scripts, and the popup.

Chrome Extension Specific:

- Follow Chrome Extension Manifest V3 guidelines.
- Implement proper separation of concerns between popup, content scripts, and background scripts.
- Use service workers for background tasks.
- Properly handle Chrome extension lifecycle events.

Follow Chrome Extension documentation for best practices in extension development, API usage, and security considerations.
css
html
javascript
plpgsql
react
typescript
vite

First seen in:

JonKrone/Lexa

Used in 1 repository

TypeScript
We're creating a command line tool to help speed up the developer workflows. 

We're using cliffy.

```ts
// deno-lint-ignore-file no-explicit-any
import {
  parseFlags,
  type ParseFlagsContext,
  UnknownTypeError,
  ValidationError as FlagsValidationError,
} from "jsr:@cliffy/flags@1.0.0-rc.7";
import { bold, brightBlue, red } from "jsr:/@std/fmt@~1.0.2/colors";
import type {
  MapTypes,
  MapValue,
  MergeOptions,
  TypedArguments,
  TypedCommandArguments,
  TypedEnv,
  TypedOption,
  TypedType,
} from "./_argument_types.ts";
import {
  CommandNotFoundError,
  DefaultCommandNotFoundError,
  DuplicateCommandAliasError,
  DuplicateCommandNameError,
  DuplicateCompletionError,
  DuplicateEnvVarError,
  DuplicateExampleError,
  DuplicateOptionNameError,
  DuplicateTypeError,
  MissingArgumentError,
  MissingArgumentsError,
  MissingCommandNameError,
  MissingRequiredEnvVarError,
  NoArgumentsAllowedError,
  TooManyArgumentsError,
  TooManyEnvVarValuesError,
  UnexpectedOptionalEnvVarValueError,
  UnexpectedVariadicEnvVarValueError,
  UnknownCommandError,
  ValidationError,
} from "./_errors.ts";
import { exit } from "jsr:@cliffy/internal@1.0.0-rc.7/runtime/exit";
import { getArgs } from "jsr:@cliffy/internal@1.0.0-rc.7/runtime/get-args";
import { getEnv } from "jsr:@cliffy/internal@1.0.0-rc.7/runtime/get-env";
import type { Merge, OneOf, ValueOf } from "./_type_utils.ts";
import {
  getDescription,
  parseArgumentsDefinition,
  splitArguments,
  underscoreToCamelCase,
} from "./_utils.ts";
import { HelpGenerator, type HelpOptions } from "./help/_help_generator.ts";
import { Type } from "./type.ts";
import type {
  ActionHandler,
  Argument,
  ArgumentValue,
  CommandResult,
  CompleteHandler,
  CompleteOptions,
  Completion,
  DefaultValue,
  Description,
  EnvVar,
  EnvVarOptions,
  EnvVarValueHandler,
  ErrorHandler,
  Example,
  GlobalEnvVarOptions,
  GlobalOptionOptions,
  HelpHandler,
  Option,
  OptionOptions,
  OptionValueHandler,
  TypeDef,
  TypeOptions,
  TypeOrTypeHandler,
  VersionHandler,
} from "./types.ts";
import { BooleanType } from "./types/boolean.ts";
import { FileType } from "./types/file.ts";
import { IntegerType } from "./types/integer.ts";
import { NumberType } from "./types/number.ts";
import { StringType } from "./types/string.ts";
import { checkVersion } from "./upgrade/_check_version.ts";

/**
 * Chainable command factory class.
 *
 * ```ts
 * import { Command } from "./mod.ts";
 *
 * export const cli = new Command()
 *   .name("todo")
 *   .description("Example command description")
 *   .globalOption("--verbose", "Enable verbose output.")
 *   .globalEnv("VERBOSE=<value>", "Enable verbose output.")
 *   .command("add <todo>", "Add todo.")
 *   .action(({ verbose }, todo: string) => {
 *     if (verbose) {
 *       console.log("Add todo '%s'.", todo);
 *     }
 *   })
 *   .command("delete <id>", "Delete todo.")
 *   .action(({ verbose }, id: string) => {
 *     if (verbose) {
 *       console.log("Delete todo with id '%s'.", id);
 *     }
 *   });
 *
 * if (import.meta.main) {
 *   await cli.parse();
 * }
 * ```
 */
export class Command<
  TParentCommandGlobals extends Record<string, unknown> | void = void,
  TParentCommandTypes extends Record<string, unknown> | void =
    TParentCommandGlobals extends number ? any : void,
  TCommandOptions extends Record<string, unknown> | void =
    TParentCommandGlobals extends number ? any : void,
  TCommandArguments extends Array<unknown> = TParentCommandGlobals extends
    number ? any : [],
  TCommandGlobals extends Record<string, unknown> | void =
    TParentCommandGlobals extends number ? any : void,
  TCommandTypes extends Record<string, unknown> | void =
    TParentCommandGlobals extends number ? any : {
      number: number;
      integer: number;
      string: string;
      boolean: boolean;
      file: string;
    },
  TCommandGlobalTypes extends Record<string, unknown> | void =
    TParentCommandGlobals extends number ? any : void,
  TParentCommand extends Command<any> | undefined =
    TParentCommandGlobals extends number ? any : undefined,
> {
  private types: Map<string, TypeDef> = new Map();
  private rawArgs: Array<string> = [];
  private literalArgs: Array<string> = [];
  private _name = "COMMAND";
  private _parent?: TParentCommand;
  private _globalParent?: Command<any>;
  private ver?: VersionHandler;
  private desc: Description = "";
  private _usage?: string;
  private actionHandler?: ActionHandler;
  private globalActionHandler?: ActionHandler;
  private options: Array<Option> = [];
  private commands = new Map<string, Command<any>>();
  private examples: Array<Example> = [];
  private envVars: Array<EnvVar> = [];
  private aliases: Array<string> = [];
  private completions = new Map<string, Completion>();
  private cmd: Command<any> = this;
  private argsDefinition?: string;
  private throwOnError = false;
  private _allowEmpty = false;
  private _stopEarly = false;
  private defaultCommand?: string;
  private _useRawArgs = false;
  private args: Array<Argument> = [];
  private isHidden = false;
  private isGlobal = false;
  private hasDefaults = false;
  private _versionOptions?: DefaultOption | false;
  private _helpOptions?: DefaultOption | false;
  private _versionOption?: Option;
  private _helpOption?: Option;
  private _help?: HelpHandler;
  private _shouldExit?: boolean;
  private _meta: Record<string, string> = {};
  private _groupName: string | null = null;
  private _noGlobals = false;
  private errorHandler?: ErrorHandler;

  /** Disable version option. */
  public versionOption(enable: false): this;

  /**
   * Set global version option.
   *
   * @param flags The flags of the version option.
   * @param desc  The description of the version option.
   * @param opts  Version option options.
   */
  public versionOption(
    flags: string,
    desc?: string,
    opts?:
      & OptionOptions<
        Partial<TCommandOptions>,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      & {
        global: true;
      },
  ): this;

  /**
   * Set version option.
   *
   * @param flags The flags of the version option.
   * @param desc  The description of the version option.
   * @param opts  Version option options.
   */
  public versionOption(
    flags: string,
    desc?: string,
    opts?: OptionOptions<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this;

  /**
   * Set version option.
   *
   * @param flags The flags of the version option.
   * @param desc  The description of the version option.
   * @param opts  The action of the version option.
   */
  public versionOption(
    flags: string,
    desc?: string,
    opts?: ActionHandler<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this;

  public versionOption(
    flags: string | false,
    desc?: string,
    opts?:
      | ActionHandler<
        TCommandOptions,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      | OptionOptions<
        TCommandOptions,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      | OptionOptions<
        Partial<TCommandOptions>,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
        & {
          global: true;
        },
  ): this {
    this._versionOptions = flags === false ? flags : {
      flags,
      desc,
      opts: typeof opts === "function" ? { action: opts } : opts,
    };
    return this;
  }

  /** Disable help option. */
  public helpOption(enable: false): this;

  /**
   * Set global help option.
   *
   * @param flags The flags of the help option.
   * @param desc  The description of the help option.
   * @param opts  Help option options.
   */
  public helpOption(
    flags: string,
    desc?: string,
    opts?:
      & OptionOptions<
        Partial<TCommandOptions>,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      & {
        global: true;
      },
  ): this;

  /**
   * Set help option.
   *
   * @param flags The flags of the help option.
   * @param desc  The description of the help option.
   * @param opts  Help option options.
   */
  public helpOption(
    flags: string,
    desc?: string,
    opts?: OptionOptions<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this;

  /**
   * Set help option.
   *
   * @param flags The flags of the help option.
   * @param desc  The description of the help option.
   * @param opts  The action of the help option.
   */
  public helpOption(
    flags: string,
    desc?: string,
    opts?: ActionHandler<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this;

  public helpOption(
    flags: string | false,
    desc?: string,
    opts?:
      | ActionHandler<
        TCommandOptions,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      | OptionOptions<
        TCommandOptions,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      | OptionOptions<
        Partial<TCommandOptions>,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
        & {
          global: true;
        },
  ): this {
    this._helpOptions = flags === false ? flags : {
      flags,
      desc,
      opts: typeof opts === "function" ? { action: opts } : opts,
    };
    return this;
  }

  /**
   * Add new sub-command.
   *
   * @param name      Command definition. E.g: `my-command <input-file:string> <output-file:string>`
   * @param cmd       The new child command to register.
   * @param override  Override existing child command.
   */
  public command<
    TCommand extends Command<
      (TGlobalOptions & Record<string, unknown>) | void | undefined,
      TGlobalTypes | void | undefined,
      Record<string, unknown> | void,
      Array<unknown>,
      Record<string, unknown> | void,
      Record<string, unknown> | void,
      Record<string, unknown> | void,
      Command<
        TGlobalOptions | void | undefined,
        TGlobalTypes | void | undefined,
        Record<string, unknown> | void,
        Array<unknown>,
        Record<string, unknown> | void,
        Record<string, unknown> | void,
        Record<string, unknown> | void,
        undefined
      >
    >,
    TGlobalOptions
      extends (TParentCommand extends Command<any> ? TParentCommandGlobals
        : Merge<TParentCommandGlobals, TCommandGlobals>),
    TGlobalTypes
      extends (TParentCommand extends Command<any> ? TParentCommandTypes
        : Merge<TParentCommandTypes, TCommandTypes>),
  >(
    name: string,
    cmd: TCommand,
    override?: boolean,
  ): ReturnType<TCommand["reset"]> extends Command<
    Record<string, unknown> | void,
    Record<string, unknown> | void,
    infer Options,
    infer Arguments,
    infer GlobalOptions,
    infer Types,
    infer GlobalTypes,
    undefined
  > ? Command<
      TGlobalOptions,
      TGlobalTypes,
      Options,
      Arguments,
      GlobalOptions,
      Types,
      GlobalTypes,
      OneOf<TParentCommand, this>
    >
    : never;

  /**
   * Add new sub-command.
   *
   * @param name      Command definition. E.g: `my-command <input-file:string> <output-file:string>`
   * @param cmd       The new child command to register.
   * @param override  Override existing child command.
   */
  public command<
    TCommand extends Command<
      TGlobalOptions | void | undefined,
      TGlobalTypes | void | undefined,
      Record<string, unknown> | void,
      Array<unknown>,
      Record<string, unknown> | void,
      Record<string, unknown> | void,
      Record<string, unknown> | void,
      OneOf<TParentCommand, this> | undefined
    >,
    TGlobalOptions
      extends (TParentCommand extends Command<any> ? TParentCommandGlobals
        : Merge<TParentCommandGlobals, TCommandGlobals>),
    TGlobalTypes
      extends (TParentCommand extends Command<any> ? TParentCommandTypes
        : Merge<TParentCommandTypes, TCommandTypes>),
  >(
    name: string,
    cmd: TCommand,
    override?: boolean,
  ): TCommand extends Command<
    Record<string, unknown> | void,
    Record<string, unknown> | void,
    infer Options,
    infer Arguments,
    infer GlobalOptions,
    infer Types,
    infer GlobalTypes,
    OneOf<TParentCommand, this> | undefined
  > ? Command<
      TGlobalOptions,
      TGlobalTypes,
      Options,
      Arguments,
      GlobalOptions,
      Types,
      GlobalTypes,
      OneOf<TParentCommand, this>
    >
    : never;

  /**
   * Add new sub-command.
   *
   * @param nameAndArguments  Command definition. E.g: `my-command <input-file:string> <output-file:string>`
   * @param desc              The description of the new child command.
   * @param override          Override existing child command.
   */
  public command<
    TNameAndArguments extends string,
    TArguments extends TypedCommandArguments<
      TNameAndArguments,
      TParentCommand extends Command<any> ? TParentCommandTypes
        : Merge<TParentCommandTypes, TCommandGlobalTypes>
    >,
  >(
    nameAndArguments: TNameAndArguments,
    desc?: string,
    override?: boolean,
  ): TParentCommandGlobals extends number ? Command<any> : Command<
    TParentCommand extends Command<any> ? TParentCommandGlobals
      : Merge<TParentCommandGlobals, TCommandGlobals>,
    TParentCommand extends Command<any> ? TParentCommandTypes
      : Merge<TParentCommandTypes, TCommandGlobalTypes>,
    void,
    TArguments,
    void,
    void,
    void,
    OneOf<TParentCommand, this>
  >;

  /**
   * Add new sub-command.
   * @param nameAndArguments  Command definition. E.g: `my-command <input-file:string> <output-file:string>`
   * @param cmdOrDescription  The description of the new child command.
   * @param override          Override existing child command.
   */
  command(
    nameAndArguments: string,
    cmdOrDescription?: Command<any> | string,
    override?: boolean,
  ): Command<any> {
    this.reset();

    const result = splitArguments(nameAndArguments);

    const name: string | undefined = result.flags.shift();
    const aliases: string[] = result.flags;

    if (!name) {
      throw new MissingCommandNameError();
    }

    if (this.getBaseCommand(name, true)) {
      if (!override) {
        throw new DuplicateCommandNameError(name);
      }
      this.removeCommand(name);
    }

    let description: string | undefined;
    let cmd: Command<any>;

    if (typeof cmdOrDescription === "string") {
      description = cmdOrDescription;
    }

    if (cmdOrDescription instanceof Command) {
      cmd = cmdOrDescription.reset();
    } else {
      cmd = new Command();
    }

    cmd._name = name;
    cmd._parent = this;

    if (description) {
      cmd.description(description);
    }

    if (result.typeDefinition) {
      cmd.arguments(result.typeDefinition);
    }

    aliases.forEach((alias: string) => cmd.alias(alias));

    this.commands.set(name, cmd);

    this.select(name);

    return this;
  }

  /**
   * Add new command alias.
   *
   * @param alias Tha name of the alias.
   */
  public alias(alias: string): this {
    if (this.cmd._name === alias || this.cmd.aliases.includes(alias)) {
      throw new DuplicateCommandAliasError(alias);
    }

    this.cmd.aliases.push(alias);

    return this;
  }

  /** Reset internal command reference to main command. */
  public reset(): OneOf<TParentCommand, this> {
    this._groupName = null;
    this.cmd = this;
    return this as OneOf<TParentCommand, this>;
  }

  /**
   * Set internal command pointer to child command with given name.
   * @param name The name of the command to select.
   */
  public select<
    TOptions extends Record<string, unknown> | void = any,
    TArguments extends Array<unknown> = any,
    TGlobalOptions extends Record<string, unknown> | void = any,
  >(
    name: string,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TOptions,
    TArguments,
    TGlobalOptions,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  > {
    const cmd = this.getBaseCommand(name, true);

    if (!cmd) {
      throw new CommandNotFoundError(name, this.getBaseCommands(true));
    }

    this.cmd = cmd;

    return this as Command<any>;
  }

  /*****************************************************************************
   **** SUB HANDLER ************************************************************
   *****************************************************************************/

  /** Set command name. Used in auto generated help and shell completions */
  public name(name: string): this {
    this.cmd._name = name;
    return this;
  }

  /**
   * Set command version.
   *
   * @param version Semantic version string string or method that returns the version string.
   */
  public version(
    version:
      | string
      | VersionHandler<
        Partial<TCommandOptions>,
        Partial<TCommandArguments>,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >,
  ): this {
    if (typeof version === "string") {
      this.cmd.ver = () => version;
    } else if (typeof version === "function") {
      this.cmd.ver = version;
    }
    return this;
  }

  /**
   * Add meta data. Will be displayed in the auto generated help and in the
   * output of the long version.
   *
   * @param name  The name/label of the metadata.
   * @param value The value of the metadata.
   */
  public meta(name: string, value: string): this {
    this.cmd._meta[name] = value;
    return this;
  }

  /** Returns an object of metadata. */
  public getMeta(): Record<string, string>;

  /** Get metadata value by name. */
  public getMeta(name: string): string;

  public getMeta(name?: string): Record<string, string> | string {
    return typeof name === "undefined" ? this._meta : this._meta[name];
  }

  /**
   * Set command help.
   *
   * @param help Help string, method, or config for generator that returns the help string.
   */
  public help(
    help:
      | string
      | HelpHandler<
        Partial<TCommandOptions>,
        Partial<TCommandArguments>,
        TCommandGlobals,
        TParentCommandGlobals
      >
      | HelpOptions,
  ): this {
    if (typeof help === "string") {
      this.cmd._help = () => help;
    } else if (typeof help === "function") {
      this.cmd._help = help;
    } else {
      this.cmd._help = (cmd: Command, options: HelpOptions): string =>
        HelpGenerator.generate(cmd, { ...help, ...options });
    }
    return this;
  }

  /**
   * Set the long command description.
   *
   * @param description The command description.
   */
  public description(
    description: Description<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this {
    this.cmd.desc = description;
    return this;
  }

  /**
   * Set the command usage. Defaults to arguments.
   *
   * @param usage The command usage.
   */
  public usage(usage: string): this {
    this.cmd._usage = usage;
    return this;
  }

  /** Hide command from help, completions, etc. */
  public hidden(): this {
    this.cmd.isHidden = true;
    return this;
  }

  /** Make command globally available. */
  public global(): this {
    this.cmd.isGlobal = true;
    return this;
  }

  /**
   * Set command arguments.
   *
   * Syntax: `<requiredArg:string> [optionalArg: number] [...restArgs:string]`
   */
  public arguments<
    TArguments extends TypedArguments<
      TArgs,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>
    >,
    TArgs extends string = string,
  >(
    args: TArgs,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TArguments,
    TCommandGlobals,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  > {
    this.cmd.argsDefinition = args;
    return this as Command<any>;
  }

  /**
   * Set command callback method.
   *
   * @param fn Command action handler.
   */
  public action(
    fn: ActionHandler<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this {
    this.cmd.actionHandler = fn;
    return this;
  }

  /**
   * Set command callback method.
   *
   * @param fn Command action handler.
   */
  public globalAction(
    fn: ActionHandler<
      Partial<TCommandOptions>,
      Array<unknown>,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
  ): this {
    this.cmd.globalActionHandler = fn;
    return this;
  }

  /**
   * Don't throw an error if the command was called without arguments.
   *
   * @param allowEmpty Enable/disable allow empty.
   */
  public allowEmpty<TAllowEmpty extends boolean | undefined = undefined>(
    allowEmpty?: TAllowEmpty,
  ): false extends TAllowEmpty ? this
    : Command<
      Partial<TParentCommandGlobals>,
      TParentCommandTypes,
      Partial<TCommandOptions>,
      TCommandArguments,
      TCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommand
    > {
    this.cmd._allowEmpty = allowEmpty !== false;
    return this as false extends TAllowEmpty ? this
      : Command<
        Partial<TParentCommandGlobals>,
        TParentCommandTypes,
        Partial<TCommandOptions>,
        TCommandArguments,
        TCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommand
      >;
  }

  /**
   * Enable stop early. If enabled, all arguments starting from the first non
   * option argument will be passed as arguments with type string to the command
   * action handler.
   *
   * For example:
   *     `command --debug-level warning server --port 80`
   *
   * Will result in:
   *     - options: `{ debugLevel: 'warning' }`
   *     - args: `['server', '--port', '80']`
   *
   * @param stopEarly Enable/disable stop early.
   */
  public stopEarly(stopEarly = true): this {
    this.cmd._stopEarly = stopEarly;
    return this;
  }

  /**
   * Disable parsing arguments. If enabled the raw arguments will be passed to
   * the action handler. This has no effect for parent or child commands. Only
   * for the command on which this method was called.
   *
   * @param useRawArgs Enable/disable raw arguments.
   */
  public useRawArgs(
    useRawArgs = true,
  ): Command<
    void,
    void,
    void,
    Array<string>,
    void,
    void,
    void,
    TParentCommand
  > {
    this.cmd._useRawArgs = useRawArgs;
    return this as Command<any>;
  }

  /**
   * Set default command. The default command is executed when the program
   * was called without any argument and if no action handler is registered.
   *
   * @param name Name of the default command.
   */
  public default(name: string): this {
    this.cmd.defaultCommand = name;
    return this;
  }

  public globalType<
    THandler extends TypeOrTypeHandler<unknown>,
    TName extends string = string,
  >(
    name: TName,
    handler: THandler,
    options?: Omit<TypeOptions, "global">,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    TCommandGlobals,
    TCommandTypes,
    Merge<TCommandGlobalTypes, TypedType<TName, THandler>>,
    TParentCommand
  > {
    return this.type(name, handler, { ...options, global: true });
  }

  /**
   * Register custom type.
   *
   * @param name    The name of the type.
   * @param handler The callback method to parse the type.
   * @param options Type options.
   */
  public type<
    THandler extends TypeOrTypeHandler<unknown>,
    TName extends string = string,
  >(
    name: TName,
    handler: THandler,
    options?: TypeOptions,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    TCommandGlobals,
    Merge<TCommandTypes, TypedType<TName, THandler>>,
    TCommandGlobalTypes,
    TParentCommand
  > {
    if (this.cmd.types.get(name) && !options?.override) {
      throw new DuplicateTypeError(name);
    }

    this.cmd.types.set(name, {
      ...options,
      name,
      handler: handler as TypeOrTypeHandler<unknown>,
    });

    if (
      handler instanceof Type &&
      (typeof handler.complete !== "undefined" ||
        typeof handler.values !== "undefined")
    ) {
      const completeHandler: CompleteHandler = (
        cmd: Command,
        parent?: Command,
      ) => handler.complete?.(cmd, parent) || [];
      this.complete(name, completeHandler, options);
    }

    return this as Command<any>;
  }

  /**
   * Register global complete handler.
   *
   * @param name      The name of the completion.
   * @param complete  The callback method to complete the type.
   * @param options   Complete options.
   */
  public globalComplete(
    name: string,
    complete: CompleteHandler,
    options?: Omit<CompleteOptions, "global">,
  ): this {
    return this.complete(name, complete, { ...options, global: true });
  }

  /**
   * Register global complete handler.
   *
   * @param name      The name of the completion.
   * @param complete  The callback method to complete the type.
   * @param options   Complete options.
   */
  public complete(
    name: string,
    complete: CompleteHandler<
      Partial<TCommandOptions>,
      Partial<TCommandArguments>,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      any
    >,
    options: CompleteOptions & { global: boolean },
  ): this;

  /**
   * Register complete handler.
   *
   * @param name      The name of the completion.
   * @param complete  The callback method to complete the type.
   * @param options   Complete options.
   */
  public complete(
    name: string,
    complete: CompleteHandler<
      TCommandOptions,
      TCommandArguments,
      TCommandGlobals,
      TParentCommandGlobals,
      TCommandTypes,
      TCommandGlobalTypes,
      TParentCommandTypes,
      TParentCommand
    >,
    options?: CompleteOptions,
  ): this;

  public complete(
    name: string,
    complete:
      | CompleteHandler<
        TCommandOptions,
        TCommandArguments,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
      | CompleteHandler<
        Partial<TCommandOptions>,
        Partial<TCommandArguments>,
        TCommandGlobals,
        TParentCommandGlobals,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        any
      >,
    options?: CompleteOptions,
  ): this {
    if (this.cmd.completions.has(name) && !options?.override) {
      throw new DuplicateCompletionError(name);
    }

    this.cmd.completions.set(name, {
      name,
      complete,
      ...options,
    });

    return this;
  }

  /**
   * Throw validation errors instead of calling `exit()` to handle
   * validation errors manually.
   *
   * A validation error is thrown when the command is wrongly used by the user.
   * For example: If the user passes some invalid options or arguments to the
   * command.
   *
   * This has no effect for parent commands. Only for the command on which this
   * method was called and all child commands.
   *
   * **Example:**
   *
   * ```ts
   * import { Command, ValidationError } from "./mod.ts";
   *
   * const cmd = new Command();
   * // ...
   *
   * try {
   *   cmd.parse();
   * } catch(error) {
   *   if (error instanceof ValidationError) {
   *     cmd.showHelp();
   *     Deno.exit(1);
   *   }
   *   throw error;
   * }
   * ```
   *
   * @see ValidationError
   */
  public throwErrors(): this {
    this.cmd.throwOnError = true;
    return this;
  }

  /**
   * Set custom error handler.
   *
   * @param handler Error handler callback function.
   */
  public error(handler: ErrorHandler): this {
    this.cmd.errorHandler = handler;
    return this;
  }

  /** Get error handler callback function. */
  private getErrorHandler(): ErrorHandler | undefined {
    return this.errorHandler ?? this._parent?.errorHandler;
  }

  /**
   * Same as `.throwErrors()` but also prevents calling `exit()` after
   * printing help or version with the --help and --version option.
   */
  public noExit(): this {
    this.cmd._shouldExit = false;
    this.throwErrors();
    return this;
  }

  /**
   * Disable inheriting global commands, options and environment variables from
   * parent commands.
   */
  public noGlobals(): this {
    this.cmd._noGlobals = true;
    return this;
  }

  /** Check whether the command should throw errors or exit. */
  protected shouldThrowErrors(): boolean {
    return this.throwOnError || !!this._parent?.shouldThrowErrors();
  }

  /** Check whether the command should exit after printing help or version. */
  protected shouldExit(): boolean {
    return this._shouldExit ?? this._parent?.shouldExit() ?? true;
  }

  /**
   * Enable grouping of options and set the name of the group.
   * All option which are added after calling the `.group()` method will be
   * grouped in the help output. If the `.group()` method can be use multiple
   * times to create more groups.
   *
   * @param name The name of the option group.
   */
  public group(name: string | null): this {
    this.cmd._groupName = name;
    return this;
  }

  /**
   * Register a global option.
   *
   * @param flags Flags string e.g: -h, --help, --manual <requiredArg:string> [optionalArg:number] [...restArgs:string]
   * @param desc Flag description.
   * @param opts Flag options or custom handler for processing flag value.
   */
  public globalOption<
    TFlags extends string,
    TGlobalOptions extends TypedOption<
      TFlags,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      undefined extends TConflicts ? TRequired : false,
      TDefaultValue
    >,
    TMappedGlobalOptions extends MapValue<
      TGlobalOptions,
      TMappedValue,
      TCollect
    >,
    TRequired extends OptionOptions["required"] = undefined,
    TCollect extends OptionOptions["collect"] = undefined,
    TConflicts extends OptionOptions["conflicts"] = undefined,
    const TDefaultValue = undefined,
    TMappedValue = undefined,
  >(
    flags: TFlags,
    desc: string,
    opts?:
      | Omit<
        GlobalOptionOptions<
          Partial<TCommandOptions>,
          TCommandArguments,
          MergeOptions<TFlags, TCommandGlobals, TGlobalOptions>,
          TParentCommandGlobals,
          TCommandTypes,
          TCommandGlobalTypes,
          TParentCommandTypes,
          TParentCommand
        >,
        "value"
      >
        & {
          default?: DefaultValue<TDefaultValue>;
          required?: TRequired;
          collect?: TCollect;
          value?: OptionValueHandler<
            MapTypes<ValueOf<TGlobalOptions>>,
            TMappedValue
          >;
        }
      | OptionValueHandler<MapTypes<ValueOf<TGlobalOptions>>, TMappedValue>,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    MergeOptions<TFlags, TCommandGlobals, TMappedGlobalOptions>,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  > {
    if (typeof opts === "function") {
      return this.option(
        flags,
        desc,
        { value: opts, global: true } as OptionOptions,
      ) as Command<any>;
    }
    return this.option(
      flags,
      desc,
      { ...opts, global: true } as OptionOptions,
    ) as Command<any>;
  }

  /**
   * Add a global option.
   *
   * @param flags Flags string e.g: -h, --help, --manual <requiredArg:string> [optionalArg:number] [...restArgs:string]
   * @param desc Flag description.
   * @param opts Flag options or custom handler for processing flag value.
   */
  public option<
    TFlags extends string,
    TGlobalOptions extends TypedOption<
      TFlags,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      undefined extends TConflicts ? TRequired : false,
      TDefaultValue
    >,
    TMappedGlobalOptions extends MapValue<
      TGlobalOptions,
      TMappedValue,
      TCollect
    >,
    TRequired extends OptionOptions["required"] = undefined,
    TCollect extends OptionOptions["collect"] = undefined,
    TConflicts extends OptionOptions["conflicts"] = undefined,
    const TDefaultValue = undefined,
    TMappedValue = undefined,
  >(
    flags: TFlags,
    desc: string,
    opts:
      | Omit<
        OptionOptions<
          Partial<TCommandOptions>,
          TCommandArguments,
          MergeOptions<TFlags, TCommandGlobals, TGlobalOptions>,
          TParentCommandGlobals,
          TCommandTypes,
          TCommandGlobalTypes,
          TParentCommandTypes,
          TParentCommand
        >,
        "value"
      >
        & {
          global: true;
          default?: DefaultValue<TDefaultValue>;
          required?: TRequired;
          collect?: TCollect;
          value?: OptionValueHandler<
            MapTypes<ValueOf<TGlobalOptions>>,
            TMappedValue
          >;
        }
      | OptionValueHandler<MapTypes<ValueOf<TGlobalOptions>>, TMappedValue>,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    MergeOptions<TFlags, TCommandGlobals, TMappedGlobalOptions>,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  >;

  /**
   * Register an option.
   *
   * @param flags Flags string e.g: -h, --help, --manual <requiredArg:string> [optionalArg:number] [...restArgs:string]
   * @param desc Flag description.
   * @param opts Flag options or custom handler for processing flag value.
   */
  public option<
    TFlags extends string,
    TOptions extends TypedOption<
      TFlags,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      undefined extends TConflicts ? TRequired : false,
      TDefaultValue
    >,
    TMappedOptions extends MapValue<TOptions, TMappedValue, TCollect>,
    TRequired extends OptionOptions["required"] = undefined,
    TCollect extends OptionOptions["collect"] = undefined,
    TConflicts extends OptionOptions["conflicts"] = undefined,
    const TDefaultValue = undefined,
    TMappedValue = undefined,
  >(
    flags: TFlags,
    desc: string,
    opts?:
      | Omit<
        OptionOptions<
          MergeOptions<TFlags, TCommandOptions, TMappedOptions>,
          TCommandArguments,
          TCommandGlobals,
          TParentCommandGlobals,
          TCommandTypes,
          TCommandGlobalTypes,
          TParentCommandTypes,
          TParentCommand
        >,
        "value"
      >
        & {
          default?: DefaultValue<TDefaultValue>;
          required?: TRequired;
          collect?: TCollect;
          conflicts?: TConflicts;
          value?: OptionValueHandler<MapTypes<ValueOf<TOptions>>, TMappedValue>;
        }
      | OptionValueHandler<MapTypes<ValueOf<TOptions>>, TMappedValue>,
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    MergeOptions<TFlags, TCommandOptions, TMappedOptions>,
    TCommandArguments,
    TCommandGlobals,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  >;

  public option(
    flags: string,
    desc: string,
    opts?: OptionOptions | OptionValueHandler,
  ): Command<any> {
    if (typeof opts === "function") {
      opts = { value: opts };
    }

    const result = splitArguments(flags);

    const args: Argument[] = result.typeDefinition
      ? parseArgumentsDefinition(result.typeDefinition)
      : [];

    const option: Option = {
      ...opts,
      name: "",
      description: desc,
      args,
      flags: result.flags,
      equalsSign: result.equalsSign,
      typeDefinition: result.typeDefinition,
      groupName: this._groupName ?? undefined,
    };

    if (option.separator) {
      for (const arg of args) {
        if (arg.list) {
          arg.separator = option.separator;
        }
      }
    }

    for (const part of option.flags) {
      const arg = part.trim();
      const isLong = /^--/.test(arg);
      const name = isLong ? arg.slice(2) : arg.slice(1);

      if (this.cmd.getBaseOption(name, true)) {
        if (opts?.override) {
          this.removeOption(name);
        } else {
          throw new DuplicateOptionNameError(name, this.getPath());
        }
      }

      if (!option.name && isLong) {
        option.name = name;
      } else if (!option.aliases) {
        option.aliases = [name];
      } else {
        option.aliases.push(name);
      }
    }

    if (option.prepend) {
      this.cmd.options.unshift(option);
    } else {
      this.cmd.options.push(option);
    }

    return this;
  }

  /**
   * Register command example.
   *
   * @param name          Name of the example.
   * @param description   The content of the example.
   */
  public example(name: string, description: string): this {
    if (this.cmd.hasExample(name)) {
      throw new DuplicateExampleError(name);
    }

    this.cmd.examples.push({ name, description });

    return this;
  }

  /**
   * @param flags Flags string e.g: -h, --help, --manual <requiredArg:string> [optionalArg:number] [...restArgs:string]
   * @param desc Flag description.
   * @param opts Flag options or custom handler for processing flag value.
   */

  /**
   * Register a global environment variable.
   *
   * @param name        Name of the environment variable.
   * @param description The description of the environment variable.
   * @param options     Environment variable options.
   */
  public globalEnv<
    TNameAndValue extends string,
    TGlobalEnvVars extends TypedEnv<
      TNameAndValue,
      TPrefix,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      TRequired
    >,
    TMappedGlobalEnvVars extends MapValue<TGlobalEnvVars, TMappedValue>,
    TRequired extends EnvVarOptions["required"] = undefined,
    TPrefix extends EnvVarOptions["prefix"] = undefined,
    TMappedValue = undefined,
  >(
    name: TNameAndValue,
    description: string,
    options?: Omit<GlobalEnvVarOptions, "value"> & {
      required?: TRequired;
      prefix?: TPrefix;
      value?: EnvVarValueHandler<
        MapTypes<ValueOf<TGlobalEnvVars>>,
        TMappedValue
      >;
    },
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    Merge<TCommandGlobals, TMappedGlobalEnvVars>,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  > {
    return this.env(
      name,
      description,
      { ...options, global: true } as EnvVarOptions,
    ) as Command<any>;
  }

  /**
   * Register a global environment variable.
   *
   * @param name        Name of the environment variable.
   * @param description The description of the environment variable.
   * @param options     Environment variable options.
   */
  public env<
    N extends string,
    G extends TypedEnv<
      N,
      P,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      R
    >,
    MG extends MapValue<G, V>,
    R extends EnvVarOptions["required"] = undefined,
    P extends EnvVarOptions["prefix"] = undefined,
    V = undefined,
  >(
    name: N,
    description: string,
    options: Omit<EnvVarOptions, "value"> & {
      global: true;
      required?: R;
      prefix?: P;
      value?: EnvVarValueHandler<MapTypes<ValueOf<G>>, V>;
    },
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    TCommandOptions,
    TCommandArguments,
    Merge<TCommandGlobals, MG>,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  >;

  /**
   * Register an environment variable.
   *
   * @param name        Name of the environment variable.
   * @param description The description of the environment variable.
   * @param options     Environment variable options.
   */
  public env<
    TNameAndValue extends string,
    TEnvVar extends TypedEnv<
      TNameAndValue,
      TPrefix,
      TCommandOptions,
      Merge<TParentCommandTypes, Merge<TCommandGlobalTypes, TCommandTypes>>,
      TRequired
    >,
    TMappedEnvVar extends MapValue<TEnvVar, TMappedValue>,
    TRequired extends EnvVarOptions["required"] = undefined,
    TPrefix extends EnvVarOptions["prefix"] = undefined,
    TMappedValue = undefined,
  >(
    name: TNameAndValue,
    description: string,
    options?: Omit<EnvVarOptions, "value"> & {
      required?: TRequired;
      prefix?: TPrefix;
      value?: EnvVarValueHandler<MapTypes<ValueOf<TEnvVar>>, TMappedValue>;
    },
  ): Command<
    TParentCommandGlobals,
    TParentCommandTypes,
    Merge<TCommandOptions, TMappedEnvVar>,
    TCommandArguments,
    TCommandGlobals,
    TCommandTypes,
    TCommandGlobalTypes,
    TParentCommand
  >;

  public env(
    name: string,
    description: string,
    options?: EnvVarOptions,
  ): Command<any> {
    const result = splitArguments(name);

    if (!result.typeDefinition) {
      result.typeDefinition = "<value:boolean>";
    }

    if (result.flags.some((envName) => this.cmd.getBaseEnvVar(envName, true))) {
      throw new DuplicateEnvVarError(name);
    }

    const details: Argument[] = parseArgumentsDefinition(
      result.typeDefinition,
    );

    if (details.length > 1) {
      throw new TooManyEnvVarValuesError(name);
    } else if (details.length && details[0].optional) {
      throw new UnexpectedOptionalEnvVarValueError(name);
    } else if (details.length && details[0].variadic) {
      throw new UnexpectedVariadicEnvVarValueError(name);
    }

    this.cmd.envVars.push({
      name: result.flags[0],
      names: result.flags,
      description,
      type: details[0].type,
      details: details.shift() as Argument,
      ...options,
    });

    return this;
  }

  /*****************************************************************************
   **** MAIN HANDLER ***********************************************************
   *****************************************************************************/

  /**
   * Parse command line arguments and execute matched command.
   *
   * @param args Command line args to parse. Ex: `cmd.parse( Deno.args )`
   */
  public parse(
    args: string[] = getArgs(),
  ): Promise<
    TParentCommand extends Command<any> ? CommandResult<
        Record<string, unknown>,
        Array<unknown>,
        Record<string, unknown>,
        Record<string, unknown>,
        Record<string, unknown>,
        Record<string, unknown>,
        Record<string, unknown>,
        undefined
      >
      : CommandResult<
        MapTypes<TCommandOptions>,
        MapTypes<TCommandArguments>,
        MapTypes<TCommandGlobals>,
        MapTypes<TParentCommandGlobals>,
        TCommandTypes,
        TCommandGlobalTypes,
        TParentCommandTypes,
        TParentCommand
      >
  > {
    const ctx: ParseContext = {
      unknown: args.slice(),
      flags: {},
      env: {},
      literal: [],
      stopEarly: false,
      stopOnUnknown: false,
      defaults: {},
      actions: [],
    };
    return this.parseCommand(ctx) as any;
  }

  private async parseCommand(ctx: ParseContext): Promise<CommandResult> {
    try {
      this.reset();
      this.registerDefaults();
      this.rawArgs = ctx.unknown.slice();

      if (this._useRawArgs) {
        await this.parseEnvVars(ctx, this.envVars);
        return await this.execute(ctx.env, ctx.unknown);
      }

      let preParseGlobals = false;
      let subCommand: Command<any> | undefined;

      // Pre parse globals to support: cmd --global-option sub-command --option
      if (ctx.unknown.length > 0) {
        // Detect sub command.
        subCommand = this.getSubCommand(ctx);

        if (!subCommand) {
          // Only pre parse globals if first arg ist a global option.
          const optionName = ctx.unknown[0].replace(/^-+/, "");
          const option = this.getOption(optionName, true);

          if (option?.global) {
            preParseGlobals = true;
            await this.parseGlobalOptionsAndEnvVars(ctx);
          }
        }
      }

      if (subCommand || ctx.unknown.length > 0) {
        subCommand ??= this.getSubCommand(ctx);

        if (subCommand) {
          subCommand._globalParent = this;
          return subCommand.parseCommand(ctx);
        }
      }

      // Parse rest options & env vars.
      await this.parseOptionsAndEnvVars(ctx, preParseGlobals);
      const options = { ...ctx.env, ...ctx.flags };
      const args = this.parseArguments(ctx, options);
      this.literalArgs = ctx.literal;

      // Execute option action.
      if (ctx.actions.length) {
        await Promise.all(
          ctx.actions.map((action) => action.call(this, options, ...args)),
        );

        if (ctx.standalone) {
          return {
            options,
            args,
            cmd: this,
            literal: this.literalArgs,
          };
        }
      }

      return await this.execute(options, args);
    } catch (error: unknown) {
      this.handleError(error);
    }
  }

  private getSubCommand(ctx: ParseContext) {
    const subCommand = this.getCommand(ctx.unknown[0], true);

    if (subCommand) {
      ctx.unknown.shift();
    }

    return subCommand;
  }

  private async parseGlobalOptionsAndEnvVars(
    ctx: ParseContext,
  ): Promise<void> {
    const isHelpOption = this.getHelpOption()?.flags.includes(ctx.unknown[0]);

    // Parse global env vars.
    const envVars = [
      ...this.envVars.filter((envVar) => envVar.global),
      ...this.getGlobalEnvVars(true),
    ];

    await this.parseEnvVars(ctx, envVars, !isHelpOption);

    // Parse global options.
    const options = [
      ...this.options.filter((option) => option.global),
      ...this.getGlobalOptions(true),
    ];

    this.parseOptions(ctx, options, {
      stopEarly: true,
      stopOnUnknown: true,
      dotted: false,
    });
  }

  private async parseOptionsAndEnvVars(
    ctx: ParseContext,
    preParseGlobals: boolean,
  ): Promise<void> {
    const helpOption = this.getHelpOption();
    const isVersionOption = this._versionOption?.flags.includes(ctx.unknown[0]);
    const isHelpOption = helpOption && ctx.flags?.[helpOption.name] === true;

    // Parse env vars.
    const envVars = preParseGlobals
      ? this.envVars.filter((envVar) => !envVar.global)
      : this.getEnvVars(true);

    await this.parseEnvVars(
      ctx,
      envVars,
      !isHelpOption && !isVersionOption,
    );

    // Parse options.
    const options = this.getOptions(true);

    this.parseOptions(ctx, options);
  }

  /** Register default options like `--version` and `--help`. */
  private registerDefaults(): this {
    if (this.hasDefaults || this.getParent()) {
      return this;
    }
    this.hasDefaults = true;

    this.reset();

    !this.types.has("string") &&
      this.type("string", new StringType(), { global: true });
    !this.types.has("number") &&
      this.type("number", new NumberType(), { global: true });
    !this.types.has("integer") &&
      this.type("integer", new IntegerType(), { global: true });
    !this.types.has("boolean") &&
      this.type("boolean", new BooleanType(), { global: true });
    !this.types.has("file") &&
      this.type("file", new FileType(), { global: true });

    if (!this._help) {
      this.help({});
    }

    if (this._versionOptions !== false && (this._versionOptions || this.ver)) {
      this.option(
        this._versionOptions?.flags || "-V, --version",
        this._versionOptions?.desc ||
          "Show the version number for this program.",
        {
          standalone: true,
          prepend: true,
          action: async function () {
            const long = this.getRawArgs().includes(
              `--${this._versionOption?.name}`,
            );
            if (long) {
              await checkVersion(this);
              this.showLongVersion();
            } else {
              this.showVersion();
            }
            this.exit();
          },
          ...(this._versionOptions?.opts ?? {}),
        },
      );
      this._versionOption = this.options[0];
    }

    if (this._helpOptions !== false) {
      this.option(
        this._helpOptions?.flags || "-h, --help",
        this._helpOptions?.desc || "Show this help.",
        {
          standalone: true,
          global: true,
          prepend: true,
          action: async function () {
            const long = this.getRawArgs().includes(
              `--${this.getHelpOption()?.name}`,
            );
            await checkVersion(this);
            this.showHelp({ long });
            this.exit();
          },
          ...(this._helpOptions?.opts ?? {}),
        },
      );
      this._helpOption = this.options[0];
    }

    return this;
  }

  /**
   * Execute command.
   * @param options A map of options.
   * @param args Command arguments.
   */
  private async execute(
    options: Record<string, unknown>,
    args: Array<unknown>,
  ): Promise<CommandResult> {
    if (this.defaultCommand) {
      const cmd = this.getCommand(this.defaultCommand, true);

      if (!cmd) {
        throw new DefaultCommandNotFoundError(
          this.defaultCommand,
          this.getCommands(),
        );
      }
      cmd._globalParent = this;

      return cmd.execute(options, args);
    }

    await this.executeGlobalAction(options, args);

    if (this.actionHandler) {
      await this.actionHandler(options, ...args);
    }

    return {
      options,
      args,
      cmd: this,
      literal: this.literalArgs,
    };
  }

  private async executeGlobalAction(
    options: Record<string, unknown>,
    args: Array<unknown>,
  ) {
    if (!this._noGlobals) {
      await this._parent?.executeGlobalAction(options, args);
    }
    await this.globalActionHandler?.(options, ...args);
  }

  /** Parse raw command line arguments. */
  protected parseOptions(
    ctx: ParseContext,
    options: Option[],
    {
      stopEarly = this._stopEarly,
      stopOnUnknown = false,
      dotted = true,
    }: ParseOptionsOptions = {},
  ): void {
    parseFlags(ctx, {
      stopEarly,
      stopOnUnknown,
      dotted,
      allowEmpty: this._allowEmpty,
      flags: options,
      ignoreDefaults: ctx.env,
      parse: (type: ArgumentValue) => this.parseType(type),
      option: (option: Option) => {
        if (option.action) {
          ctx.actions.push(option.action);
        }
      },
    });
  }

  /** Parse argument type. */
  protected parseType(type: ArgumentValue): unknown {
    const typeSettings: TypeDef | undefined = this.getType(type.type);

    if (!typeSettings) {
      throw new UnknownTypeError(
        type.type,
        this.getTypes().map((type) => type.name),
      );
    }

    return typeSettings.handler instanceof Type
      ? typeSettings.handler.parse(type)
      : typeSettings.handler(type);
  }

  /**
   * Read and validate environment variables.
   * @param ctx Parse context.
   * @param envVars env vars defined by the command.
   * @param validate when true, throws an error if a required env var is missing.
   */
  protected async parseEnvVars(
    ctx: ParseContext,
    envVars: Array<EnvVar>,
    validate = true,
  ): Promise<void> {
    for (const envVar of envVars) {
      const env = await this.findEnvVar(envVar.names);

      if (env) {
        const parseType = (value: string) => {
          return this.parseType({
            label: "Environment variable",
            type: envVar.type,
            name: env.name,
            value,
          });
        };

        const propertyName = underscoreToCamelCase(
          envVar.prefix
            ? envVar.names[0].replace(new RegExp(`^${envVar.prefix}`), "")
            : envVar.names[0],
        );

        if (envVar.details.list) {
          ctx.env[propertyName] = env.value
            .split(envVar.details.separator ?? ",")
            .map(parseType);
        } else {
          ctx.env[propertyName] = parseType(env.value);
        }

        if (envVar.value && typeof ctx.env[propertyName] !== "undefined") {
          ctx.env[propertyName] = envVar.value(ctx.env[propertyName]);
        }
      } else if (envVar.required && validate) {
        throw new MissingRequiredEnvVarError(envVar);
      }
    }
  }

  protected async findEnvVar(
    names: readonly string[],
  ): Promise<{ name: string; value: string } | undefined> {
    for (const name of names) {
      const status = await (globalThis as any).Deno?.permissions.query({
        name: "env",
        variable: name,
      });

      if (!status || status.state === "granted") {
        const value = getEnv(name);

        if (value) {
          return { name, value };
        }
      }
    }

    return undefined;
  }

  /**
   * Parse command-line arguments.
   * @param ctx     Parse context.
   * @param options Parsed command line options.
   */
  protected parseArguments(
    ctx: ParseContext,
    options: Record<string, unknown>,
  ): TCommandArguments {
    const params: Array<unknown> = [];
    const args = ctx.unknown.slice();

    if (!this.hasArguments()) {
      if (args.length) {
        if (this.hasCommands(true)) {
          if (this.hasCommand(args[0], true)) {
            // e.g: command --global-foo --foo sub-command
            throw new TooManyArgumentsError(args);
          } else {
            throw new UnknownCommandError(args[0], this.getCommands());
          }
        } else {
          throw new NoArgumentsAllowedError(this.getPath());
        }
      }
    } else {
      if (!args.length) {
        const required = this.getArguments()
          .filter((expectedArg) => !expectedArg.optional)
          .map((expectedArg) => expectedArg.name);

        if (required.length) {
          const optionNames: string[] = Object.keys(options);
          const hasStandaloneOption = !!optionNames.find((name) =>
            this.getOption(name, true)?.standalone
          );

          if (!hasStandaloneOption) {
            throw new MissingArgumentsError(required);
          }
        }
      } else {
        for (const expectedArg of this.getArguments()) {
          if (!args.length) {
            if (expectedArg.optional) {
              break;
            }
            throw new MissingArgumentError(expectedArg.name);
          }

          let arg: unknown;

          const parseArgValue = (value: string) => {
            return expectedArg.list
              ? value.split(",").map((value) => parseArgType(value))
              : parseArgType(value);
          };

          const parseArgType = (value: string) => {
            return this.parseType({
              label: "Argument",
              type: expectedArg.type,
              name: expectedArg.name,
              value,
            });
          };

          if (expectedArg.variadic) {
            arg = args.splice(0, args.length).map((value) =>
              parseArgValue(value)
            );
          } else {
            arg = parseArgValue(args.shift() as string);
          }

          if (expectedArg.variadic && Array.isArray(arg)) {
            params.push(...arg);
          } else if (typeof arg !== "undefined") {
            params.push(arg);
          }
        }

        if (args.length) {
          throw new TooManyArgumentsError(args);
        }
      }
    }

    return params as TCommandArguments;
  }

  private handleError(error: unknown): never {
    this.throw(
      error instanceof FlagsValidationError
        ? new ValidationError(error.message)
        : error instanceof Error
        ? error
        : new Error(`[non-error-thrown] ${error}`),
    );
  }

  /**
   * Handle error. If `throwErrors` is enabled the error will be thrown,
   * otherwise a formatted error message will be printed and `exit(1)`
   * will be called. This will also trigger registered error handlers.
   *
   * @param error The error to handle.
   */
  public throw(error: Error): never {
    if (error instanceof ValidationError) {
      error.cmd = this as unknown as Command;
    }
    this.getErrorHandler()?.(error, this as unknown as Command);

    if (this.shouldThrowErrors() || !(error instanceof ValidationError)) {
      throw error;
    }
    this.showHelp();

    console.error(red(`  ${bold("error")}: ${error.message}\n`));

    exit(error instanceof ValidationError ? error.exitCode : 1);
  }

  /*****************************************************************************
   **** GETTER *****************************************************************
   *****************************************************************************/

  /** Get command name. */
  public getName(): string {
    return this._name;
  }

  /** Get parent command. */
  public getParent(): TParentCommand {
    return this._parent as TParentCommand;
  }

  /**
   * Get parent command from global executed command.
   * Be sure, to call this method only inside an action handler. Unless this or any child command was executed,
   * this method returns always undefined.
   */
  public getGlobalParent(): Command<any> | undefined {
    return this._globalParent;
  }

  /** Get main command. */
  public getMainCommand(): Command<any> {
    return this._parent?.getMainCommand() ?? this;
  }

  /** Get command name aliases. */
  public getAliases(): string[] {
    return this.aliases;
  }

  /**
   * Get full command path.
   *
   * @param name Override the main command name.
   */
  public getPath(name?: string): string {
    return this._parent
      ? this._parent.getPath(name) + " " + this._name
      : name || this._name;
  }

  /** Get arguments definition. E.g: <input-file:string> <output-file:string> */
  public getArgsDefinition(): string | undefined {
    return this.argsDefinition;
  }

  /**
   * Get argument by name.
   *
   * @param name Name of the argument.
   */
  public getArgument(name: string): Argument | undefined {
    return this.getArguments().find((arg) => arg.name === name);
  }

  /** Get arguments. */
  public getArguments(): Argument[] {
    if (!this.args.length && this.argsDefinition) {
      this.args = parseArgumentsDefinition(this.argsDefinition);
    }

    return this.args;
  }

  /** Check if command has arguments. */
  public hasArguments(): boolean {
    return !!this.argsDefinition;
  }

  /** Get command version. */
  public getVersion(): string | undefined {
    return this.getVersionHandler()?.call(this, this);
  }

  /** Get help handler method. */
  private getVersionHandler(): VersionHandler | undefined {
    return this.ver ?? this._parent?.getVersionHandler();
  }

  /** Get command description. */
  public getDescription(): string {
    // call description method only once
    return typeof this.desc === "function"
      ? this.desc = this.desc()
      : this.desc;
  }

  /** Get auto generated command usage. */
  public getUsage(): string {
    return this._usage ??
      [this.getArgsDefinition(), this.getRequiredOptionsDefinition()]
        .join(" ")
        .trim();
  }

  private getRequiredOptionsDefinition() {
    return this.getOptions()
      .filter((option) => option.required)
      .map((option) =>
        [findFlag(option.flags), option.typeDefinition].filter((v) => v)
          .join(" ")
          .trim()
      )
      .join(" ");
  }

  /** Get short command description. This is the first line of the description. */
  public getShortDescription(): string {
    return getDescription(this.getDescription(), true);
  }

  /** Get original command-line arguments. */
  public getRawArgs(): string[] {
    return this.rawArgs;
  }

  /** Get all arguments defined after the double dash. */
  public getLiteralArgs(): string[] {
    return this.literalArgs;
  }

  /** Output generated help without exiting. */
  public showVersion(): void {
    console.log(this.getVersion());
  }

  /** Returns command name, version and meta data. */
  public getLongVersion(): string {
    return `${bold(this.getMainCommand().getName())} ${
      brightBlue(this.getVersion() ?? "")
    }` +
      Object.entries(this.getMeta()).map(
        ([k, v]) => `\n${bold(k)} ${brightBlue(v)}`,
      ).join("");
  }

  /** Outputs command name, version and meta data. */
  public showLongVersion(): void {
    console.log(this.getLongVersion());
  }

  /** Output generated help without exiting. */
  public showHelp(options?: HelpOptions): void {
    console.log(this.getHelp(options));
  }

  /** Get generated help. */
  public getHelp(options?: HelpOptions): string {
    this.registerDefaults();
    return this.getHelpHandler().call(this, this, options ?? {});
  }

  /** Get help handler method. */
  private getHelpHandler(): HelpHandler {
    return this._help ?? this._parent?.getHelpHandler() as HelpHandler;
  }

  private exit(code = 0) {
    if (this.shouldExit()) {
      exit(code);
    }
  }

  /*****************************************************************************
   **** Options GETTER *********************************************************
   *****************************************************************************/

  /**
   * Checks whether the command has options or not.
   *
   * @param hidden Include hidden options.
   */
  public hasOptions(hidden?: boolean): boolean {
    return this.getOptions(hidden).length > 0;
  }

  /**
   * Get options.
   *
   * @param hidden Include hidden options.
   */
  public getOptions(hidden?: boolean): Option[] {
    return this.getGlobalOptions(hidden).concat(this.getBaseOptions(hidden));
  }

  /**
   * Get base options.
   *
   * @param hidden Include hidden options.
   */
  public getBaseOptions(hidden?: boolean): Option[] {
    if (!this.options.length) {
      return [];
    }

    return hidden
      ? this.options.slice(0)
      : this.options.filter((opt) => !opt.hidden);
  }

  /**
   * Get global options.
   *
   * @param hidden Include hidden options.
   */
  public getGlobalOptions(hidden?: boolean): Option[] {
    const helpOption = this.getHelpOption();
    const getGlobals = (
      cmd: Command<any>,
      noGlobals: boolean,
      options: Option[] = [],
      names: string[] = [],
    ): Option[] => {
      if (cmd.options.length) {
        for (const option of cmd.options) {
          if (
            option.global &&
            !this.options.find((opt) => opt.name === option.name) &&
            names.indexOf(option.name) === -1 &&
            (hidden || !option.hidden)
          ) {
            if (noGlobals && option !== helpOption) {
              continue;
            }

            names.push(option.name);
            options.push(option);
          }
        }
      }

      return cmd._parent
        ? getGlobals(
          cmd._parent,
          noGlobals || cmd._noGlobals,
          options,
          names,
        )
        : options;
    };

    return this._parent ? getGlobals(this._parent, this._noGlobals) : [];
  }

  /**
   * Checks whether the command has an option with given name or not.
   *
   * @param name Name of the option. Must be in param-case.
   * @param hidden Include hidden options.
   */
  public hasOption(name: string, hidden?: boolean): boolean {
    return !!this.getOption(name, hidden);
  }

  /**
   * Get option by name.
   *
   * @param name Name of the option. Must be in param-case.
   * @param hidden Include hidden options.
   */
  public getOption(name: string, hidden?: boolean): Option | undefined {
    return this.getBaseOption(name, hidden) ??
      this.getGlobalOption(name, hidden);
  }

  /**
   * Get base option by name.
   *
   * @param name Name of the option. Must be in param-case.
   * @param hidden Include hidden options.
   */
  public getBaseOption(name: string, hidden?: boolean): Option | undefined {
    const option = this.options.find((option) =>
      option.name === name || option.aliases?.includes(name)
    );

    return option && (hidden || !option.hidden) ? option : undefined;
  }

  /**
   * Get global option from parent commands by name.
   *
   * @param name Name of the option. Must be in param-case.
   * @param hidden Include hidden options.
   */
  public getGlobalOption(name: string, hidden?: boolean): Option | undefined {
    const helpOption = this.getHelpOption();
    const getGlobalOption = (
      parent: Command,
      noGlobals: boolean,
    ): Option | undefined => {
      const option: Option | undefined = parent.getBaseOption(
        name,
        hidden,
      );

      if (!option?.global) {
        return parent._parent && getGlobalOption(
          parent._parent,
          noGlobals || parent._noGlobals,
        );
      }
      if (noGlobals && option !== helpOption) {
        return;
      }

      return option;
    };

    return this._parent && getGlobalOption(
      this._parent,
      this._noGlobals,
    );
  }

  /**
   * Remove option by name.
   *
   * @param name Name of the option. Must be in param-case.
   */
  public removeOption(name: string): Option | undefined {
    const index = this.options.findIndex((option) => option.name === name);

    if (index === -1) {
      return;
    }

    return this.options.splice(index, 1)[0];
  }

  /**
   * Checks whether the command has sub-commands or not.
   *
   * @param hidden Include hidden commands.
   */
  public hasCommands(hidden?: boolean): boolean {
    return this.getCommands(hidden).length > 0;
  }

  /**
   * Get commands.
   *
   * @param hidden Include hidden commands.
   */
  public getCommands(hidden?: boolean): Array<Command<any>> {
    return this.getGlobalCommands(hidden).concat(this.getBaseCommands(hidden));
  }

  /**
   * Get base commands.
   *
   * @param hidden Include hidden commands.
   */
  public getBaseCommands(hidden?: boolean): Array<Command<any>> {
    const commands = Array.from(this.commands.values());
    return hidden ? commands : commands.filter((cmd) => !cmd.isHidden);
  }

  /**
   * Get global commands.
   *
   * @param hidden Include hidden commands.
   */
  public getGlobalCommands(hidden?: boolean): Array<Command<any>> {
    const getCommands = (
      command: Command<any>,
      noGlobals: boolean,
      commands: Array<Command<any>> = [],
      names: string[] = [],
    ): Array<Command<any>> => {
      if (command.commands.size) {
        for (const [_, cmd] of command.commands) {
          if (
            cmd.isGlobal &&
            this !== cmd &&
            !this.commands.has(cmd._name) &&
            names.indexOf(cmd._name) === -1 &&
            (hidden || !cmd.isHidden)
          ) {
            if (noGlobals && cmd?.getName() !== "help") {
              continue;
            }

            names.push(cmd._name);
            commands.push(cmd);
          }
        }
      }

      return command._parent
        ? getCommands(
          command._parent,
          noGlobals || command._noGlobals,
          commands,
          names,
        )
        : commands;
    };

    return this._parent ? getCommands(this._parent, this._noGlobals) : [];
  }

  /**
   * Checks whether a child command exists by given name or alias.
   *
   * @param name Name or alias of the command.
   * @param hidden Include hidden commands.
   */
  public hasCommand(name: string, hidden?: boolean): boolean {
    return !!this.getCommand(name, hidden);
  }

  /**
   * Get command by name or alias.
   *
   * @param name Name or alias of the command.
   * @param hidden Include hidden commands.
   */
  public getCommand<TCommand extends Command<any>>(
    name: string,
    hidden?: boolean,
  ): TCommand | undefined {
    return this.getBaseCommand(name, hidden) ??
      this.getGlobalCommand(name, hidden);
  }

  /**
   * Get base command by name or alias.
   *
   * @param name Name or alias of the command.
   * @param hidden Include hidden commands.
   */
  public getBaseCommand<TCommand extends Command<any>>(
    name: string,
    hidden?: boolean,
  ): TCommand | undefined {
    for (const cmd of this.commands.values()) {
      if (cmd._name === name || cmd.aliases.includes(name)) {
        return (cmd && (hidden || !cmd.isHidden) ? cmd : undefined) as
          | TCommand
          | undefined;
      }
    }
  }

  /**
   * Get global command by name or alias.
   *
   * @param name Name or alias of the command.
   * @param hidden Include hidden commands.
   */
  public getGlobalCommand<TCommand extends Command<any>>(
    name: string,
    hidden?: boolean,
  ): TCommand | undefined {
    const getGlobalCommand = (
      parent: Command,
      noGlobals: boolean,
    ): Command | undefined => {
      const cmd: Command | undefined = parent.getBaseCommand(name, hidden);

      if (!cmd?.isGlobal) {
        return parent._parent &&
          getGlobalCommand(parent._parent, noGlobals || parent._noGlobals);
      }
      if (noGlobals && cmd.getName() !== "help") {
        return;
      }

      return cmd;
    };

    return this._parent &&
      getGlobalCommand(this._parent, this._noGlobals) as TCommand;
  }

  /**
   * Remove sub-command by name or alias.
   *
   * @param name Name or alias of the command.
   */
  public removeCommand(name: string): Command<any> | undefined {
    const command = this.getBaseCommand(name, true);

    if (command) {
      this.commands.delete(command._name);
    }

    return command;
  }

  /** Get types. */
  public getTypes(): Array<TypeDef> {
    return this.getGlobalTypes().concat(this.getBaseTypes());
  }

  /** Get base types. */
  public getBaseTypes(): Array<TypeDef> {
    return Array.from(this.types.values());
  }

  /** Get global types. */
  public getGlobalTypes(): Array<TypeDef> {
    const getTypes = (
      cmd: Command<any> | undefined,
      types: Array<TypeDef> = [],
      names: Array<string> = [],
    ): Array<TypeDef> => {
      if (cmd) {
        if (cmd.types.size) {
          cmd.types.forEach((type: TypeDef) => {
            if (
              type.global &&
              !this.types.has(type.name) &&
              names.indexOf(type.name) === -1
            ) {
              names.push(type.name);
              types.push(type);
            }
          });
        }

        return getTypes(cmd._parent, types, names);
      }

      return types;
    };

    return getTypes(this._parent);
  }

  /**
   * Get type by name.
   *
   * @param name Name of the type.
   */
  public getType(name: string): TypeDef | undefined {
    return this.getBaseType(name) ?? this.getGlobalType(name);
  }

  /**
   * Get base type by name.
   *
   * @param name Name of the type.
   */
  public getBaseType(name: string): TypeDef | undefined {
    return this.types.get(name);
  }

  /**
   * Get global type by name.
   *
   * @param name Name of the type.
   */
  public getGlobalType(name: string): TypeDef | undefined {
    if (!this._parent) {
      return;
    }

    const cmd: TypeDef | undefined = this._parent.getBaseType(name);

    if (!cmd?.global) {
      return this._parent.getGlobalType(name);
    }

    return cmd;
  }

  /** Get completions. */
  public getCompletions(): Completion<
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any
  >[] {
    return this.getGlobalCompletions().concat(this.getBaseCompletions());
  }

  /** Get base completions. */
  public getBaseCompletions(): Completion[] {
    return Array.from(this.completions.values());
  }

  /** Get global completions. */
  public getGlobalCompletions(): Completion[] {
    const getCompletions = (
      cmd: Command<any> | undefined,
      completions: Completion[] = [],
      names: string[] = [],
    ): Completion[] => {
      if (cmd) {
        if (cmd.completions.size) {
          cmd.completions.forEach((completion: Completion) => {
            if (
              completion.global &&
              !this.completions.has(completion.name) &&
              names.indexOf(completion.name) === -1
            ) {
              names.push(completion.name);
              completions.push(completion);
            }
          });
        }

        return getCompletions(cmd._parent, completions, names);
      }

      return completions;
    };

    return getCompletions(this._parent);
  }

  /**
   * Get completion by name.
   *
   * @param name Name of the completion.
   */
  public getCompletion(name: string): Completion | undefined {
    return this.getBaseCompletion(name) ?? this.getGlobalCompletion(name);
  }

  /**
   * Get base completion by name.
   *
   * @param name Name of the completion.
   */
  public getBaseCompletion(name: string): Completion | undefined {
    return this.completions.get(name);
  }

  /**
   * Get global completions by name.
   *
   * @param name Name of the completion.
   */
  public getGlobalCompletion(name: string): Completion | undefined {
    if (!this._parent) {
      return;
    }

    const completion: Completion | undefined = this._parent.getBaseCompletion(
      name,
    );

    if (!completion?.global) {
      return this._parent.getGlobalCompletion(name);
    }

    return completion;
  }

  /**
   * Checks whether the command has environment variables or not.
   *
   * @param hidden Include hidden environment variable.
   */
  public hasEnvVars(hidden?: boolean): boolean {
    return this.getEnvVars(hidden).length > 0;
  }

  /**
   * Get environment variables.
   *
   * @param hidden Include hidden environment variable.
   */
  public getEnvVars(hidden?: boolean): EnvVar[] {
    return this.getGlobalEnvVars(hidden).concat(this.getBaseEnvVars(hidden));
  }

  /**
   * Get base environment variables.
   *
   * @param hidden Include hidden environment variable.
   */
  public getBaseEnvVars(hidden?: boolean): EnvVar[] {
    if (!this.envVars.length) {
      return [];
    }

    return hidden
      ? this.envVars.slice(0)
      : this.envVars.filter((env) => !env.hidden);
  }

  /**
   * Get global environment variables.
   *
   * @param hidden Include hidden environment variable.
   */
  public getGlobalEnvVars(hidden?: boolean): EnvVar[] {
    if (this._noGlobals) {
      return [];
    }

    const getEnvVars = (
      cmd: Command<any> | undefined,
      envVars: EnvVar[] = [],
      names: string[] = [],
    ): EnvVar[] => {
      if (cmd) {
        if (cmd.envVars.length) {
          cmd.envVars.forEach((envVar: EnvVar) => {
            if (
              envVar.global &&
              !this.envVars.find((env) => env.names[0] === envVar.names[0]) &&
              names.indexOf(envVar.names[0]) === -1 &&
              (hidden || !envVar.hidden)
            ) {
              names.push(envVar.names[0]);
              envVars.push(envVar);
            }
          });
        }

        return getEnvVars(cmd._parent, envVars, names);
      }

      return envVars;
    };

    return getEnvVars(this._parent);
  }

  /**
   * Checks whether the command has an environment variable with given name or not.
   *
   * @param name Name of the environment variable.
   * @param hidden Include hidden environment variable.
   */
  public hasEnvVar(name: string, hidden?: boolean): boolean {
    return !!this.getEnvVar(name, hidden);
  }

  /**
   * Get environment variable by name.
   *
   * @param name Name of the environment variable.
   * @param hidden Include hidden environment variable.
   */
  public getEnvVar(name: string, hidden?: boolean): EnvVar | undefined {
    return this.getBaseEnvVar(name, hidden) ??
      this.getGlobalEnvVar(name, hidden);
  }

  /**
   * Get base environment variable by name.
   *
   * @param name Name of the environment variable.
   * @param hidden Include hidden environment variable.
   */
  public getBaseEnvVar(name: string, hidden?: boolean): EnvVar | undefined {
    const envVar: EnvVar | undefined = this.envVars.find((env) =>
      env.names.indexOf(name) !== -1
    );

    return envVar && (hidden || !envVar.hidden) ? envVar : undefined;
  }

  /**
   * Get global environment variable by name.
   *
   * @param name Name of the environment variable.
   * @param hidden Include hidden environment variable.
   */
  public getGlobalEnvVar(name: string, hidden?: boolean): EnvVar | undefined {
    if (!this._parent || this._noGlobals) {
      return;
    }

    const envVar: EnvVar | undefined = this._parent.getBaseEnvVar(
      name,
      hidden,
    );

    if (!envVar?.global) {
      return this._parent.getGlobalEnvVar(name, hidden);
    }

    return envVar;
  }

  /** Checks whether the command has examples or not. */
  public hasExamples(): boolean {
    return this.examples.length > 0;
  }

  /** Get all examples. */
  public getExamples(): Example[] {
    return this.examples;
  }

  /** Checks whether the command has an example with given name or not. */
  public hasExample(name: string): boolean {
    return !!this.getExample(name);
  }

  /** Get example with given name. */
  public getExample(name: string): Example | undefined {
    return this.examples.find((example) => example.name === name);
  }

  private getHelpOption(): Option | undefined {
    return this._helpOption ?? this._parent?.getHelpOption();
  }
}

function findFlag(flags: Array<string>): string {
  for (const flag of flags) {
    if (flag.startsWith("--")) {
      return flag;
    }
  }
  return flags[0];
}

interface DefaultOption {
  flags: string;
  desc?: string;
  opts?: OptionOptions;
}

interface ParseContext extends ParseFlagsContext<Record<string, unknown>> {
  actions: Array<ActionHandler>;
  env: Record<string, unknown>;
}

interface ParseOptionsOptions {
  stopEarly?: boolean;
  stopOnUnknown?: boolean;
  dotted?: boolean;
}
```
less
rest-api
typescript

First seen in:

zhorton34/stubscli

Used in 1 repository