Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions create-quasar/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Contributing to Quasar Create CLI

Thank you for your interest in contributing to the Quasar Create CLI tool! This guide will help you understand how the CLI parameter system works and how to extend it when adding or modifying templates and prompts.

## CLI Parameter System Overview

The Quasar Create CLI supports both interactive and non-interactive modes. The parameter system is designed to be:

1. **Modular**: Each template type manages its own parameters
2. **Extensible**: Easy to add new parameters or templates
3. **Dynamic**: Help text is generated based on template type
4. **Default-friendly**: Supports falling back to default values

## How Parameters Work

When a user runs the CLI with parameters, the following happens:

1. Command-line arguments are parsed by `minimist` in `index.js`
2. Arguments are passed to the `utils` module via `setCliArgs()`
3. Template-specific parameter mappings are loaded from `templates/<type>/params.js`
4. Parameters are mapped to prompt names and used to answer prompts
5. For non-interactive mode (`--yes` flag), default values are used for missing parameters

## Adding Parameters for New Templates or Prompts

If you're adding a new template or modifying an existing one with new prompts, follow these steps:

### 1. Update the Template's `params.js` File

Each template has a `params.js` file in its directory that defines:
- Parameter mappings (CLI parameter → prompt name)
- Help text for each parameter

```js
// Example: /templates/your-template/params.js
export default {
// Parameter name: prompt name
paramMap: {
'type': 'type',
'folder': 'folder',
'your-param': 'yourPromptName',
// Add your new parameters here
},

// Help text for the parameters
helpText: {
'type': 'Project type (your-template)',
'folder': 'Project folder name',
'your-param': 'Description of your parameter',
// Add help text for your parameters here
}
}
```

### 2. Handle Special Parameter Types

Different prompt types need special handling:

#### Text and Select Prompts

These work automatically. For `select` prompts, validation against choices is handled for you.

#### Multiselect Prompts

For multiselect prompts, values are passed as comma-separated strings:

```js
// CLI usage: --preset value1,value2,value3
```

The system automatically converts these to the format expected by the prompts.

#### Boolean Prompts

For boolean prompts (confirm type), you can pass `true`, `false`, or just the flag name:

```js
// All of these set the flag to true:
--your-boolean-flag
--your-boolean-flag true
--your-boolean-flag=true

// To set it to false explicitly:
--your-boolean-flag false
```

### 3. Conditional Prompts

If your prompt is conditional based on previous answers, the parameter system will handle this correctly. Just ensure your prompt's `type` function properly evaluates both interactive and non-interactive inputs:

```js
{
type: (_, { previousAnswer } = {}) => (previousAnswer ? 'text' : null),
name: 'conditionalPrompt',
message: 'This only appears if previousAnswer is true'
}
```

### 4. Default Values

When using non-interactive mode with the `--yes` flag, the system uses default values for missing parameters:

- For `select` prompts, it uses the item with `selected: true` or the first item
- For `text` prompts, it uses the `initial` value
- For function-based values, it calls the function to get the default

Make sure your prompts have appropriate default values!

## Testing Your Parameters

Always test your parameters in both interactive and non-interactive modes:

```bash
# Test help for your template
node create-quasar/index.js --help --type your-template

# Test with specific parameters
node create-quasar/index.js --type your-template --your-param value

# Test non-interactive mode
node create-quasar/index.js --type your-template --yes
```

## Common Issues and Solutions

- **Parameter not working**: Check the mapping in your template's `params.js` file
- **Wrong default used**: Ensure default values are correctly set in the prompt definition
- **Conditional prompt not working**: Make sure the condition function handles both interactive and CLI inputs
- **Parameter validation failing**: Ensure CLI validation matches the interactive prompt validation

## Best Practices

1. **Keep help text clear and concise**, including expected values or format
2. **Document all parameters** in the template's `params.js` file
3. **Use consistent naming** between CLI parameters and prompt names
4. **Test all parameters** in both interactive and non-interactive modes
5. **Include example usage** in comments or documentation

