cra-template-sdw
Version:
The base SDW template for Create React App.
406 lines (385 loc) • 13.9 kB
JavaScript
const { isEmpty, padStart, replace, trimStart } = require('lodash');
const required = () => {
return (value) => {
return isEmpty(value) ? 'This field is required' : true;
};
};
const validateConfirm = () => {
return (value) => {
return value !== 'y' || value !== 'N' ? '"y" or "N" only' : true;
};
};
const sanitize = value => replace(value, ' ', '');
const withConcat = value => `with hoc${trimStart(
padStart(value, value.length + 1),
'withoc'
)}`;
module.exports = (plop) => {
plop.setGenerator('page', {
description: 'Generate a Page',
prompts: [
{
type: 'input',
name: 'name',
message: 'Enter name of Page:',
validate: required(),
},
{
type: 'input',
name: 'element',
message: 'What is the first HTML element of your page? Default:',
default: 'main',
filter: sanitize,
},
{
type: 'confirm',
name: 'wantBase',
message: 'Do you want to generate base Page? Default: N',
default: false,
validate: validateConfirm(),
},
],
actions: ({ wantBase }) => {
let actions = [
{
type: 'add',
path: 'src/pages/{{pascalCase name}}/{{pascalCase name}}.scss',
templateFile: 'plop-templates/pages/Page/Page.scss.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/pages/index.ts',
pattern: '/* INDEX_EXPORTS */',
template: "export * from './{{pascalCase name}}';",
},
{
type: 'append',
path: 'src/index.tsx',
pattern: '/* PAGE_IMPORTS */',
template: '\t{{pascalCase name}},\n' +
'\t{{pascalCase name}}WithHoc,',
},
{
type: 'append',
path: 'src/index.tsx',
pattern: '<Routes>',
template: "\t\t\t\t\t<Route path='/{{dashCase name}}' element={<{{pascalCase name}}WithHoc />} />",
},
];
if (wantBase) {
actions = actions.concat([
{
type: 'add',
path: 'src/pages/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/pages/Page/index-base.tsx.hbs',
skipIfExists: true,
},
]);
return actions;
}
actions = actions.concat([
{
type: 'add',
path: 'src/pages/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/pages/Page/index.tsx.hbs',
skipIfExists: true,
},
]);
return actions;
},
});
plop.setGenerator('component', {
description: 'Generate a Component',
prompts: [
{
type: 'input',
name: 'name',
message: 'Enter name of Component:',
validate: required(),
},
{
type: 'input',
name: 'element',
message: 'What is the main HTML element wrapper? Default:',
default: 'div',
filter: sanitize,
},
{
type: 'confirm',
name: 'wantBase',
message: 'Do you want to generate base Component? Default: N',
default: false,
validate: validateConfirm(),
},
],
actions: ({ wantBase }) => {
let actions = [
{
type: 'add',
path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.scss',
templateFile: 'plop-templates/components/Component/Component.scss.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/components/index.ts',
pattern: '/* INDEX_EXPORTS */',
template: "export * from './{{pascalCase name}}';",
},
];
if (wantBase) {
actions = actions.concat([
{
type: 'add',
path: 'src/components/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/components/Component/index-base.tsx.hbs',
skipIfExists: true,
},
]);
return actions;
}
actions = actions.concat([
{
type: 'add',
path: 'src/components/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/components/Component/index.tsx.hbs',
skipIfExists: true,
},
]);
return actions;
},
});
plop.setGenerator('hoc', {
description: 'Generate a Higher-Order Component',
prompts: [
{
type: 'input',
name: 'name',
message: 'Enter name of Higher-Order Component:',
validate: required(),
filter: withConcat,
},
],
actions: [
{
type: 'add',
path: 'src/hoc/{{pascalCase name}}/index.tsx',
templateFile: 'plop-templates/hoc/WithHoc/index.tsx.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/hoc/index.ts',
pattern: '/* INDEX_EXPORTS */',
template: "export * from './{{pascalCase name}}';",
},
],
});
plop.setGenerator('redux', {
description: 'Generate a Redux Structure',
prompts: [
{
type: 'input',
name: 'model',
message: 'Enter name of Model:',
validate: required(),
},
{
type: 'input',
name: 'page',
message: 'In what page you want to add Redux imports? Default:',
default: 'app',
},
{
type: 'confirm',
name: 'wantImportsOnly',
message: 'Do you want Redux imports only? Default: N',
default: false,
validate: validateConfirm(),
},
{
type: 'confirm',
name: 'wantFormikYup',
message: 'Will you use Formik and Yup? Default: Y',
default: true,
validate: validateConfirm(),
},
],
actions: ({ wantImportsOnly, wantFormikYup }) => {
let actions = [
{
type: 'append',
path: 'src/pages/{{pascalCase page}}/index.tsx',
pattern: "} from '../../hoc';",
template: '\nimport {\n' +
'\tcreate{{pascalCase model}},\n' +
'\tdelete{{pascalCase model}},\n' +
'\tgetAll{{pascalCase model}}s,\n' +
'\tgetOne{{pascalCase model}},\n' +
'\tupdate{{pascalCase model}},\n' +
"} from '../../controllers';\n\n" +
'import {\n' +
'\tresetCreate{{pascalCase model}},\n'+
'\tresetUpdate{{pascalCase model}},\n'+
'\tselectAll{{pascalCase model}}s,\n' +
'\tselectAll{{pascalCase model}}sError,\n' +
'\tselectAll{{pascalCase model}}sStatus,\n' +
'\tselectCreated{{pascalCase model}},\n' +
'\tselectCreate{{pascalCase model}}Error,\n' +
'\tselectCreate{{pascalCase model}}Status,\n' +
'\tselectDeleted{{pascalCase model}},\n' +
'\tselectDelete{{pascalCase model}}Error,\n' +
'\tselectDelete{{pascalCase model}}Status,\n' +
'\tselectOne{{pascalCase model}},\n' +
'\tselectOne{{pascalCase model}}Error,\n' +
'\tselectOne{{pascalCase model}}Status,\n' +
'\tselectUpdated{{pascalCase model}},\n' +
'\tselectUpdate{{pascalCase model}}Error,\n' +
'\tselectUpdate{{pascalCase model}}Status,\n' +
'\tsetCreate{{pascalCase model}},\n' +
'\tsetUpdate{{pascalCase model}},\n' +
"} from '../../store';",
abortOnFail: true,
},
{
type: 'append',
path: 'src/pages/{{pascalCase page}}/index.tsx',
pattern: 'const dispatch = useAppDispatch();',
template: '\n\tuseEffect(() => {\n' +
'\t\tdispatch(getAll{{pascalCase model}}s());\n' +
'\t\tdispatch(getOne{{pascalCase model}}(1));\n' +
'\t}, [dispatch]);\n\n' +
'\tconst all{{pascalCase model}}s = useAppSelector(selectAll{{pascalCase model}}s);\n' +
'\tconst all{{pascalCase model}}sStatus = useAppSelector(selectAll{{pascalCase model}}sStatus);\n' +
'\tconst all{{pascalCase model}}sError = useAppSelector(selectAll{{pascalCase model}}sError);\n\n' +
'\tconst handleGetOne{{pascalCase model}} = (id: number) => {\n' +
'\t\tdispatch(getOne{{pascalCase model}}(id));\n' +
'\t};\n\n' +
'\tconst one{{pascalCase model}} = useAppSelector(selectOne{{pascalCase model}});\n' +
'\tconst one{{pascalCase model}}Status = useAppSelector(selectOne{{pascalCase model}}Status);\n' +
'\tconst one{{pascalCase model}}Error = useAppSelector(selectOne{{pascalCase model}}Error);\n\n' +
'\tconst handleCreate{{pascalCase model}} = (e: any, values: any, resetForm: any) => {\n' +
'\t\thandleFormDataChange(e, setCreate{{pascalCase model}});\n' +
'\t\thandleFormikDataChange(values, setCreate{{pascalCase model}}, resetForm);\n' +
'\t\tdispatch(create{{pascalCase model}}()).unwrap()\n' +
'\t\t\t.then(() => {\n' +
'\t\t\t\tdispatch(resetCreate{{pascalCase model}}());\n' +
'\t\t\t});\n' +
'\t};\n\n' +
'\tconst created{{pascalCase model}} = useAppSelector(selectCreated{{pascalCase model}});\n' +
'\tconst create{{pascalCase model}}Status = useAppSelector(selectCreate{{pascalCase model}}Status);\n' +
'\tconst create{{pascalCase model}}Error = useAppSelector(selectCreate{{pascalCase model}}Error);\n\n' +
'\tconst handleUpdate{{pascalCase model}} = (e: any, values: any, resetForm: any, id: number) => {\n' +
'\t\thandleFormDataChange(e, setUpdate{{pascalCase model}});\n' +
'\t\thandleFormikDataChange(values, setUpdate{{pascalCase model}}, resetForm);\n' +
'\t\tdispatch(update{{pascalCase model}}(id)).unwrap()\n' +
'\t\t\t.then(() => {\n' +
'\t\t\t\tdispatch(resetUpdate{{pascalCase model}}());\n' +
'\t\t\t});\n' +
'\t};\n\n' +
'\tconst updated{{pascalCase model}} = useAppSelector(selectUpdated{{pascalCase model}});\n' +
'\tconst update{{pascalCase model}}Status = useAppSelector(selectUpdate{{pascalCase model}}Status);\n' +
'\tconst update{{pascalCase model}}Error = useAppSelector(selectUpdate{{pascalCase model}}Error);\n\n' +
'\tconst handleDelete{{pascalCase model}} = (id: number) => {\n' +
'\t\tdispatch(delete{{pascalCase model}}(id));\n' +
'\t};\n\n' +
'\tconst deleted{{pascalCase model}} = useAppSelector(selectDeleted{{pascalCase model}});\n' +
'\tconst delete{{pascalCase model}}Status = useAppSelector(selectDelete{{pascalCase model}}Status);\n' +
'\tconst delete{{pascalCase model}}Error = useAppSelector(selectDelete{{pascalCase model}}Error);',
abortOnFail: true,
},
];
if (wantImportsOnly) return actions;
actions = actions.concat([
{
type: 'add',
path: 'src/models/{{pascalCase model}}.ts',
templateFile: 'plop-templates/models/Model.ts.hbs',
skipIfExists: true,
},
{
type: 'add',
path: 'src/models/index.ts',
templateFile: 'plop-templates/models/index.ts.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/models/index.ts',
pattern: '/* MODEL_EXPORTS */',
template: "export * from './{{pascalCase model}}';",
},
{
type: 'add',
path: 'src/controllers/{{camelCase model}}Controller.ts',
templateFile: 'plop-templates/controllers/modelController.ts.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/controllers/index.ts',
pattern: '/* CONTROLLER_EXPORTS */',
template: "export * from './{{camelCase model}}Controller';",
},
{
type: 'add',
path: 'src/requests/{{camelCase model}}Request.ts',
templateFile: `plop-templates/requests/${
wantFormikYup ? 'modelRequest' : 'modelRequest-base'
}.ts.hbs`,
skipIfExists: true,
},
{
type: 'append',
path: 'src/requests/index.ts',
pattern: '/* REQUEST_EXPORTS */',
template: "export * from './{{camelCase model}}Request';",
},
{
type: 'add',
path: 'src/store/{{pascalCase model}}/{{camelCase model}}Slice.ts',
templateFile: 'plop-templates/store/Model/modelSlice.ts.hbs',
skipIfExists: true,
},
{
type: 'add',
path: 'src/store/{{pascalCase model}}/index.ts',
templateFile: 'plop-templates/store/Model/index.ts.hbs',
skipIfExists: true,
},
{
type: 'append',
path: 'src/store/index.ts',
pattern: "import { Action, configureStore, ThunkAction } from '@reduxjs/toolkit';",
template: "import { {{pascalCase model}}Reducer } from './{{pascalCase model}}';",
},
{
type: 'append',
path: 'src/store/index.ts',
pattern: 'reducer: {',
template: '\t\t{{camelCase model}}: {{pascalCase model}}Reducer,'
},
{
type: 'append',
path: 'src/store/index.ts',
pattern: '/* STORE_EXPORTS */',
template: "export * from './{{pascalCase model}}';",
},
]);
return actions;
}
});
plop.setGenerator('env', {
description: 'Generate env',
prompts: [],
actions: [
{
type: 'add',
path: './.env',
templateFile: 'plop-templates/.env.hbs',
skipIfExists: true,
},
],
});
};