Skip to content

Commit

Permalink
Merge pull request #234 from pro-vision/bugfix/create-component-types
Browse files Browse the repository at this point in the history
docs(pv-create-component): fix minor typing issue
  • Loading branch information
friewerts authored Nov 26, 2024
2 parents cf0c2bd + c2880b5 commit f65d7b7
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 14 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
26 changes: 14 additions & 12 deletions packages/pv-create-component/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare namespace PvCreateComponent {
name: ComponentName; // e.g. "related content"
type: ComponentTypes; // is this an element or module
hasScss: boolean; // component has .scss file
hasHbs: hasHbs; // component has .hbs file
hasHbs: boolean; // component has .hbs file
dataFile: DataFileType | false;
hasTs: boolean; // component has .ts file
hasJs: boolean; // component has .js file
Expand All @@ -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
when?: boolean | ((opt: Options) => boolean) = true;
// function which returns the boilerplate code to be used as the starter
/** 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 */
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
when: boolean | ((opt: Options) => boolean) = true;
// path of file where the import statement is added to
/** whether or not the import should be added, if not set, it is assumed as `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
/** 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 f65d7b7

Please sign in to comment.