By following these guidelines, you'll ensure that Quasar CLI maintains its excellent developer experience while being extensible for future needs.
56 changes: 56 additions & 0 deletions create-quasar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,62 @@ pnpm create quasar
bun create quasar
```

## Command-Line Parameters

The create-quasar tool supports both interactive and non-interactive modes. By default, it runs in interactive mode, prompting you for each option. However, you can also provide command-line parameters to automate the project creation process.

### Basic Usage

```bash
npm init quasar -- --type app --folder my-project
# or
yarn create quasar --type app --folder my-project
```

### Non-Interactive Mode

To run in fully non-interactive mode, use the `--yes` flag. This will use default values for any parameters not explicitly specified:

```bash
npm init quasar -- --type app --folder my-project --yes
```

### Template-Specific Options

Each template type (app, app-extension, ui-kit) has its own set of specific options. To see the available options for a particular template type, use:

```bash
npm init quasar -- --help --type <template-type>
```

For example:

```bash
npm init quasar -- --help --type app
npm init quasar -- --help --type app-extension
npm init quasar -- --help --type ui-kit
```

### Examples

#### Creating a standard app with specific options:

```bash
npm init quasar -- --type app --folder my-app --script-type js --engine vite-2 --preset eslint,pinia,axios --css scss --yes
```

#### Creating an app extension:

```bash
npm init quasar -- --type app-extension --folder my-extension --name my-ext --description "My Quasar Extension" --preset prompts,install --yes
```

#### Creating a UI kit:

```bash
npm init quasar -- --type ui-kit --folder my-ui-kit --name my-component --features component,ae --yes
```

## Supporting Quasar

Quasar Framework is an MIT-licensed open source project. Its ongoing development is made possible thanks to the support by these awesome [backers](https://github.com/rstoenescu/quasar-framework/blob/dev/backers.md).
Expand Down
86 changes: 84 additions & 2 deletions create-quasar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,97 @@ import parseArgs from 'minimist'

const argv = parseArgs(process.argv.slice(2), {
alias: {
n: 'nogit',
h: 'help',
y: 'yes'
},

boolean: [ 'n' ],
boolean: [ 'help', 'nogit', 'prettier', 'yes' ],
string: [ 'type', 'folder', 'preset', 'package-manager', 'script-type', 'engine',
'name', 'product-name', 'description', 'sfc-style', 'css' ],
})

// Show help if requested
if (argv.help) {
const validTypes = ['app', 'app-extension', 'ui-kit']

// Dynamic help text loading function
const showHelp = async () => {
// Common options for all templates
const baseOptions = [
['type', 'Project type (app, app-extension, ui-kit)'],
['folder', 'Project folder name'],
['nogit', 'Skip git initialization'],
['yes, -y', 'Non-interactive mode, use default values for missing options'],
['help, -h', 'Show this help message']
]

// If a specific type is selected, show detailed help for that type
if (argv.type && validTypes.includes(argv.type)) {
const selectedType = argv.type
let templateSpecificOptions = []

try {
// Load params from the selected template
const { default: params } = await import(`./templates/${selectedType}/params.js`)
if (params && params.helpText) {
templateSpecificOptions = Object.entries(params.helpText).map(([key, desc]) => [key, desc])
}
} catch (err) {
console.error(`Could not load help text for template type: ${selectedType}`)
}

// Print header for specific template
console.log(`
Usage: create-quasar [options]

Options for ${selectedType} projects:`)

// Print all options for the specific template
const allOptions = [...baseOptions, ...templateSpecificOptions]
allOptions.forEach(([key, desc]) => {
console.log(` --${key.padEnd(20)} ${desc}`)
})
} else {
// General help without a specific template selected
console.log(`
Usage: create-quasar [options]

