Skip to content

Commit

Permalink
feat(config): read config from package.json, rc file and args
Browse files Browse the repository at this point in the history
  • Loading branch information
nivekcode committed Mar 7, 2020
1 parent 697fece commit 524655f
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 96 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"format:write": "prettier --write 'src/**/*.ts'",
"prebuild": "npm run copy:readme",
"start": "ts-node ./src/bin/svg-to-ts.ts -s './inputfiles/*.svg'",
"start:ofl": "ts-node ./src/bin/svg-to-ts.ts -s './inputfiles/*.svg' --optimizeForLazyLoading true",
"start:help": "ts-node ./src/bin/svg-to-ts.ts -h",
"start:regex": "ts-node ./src/bin/svg-to-ts.ts -s './inputfilesRegex/**/*.svg'",
"start:kebap": "ts-node ./src/bin/svg-to-ts.ts -s './inputfiles/*.svg' -d KEBAB",
Expand Down Expand Up @@ -53,6 +54,7 @@
"chalk": "^3.0.0",
"commander": "^4.0.1",
"cosmiconfig": "^6.0.0",
"glob": "^7.1.6",
"lodash.camelcase": "^4.3.0",
"lodash.kebabcase": "^4.1.1",
"lodash.snakecase": "^4.1.1",
Expand All @@ -66,7 +68,6 @@
"@types/jest": "^24.0.23",
"@types/node": "^12.12.8",
"copyfiles": "^2.1.1",
"glob": "^7.1.6",
"husky": "^3.1.0",
"jest": "^24.9.0",
"pretty-quick": "^2.0.1",
Expand Down
111 changes: 34 additions & 77 deletions src/bin/svg-to-ts.ts
Original file line number Diff line number Diff line change
@@ -1,97 +1,54 @@
#!/usr/bin/env node
import commander from 'commander';
import { cosmiconfig, cosmiconfigSync } from 'cosmiconfig';

import * as packgeJSON from '../../package.json';
import { Delimiter } from '../lib/generators/code-snippet-generators';
import { convertToSingleFile } from '../lib/converters/single-file.converter';
import { convertToMultipleFiles } from '../lib/converters/multiple-files.converter';
import { DEFAULT_OPTIONS } from '../lib/options/default-options';
import { getOptions, MultiFileConvertionOptions, SingleFileConvertionOptions } from '../lib/options/convertion-options';

import * as packgeJSON from '../../package.json';

export interface ConvertionOptions {
delimiter: Delimiter;
typeName: string;
prefix: string;
fileName: string;
interfaceName: string;
srcFiles: string[];
outputDirectory: string;
modelOutputPath: string;
modelFileName: string;
}

const DEFAULTS = {
fileName: 'my-icons',
delimiter: Delimiter.SNAKE,
interfaceName: 'MyIcon',
outputDirectory: './dist',
prefix: 'myIcon',
sourceFilesRegex: ['*.svg'],
typeName: 'myIcons',
optimizeForLazyLoading: false
};

function collect(value, previous) {
return previous.concat([value]);
}

const moduleName = 'svg-to-ts';
const explorerSync = cosmiconfigSync(moduleName);

const searchedFor = explorerSync.search();
console.log('Searchedfor', searchedFor);
const collect = (value, previous) => previous.concat([value]);

