Skip to content

Commit

Permalink
Add fs utility file and more readability touches
Browse files Browse the repository at this point in the history
  • Loading branch information
ItzikGabay committed Jan 14, 2023
1 parent f44a093 commit a7c2fe1
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 111 deletions.
27 changes: 15 additions & 12 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#! /usr/bin/env node

import { componentPrompt } from './lib/inquirer.js';
import { createFiles, getApplicationModes } from './lib/utils.js';
import { warnUser } from './lib/logs.js';
import { getApplicationModes } from './lib/utils.js';
import { successLog, warnUser } from './lib/logs.js';
import { validateComponentName } from './lib/validation.js';

import language from './lib/language.js';
import appConfig from './lib/config.js';
import { createFiles } from './lib/fs.js';

const init = async () => {
const { isSilentMode, isInteractiveMode } = getApplicationModes(
Expand All @@ -16,13 +17,7 @@ const init = async () => {
if (isInteractiveMode) {
try {
const output = await componentPrompt();

createFiles(
output.inputComponentName,
output.generateFileTypes,
output.componentTemplate,
output.nameConvention,
);
createFiles.apply(null, Object.values(output));
} catch (error) {
if (error.isTtyError) {
throw new Error(language.ERROR_RENDERING_ERR);
Expand Down Expand Up @@ -66,13 +61,15 @@ const init = async () => {
? 'regular'
: appConfig.interactive.defaultComponentTemplate;

createFiles(
const output = [
name,
fileTypeList,
componentTemplate,
appConfig.interactive.defaultNameConvention,
path,
);
];

createFiles.apply(null, output);

return;
}
Expand All @@ -82,6 +79,12 @@ const init = async () => {

try {
await init();
successLog(language.THANK_YOU_MSG);
} catch (error) {
console.log('Internal error: ', error);
if (error.code === 'EEXIST') {
warnUser(language.DIR_ALREADY_EXISTS_ERR);
} else {
warnUser(language.INTERNAL_ERR, error);
console.log(error);
}
}
70 changes: 70 additions & 0 deletions src/lib/fs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import fs from 'fs';
import { CSStemplate, JSXtemplate } from '../react-library/template.js';
import { extractComponentPaths } from './utils.js';

export const createComponentFileType = (name, type, data = '') => {
if (type === 'index') {
return fs.writeFileSync(name, data);
}

if (type.includes('module')) {
return fs.writeFileSync(`${name}.${type}`, data);
}

if (type === 'jsx' || type === 'js') {
return fs.writeFileSync(`${name}.${type}`, data);
}

return fs.writeFileSync(`${name}.${type}.js`, data);
};

export function createFiles(
name,
filesToCreate,
componentTemplate,
nameConvention,
filesPath = '',
) {
if (filesPath.includes('--')) {
filesPath = '';
}

const cmpPaths = extractComponentPaths(name, filesPath);

for (let fileType of filesToCreate) {
// TODO: Create generator class
if (fileType === 'folder') {
fs.mkdirSync(cmpPaths.folder);
}

if (fileType === 'index') {
createComponentFileType(cmpPaths.index, fileType);
}

if (fileType === 'js' || fileType === 'controller') {
createComponentFileType(cmpPaths.clean, fileType);
}

if (fileType === 'css' || fileType === 'scss') {
const styleType = `module.${fileType}`;
const template = CSStemplate(cmpPaths.cnWithCssSupport, fileType);

createComponentFileType(cmpPaths.clean, styleType, template);
}

if (fileType === 'jsx') {
const styleType = filesToCreate.includes('scss') ? 'scss' : 'css';

const template = JSXtemplate(
cmpPaths.cnWithCssSupport,
cmpPaths.cnNormalized,
styleType,
componentTemplate,
);

createComponentFileType(cmpPaths.clean, fileType, template);
}
}

console.log(`Component '${cmpPaths.name}' generated at '${cmpPaths.folder}'`);
}
4 changes: 4 additions & 0 deletions src/lib/language.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ const language = {
NO_ARGUMENTS_ERR: 'No arguments provided.',
NO_CMP_NAME_ERR: 'No component name found. Please provide a component name.',
PROVIDE_VALID_NAME_ERR: 'Please provide a valid component name.',
DIR_ALREADY_EXISTS_ERR:
'Directory already exists. Please provide a new name.',
INTERNAL_ERR: 'Internal error. Please try again: ',
THANK_YOU_MSG: 'Thank you for using crxo!',
};

export default language;
4 changes: 4 additions & 0 deletions src/lib/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export const consoleUser = (color, output) => {
console.log(`${color}${output}\x1b[0m`);
};

export const successLog = output => {
consoleUser('green', output);
};

export const warnUser = message => {
consoleUser('red', message);
};
121 changes: 25 additions & 96 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
import fs from 'fs';
import path from 'path';
import appConfig from './config.js';

import { JSXtemplate, CSStemplate } from '../react-library/template.js';
import { cleanPath, uppercasedString, underscoredString } from './string.js';

function extractComponentPaths(componentName, userInputPath = '') {
export function getApplicationModes(mode) {
const isInteractiveMode = mode === 'interactive' || mode === '-i' || !mode;
const isSilentMode = mode === 'create' || mode === '-c';

return {
isInteractiveMode,
isSilentMode,
};
}

export function getDefaultFilesTypesOptions() {
const allTypes = [
...appConfig.interactive.defaultOptions,
...appConfig.interactive.extrasOptions,
];

return allTypes.map(type => {
return {
name: type,
checked: appConfig.interactive.defaultOptions.includes(type),
};
});
}

export function extractComponentPaths(componentName, userInputPath) {
const cnWithoutSpecialChar = uppercasedString(componentName);
const cnWithCssSupport = underscoredString(componentName);
const cleanUserInputPath = cleanPath(userInputPath);
Expand All @@ -31,95 +52,3 @@ function extractComponentPaths(componentName, userInputPath = '') {
cnWithCssSupport,
};
}

const createComponentFileType = (name, type, data) => {
if (!data) {
data = '';
}

if (type === 'index') {
return fs.writeFileSync(name, data);
}

if (type.includes('module')) {
return fs.writeFileSync(`${name}.${type}`, data);
}

if (type === 'jsx' || type === 'js') {
return fs.writeFileSync(`${name}.${type}`, data);
}

return fs.writeFileSync(`${name}.${type}.js`, data);
};

export function createFiles(
name,
filesToCreate,
componentTemplate,
nameConvention,
filesPath = '',
) {
const cmpPaths = extractComponentPaths(name, filesPath);

for (let fileType of filesToCreate) {
if (fileType === 'folder') {
fs.mkdirSync(cmpPaths.folder);
}

if (fileType === 'index') {
createComponentFileType(cmpPaths.index, fileType);
}

if (fileType === 'js' || fileType === 'controller') {
createComponentFileType(cmpPaths.clean, fileType);
}

if (fileType === 'css' || fileType === 'scss') {
const styleType = `module.${fileType}`;
const template = CSStemplate(cmpPaths.cnWithCssSupport, fileType);

createComponentFileType(cmpPaths.clean, styleType, template);
}

if (fileType === 'jsx') {
const styleType = filesToCreate.includes('scss') ? 'scss' : 'css';

const template = JSXtemplate(
cmpPaths.cnWithCssSupport,
cmpPaths.cnNormalized,
styleType,
componentTemplate,
);

createComponentFileType(cmpPaths.clean, fileType, template);
}
}

console.log(
`[crxo][success] component "${cmpPaths.name}" generated at "${cmpPaths.folder}"`,
);
}

export function getDefaultFilesTypesOptions() {
const allTypes = [
...appConfig.interactive.defaultOptions,
...appConfig.interactive.extrasOptions,
];

return allTypes.map(type => {
return {
name: type,
checked: appConfig.interactive.defaultOptions.includes(type),
};
});
}

export function getApplicationModes(mode) {
const isInteractiveMode = mode === 'interactive' || mode === '-i' || !mode;
const isSilentMode = mode === 'create' || mode === '-c';

return {
isInteractiveMode,
isSilentMode,
};
}
8 changes: 5 additions & 3 deletions src/react-library/template.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { addTemplateImports, addTemplateHooks } from './imports.js';

export const JSXtemplate = (name, uppercased, cssType, templateType) => {
return `${addTemplateImports(templateType, uppercased, cssType)}
const templateImports = addTemplateImports(templateType, uppercased, cssType);
const templateHooks = addTemplateHooks(templateType);

return `${templateImports}
const ${uppercased} = () => {
${addTemplateHooks(templateType)}
return (
${templateHooks} return (
<section className={styles.container}>
<header className={styles.header}>
<p>Component created successfully.</p>
Expand Down

0 comments on commit a7c2fe1

Please sign in to comment.