cra-template-econsor
Advanced tools
Comparing version 0.1.4 to 0.1.5
{ | ||
"name": "cra-template-econsor", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "react", |
@@ -28,3 +28,5 @@ { | ||
"@data-driven-forms/mui-component-mapper": "^3.8.4", | ||
"@data-driven-forms/react-form-renderer": "^3.8.4" | ||
"@data-driven-forms/react-form-renderer": "^3.8.4", | ||
"commander": "^7.2.0", | ||
"inquirer": "^8.1.1" | ||
}, | ||
@@ -31,0 +33,0 @@ "eslintConfig": { |
const fs = require('fs'); | ||
const path = require('path'); | ||
const mkdirp = require('mkdirp'); | ||
const { program } = require('commander'); | ||
const { prompt } = require('inquirer'); | ||
@@ -42,22 +44,4 @@ const getReplaceNames = processName => { | ||
const getTemplateFiles = async (dirPath) => { | ||
const files = []; | ||
const pathsInDir = await fs.promises.readdir(dirPath); | ||
for (const pathInDir of pathsInDir) { | ||
const path = `${dirPath}/${pathInDir}`; | ||
const isDirectory = (await fs.promises.stat(path)).isDirectory(); | ||
if (isDirectory) { | ||
const subPaths = await getTemplateFiles(path); | ||
files.push(...subPaths); | ||
} else { | ||
if (path.includes('linkingActions.js')) continue; | ||
const data = await fs.promises.readFile(path, 'utf8'); | ||
files.push({ path, data }); | ||
} | ||
} | ||
return files; | ||
}; | ||
const getLinkingActions = async (filePath) => { | ||
const linkingActions = require(filePath); | ||
const getLinkingActions = async () => { | ||
const linkingActions = eval(require('./crp.config').find(x => x.path.includes('/src/features/HelloWorlds/links.js')).data); | ||
const actions = []; | ||
@@ -84,2 +68,83 @@ for (const linkingAction of linkingActions) { | ||
const label = key => key | ||
.replace(/([A-Z])/g, ' $1') | ||
.replace(/^./, str => str.toUpperCase()); | ||
const schemaMap = (type, key, options) => { | ||
const commonOptions = { | ||
name: key, | ||
label: label(key), | ||
isRequired: true, | ||
validate: [{ type: 'required' }], | ||
}; | ||
switch (type) { | ||
case 'string': | ||
return { | ||
...commonOptions, | ||
component: 'text-field', | ||
type: 'text', | ||
}; | ||
case 'text': | ||
return { | ||
...commonOptions, | ||
component: 'textarea', | ||
}; | ||
case 'email': | ||
return { | ||
...commonOptions, | ||
component: 'text-field', | ||
validate: [ | ||
{ type: 'required' }, | ||
{ type: 'pattern', pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,}$' }, | ||
], | ||
}; | ||
case 'richtext': | ||
return { | ||
...commonOptions, | ||
component: 'textarea', | ||
}; | ||
case 'password': | ||
return { | ||
...commonOptions, | ||
component: 'text-field', | ||
type: 'password', | ||
}; | ||
case 'integer': | ||
case 'biginteger': | ||
case 'decimal': | ||
case 'float': | ||
return { | ||
...commonOptions, | ||
component: 'text-field', | ||
type: 'number', | ||
}; | ||
case 'enumeration': | ||
return { | ||
...commonOptions, | ||
component: 'select', | ||
options: options.map((option) => ({ | ||
value: option, | ||
label: label(option), | ||
})), | ||
}; | ||
case 'date': | ||
case 'datetime': | ||
case 'time': | ||
return { | ||
...commonOptions, | ||
component: 'date-picker', | ||
}; | ||
case 'boolean': | ||
return { | ||
...commonOptions, | ||
component: 'switch', | ||
}; | ||
case 'json': | ||
return { | ||
...commonOptions, | ||
component: 'textarea', | ||
}; | ||
} | ||
}; | ||
const updateSchemasFile = async () => { | ||
@@ -93,72 +158,14 @@ const filePath = `${__dirname}/src/config/schemas.ts`; | ||
const generate = (attributes) => { | ||
const fields = Object.entries(attributes).map(([key, value]) => { | ||
switch (value.type) { | ||
case 'string': | ||
return { | ||
component: 'text-field', | ||
name: key, | ||
label: label(key), | ||
type: 'text', | ||
isRequired: true, | ||
validate: [{ type: 'required' }], | ||
}; | ||
case 'text': | ||
case 'richtext': | ||
return { | ||
component: 'plain-text', | ||
name: key, | ||
label: label(key), | ||
type: 'text', | ||
isRequired: true, | ||
validate: [{ type: 'required' }], | ||
}; | ||
case 'email': | ||
return { | ||
component: 'text-field', | ||
name: key, | ||
label: label(key), | ||
validate: [{ type: 'pattern', pattern: '[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,}$' }], | ||
}; | ||
case 'password': | ||
return { | ||
component: 'text-field', | ||
name: key, | ||
label: label(key), | ||
type: 'password', | ||
isRequired: true, | ||
validate: [{ type: 'required' }], | ||
}; | ||
case 'integer': | ||
case 'decimal': | ||
case 'float': | ||
case 'biginteger': | ||
return { | ||
component: 'text-field', | ||
name: key, | ||
label: label(key), | ||
type: 'number', | ||
isRequired: true, | ||
validate: [{ type: 'required' }], | ||
}; | ||
case 'boolean': | ||
return { | ||
component: 'switch', | ||
name: key, | ||
label: label(key), | ||
}; | ||
case 'datetime': | ||
case 'time': | ||
case 'enumeration': | ||
default: | ||
return null; | ||
const insert = (replaceNames, attributes) => { | ||
data += '\n'; | ||
const attr = []; | ||
Object.entries(attributes).forEach(([key, value]) => { | ||
const x = schemaMap(value.type, key, value.enum); | ||
if (x) { | ||
attr.push(x); | ||
} | ||
}); | ||
return { fields }; | ||
}; | ||
const insert = (replaceNames, attributes) => { | ||
data += replaceNames(`export const helloWorldSchema = ${JSON.stringify({ fields: attr })};`); | ||
data += '\n'; | ||
data += replaceNames(`export const helloWorldSchema = ${JSON.stringify(generate(attributes))};`); | ||
data += '\n'; | ||
}; | ||
@@ -184,4 +191,4 @@ const commit = async () => { | ||
case 'text': | ||
case 'email': | ||
case 'richtext': | ||
case 'email': | ||
case 'password': | ||
@@ -191,19 +198,22 @@ reval += `string;`; | ||
case 'integer': | ||
case 'biginteger': | ||
case 'decimal': | ||
case 'float': | ||
case 'biginteger': | ||
reval += `number;`; | ||
break; | ||
case 'boolean': | ||
reval += `boolean;`; | ||
case 'enumeration': | ||
reval += value.enum.reduce((previousValue, currentValue) => `${[previousValue]} | '${currentValue}'`, '').slice(3); | ||
reval += ';'; | ||
break; | ||
case 'date': | ||
case 'datetime': | ||
case 'time': | ||
reval += `string;`; | ||
reval += `Date;`; | ||
break; | ||
case 'enumeration': | ||
reval += value.enum.reduce((previousValue, currentValue) => `${[previousValue]} | '${currentValue}'`, '').slice(3); | ||
reval += ';'; | ||
case 'boolean': | ||
reval += `boolean;`; | ||
break; | ||
case 'json': | ||
default: | ||
reval += `any;`; | ||
break; | ||
@@ -230,29 +240,101 @@ } | ||
program | ||
.version('0.0.1') | ||
.description('Create React Feature'); | ||
(async () => { | ||
const templatePath = `${__dirname}/src/features/HelloWorlds`; | ||
const templateFiles = await getTemplateFiles(templatePath); | ||
const schemasFile = await updateSchemasFile(); | ||
const typesFile = await updateTypesFile(); | ||
const { apply, commit } = await getLinkingActions(path.join(templatePath, 'linkingActions.js')); | ||
program | ||
.command('generate [apiPath] [featureName]') | ||
.description('Generate Features') | ||
.action(async (apiPath, featureName) => { | ||
if (!apiPath) { | ||
const answers = await prompt({ | ||
type: 'input', | ||
name: 'path', | ||
message: 'Please specify the path of your strapi API root directory', | ||
}); | ||
apiPath = answers.path; | ||
} | ||
apiPath = path.join(process.cwd(), apiPath, 'api'); | ||
const apiPath = path.join(process.argv[2], 'api'); | ||
for (const processName of await fs.promises.readdir(apiPath)) { | ||
if (processName === 'hello-world' || processName.includes('.')) continue; | ||
if (!featureName) { | ||
const apiFeatures = (await fs.promises.readdir(apiPath)).filter(n => !n.includes('.')); | ||
const answers = await prompt({ | ||
type: 'list', | ||
name: 'featureName', | ||
message: 'Please specify the feature you want to generate', | ||
choices: apiFeatures, | ||
}); | ||
featureName = answers.featureName; | ||
} | ||
const replaceNames = getReplaceNames(processName); | ||
for (let templateFile of templateFiles) { | ||
const filePath = replaceNames(templateFile.path); | ||
const files = require('./crp.config').filter(x => !x.path.includes('/src/features/HelloWorlds/links.js')); | ||
const schemasFile = await updateSchemasFile(); | ||
const typesFile = await updateTypesFile(); | ||
const linkingActions = await getLinkingActions(); | ||
const replaceNames = getReplaceNames(featureName); | ||
for (let templateFile of files) { | ||
const filePath = path.join(__dirname, replaceNames(templateFile.path)); | ||
await mkdirp(path.dirname(filePath)); | ||
await fs.promises.writeFile(filePath, replaceNames(templateFile.data)); | ||
} | ||
const settingsFile = require(path.join(apiPath, processName, `/models/${processName}.settings.json`)).attributes; | ||
const settingsFile = require(path.join(apiPath, featureName, `/models/${featureName}.settings.json`)).attributes; | ||
schemasFile.insert(replaceNames, settingsFile); | ||
typesFile.insert(replaceNames, settingsFile); | ||
apply(replaceNames); | ||
linkingActions.apply(replaceNames); | ||
await schemasFile.commit(); | ||
await typesFile.commit(); | ||
await linkingActions.commit(); | ||
}); | ||
program | ||
.command('eject') | ||
.description('Eject the HelloWorld template') | ||
.action(async () => { | ||
const files = require('./crp.config').filter(x => !x.path.includes('/src/features/HelloWorlds/links.js')); | ||
for (const file of files) { | ||
const filePath = path.join(__dirname, file.path); | ||
await mkdirp(path.dirname(filePath)); | ||
await fs.promises.writeFile(filePath, file.data); | ||
} | ||
const links = require('./crp.config').find(x => x.path.includes('/src/features/HelloWorlds/links.js')); | ||
const filePath = path.join(__dirname, links.path); | ||
await mkdirp(path.dirname(filePath)); | ||
await fs.promises.writeFile(filePath, `module.exports = ${links.data}`); | ||
}); | ||
const getTemplateFiles = async (dirPath) => { | ||
const files = []; | ||
const pathsInDir = await fs.promises.readdir(dirPath); | ||
for (const pathInDir of pathsInDir) { | ||
const path = `${dirPath}/${pathInDir}`; | ||
const isDirectory = (await fs.promises.stat(path)).isDirectory(); | ||
if (isDirectory) { | ||
const subPaths = await getTemplateFiles(path); | ||
files.push(...subPaths); | ||
} else { | ||
if (path.includes('linkingActions.js')) continue; | ||
const data = await fs.promises.readFile(path, 'utf8'); | ||
files.push({ path, data }); | ||
} | ||
} | ||
await schemasFile.commit(); | ||
await typesFile.commit(); | ||
await commit(); | ||
return files; | ||
}; | ||
program | ||
.command('update') | ||
.description('Update the template') | ||
.action(async () => { | ||
const templateFiles = (await getTemplateFiles(path.join(__dirname, '/src/features/HelloWorlds'))).map(x => ({ | ||
...x, | ||
path: x.path.split(__dirname)[1], | ||
})); | ||
await fs.promises.writeFile(path.join(__dirname, './crp.config.js'), `module.exports = ${JSON.stringify(templateFiles)}`); | ||
}); | ||
(async () => { | ||
await program.parseAsync(process.argv); | ||
})(); |
Sorry, the diff of this file is not supported yet
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
83433
119
3
35
1108
3