commander
.version(packgeJSON.version)
.option('-t --typeName <string>', 'name of the generated enumeration type', DEFAULTS.typeName)
.option('-f --fileName <string>', 'name of the generated file', DEFAULTS.fileName)
.option('-t --typeName <string>', 'name of the generated enumeration type', DEFAULT_OPTIONS.typeName)
.option('-f --fileName <string>', 'name of the generated file', DEFAULT_OPTIONS.fileName)
.option(
'-d --delimiter <Delimiter>',
`delimiter which is used to generate the types and name properties (${Object.values(Delimiter).join(',')})`,
DEFAULTS.delimiter
DEFAULT_OPTIONS.delimiter
)
.option('-p --prefix <string>', 'prefix for the generated svg constants', DEFAULTS.prefix)
.option('-i --interfaceName <string>', 'name for the generated interface', DEFAULTS.interfaceName)
.option('-p --prefix <string>', 'prefix for the generated svg constants', DEFAULT_OPTIONS.prefix)
.option('-i --interfaceName <string>', 'name for the generated interface', DEFAULT_OPTIONS.interfaceName)
.option('-s --srcFiles <value>', 'name of the source directory', collect, [])
.option('-o --outputDirectory <string>', 'name of the output directory', DEFAULTS.outputDirectory)
.option('--optimizeForLazyLoading <boolean>', 'optimize the output for lazyloading', DEFAULTS.optimizeForLazyLoading)
.option('--modelOutputPath <string>', 'Output path for the types file')
.option('--modelFileName <string>', 'FileName of the model file')
.option('-o --outputDirectory <string>', 'name of the output directory', DEFAULT_OPTIONS.outputDirectory)
.option(
'--optimizeForLazyLoading <boolean>',
'optimize the output for lazyloading',
DEFAULT_OPTIONS.optimizeForLazyLoading
)
.option(
'--modelOutputPath <string>',
'Output path for the types file (only necessary when optimizeForLazyLoading option is enabled)',
DEFAULT_OPTIONS.modelOutputPath
)
.option(
'--modelFileName <string>',
'FileName of the model file (only necessary when optimizeForLazyLoading option is enabled)',
DEFAULT_OPTIONS.modelFileName
)
.option(
'--iconsFolderName <string>',
'Name of the folder the icons will be generated to (only necessary when optimizeForLazyLoading option is enabled)',
DEFAULT_OPTIONS.iconsFolderName
)
.parse(process.argv);

const {
delimiter,
fileName,
interfaceName,
outputDirectory,
prefix,
typeName,
modelFileName,
modelOutputPath
} = commander;

// Because of commander adding default value to params
// See: https://stackoverflow.com/questions/30238654/commander-js-collect-multiple-options-always-include-default
let srcFiles = commander.srcFiles;
if (srcFiles.length === 0) {
srcFiles = DEFAULTS.sourceFilesRegex;
}
const optimizeForLazyLoading = commander.optimizeForLazyLoading;

const convertionOptions = {
delimiter,
typeName,
fileName,
prefix,
interfaceName,
srcFiles,
outputDirectory,
modelOutputPath,
modelFileName
};
const convertionOptions = getOptions();

