diff --git a/packages/falso/src/lib/abbreviation.ts b/packages/falso/src/lib/abbreviation.ts index 5d4dbf5f7..030b5aa7d 100644 --- a/packages/falso/src/lib/abbreviation.ts +++ b/packages/falso/src/lib/abbreviation.ts @@ -13,7 +13,7 @@ import { data } from './abbreviation.json'; * @example * * randAbbreviation({ length: 10 }) - * + * * @automaticallyGeneratedExamples * @example * SCSI diff --git a/packages/falso/src/lib/account.ts b/packages/falso/src/lib/account.ts index 839d89f07..c638b990c 100644 --- a/packages/falso/src/lib/account.ts +++ b/packages/falso/src/lib/account.ts @@ -21,7 +21,13 @@ export interface AccountOptions extends FakeOptions { * * randAccount({ length: 10 }) * + * @automaticallyGeneratedExamples + * @example + * 752923821 + * 334864247 + * 556647372 */ + export function randAccount( options?: Options ) { diff --git a/scripts/example-generator.js b/scripts/example-generator.js index 21df995b2..e371acef7 100644 --- a/scripts/example-generator.js +++ b/scripts/example-generator.js @@ -1,39 +1,91 @@ const fs = require('fs'); -const [libDirectoryPath] = process.argv.slice(2); +const [directoryPath] = process.argv.slice(2); const GENERATE_INDICATOR = "@automaticallyGeneratedExamples" -// https://regex101.com/r/rlqGTA/1 -const regexp = new RegExp(`(${GENERATE_INDICATOR}).*\\/`,"gs"); -const errors = []; +// https://regex101.com/r/qxpfyX/1 +const regexp = new RegExp(`(${GENERATE_INDICATOR}).*[*]\\/`,"gs"); console.log('Generating examples...') -const filenames = fs -.readdirSync(libDirectoryPath) -.filter((jsonFilename, index, array) => jsonFilename.includes(".json") && array.find(tsFilename => tsFilename.replace('ts','json') === jsonFilename)) - -filenames.forEach(filename => { - try { - const tsFilepath = `${libDirectoryPath}${filename.replace('json','ts')}` - const tsFileContent = fs.readFileSync(tsFilepath).toString(); - if(!tsFileContent.includes(GENERATE_INDICATOR)) { - console.log(`file is missing '${GENERATE_INDICATOR}' and will be ignored ${filename.replace('json','ts')}`); - return; - } - const jsonFilepath = `${libDirectoryPath}${filename}` - const jsonFileContent = JSON.parse(fs.readFileSync(jsonFilepath)); - if(jsonFileContent.data === undefined) { - throw Error(`missing data field in file: ${filename}`); - } - if(!(jsonFileContent.data instanceof Array)) { - throw Error(`invalid data field, must be an array: ${filename}`); - } - fs.writeFileSync(tsFilepath, tsFileContent.replace(regexp, `${GENERATE_INDICATOR}\n * @example\n${jsonFileContent.data.slice(0,3).map(example => ` * ${example}\n`).join('')} */`)); - } catch(error) { - errors.push({filename, error}); + +const ERRORS = { + missingIndicatorProperty: `'${GENERATE_INDICATOR}' is missing in jsdoc`, + tsFileDoesNotExists: `corresponding ts file does not exists`, + missingJsonDataField: `'json.data' field is missing`, + jsonDataFieldValueMustBeArray: "'json.data' field value is not array", + jsonDataMustNotBeEmptyArray: "'json.data' field value is empty array", + tsFileDoesNotContainRandFunction: "ts file must contain function which name starts with 'rand'" +}; + +const getFileContent = (filepath) => { + try { + return fs.readFileSync(filepath).toString() + } catch(error) { + if(error.message.startsWith("ENOENT")) { + return null; } - }); + throw error; + } +}; - if(errors.length > 0) { - console.log(errors); +const getExamplesFromJson = (json) => { + if(json.data === undefined) { + return [null, ERRORS.missingJsonDataField]; + } + if(!(json.data instanceof Array)) { + return [null, ERRORS.jsonDataFieldValueMustBeArray] + } + const examples = json.data.slice(0,3); + if(examples.length === 0) { + return [null, ERRORS.jsonDataMustNotBeEmptyArray] } - console.log(`Generating examples finished ${filenames.length - errors.length}/${filenames.length}`); + return [examples, null]; +}; + + +const getExamplesFromTs = (tsContent) => { + const [,randFunction] = Object.entries(tsContent).find(([key]) => key.startsWith('rand')); + if(randFunction === undefined || typeof randFunction !== 'function') { + return [null, ERRORS.tsFileDoesNotContainRandFunction] + } + return [Array.from({ length: 3 }, randFunction), null] +}; + +const directoryFilenames = fs.readdirSync(directoryPath) + .map(filename => filename.split('.')[0]) + .filter((filename, index, filenames) => filenames.indexOf(filename) === index); + + + const errors = directoryFilenames.reduce((acc, filename) => { + const basePath = `${directoryPath}${filename}` + const filePath = { + ts: `${basePath}.ts`, + json: `${basePath}.json`, + }; + const tsFileContent = getFileContent(filePath.ts); + if(tsFileContent === null) { + acc[ERRORS.tsFileDoesNotExists].push(filename); + return acc; + } + if(!tsFileContent.includes(GENERATE_INDICATOR)) { + acc[ERRORS.missingIndicatorProperty].push(filename); + return acc; + } + const jsonFileContent = getFileContent(filePath.json); + const [examples, error] = jsonFileContent === null + ? getExamplesFromTs(require(`../${basePath}`)) + : getExamplesFromJson(JSON.parse(jsonFileContent)); + if(error !== null) { + acc[error].push(filename); + return acc; + } + + const replacement = `${GENERATE_INDICATOR}\n * @example\n${examples.map(example => ` * ${example}\n`).join('')} */` + fs.writeFileSync(`${basePath}.ts`, tsFileContent.replace(regexp, replacement)); + return acc; +}, Object.values(ERRORS).reduce((acc, errorText) => ({...acc, [errorText]: []}), {})); + +console.log(Object.entries(errors).reduce((acc, [key, value]) => `${acc}--> ${value.length} - ${key}:\n [${value.join(', ')}]\n` ,'<<-- Generator Errors -->>\n')); +console.log(`<<-- Generator Result -->> +--> generated: ${directoryFilenames.length - Object.values(errors).flat().length} +--> files: ${directoryFilenames.length}`); +