aboutsummaryrefslogtreecommitdiff
path: root/src/modules/name
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/name')
-rw-r--r--src/modules/name/index.ts350
1 files changed, 350 insertions, 0 deletions
diff --git a/src/modules/name/index.ts b/src/modules/name/index.ts
new file mode 100644
index 00000000..c1ac22a7
--- /dev/null
+++ b/src/modules/name/index.ts
@@ -0,0 +1,350 @@
+import type { Faker } from '../..';
+import { deprecated } from '../../internal/deprecated';
+
+export enum Gender {
+ female = 'female',
+ male = 'male',
+}
+
+// TODO @Shinigami92 2022-03-21: Remove 0 and 1 in v7
+export type GenderType = 'female' | 'male' | 0 | 1;
+
+/**
+ * Normalize gender.
+ *
+ * @param gender Gender.
+ * @param functionName Temporary parameter for deprecation message.
+ * @returns Normalized gender.
+ */
+function normalizeGender(
+ gender?: GenderType,
+ functionName?: string
+): Exclude<GenderType, number> | undefined {
+ if (gender == null || typeof gender === 'string') {
+ // TODO @Shinigami92 2022-03-21: Cast can be removed when we set `strict: true`
+ return gender as Exclude<GenderType, number>;
+ }
+
+ const normalizedGender = gender === 0 ? 'male' : 'female';
+
+ deprecated({
+ deprecated: `name.${functionName}(number)`,
+ proposed: "'female' or 'male'",
+ since: 'v6.1.0',
+ until: 'v7.0.0',
+ });
+
+ return normalizedGender;
+}
+
+/**
+ * Select a definition based on given gender.
+ *
+ * @param faker Faker instance.
+ * @param gender Gender.
+ * @param param2 Definitions.
+ * @param param2.generic Non-gender definitions.
+ * @param param2.female Female definitions.
+ * @param param2.male Male definitions.
+ * @param functionName Temporary parameter for deprecation message.
+ * @returns Definition based on given gender.
+ */
+function selectDefinition(
+ faker: Faker,
+ gender: GenderType | undefined,
+ // TODO @Shinigami92 2022-03-21: Remove fallback empty object when `strict: true`
+ {
+ generic,
+ female,
+ male,
+ }: { generic?: string[]; female?: string[]; male?: string[] } = {},
+ functionName?: string
+) {
+ const normalizedGender = normalizeGender(gender, functionName);
+
+ let values: string[] | undefined;
+ switch (normalizedGender) {
+ case 'female':
+ values = female;
+ break;
+ case 'male':
+ values = male;
+ break;
+ default:
+ values = generic;
+ break;
+ }
+
+ if (values == null) {
+ if (female != null && male != null) {
+ values = faker.helpers.arrayElement([female, male]);
+ } else {
+ values = generic;
+ }
+ }
+
+ return faker.helpers.arrayElement(values);
+}
+
+/**
+ * Module to generate people's names and titles.
+ */
+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);
+ }
+ }
+
+ /**
+ * Returns a random first name.
+ *
+ * @param gender The optional gender to use.
+ * Can be either `'female'` or `'male'`.
+ *
+ * @example
+ * faker.name.firstName() // 'Antwan'
+ * faker.name.firstName("female") // 'Victoria'
+ * faker.name.firstName("male") // 'Tom'
+ */
+ firstName(gender?: GenderType): string {
+ const { first_name, female_first_name, male_first_name } =
+ this.faker.definitions.name;
+
+ return selectDefinition(
+ this.faker,
+ gender,
+ {
+ generic: first_name,
+ female: female_first_name,
+ male: male_first_name,
+ },
+ 'firstName'
+ );
+ }
+
+ /**
+ * Returns a random last name.
+ *
+ * @param gender The optional gender to use.
+ * Can be either `'female'` or `'male'`.
+ *
+ * @example
+ * faker.name.lastName() // 'Hauck'
+ * faker.name.lastName("female") // 'Grady'
+ * faker.name.lastName("male") // 'Barton'
+ */
+ lastName(gender?: GenderType): string {
+ const { last_name, female_last_name, male_last_name } =
+ this.faker.definitions.name;
+
+ return selectDefinition(
+ this.faker,
+ gender,
+ {
+ generic: last_name,
+ female: female_last_name,
+ male: male_last_name,
+ },
+ 'lastName'
+ );
+ }
+
+ /**
+ * Returns a random middle name.
+ *
+ * @param gender The optional gender to use.
+ * Can be either `'female'` or `'male'`.
+ *
+ * @example
+ * faker.name.middleName() // 'Доброславівна'
+ * faker.name.middleName("female") // 'Анастасівна'
+ * faker.name.middleName("male") // 'Вікторович'
+ */
+ middleName(gender?: GenderType): string {
+ const { middle_name, female_middle_name, male_middle_name } =
+ this.faker.definitions.name;
+
+ return selectDefinition(
+ this.faker,
+ gender,
+ {
+ generic: middle_name,
+ female: female_middle_name,
+ male: male_middle_name,
+ },
+ 'middleName'
+ );
+ }
+
+ /**
+ * Generates a random full name.
+ *
+ * @param firstName The optional first name to use. If not specified a random one will be chosen.
+ * @param lastName The optional last name to use. If not specified a random one will be chosen.
+ * @param gender The optional gender to use.
+ * Can be either `'female'` or `'male'`.
+ *
+ * @example
+ * faker.name.findName() // 'Allen Brown'
+ * faker.name.findName('Joann') // 'Joann Osinski'
+ * faker.name.findName('Marcella', '', 'female') // 'Mrs. Marcella Huels'
+ * faker.name.findName(undefined, 'Beer') // 'Mr. Alfonso Beer'
+ * faker.name.findName(undefined, undefined, 'male') // 'Fernando Schaefer'
+ */
+ findName(firstName?: string, lastName?: string, gender?: GenderType): string {
+ const variant = this.faker.datatype.number(8);
+ let prefix = '';
+ let suffix = '';
+
+ const normalizedGender: Exclude<GenderType, number> =
+ normalizeGender(gender, 'findName') ??
+ this.faker.helpers.arrayElement(['female', 'male']);
+
+ firstName = firstName || this.firstName(normalizedGender);
+ lastName = lastName || this.lastName(normalizedGender);
+
+ switch (variant) {
+ // TODO @Shinigami92 2022-03-21: Add possibility to have a prefix together with a suffix
+ case 0:
+ prefix = this.prefix(gender);
+ if (prefix) {
+ return `${prefix} ${firstName} ${lastName}`;
+ }
+ // TODO @Shinigami92 2022-01-21: Not sure if this fallthrough is wanted
+ // eslint-disable-next-line no-fallthrough
+ case 1:
+ suffix = this.suffix();
+ if (suffix) {
+ return `${firstName} ${lastName} ${suffix}`;
+ }
+ }
+
+ return `${firstName} ${lastName}`;
+ }
+
+ /**
+ * Return a random gender.
+ *
+ * @param binary Whether to return only binary gender names. Defaults to `false`.
+ *
+ * @example
+ * faker.name.gender() // 'Trans*Man'
+ * faker.name.gender(true) // 'Female'
+ */
+ gender(binary?: boolean): string {
+ if (binary) {
+ return this.faker.helpers.arrayElement(
+ this.faker.definitions.name.binary_gender
+ );
+ }
+
+ return this.faker.helpers.arrayElement(this.faker.definitions.name.gender);
+ }
+
+ /**
+ * Returns a random name prefix.
+ *
+ * @param gender The optional gender to use.
+ * Can be either `'female'` or `'male'`.
+ *
+ * @example
+ * faker.name.prefix() // 'Miss'
+ * faker.name.prefix('female') // 'Ms.'
+ * faker.name.prefix('male') // 'Mr.'
+ */
+ prefix(gender?: GenderType): string {
+ const { prefix, female_prefix, male_prefix } = this.faker.definitions.name;
+
+ return selectDefinition(
+ this.faker,
+ gender,
+ {
+ generic: prefix,
+ female: female_prefix,
+ male: male_prefix,
+ },
+ 'prefix'
+ );
+ }
+
+ /**
+ * Returns a random name suffix.
+ *
+ * @example
+ * faker.name.suffix() // 'DDS'
+ */
+ suffix(): string {
+ // TODO @Shinigami92 2022-03-21: Add female_suffix and male_suffix
+ return this.faker.helpers.arrayElement(this.faker.definitions.name.suffix);
+ }
+
+ /**
+ * Generates a random job title.
+ *
+ * @example
+ * faker.name.title() // 'International Integration Manager'
+ *
+ * @deprecated
+ */
+ title(): string {
+ deprecated({
+ deprecated: 'faker.name.title()',
+ proposed: 'faker.name.jobTitle()',
+ since: 'v6.1.2',
+ until: 'v7.0.0',
+ });
+
+ return this.jobTitle();
+ }
+
+ /**
+ * Generates a random job title.
+ *
+ * @example
+ * faker.name.jobTitle() // 'Global Accounts Engineer'
+ */
+ jobTitle(): string {
+ return `${this.jobDescriptor()} ${this.jobArea()} ${this.jobType()}`;
+ }
+
+ /**
+ * Generates a random job descriptor.
+ *
+ * @example
+ * faker.name.jobDescriptor() // 'Customer'
+ */
+ jobDescriptor(): string {
+ return this.faker.helpers.arrayElement(
+ this.faker.definitions.name.title.descriptor
+ );
+ }
+
+ /**
+ * Generates a random job area.
+ *
+ * @example
+ * faker.name.jobArea() // 'Brand'
+ */
+ jobArea(): string {
+ return this.faker.helpers.arrayElement(
+ this.faker.definitions.name.title.level
+ );
+ }
+
+ /**
+ * Generates a random job type.
+ *
+ * @example
+ * faker.name.jobType() // 'Assistant'
+ */
+ jobType(): string {
+ return this.faker.helpers.arrayElement(
+ this.faker.definitions.name.title.job
+ );
+ }
+}