Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: migrate name #103

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Git } from './git';
import { Hacker } from './hacker';
import { Helpers } from './helpers';
import { Mersenne } from './mersenne';
import { Name } from './name';
import { Random } from './random';

export interface FakerOptions {
Expand Down Expand Up @@ -181,7 +182,7 @@ export class Faker {
readonly internet = new (require('./internet'))(this);
readonly lorem = new (require('./lorem'))(this);
readonly music = new (require('./music'))(this);
readonly name = new (require('./name'))(this);
readonly name: Name = new Name(this);
readonly phone = new (require('./phone_number'))(this);
readonly system = new (require('./system'))(this);
readonly time = new (require('./time'))(this);
Expand Down
298 changes: 298 additions & 0 deletions src/name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
import type { Faker } from '.';

export class Name {
constructor(private readonly faker: Faker) {
// Bind `this` so namespaced is working correctly
for (const name of Object.getOwnPropertyNames(Name.prototype)) {
if (name === 'constructor' || typeof this[name] !== 'function') {
continue;
}
this[name] = this[name].bind(this);
}
}

/**
* firstName
*
* @method faker.name.firstName
* @param gender
* @memberof faker.name
*/
firstName(gender?: string | number): string {
if (
typeof this.faker.definitions.name.male_first_name !== 'undefined' &&
typeof this.faker.definitions.name.female_first_name !== 'undefined'
) {
// some locale datasets ( like ru ) have first_name split by gender. since the name.first_name field does not exist in these datasets,
// we must randomly pick a name from either gender array so faker.name.firstName will return the correct locale data ( and not fallback )

if (typeof gender === 'string') {
if (gender.toLowerCase() === 'male') {
gender = 0;
} else if (gender.toLowerCase() === 'female') {
gender = 1;
}
}

if (typeof gender !== 'number') {
if (typeof this.faker.definitions.name.first_name === 'undefined') {
gender = this.faker.datatype.number(1);
} else {
// Fall back to non-gendered names if they exist and gender wasn't specified
return this.faker.random.arrayElement(
this.faker.definitions.name.first_name
);
}
}
if (gender === 0) {
return this.faker.random.arrayElement(
this.faker.definitions.name.male_first_name
);
} else {
return this.faker.random.arrayElement(
this.faker.definitions.name.female_first_name
);
}
}

return this.faker.random.arrayElement(
this.faker.definitions.name.first_name
);
}

/**
* lastName
*
* @method lastName
* @param gender
* @memberof faker.name
*/
lastName(gender?: string | number): string {
if (
typeof this.faker.definitions.name.male_last_name !== 'undefined' &&
typeof this.faker.definitions.name.female_last_name !== 'undefined'
) {
// some locale datasets ( like ru ) have last_name split by gender. i have no idea how last names can have genders, but also i do not speak russian
// see above comment of firstName method
if (typeof gender !== 'number') {
gender = this.faker.datatype.number(1);
}
if (gender === 0) {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.male_last_name
);
} else {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.female_last_name
);
}
}

return this.faker.random.arrayElement(
this.faker.definitions.name.last_name
);
}

/**
* middleName
*
* @method middleName
* @param gender
* @memberof faker.name
*/
middleName(gender?: string | number): string {
if (
typeof this.faker.definitions.name.male_middle_name !== 'undefined' &&
typeof this.faker.definitions.name.female_middle_name !== 'undefined'
) {
if (typeof gender !== 'number') {
gender = this.faker.datatype.number(1);
}
if (gender === 0) {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.male_middle_name
);
} else {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.female_middle_name
);
}
}

return this.faker.random.arrayElement(
this.faker.definitions.name.middle_name
);
}

/**
* findName
*
* @method findName
* @param firstName
* @param lastName
* @param gender
* @memberof faker.name
*/
findName(
firstName?: string,
lastName?: string,
gender?: string | number
): string {
const r = this.faker.datatype.number(8);
let prefix: string = '',
suffix: string = '';

// in particular locales first and last names split by gender,
// thus we keep consistency by passing 0 as male and 1 as female

if (typeof gender !== 'number') {
gender = this.faker.datatype.number(1);
}

firstName ||= this.faker.name.firstName(gender);
lastName ||= this.faker.name.lastName(gender);

switch (r) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note, this should be later transformed to a if

case 0:
prefix = this.faker.name.prefix(gender);
if (prefix) {
return prefix + ' ' + firstName + ' ' + lastName;
}
case 1:
suffix = this.faker.name.suffix();
if (suffix) {
return firstName + ' ' + lastName + ' ' + suffix;
}
}

return firstName + ' ' + lastName;
}

/**
* jobTitle
*
* @method jobTitle
* @memberof faker.name
*/
jobTitle(): string {
return (
this.faker.name.jobDescriptor() +
' ' +
this.faker.name.jobArea() +
' ' +
this.faker.name.jobType()
);
}

/**
* gender
*
* @method gender
* @param binary
* @memberof faker.name
*/
gender(binary: boolean): string {
if (binary) {
return this.faker.random.arrayElement(
this.faker.definitions.name.binary_gender
);
} else {
return this.faker.random.arrayElement(this.faker.definitions.name.gender);
}
}

/**
* prefix
*
* @method prefix
* @param gender
* @memberof faker.name
*/
prefix(gender?: string | number): string {
if (
typeof this.faker.definitions.name.male_prefix !== 'undefined' &&
typeof this.faker.definitions.name.female_prefix !== 'undefined'
) {
if (typeof gender !== 'number') {
gender = this.faker.datatype.number(1);
}
if (gender === 0) {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.male_prefix
);
} else {
return this.faker.random.arrayElement(
this.faker.locales[this.faker.locale].name.female_prefix
);
}
}

return this.faker.random.arrayElement(this.faker.definitions.name.prefix);
}

/**
* suffix
*
* @method suffix
* @memberof faker.name
*/
suffix(): string {
return this.faker.random.arrayElement(this.faker.definitions.name.suffix);
}

/**
* title
*
* @method title
* @memberof faker.name
*/
title(): string {
var descriptor = this.faker.random.arrayElement(
this.faker.definitions.name.title.descriptor
),
level = this.faker.random.arrayElement(
this.faker.definitions.name.title.level
),
job = this.faker.random.arrayElement(
this.faker.definitions.name.title.job
);

return descriptor + ' ' + level + ' ' + job;
}

/**
* jobDescriptor
*
* @method jobDescriptor
* @memberof faker.name
*/
jobDescriptor(): string {
return this.faker.random.arrayElement(
this.faker.definitions.name.title.descriptor
);
}

/**
* jobArea
*
* @method jobArea
* @memberof faker.name
*/
jobArea(): string {
return this.faker.random.arrayElement(
this.faker.definitions.name.title.level
);
}

/**
* jobType
*
* @method jobType
* @memberof faker.name
*/
jobType(): string {
return this.faker.random.arrayElement(
this.faker.definitions.name.title.job
);
}
}