Basic Options:`)

// Print basic options
baseOptions.forEach(([key, desc]) => {
console.log(` --${key.padEnd(20)} ${desc}`)
})

// Show template selection information
console.log(`
Available Template Types:
app Standard Quasar application
app-extension Quasar App Extension
ui-kit UI component library

To see template-specific options, use:
create-quasar --help --type <template-type>

Examples:
create-quasar --help --type app
create-quasar --help --type app-extension
create-quasar --help --type ui-kit`)
}

console.log() // Empty line for better formatting
process.exit(0)
}

showHelp()
}

const defaultProjectFolder = 'quasar-project'
const scope = {}

// Pass command-line arguments to utils module
utils.setCliArgs(argv)

await utils.prompts(scope, [
{
type: 'select',
Expand Down
41 changes: 41 additions & 0 deletions create-quasar/templates/app-extension/params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Parameter mappings for app-extension template
*
* CONTRIBUTOR GUIDE:
* ----------------
* When adding new prompts to this template, follow these steps:
* 1. Add a mapping from CLI parameter to prompt name in the paramMap object
* 2. Add help text for the parameter in the helpText object
* 3. Make sure the parameter name is kebab-case (e.g., 'need-org-name') for CLI
* 4. Ensure the prompt name matches what's used in your prompts function
* 5. Test both interactive and non-interactive modes
*
* See /create-quasar/CONTRIBUTING.md for more details on the parameter system
*/
export default {
// Parameter name: prompt name
paramMap: {
'type': 'type',
'folder': 'folder',
'name': 'name',
'need-org-name': 'needOrgName',
'org-name': 'orgName',
'description': 'description',
'license': 'license',
'code-format': 'codeFormat',
'preset': 'preset'
},

// Help text for the parameters
helpText: {
'type': 'Project type (app-extension)',
'folder': 'Project folder name',
'name': 'Quasar App Extension ext-id (without "quasar-app-extension" prefix)',
'need-org-name': 'Use organization name (boolean)',
'org-name': 'Organization name',
'description': 'Project description',
'license': 'License type (MIT, Apache-2.0, etc.)',
'code-format': 'Code format (esm, commonjs)',
'preset': 'Features preset (comma-separated: prompts,install,uninstall)'
}
}
47 changes: 47 additions & 0 deletions create-quasar/templates/app/params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Parameter mappings for app template
*
* CONTRIBUTOR GUIDE:
* ----------------
* When adding new prompts to this template, follow these steps:
* 1. Add a mapping from CLI parameter to prompt name in the paramMap object
* 2. Add help text for the parameter in the helpText object
* 3. Make sure the parameter name is kebab-case (e.g., 'script-type') for CLI
* 4. Ensure the prompt name matches what's used in your prompts function
* 5. Test both interactive and non-interactive modes
*
* See /create-quasar/CONTRIBUTING.md for more details on the parameter system
*/
export default {
// Parameter name: prompt name
paramMap: {
'type': 'type',
'folder': 'folder',
'package-manager': 'package-manager',
'script-type': 'scriptType',
'engine': 'engine',
'name': 'name',
'product-name': 'productName',
'description': 'description',
'sfc-style': 'sfcStyle',
'css': 'css',
'preset': 'preset',
'prettier': 'prettier'
},

// Help text for the parameters
helpText: {
'type': 'Project type (app)',
'folder': 'Project folder name',
'script-type': 'Script type (js, ts)',
'engine': 'Engine variant (vite-2, webpack-4)',
'name': 'Package name',
'product-name': 'Product name',
'description': 'Project description',
'preset': 'Features preset (comma-separated: eslint,pinia,axios,i18n)',
'prettier': 'Add Prettier for code formatting (boolean)',
'sfc-style': 'Vue component style (composition-setup, composition, options)',
'css': 'CSS preprocessor (scss, sass, css)',
'package-manager': 'Package manager to use (yarn, npm, pnpm, bun)'
}
}
Loading