if (optimizeForLazyLoading) {
convertToMultipleFiles(convertionOptions);
if (convertionOptions.optimizeForLazyLoading) {
convertToMultipleFiles(convertionOptions as MultiFileConvertionOptions);
} else {
convertToSingleFile(convertionOptions);
convertToSingleFile(convertionOptions as SingleFileConvertionOptions);
}
23 changes: 11 additions & 12 deletions src/lib/converters/multiple-files.converter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as path from 'path';

import { ConvertionOptions } from '../../bin/svg-to-ts';

import {
generateExportStatement,
generateInterfaceDefinition,
Expand All @@ -15,11 +13,11 @@ import { deleteFiles, deleteFolder, extractSvgContent, writeFile } from '../help
import { compileSources } from '../compiler/typescript-compiler';
import { info, success } from '../helpers/log-helper';
import { svgOptimizer } from '../helpers/svg-optimization';
import { MultiFileConvertionOptions } from '../options/convertion-options';

const generateIconsFolderName = 'build';
const typesDelimitor = ' | ';

export const convertToMultipleFiles = async (convertionOptions: ConvertionOptions): Promise<void> => {
export const convertToMultipleFiles = async (convertionOptions: MultiFileConvertionOptions): Promise<void> => {
const {
typeName,
interfaceName,
Expand All @@ -28,15 +26,16 @@ export const convertToMultipleFiles = async (convertionOptions: ConvertionOption
outputDirectory,
srcFiles,
modelOutputPath,
modelFileName
modelFileName,
iconsFolderName
} = convertionOptions;
let indexFileContent = '';
let types = generateTypeDefinition(typeName);

try {
const filePaths = await getFilePathsFromRegex(srcFiles);
await deleteFolder(`${outputDirectory}/${generateIconsFolderName}`);
info(`deleting output directory: ${outputDirectory}/${generateIconsFolderName}`);
await deleteFolder(`${outputDirectory}/${iconsFolderName}`);
info(`deleting output directory: ${outputDirectory}/${iconsFolderName}`);

for (let i = 0; i < filePaths.length; i++) {
const fileNameWithEnding = path.basename(filePaths[i]);
Expand All @@ -50,17 +49,17 @@ export const convertToMultipleFiles = async (convertionOptions: ConvertionOption
const typeName = generateTypeName(filenameWithoutEnding, delimiter);
const svgConstant = generateUntypedSvgConstant(variableName, typeName, optimizedSvg.data);
const generatedFileName = `${prefix}-${filenameWithoutEnding}.icon`;
indexFileContent += generateExportStatement(generatedFileName, generateIconsFolderName);
await writeFile(`${outputDirectory}/${generateIconsFolderName}`, generatedFileName, svgConstant);
info(`write file svg: ${outputDirectory}/${generateIconsFolderName}/${generatedFileName}.ts`);
indexFileContent += generateExportStatement(generatedFileName, iconsFolderName);
await writeFile(`${outputDirectory}/${iconsFolderName}`, generatedFileName, svgConstant);
info(`write file svg: ${outputDirectory}/${iconsFolderName}/${generatedFileName}.ts`);

types += i === filePaths.length - 1 ? `'${typeName}';` : `'${typeName}'${typesDelimitor}`;
}
}
await writeFile(outputDirectory, 'index', indexFileContent);
info(`write index.ts`);
const generatedTypeScriptFilePaths = await getFilePathsFromRegex([
`${outputDirectory}/${generateIconsFolderName}/*.ts`,
`${outputDirectory}/${iconsFolderName}/*.ts`,
`${outputDirectory}/index.ts`
]);
compileSources(generatedTypeScriptFilePaths);
Expand All @@ -70,7 +69,7 @@ export const convertToMultipleFiles = async (convertionOptions: ConvertionOption

if (modelOutputPath && modelFileName) {
const modelFile = (types += generateInterfaceDefinition(interfaceName, typeName));
await writeFile(modelOutputPath, `${modelFileName}.model`, modelFile);
await writeFile(modelOutputPath, modelFileName, modelFile);
info(`model-file successfully generated under ${modelOutputPath}/${modelFileName}.model.ts`);
}

Expand Down
11 changes: 5 additions & 6 deletions src/lib/converters/single-file.converter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as path from 'path';

import { ConvertionOptions } from '../../bin/svg-to-ts';

import {
generateInterfaceDefinition,
generateSvgConstant,
Expand All @@ -11,12 +9,13 @@ import {
} from '../generators/code-snippet-generators';
import { getFilePathsFromRegex } from '../helpers/regex-helpers';
import { extractSvgContent, writeFile } from '../helpers/file-helpers';
import { success, underlineSuccess } from '../helpers/log-helper';
import { error, success, underlineSuccess } from '../helpers/log-helper';
import { svgOptimizer } from '../helpers/svg-optimization';
import { SingleFileConvertionOptions } from '../options/convertion-options';

const typesDelimitor = ' | ';

export const convertToSingleFile = async (convertionOptions: ConvertionOptions): Promise<void> => {
export const convertToSingleFile = async (convertionOptions: SingleFileConvertionOptions): Promise<void> => {
const { typeName, prefix, delimiter, interfaceName, outputDirectory, srcFiles, fileName } = convertionOptions;
let svgConstants = '';
let types = generateTypeDefinition(typeName);
Expand Down Expand Up @@ -44,7 +43,7 @@ export const convertToSingleFile = async (convertionOptions: ConvertionOptions):
await writeFile(outputDirectory, fileName, fileContent);
success(`Icons file successfully generated under ${underlineSuccess(outputDirectory)}`);
}
} catch (error) {
error('Something went wrong', error);
} catch (exception) {
error(`Something went wrong: ${exception}`);
}
};
39 changes: 39 additions & 0 deletions src/lib/options/args-collector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import commander from 'commander';
import { MultiFileConvertionOptions, SingleFileConvertionOptions } from './convertion-options';
import { DEFAULT_OPTIONS } from './default-options';

export const collectArgumentOptions = (): SingleFileConvertionOptions | MultiFileConvertionOptions => {
const {
delimiter,
fileName,
interfaceName,
outputDirectory,
prefix,
typeName,
modelFileName,
modelOutputPath,
iconsFolderName,
optimizeForLazyLoading
} = commander;

// Because of commander adding default value to params
// See: https://stackoverflow.com/questions/30238654/commander-js-collect-multiple-options-always-include-default
let srcFiles = commander.srcFiles;
if (srcFiles.length === 0) {
srcFiles = DEFAULT_OPTIONS.srcFiles;
}

return {
delimiter,
fileName,
interfaceName,
srcFiles,
outputDirectory,
prefix,
typeName,
modelFileName,
modelOutputPath,
iconsFolderName,
optimizeForLazyLoading
};
};
74 changes: 74 additions & 0 deletions src/lib/options/config-collector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { cosmiconfigSync } from 'cosmiconfig';

import * as packgeJSON from '../../../package.json';
import { info } from '../helpers/log-helper';

import { MultiFileConvertionOptions, SingleFileConvertionOptions } from './convertion-options';
import { DEFAULT_OPTIONS } from './default-options';

export const collectConfigurationOptions = (): SingleFileConvertionOptions | MultiFileConvertionOptions | null => {
const explorerSync = cosmiconfigSync(packgeJSON.name);
const cosmiConfigResult = explorerSync.search();
cosmiConfigResult ? info(`Configuration found under: ${cosmiConfigResult.filepath}`) : info('No config found');
return cosmiConfigResult ? mergeWithDefaults(cosmiConfigResult.config) : null;
};

const mergeWithDefaults = (
options: MultiFileConvertionOptions | SingleFileConvertionOptions
): MultiFileConvertionOptions | SingleFileConvertionOptions => {
const configOptions = { ...options };
if (!configOptions.typeName) {
configOptions.typeName = DEFAULT_OPTIONS.typeName;
info(`No typeName provided, "${DEFAULT_OPTIONS.typeName}" will be used`);
}

if (!configOptions.interfaceName) {
configOptions.interfaceName = DEFAULT_OPTIONS.interfaceName;
info(`No interfaceName provided, "${DEFAULT_OPTIONS.interfaceName}" will be used`);
}

if (!configOptions.prefix) {
configOptions.prefix = DEFAULT_OPTIONS.prefix;
info(`No prefix provided, "${DEFAULT_OPTIONS.prefix}" will be used`);
}

if (!configOptions.delimiter) {
configOptions.delimiter = DEFAULT_OPTIONS.delimiter;
info(`No delimiter provided, "${DEFAULT_OPTIONS.delimiter}" will be used`);
}

if (!configOptions.outputDirectory) {
configOptions.outputDirectory = DEFAULT_OPTIONS.outputDirectory;
info(`No outputDirectory provided, "${DEFAULT_OPTIONS.outputDirectory}" will be used`);
}

if (!configOptions.srcFiles) {
configOptions.srcFiles = DEFAULT_OPTIONS.srcFiles;
info(`No srcFiles provided, "${DEFAULT_OPTIONS.srcFiles}" will be used`);
}

if (configOptions.optimizeForLazyLoading) {
if (!(configOptions as MultiFileConvertionOptions).modelOutputPath) {
(configOptions as MultiFileConvertionOptions).modelOutputPath = DEFAULT_OPTIONS.modelOutputPath;
info(`No modelOutputPath provided, "${DEFAULT_OPTIONS.modelOutputPath}" will be used`);
}

if (!(configOptions as MultiFileConvertionOptions).modelFileName) {
(configOptions as MultiFileConvertionOptions).modelFileName = DEFAULT_OPTIONS.modelFileName;
info(`No modelFileName provided, "${DEFAULT_OPTIONS.modelFileName}" will be used`);
}

if (!(configOptions as MultiFileConvertionOptions).iconsFolderName) {
(configOptions as MultiFileConvertionOptions).iconsFolderName = DEFAULT_OPTIONS.iconsFolderName;
info(`No iconsFolderName provided, "${DEFAULT_OPTIONS.iconsFolderName}" will be used`);
}

return configOptions as MultiFileConvertionOptions;
} else {
if (!(configOptions as SingleFileConvertionOptions).fileName) {
(configOptions as SingleFileConvertionOptions).fileName = DEFAULT_OPTIONS.modelFileName;
info(`No fileName provided, "${DEFAULT_OPTIONS.modelFileName}" will be used`);
}
return configOptions as SingleFileConvertionOptions;
}
};
Loading

0 comments on commit 524655f

Please sign in to comment.