Skip to content

Commit

Permalink
docs(pv-create-component): add documentation for setting a new config…
Browse files Browse the repository at this point in the history
… file

also make sure a configuration without "name" prompt, doesn't throw
  • Loading branch information
mbehzad committed Nov 25, 2024
1 parent a3c6bbd commit c2880b5
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 11 deletions.
110 changes: 110 additions & 0 deletions packages/pv-create-component/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ Generate TypeScript files instead of Javascript files.

Similar to the templates for boilerplate code, the questions asked in the CLI and the logic behind creating the files can be extended or modified.

### Extend default config

For this create `scripts/create-component/config.js` which should have a default export of the modified configurations. (See [pv-create-component/config.js](https://github.com/pro-vision/fe-tools/tree/master/packages/pv-create-component/config.js))

```js
Expand Down Expand Up @@ -168,6 +170,9 @@ config.push({
config.find(item => item.id === "SCSS").imports[0].placeholder = options =>
options.type === "Element" ? "/* Element Import */" : "/* Module Import */";

/* remove an option by setting it to `undefined` */
config[config.findIndex(item => item.id === "UNIT")] = undefined;


/* allow creating components without type prefix for example for core component */
config.find(item => item.id === "TYPE").prompt.choices.push("Core Component");
Expand All @@ -178,6 +183,111 @@ module.exports = config;

See [pv-create-component/types.d.ts](https://github.com/pro-vision/fe-tools/tree/master/packages/pv-create-component/types.d.ts) for info regarding the options.

### New Configuration

If the desired project tech-stack doesn't match the provided default config, a complete new configuration can also be created and used for the create new component cli.
The file, as was explained in the previous section, is a common js module that is placed at `scripts/create-component/config.js` or the path that is passed via the `--config` parameter and has a default export, that returns a list of configuration items.

Each item consist of 3 optional parts:

```ts
{
// the question that the user is asked
prompt?: inquirer.Question;

// the files that will be created
files?: Array<{
// whether or not the file should be created
// `opt` is an object with the result of all the prompts, plus the cli options
when?: boolean | ((opt: Options) => boolean);
// a function which returns the boilerplate code that will be written into te file
// `opt` is the result of the prompt,
// plus if there is a prompt with `name: "name"` than its value will be converted to camelCase, kebab-case ... and be part of opt option, similar to what is described in the "Custom Templates" section.
// plus the cli options
template: (opt: TemplateOptions) => string;
// path to store the generated file. is relative to the cmd cwd
path: (opt: TemplateOptions) => string;
}>;

// a modification to an existing file, usually this is an import of the created file
imports?: Array<{
// whether or not the import should be added
// if not set, it falls back to always (i.e. `when: true`)
when?: boolean | ((opt: Options) => boolean);
// path of the file where the import statement is added to
path: string | ((opt: TemplateOptions) => string);
// should return the import statement or any text which will be added to the file
template: (opt: TemplateOptions) => string;
// if provided, the import statement will be placed before this placeholder,
// otherwise it will be added at the end of file
placeholder?: string | ((opt: TemplateOptions) => string);
}>;
}
```

example:

```js
/// <reference types="@pro-vision/pv-create-component/types.d.ts"/>

/**
* @type {PvCreateComponent.Config}
*/
module.exports = [
{
prompt: {
name: "name",
type: "input",
message: "What's the component's name?:",
validate(value) {
// only letters and numbers. (no special characters such as '-' and '_')
const pass = value.match(/(^[a-zA-Z0-9 ]+$)/g);
if (pass) return true;
return "Please enter only letters, numbers and spaces";
},
filter(name) {
// " Related Topics " -> "related topics"
return (
name
.trim()
.toLowerCase()
// only one empty space between letters is allowed
.replace(/ ( )+/g, " ")
);
},
},
},
{
prompt: {
name: "type",
type: "list",
message: "What type of component should it be",
choices: ["UI", "HOC"],
},
files: [
{
when: (opt) => opt.type === "UI",
template: require("./templates/uiComponentTemplate"),
path: (opt) => `src/${opt.kebabCase}.js`,
},
{
when: (opt) => opt.type === "UI",
template: require("./templates/uiComponentTemplate"),
path: (opt) => `src/${opt.camelCase}.jsx`,
},
],
imports: [
{
when: (opt) => opt.type === "UI",
path: "/src/main.js",
template: (opt) => `import "src/${opt.camelCase}.jsx"`,
placeholder: "/* IMPORT PLACEHOLDER */",
},
],
},
];
```

## Using Programmatically

You can also use the generator directly. For example in a project scaffolding script.
Expand Down
4 changes: 2 additions & 2 deletions packages/pv-create-component/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ module.exports = async function generateFiles(options, config = require("../conf

const {
namespace = "",
name,
type,
name = "",
type = "",
hasTs = false,
hasJs = false,
} = options;
Expand Down
20 changes: 11 additions & 9 deletions packages/pv-create-component/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,28 +48,30 @@ declare namespace PvCreateComponent {
export type Prompt = import("@types/inquirer").Question;

export interface ConfigItem {
// identifier which might be used by the user to find the config which needs modification
/** identifier which might be used by the user to find the config which needs modification */
id?: string;
prompt?: Prompt;
files?: Array<{
id?: string;
// whether or not the file should be created
/** whether or not the file should be created, if not set, it is assumed as `true` */
when?: boolean | ((opt: Options) => boolean);
// function which returns the boilerplate code to be used as the starter
/** function which returns the boilerplate code to be used as the starter */
template: (opt: TemplateOptions) => string;
// path to stored the generated file. is relative to the cmd cwd
/** path to store the generated file. is relative to the cmd cwd */
path: (opt: TemplateOptions) => string;
}>;
imports?: Array<{
id?: string;
// whether or not the import should be added
/** whether or not the import should be added, if not set, it is assumed as `true` */
when?: boolean | ((opt: Options) => boolean);
// path of file where the import statement is added to
/** path of the file where the import statement is added to */
path: string | ((opt: TemplateOptions) => string);
// should return the import statement or any text which will be added to the file
/** should return the import statement or any text which will be added to the file */
template: (opt: TemplateOptions) => string;
// if provided, the import statement will be placed before it,
// otherwise it will be added at the end of file
/**
* if provided, the import statement will be placed before it,
* otherwise it will be added at the end of file
*/
placeholder?: string | ((opt: TemplateOptions) => string);
}>;
}
Expand Down

0 comments on commit c2880b5

Please sign in to comment.