From 7e89379e568dd12ad336f625d74fd4d9d4dc0a96 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Thu, 5 Oct 2023 23:42:34 +0200 Subject: [PATCH 01/20] infra: enable strictNullChecks in tsconfig --- cypress/e2e/api.cy.ts | 2 +- docs/.vitepress/config.ts | 13 +++-- docs/.vitepress/versions.ts | 3 +- scripts/apidoc/fakerClass.ts | 6 ++- scripts/apidoc/signature.ts | 2 +- src/definitions/definitions.ts | 2 +- src/locales/ar/date/weekday.ts | 10 +++- src/locales/ur/date/month.ts | 15 +++++- src/locales/ur/date/weekday.ts | 2 +- src/modules/airline/index.ts | 2 +- src/modules/commerce/index.ts | 2 +- src/modules/date/index.ts | 44 ++++++++++++----- src/modules/finance/index.ts | 6 +-- src/modules/helpers/index.ts | 22 +++++---- src/modules/helpers/unique.ts | 4 +- src/modules/internet/index.ts | 2 + src/modules/person/index.ts | 47 ++++++++++++++----- src/modules/random/index.ts | 2 +- test/faker.spec.ts | 4 +- test/modules/airline.spec.ts | 8 ++-- test/modules/finance_iban.spec.ts | 12 ++--- test/modules/helpers.spec.ts | 3 +- test/scripts/apidoc/verify-jsdoc-tags.spec.ts | 2 +- test/vitest-extensions.ts | 1 + tsconfig.json | 1 - 25 files changed, 147 insertions(+), 70 deletions(-) diff --git a/cypress/e2e/api.cy.ts b/cypress/e2e/api.cy.ts index be61f5dfc5b..d46434cb46d 100644 --- a/cypress/e2e/api.cy.ts +++ b/cypress/e2e/api.cy.ts @@ -34,7 +34,7 @@ describe('API Test', () => { cy.get('.api-group li').each(($el) => { const anchor = $el.find('a'); const text = anchor.text(); - const link = anchor.attr('href').split('#')[0]; + const link = anchor.attr('href')!.split('#')[0]; if (checked.has(link)) { return; } diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 12fea107d34..e8484526a74 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -121,11 +121,14 @@ const config = defineConfig({ { icon: 'github', link: 'https://github.com/faker-js/faker' }, ], - algolia: { - apiKey: process.env.API_KEY, - appId: process.env.APP_ID, - indexName: 'fakerjs', - }, + algolia: + process.env.API_KEY == null || process.env.APP_ID == null + ? undefined + : { + apiKey: process.env.API_KEY, + appId: process.env.APP_ID, + indexName: 'fakerjs', + }, footer: { message: 'Released under the MIT License.', diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts index 2964557cee9..c9e34e8c73d 100644 --- a/docs/.vitepress/versions.ts +++ b/docs/.vitepress/versions.ts @@ -23,8 +23,9 @@ function readOtherLatestReleaseTagNames(): string[] { } return acc; }, {}); + return Object.entries(latestReleaseTagNames) - .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`)) + .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`)!) .sort(semver.rcompare); } diff --git a/scripts/apidoc/fakerClass.ts b/scripts/apidoc/fakerClass.ts index ea190cc7e7c..9bbd7650f8d 100644 --- a/scripts/apidoc/fakerClass.ts +++ b/scripts/apidoc/fakerClass.ts @@ -28,6 +28,10 @@ export async function processFakerRandomizer( .getChildrenByKind(ReflectionKind.Interface) .find((clazz) => clazz.name === 'Randomizer'); + if (randomizerClass == null) { + throw new Error('Randomizer class not found'); + } + return processClass(randomizerClass); } @@ -62,7 +66,7 @@ async function processClass( function hasConstructor(clazz: DeclarationReflection): boolean { return clazz .getChildrenByKind(ReflectionKind.Constructor) - .some((constructor) => constructor.signatures.length > 0); + .some((constructor) => constructor.signatures!.length > 0); } async function processConstructor( diff --git a/scripts/apidoc/signature.ts b/scripts/apidoc/signature.ts index 113df911650..89d8cafde2f 100644 --- a/scripts/apidoc/signature.ts +++ b/scripts/apidoc/signature.ts @@ -305,7 +305,7 @@ async function signatureTypeToText( await Promise.all( signature.parameters?.map( async (p) => `${p.name}: ${await typeToText(p.type)}` - ) + ) ?? [] ) ).join(', ')}) => ${await typeToText(signature.type)}`; } diff --git a/src/definitions/definitions.ts b/src/definitions/definitions.ts index ca495e3477a..c2a3b560099 100644 --- a/src/definitions/definitions.ts +++ b/src/definitions/definitions.ts @@ -50,4 +50,4 @@ export type LocaleDefinition = { system?: SystemDefinition; vehicle?: VehicleDefinition; word?: WordDefinition; -} & Record | undefined>; +} & Record>; diff --git a/src/locales/ar/date/weekday.ts b/src/locales/ar/date/weekday.ts index 7034cd26fc6..080b33bd4b0 100644 --- a/src/locales/ar/date/weekday.ts +++ b/src/locales/ar/date/weekday.ts @@ -1,5 +1,13 @@ export default { - abbr: null, + abbr: [ + 'الأحَد', + 'الإثنين', + 'الثلاثاء', + 'الأربعاء', + 'الخميس', + 'الجمعة', + 'السبت', + ], wide: [ 'الأحَد', 'الإثنين', diff --git a/src/locales/ur/date/month.ts b/src/locales/ur/date/month.ts index 37fdfa288fd..7a72f10ea5e 100644 --- a/src/locales/ur/date/month.ts +++ b/src/locales/ur/date/month.ts @@ -1,5 +1,18 @@ export default { - abbr: null, + abbr: [ + 'جنوری', + 'فروری', + 'مارچ', + 'اپریل', + 'مئ', + 'جون', + 'جولائ', + 'اگست', + 'ستمبر', + 'اکتوبر', + 'نومبر', + 'دسمبر', + ], wide: [ 'جنوری', 'فروری', diff --git a/src/locales/ur/date/weekday.ts b/src/locales/ur/date/weekday.ts index 25f239f2c09..013fc789db7 100644 --- a/src/locales/ur/date/weekday.ts +++ b/src/locales/ur/date/weekday.ts @@ -1,4 +1,4 @@ export default { - abbr: null, + abbr: ['اتور', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], wide: ['اتور', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], }; diff --git a/src/modules/airline/index.ts b/src/modules/airline/index.ts index f6d2fdc7cea..12416e61e08 100644 --- a/src/modules/airline/index.ts +++ b/src/modules/airline/index.ts @@ -160,7 +160,7 @@ export class AirlineModule { ): string { const { allowNumerics = false, allowVisuallySimilarCharacters = false } = options; - const excludedChars = []; + const excludedChars: string[] = []; if (!allowNumerics) { excludedChars.push(...numerics); } diff --git a/src/modules/commerce/index.ts b/src/modules/commerce/index.ts index 2464af03020..843e7b025ad 100644 --- a/src/modules/commerce/index.ts +++ b/src/modules/commerce/index.ts @@ -386,7 +386,7 @@ export class CommerceModule { const registrantLength = groupRules.find( ([rangeMaximum]) => elementValue <= rangeMaximum - )[1]; + )![1]; const registrant = element.slice(0, registrantLength); const publication = element.slice(registrantLength); diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index 8f7efaaeed4..251e11151cd 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -15,6 +15,10 @@ function toDate( date: string | Date | number | undefined, fallback: () => Date ): Date { + if (date == null) { + return fallback(); + } + date = new Date(date); if (isNaN(date.valueOf())) { date = fallback(); @@ -387,14 +391,15 @@ export class SimpleDateModule { }, legacyTo?: string | Date | number ): Date { - if (typeof options !== 'object' || options instanceof Date) { + if (options instanceof Date || typeof options !== 'object') { deprecated({ deprecated: 'faker.date.between(from, to)', proposed: 'faker.date.between({ from, to })', since: '8.0', until: '9.0', }); - options = { from: options, to: legacyTo }; + // We use options as fallback for legacyTo avoid TS errors for unintended usage. + options = { from: options, to: legacyTo ?? options }; } const { from, to } = options; @@ -563,14 +568,15 @@ export class SimpleDateModule { legacyTo?: string | Date | number, legacyCount: number = 3 ): Date[] { - if (typeof options !== 'object' || options instanceof Date) { + if (options instanceof Date || typeof options !== 'object') { deprecated({ deprecated: 'faker.date.betweens(from, to, count)', proposed: 'faker.date.betweens({ from, to, count })', since: '8.0', until: '9.0', }); - options = { from: options, to: legacyTo, count: legacyCount }; + // We use options as fallback for legacyTo avoid TS errors for unintended usage. + options = { from: options, to: legacyTo ?? options, count: legacyCount }; } const { from, to, count = 3 } = options; @@ -868,12 +874,6 @@ export class SimpleDateModule { refDate?: string | Date | number; } = {} ): Date { - if (options.max < options.min) { - throw new FakerError( - `Max ${options.max} should be larger than or equal to min ${options.min}.` - ); - } - const mode = options.mode === 'age' ? 'age' : 'year'; const refDate = toDate(options.refDate, this.faker.defaultRefDate); const refYear = refDate.getUTCFullYear(); @@ -898,6 +898,12 @@ export class SimpleDateModule { ); } + if (max < min) { + throw new FakerError( + `Max ${options.max} should be larger than or equal to min ${options.min}.` + ); + } + return new Date(this.faker.number.int({ min, max })); } } @@ -1108,7 +1114,14 @@ export class DateModule extends SimpleDateModule { type = 'wide'; } - return this.faker.helpers.arrayElement(source[type]); + const values = source[type]; + + if (values == null) { + // This should never happen due to the checks above, but TS doesn't know that + throw new FakerError(`No month values found for type '${type}'.`); + } + + return this.faker.helpers.arrayElement(values); } /** @@ -1298,6 +1311,13 @@ export class DateModule extends SimpleDateModule { type = 'wide'; } - return this.faker.helpers.arrayElement(source[type]); + const values = source[type]; + + if (values == null) { + // This should never happen due to the checks above, but TS doesn't know that + throw new FakerError(`No weekday values found for type '${type}'.`); + } + + return this.faker.helpers.arrayElement(values); } } diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts index 43cd16a1c5e..2fb27d42bde 100644 --- a/src/modules/finance/index.ts +++ b/src/modules/finance/index.ts @@ -679,9 +679,9 @@ export class FinanceModule { */ currencySymbol(): string { let symbol: string; - while (!symbol) { + do { symbol = this.currency().symbol; - } + } while (!symbol); return symbol; } @@ -1163,7 +1163,7 @@ export class FinanceModule { const result = `${ibanFormat.country}${checksum}${s}`; - return formatted ? result.match(/.{1,4}/g).join(' ') : result; + return formatted ? result.replace(/(.{4})(?=.)/g, '$1 ') : result; } /** diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index f5e7e1771a8..65f94c11c04 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -422,6 +422,7 @@ export class SimpleHelpersModule { const quantifierMin: string = token[2]; const quantifierMax: string = token[3]; const quantifierSymbol: string = token[4]; + const tokenIndex: number = token.index!; repetitions = getRepetitionsBasedOnQuantifierParameters( this.faker, @@ -431,9 +432,9 @@ export class SimpleHelpersModule { ); pattern = - pattern.slice(0, token.index) + + pattern.slice(0, tokenIndex) + token[1].repeat(repetitions) + - pattern.slice(token.index + token[0].length); + pattern.slice(tokenIndex + token[0].length); token = pattern.match(SINGLE_CHAR_REG); } @@ -448,6 +449,7 @@ export class SimpleHelpersModule { const quantifierMin: string = token[4]; const quantifierMax: string = token[5]; const quantifierSymbol: string = token[6]; + const tokenIndex: number = token.index!; const rangeCodes: number[] = []; @@ -542,9 +544,9 @@ export class SimpleHelpersModule { ).join(''); pattern = - pattern.slice(0, token.index) + + pattern.slice(0, tokenIndex) + generatedString + - pattern.slice(token.index + token[0].length); + pattern.slice(tokenIndex + token[0].length); token = pattern.match(RANGE_ALPHANUMEMRIC_REG); } @@ -554,6 +556,7 @@ export class SimpleHelpersModule { while (token != null) { min = parseInt(token[2]); max = parseInt(token[3]); + const tokenIndex = token.index!; // throw error if min larger than max if (min > max) { throw new FakerError('Numbers out of order in {} quantifier.'); @@ -561,9 +564,9 @@ export class SimpleHelpersModule { repetitions = this.faker.number.int({ min, max }); pattern = - pattern.slice(0, token.index) + + pattern.slice(0, tokenIndex) + token[1].repeat(repetitions) + - pattern.slice(token.index + token[0].length); + pattern.slice(tokenIndex + token[0].length); token = pattern.match(RANGE_REP_REG); } @@ -572,10 +575,11 @@ export class SimpleHelpersModule { token = pattern.match(REP_REG); while (token != null) { repetitions = parseInt(token[2]); + const tokenIndex = token.index!; pattern = - pattern.slice(0, token.index) + + pattern.slice(0, tokenIndex) + token[1].repeat(repetitions) + - pattern.slice(token.index + token[0].length); + pattern.slice(tokenIndex + token[0].length); token = pattern.match(REP_REG); } @@ -1117,7 +1121,7 @@ export class SimpleHelpersModule { ) => RecordKey, >( method: TMethod, - args: Parameters = [] as Parameters, + args: Parameters = [] as unknown as Parameters, options: { /** * This parameter does nothing. diff --git a/src/modules/helpers/unique.ts b/src/modules/helpers/unique.ts index c096854a6eb..efb4956088d 100644 --- a/src/modules/helpers/unique.ts +++ b/src/modules/helpers/unique.ts @@ -96,9 +96,9 @@ export function exec< maxTime = 50, maxRetries = 50, compare = defaultCompare, - store, + store = {}, } = options; - let { exclude } = options; + let { exclude = [] } = options; options.currentIterations = options.currentIterations ?? 0; // Support single exclude argument as string diff --git a/src/modules/internet/index.ts b/src/modules/internet/index.ts index 842ab1538af..e8fa358e2cf 100644 --- a/src/modules/internet/index.ts +++ b/src/modules/internet/index.ts @@ -625,6 +625,7 @@ export class InternetModule { firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName; break; case 2: + default: result = `${firstName}${this.faker.helpers.arrayElement([ '.', '_', @@ -810,6 +811,7 @@ export class InternetModule { firstName + this.faker.helpers.arrayElement(['.', '_']) + lastName; break; case 2: + default: result = `${firstName}${this.faker.helpers.arrayElement([ '.', '_', diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts index f07727a2c96..8b0688f508f 100644 --- a/src/modules/person/index.ts +++ b/src/modules/person/index.ts @@ -1,4 +1,5 @@ import type { Faker } from '../..'; +import { FakerError } from '../../errors/faker-error'; import { bindThisToMemberFunctions } from '../../internal/bind-this-to-member-functions'; export enum Sex { @@ -26,9 +27,13 @@ function selectDefinition( elementSelectorFn: (values: T[]) => string, sex: SexType | undefined, // TODO @Shinigami92 2022-03-21: Remove fallback empty object when `strict: true` - { generic, female, male }: { generic?: T[]; female?: T[]; male?: T[] } = {} + { + generic, + female, + male, + }: { generic?: T[] | null; female?: T[] | null; male?: T[] | null } = {} ): string { - let values: T[] | undefined; + let values: T[] | undefined | null; switch (sex) { case Sex.Female: @@ -50,6 +55,12 @@ function selectDefinition( } else { values = generic; } + + if (values == null) { + throw new FakerError( + 'Neither female, male or generic definitions are available.' + ); + } } return elementSelectorFn(values); @@ -97,7 +108,7 @@ export class PersonModule { this.faker.rawDefinitions.person ?? {}; return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: first_name, + generic: first_name ?? undefined, female: female_first_name, male: male_first_name, }); @@ -352,9 +363,13 @@ export class PersonModule { * @since 8.0.0 */ jobDescriptor(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.descriptor - ); + const values = this.faker.definitions.person.title.descriptor; + + if (values == null) { + throw new FakerError('No person.title.descriptor definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** @@ -366,9 +381,13 @@ export class PersonModule { * @since 8.0.0 */ jobArea(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.level - ); + const values = this.faker.definitions.person.title.level; + + if (values == null) { + throw new FakerError('No person.title.area definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** @@ -380,9 +399,13 @@ export class PersonModule { * @since 8.0.0 */ jobType(): string { - return this.faker.helpers.arrayElement( - this.faker.definitions.person.title.job - ); + const values = this.faker.definitions.person.title.job; + + if (values == null) { + throw new FakerError('No person.title.job definitions available.'); + } + + return this.faker.helpers.arrayElement(values); } /** diff --git a/src/modules/random/index.ts b/src/modules/random/index.ts index 7fa16f40bfe..4644864cc24 100644 --- a/src/modules/random/index.ts +++ b/src/modules/random/index.ts @@ -128,7 +128,7 @@ export class RandomModule { '_', '-', ]; - let result: string; + let result = ''; let iteration = 0; diff --git a/test/faker.spec.ts b/test/faker.spec.ts index 2ff5aab9468..116505a9fd8 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -41,7 +41,7 @@ describe('faker', () => { describe('rawDefinitions', () => { it('locale rawDefinition accessibility', () => { // Metadata - expect(faker.rawDefinitions.metadata.title).toBeDefined(); + expect(faker.rawDefinitions.metadata!.title).toBeDefined(); // Standard modules expect(faker.rawDefinitions.location?.city_name).toBeDefined(); // Non-existing module @@ -62,7 +62,7 @@ describe('faker', () => { // Non-existing module expect(faker.definitions.missing).toBeDefined(); // Non-existing definition in a non-existing module - expect(() => faker.definitions.missing.missing).toThrow(); + expect(() => faker.definitions.missing?.missing).toThrow(); // Non-existing definition in an existing module expect(() => faker.definitions.location.missing).toThrow(); }); diff --git a/test/modules/airline.spec.ts b/test/modules/airline.spec.ts index 2cbb47c3a14..d43cad19f16 100644 --- a/test/modules/airline.spec.ts +++ b/test/modules/airline.spec.ts @@ -95,7 +95,7 @@ describe('airline', () => { const seatRegex = /^(\d{1,2})([A-K])$/; it('should return a random narrowbody seat when not passing an argument', () => { const seat = faker.airline.seat(); - const matchResult = seat.match(seatRegex); + const matchResult = seat.match(seatRegex)!; expect(matchResult).not.toBeNull(); const row = matchResult[1]; const seatLetter = matchResult[2]; @@ -106,7 +106,7 @@ describe('airline', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Narrowbody, }); - const matchResult = seat.match(seatRegex); + const matchResult = seat.match(seatRegex)!; expect(matchResult).not.toBeNull(); const row = matchResult[1]; const seatLetter = matchResult[2]; @@ -115,7 +115,7 @@ describe('airline', () => { }); it('should return a random regional seat', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Regional }); - const matchResult = seat.match(seatRegex); + const matchResult = seat.match(seatRegex)!; expect(matchResult).not.toBeNull(); const row = matchResult[1]; const seatLetter = matchResult[2]; @@ -124,7 +124,7 @@ describe('airline', () => { }); it('should return a random widebody seat', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Widebody }); - const matchResult = seat.match(seatRegex); + const matchResult = seat.match(seatRegex)!; expect(matchResult).not.toBeNull(); const row = matchResult[1]; const seatLetter = matchResult[2]; diff --git a/test/modules/finance_iban.spec.ts b/test/modules/finance_iban.spec.ts index 5c32fed384c..f43d0954399 100644 --- a/test/modules/finance_iban.spec.ts +++ b/test/modules/finance_iban.spec.ts @@ -36,7 +36,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormatted = iban.match(/.{1,4}/g).join(' '); + const ibanFormatted = iban.match(/.{1,4}/g)!.join(' '); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -96,7 +96,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -162,7 +162,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -232,7 +232,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -291,7 +291,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -336,7 +336,7 @@ describe('finance_iban', () => { // Bank account number 16 digit const iban = faker.finance.iban(false, 'AL'); - const ibanFormated = iban.match(/.{1,4}/g).join(' '); + const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); expect(iban).toSatisfy(validator.isIBAN); diff --git a/test/modules/helpers.spec.ts b/test/modules/helpers.spec.ts index 7b709373f24..9c167498aa9 100644 --- a/test/modules/helpers.spec.ts +++ b/test/modules/helpers.spec.ts @@ -222,7 +222,6 @@ describe('helpers', () => { }); it('should throw on an empty array', () => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return expect(() => faker.helpers.arrayElement([])).toThrow( new FakerError('Cannot get value from empty dataset.') ); @@ -1062,7 +1061,7 @@ describe('helpers', () => { }); it('should be able to return locale definition strings', () => { - expect(faker.definitions.cell_phone.formats).toContain( + expect(faker.definitions.cell_phone?.formats).toContain( faker.helpers.fake('{{cell_phone.formats}}') ); }); diff --git a/test/scripts/apidoc/verify-jsdoc-tags.spec.ts b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts index 586605a6610..19ffb4d0e88 100644 --- a/test/scripts/apidoc/verify-jsdoc-tags.spec.ts +++ b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts @@ -110,7 +110,7 @@ describe('verify JSDoc tags', () => { // Write temp files to disk // Extract examples and make them runnable - const examples = extractJoinedRawExamples(signature); + const examples = extractJoinedRawExamples(signature) ?? ''; // Save examples to a file to run them later in the specific tests const dir = resolveDirToModule(moduleName); diff --git a/test/vitest-extensions.ts b/test/vitest-extensions.ts index c241fcf99ea..e5f2a57dca8 100644 --- a/test/vitest-extensions.ts +++ b/test/vitest-extensions.ts @@ -11,6 +11,7 @@ expect.extend({ return { pass: uniqueDuplication.length !== 0, message: () => + // @ts-expect-error: `isNot` is incorrectly inferred as `function`. isNot ? `Duplicated values are [${uniqueDuplication.join(', ')}]` : `No duplicate values in [${received.join(', ')}]`, diff --git a/tsconfig.json b/tsconfig.json index cda27929e8f..da5cd4e6926 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,6 @@ "stripInternal": true, // We need to disable these for now, and need to tackle them in another PR - "strictNullChecks": false, "noImplicitAny": false, // These are configs specifically for !build and have to be reverted in the tsconfig.build.json From 8d3497bafed95a898a6a12063e721f895037634a Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 00:05:07 +0200 Subject: [PATCH 02/20] Apply suggestions from code review --- src/modules/person/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts index 8b0688f508f..693ca2d88be 100644 --- a/src/modules/person/index.ts +++ b/src/modules/person/index.ts @@ -108,7 +108,7 @@ export class PersonModule { this.faker.rawDefinitions.person ?? {}; return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: first_name ?? undefined, + generic: first_name, female: female_first_name, male: male_first_name, }); From 3ba4b4e978e2a71175a615b5e84826f7f5df1d30 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 00:06:39 +0200 Subject: [PATCH 03/20] Apply suggestions from code review --- docs/.vitepress/versions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts index c9e34e8c73d..4ac78f8c095 100644 --- a/docs/.vitepress/versions.ts +++ b/docs/.vitepress/versions.ts @@ -23,7 +23,6 @@ function readOtherLatestReleaseTagNames(): string[] { } return acc; }, {}); - return Object.entries(latestReleaseTagNames) .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`)!) .sort(semver.rcompare); From c555cb8d1ee97b25761533d76c872a1671ef02b1 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 00:21:12 +0200 Subject: [PATCH 04/20] build it From 2c3c7c6796d8f3fc93a799f67cdddec8c369e1d8 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 01:38:56 +0200 Subject: [PATCH 05/20] Update src/modules/finance/index.ts Co-authored-by: DivisionByZero --- src/modules/finance/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts index 2fb27d42bde..d00652e1d6f 100644 --- a/src/modules/finance/index.ts +++ b/src/modules/finance/index.ts @@ -681,7 +681,7 @@ export class FinanceModule { let symbol: string; do { symbol = this.currency().symbol; - } while (!symbol); + } while (symbol.length === 0); return symbol; } From 3caf9d51a510ead83a3da48988925aec3c24b443 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 01:43:00 +0200 Subject: [PATCH 06/20] Apply suggestions from code review --- cypress/e2e/api.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/e2e/api.cy.ts b/cypress/e2e/api.cy.ts index d46434cb46d..e87ea856f50 100644 --- a/cypress/e2e/api.cy.ts +++ b/cypress/e2e/api.cy.ts @@ -34,7 +34,7 @@ describe('API Test', () => { cy.get('.api-group li').each(($el) => { const anchor = $el.find('a'); const text = anchor.text(); - const link = anchor.attr('href')!.split('#')[0]; + const link = anchor.attr('href')?.split('#')[0] ?? 'MISSING'; if (checked.has(link)) { return; } From 28188477d489148c3d992e82262a99979af4ec14 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 21:08:35 +0200 Subject: [PATCH 07/20] Update test/faker.spec.ts Co-authored-by: DivisionByZero --- test/faker.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/faker.spec.ts b/test/faker.spec.ts index 116505a9fd8..bd42246a5a5 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -41,7 +41,7 @@ describe('faker', () => { describe('rawDefinitions', () => { it('locale rawDefinition accessibility', () => { // Metadata - expect(faker.rawDefinitions.metadata!.title).toBeDefined(); + expect(faker.rawDefinitions.metadata?.title).toBeDefined(); // Standard modules expect(faker.rawDefinitions.location?.city_name).toBeDefined(); // Non-existing module From 50531c84decfb07a706835c52bf08ae44ba4b5b2 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 21:10:55 +0200 Subject: [PATCH 08/20] Update scripts/apidoc/fakerClass.ts Co-authored-by: DivisionByZero --- scripts/apidoc/fakerClass.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/apidoc/fakerClass.ts b/scripts/apidoc/fakerClass.ts index 9bbd7650f8d..3bd6e551f8f 100644 --- a/scripts/apidoc/fakerClass.ts +++ b/scripts/apidoc/fakerClass.ts @@ -66,7 +66,7 @@ async function processClass( function hasConstructor(clazz: DeclarationReflection): boolean { return clazz .getChildrenByKind(ReflectionKind.Constructor) - .some((constructor) => constructor.signatures!.length > 0); + .some((constructor) => (constructor.signatures?.length ?? 0) > 0); } async function processConstructor( From ebc6ac5d61ffbb1c1ee79750fd2f6d0796ed9b08 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 21:15:03 +0200 Subject: [PATCH 09/20] chore: work around ts error in vitest extension --- test/vitest-extensions.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/vitest-extensions.ts b/test/vitest-extensions.ts index e5f2a57dca8..b704e901744 100644 --- a/test/vitest-extensions.ts +++ b/test/vitest-extensions.ts @@ -2,7 +2,7 @@ import { expect } from 'vitest'; expect.extend({ toContainDuplicates(received: T[]) { - const { isNot } = this; + const { isNot = false } = this; const uniques = new Set(received); const duplications = received.filter((entry) => !uniques.delete(entry)); @@ -11,7 +11,6 @@ expect.extend({ return { pass: uniqueDuplication.length !== 0, message: () => - // @ts-expect-error: `isNot` is incorrectly inferred as `function`. isNot ? `Duplicated values are [${uniqueDuplication.join(', ')}]` : `No duplicate values in [${received.join(', ')}]`, From 00f0fcf6e08b2dd23d4bdef61ac9092d0aa6bea0 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 21:39:42 +0200 Subject: [PATCH 10/20] chore: simplify version grouping --- docs/.vitepress/versions.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/.vitepress/versions.ts b/docs/.vitepress/versions.ts index 4ac78f8c095..90b0fc8dd25 100644 --- a/docs/.vitepress/versions.ts +++ b/docs/.vitepress/versions.ts @@ -14,18 +14,23 @@ function readOtherLatestReleaseTagNames(): string[] { .toString('utf8') .split('\n') .filter((tag) => semver.valid(tag)) - .reduce>((acc, tag) => { - const majorVersion = semver.major(tag); + .filter((tag) => { // Only consider tags for our deployed website versions, // excluding the current major version. - if (majorVersion >= 6 && majorVersion !== currentMajorVersion) { - (acc[majorVersion] = acc[majorVersion] ?? []).push(tag); + const majorVersion = semver.major(tag); + return majorVersion >= 6 && majorVersion !== currentMajorVersion; + }) + .reduce>((latestTagByMajor, tag) => { + const majorVersion = semver.major(tag); + + const latestTag = latestTagByMajor[majorVersion]; + if (latestTag == null || semver.lt(latestTag, tag)) { + latestTagByMajor[majorVersion] = tag; } - return acc; + + return latestTagByMajor; }, {}); - return Object.entries(latestReleaseTagNames) - .map(([major, tags]) => semver.maxSatisfying(tags, `^${major}`)!) - .sort(semver.rcompare); + return Object.values(latestReleaseTagNames).sort(semver.rcompare); } // Set by netlify From 0042bdfeb71289aced69b7547c536264019c6c34 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 6 Oct 2023 23:55:50 +0200 Subject: [PATCH 11/20] chore: prettyPrintIban helper function --- src/modules/finance/index.ts | 18 +++++++++++++++++- test/modules/finance_iban.spec.ts | 13 +++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/modules/finance/index.ts b/src/modules/finance/index.ts index d00652e1d6f..5a60eb4d10e 100644 --- a/src/modules/finance/index.ts +++ b/src/modules/finance/index.ts @@ -24,6 +24,22 @@ export interface Currency { symbol: string; } +/** + * Puts a space after every 4 characters. + * + * @internal + * + * @param iban The iban to pretty print. + */ +export function prettyPrintIban(iban: string): string { + let pretty = ''; + for (let i = 0; i < iban.length; i += 4) { + pretty += `${iban.substring(i, i + 4)} `; + } + + return pretty.trimEnd(); +} + /** * Module to generate finance and money related entries. * @@ -1163,7 +1179,7 @@ export class FinanceModule { const result = `${ibanFormat.country}${checksum}${s}`; - return formatted ? result.replace(/(.{4})(?=.)/g, '$1 ') : result; + return formatted ? prettyPrintIban(result) : result; } /** diff --git a/test/modules/finance_iban.spec.ts b/test/modules/finance_iban.spec.ts index f43d0954399..695dfb84b20 100644 --- a/test/modules/finance_iban.spec.ts +++ b/test/modules/finance_iban.spec.ts @@ -1,6 +1,7 @@ import validator from 'validator'; import { describe, expect, it } from 'vitest'; import { faker } from '../../src'; +import { prettyPrintIban } from '../../src/modules/finance'; import ibanLib from '../../src/modules/finance/iban'; import { times } from './../support/times'; @@ -36,7 +37,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormatted = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormatted = prettyPrintIban(iban); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -96,7 +97,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormated = prettyPrintIban(iban); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -162,7 +163,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormated = prettyPrintIban(iban); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -232,7 +233,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormated = prettyPrintIban(iban); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -291,7 +292,7 @@ describe('finance_iban', () => { expect(iban).toSatisfy(validator.isIBAN); - const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormated = prettyPrintIban(iban); const bban = iban.substring(4) + iban.substring(0, 4); expect( @@ -336,7 +337,7 @@ describe('finance_iban', () => { // Bank account number 16 digit const iban = faker.finance.iban(false, 'AL'); - const ibanFormated = iban.match(/.{1,4}/g)!.join(' '); + const ibanFormated = prettyPrintIban(iban); expect(iban).toSatisfy(validator.isIBAN); From 45f6b0636f7b801e576921ce7c726672303292e2 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Sat, 7 Oct 2023 00:55:02 +0200 Subject: [PATCH 12/20] chore: add assertLocaleData --- src/definitions/date.ts | 3 +- src/locale-proxy.ts | 44 +++++++++++++------ src/locales/ar/date/weekday.ts | 10 +---- src/locales/ur/date/month.ts | 15 +------ src/locales/ur/date/weekday.ts | 2 +- src/modules/date/index.ts | 15 ++----- src/modules/person/index.ts | 79 ++++++++++++++++++++++------------ 7 files changed, 90 insertions(+), 78 deletions(-) diff --git a/src/definitions/date.ts b/src/definitions/date.ts index 16cfb28aa26..2265a0256cf 100644 --- a/src/definitions/date.ts +++ b/src/definitions/date.ts @@ -26,8 +26,9 @@ export interface DateEntryDefinition { /** * The short name/abbreviation of the entry. + * If null, the locale does not support a short name/abbreviation for the entry. */ - abbr: string[]; + abbr: string[] | null; /** * The wide name of the entry when used in context. If absent wide will be used instead. diff --git a/src/locale-proxy.ts b/src/locale-proxy.ts index 67b29d473cc..6c59ec291f3 100644 --- a/src/locale-proxy.ts +++ b/src/locale-proxy.ts @@ -54,6 +54,34 @@ export function createLocaleProxy(locale: LocaleDefinition): LocaleProxy { }) as LocaleProxy; } +/** + * Checks that the value is not null or undefined and throws an error if it is. + * + * @param value The value to check. + * @param path The path to the locale data. + */ +export function assertLocaleData( + value: T, + ...path: string[] +): asserts value is NonNullable { + if (value == null) { + if (value === null) { + throw new FakerError( + `The locale data for '${path.join( + '.' + )}' aren't applicable to this locale. + If you think this is a bug, please report it at: https://github.com/faker-js/faker` + ); + } else if (value === undefined) { + throw new FakerError( + `The locale data for '${path.join('.')}' are missing in this locale. + Please contribute the missing data to the project or use a locale/Faker instance that has these data. + For more information see https://fakerjs.dev/guide/localization.html` + ); + } + } +} + /** * Creates a proxy for a category that throws an error when accessing an undefined property. * @@ -79,20 +107,10 @@ function createCategoryProxy< const value = target[entryName]; if (typeof entryName === 'symbol' || entryName === 'nodeType') { return value; - } else if (value === null) { - throw new FakerError( - `The locale data for '${categoryName}.${entryName.toString()}' aren't applicable to this locale. - If you think this is a bug, please report it at: https://github.com/faker-js/faker` - ); - } else if (value === undefined) { - throw new FakerError( - `The locale data for '${categoryName}.${entryName.toString()}' are missing in this locale. - Please contribute the missing data to the project or use a locale/Faker instance that has these data. - For more information see https://fakerjs.dev/guide/localization.html` - ); - } else { - return value; } + + assertLocaleData(value, categoryName, entryName.toString()); + return value; }, set: throwReadOnlyError, diff --git a/src/locales/ar/date/weekday.ts b/src/locales/ar/date/weekday.ts index 080b33bd4b0..7034cd26fc6 100644 --- a/src/locales/ar/date/weekday.ts +++ b/src/locales/ar/date/weekday.ts @@ -1,13 +1,5 @@ export default { - abbr: [ - 'الأحَد', - 'الإثنين', - 'الثلاثاء', - 'الأربعاء', - 'الخميس', - 'الجمعة', - 'السبت', - ], + abbr: null, wide: [ 'الأحَد', 'الإثنين', diff --git a/src/locales/ur/date/month.ts b/src/locales/ur/date/month.ts index 7a72f10ea5e..37fdfa288fd 100644 --- a/src/locales/ur/date/month.ts +++ b/src/locales/ur/date/month.ts @@ -1,18 +1,5 @@ export default { - abbr: [ - 'جنوری', - 'فروری', - 'مارچ', - 'اپریل', - 'مئ', - 'جون', - 'جولائ', - 'اگست', - 'ستمبر', - 'اکتوبر', - 'نومبر', - 'دسمبر', - ], + abbr: null, wide: [ 'جنوری', 'فروری', diff --git a/src/locales/ur/date/weekday.ts b/src/locales/ur/date/weekday.ts index 013fc789db7..25f239f2c09 100644 --- a/src/locales/ur/date/weekday.ts +++ b/src/locales/ur/date/weekday.ts @@ -1,4 +1,4 @@ export default { - abbr: ['اتور', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], + abbr: null, wide: ['اتور', 'پیر', 'منگل', 'بدھ', 'جمعرات', 'جمعہ', 'ہفتہ'], }; diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index 251e11151cd..423a2017afc 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -3,6 +3,7 @@ import type { DateEntryDefinition } from '../../definitions'; import { FakerError } from '../../errors/faker-error'; import { bindThisToMemberFunctions } from '../../internal/bind-this-to-member-functions'; import { deprecated } from '../../internal/deprecated'; +import { assertLocaleData } from '../../locale-proxy'; /** * Converts date passed as a string, number or Date to a Date object. @@ -1115,12 +1116,7 @@ export class DateModule extends SimpleDateModule { } const values = source[type]; - - if (values == null) { - // This should never happen due to the checks above, but TS doesn't know that - throw new FakerError(`No month values found for type '${type}'.`); - } - + assertLocaleData(values, 'date.month', type); return this.faker.helpers.arrayElement(values); } @@ -1312,12 +1308,7 @@ export class DateModule extends SimpleDateModule { } const values = source[type]; - - if (values == null) { - // This should never happen due to the checks above, but TS doesn't know that - throw new FakerError(`No weekday values found for type '${type}'.`); - } - + assertLocaleData(values, 'date.weekday', type); return this.faker.helpers.arrayElement(values); } } diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts index 693ca2d88be..711669d3fbb 100644 --- a/src/modules/person/index.ts +++ b/src/modules/person/index.ts @@ -1,6 +1,7 @@ import type { Faker } from '../..'; import { FakerError } from '../../errors/faker-error'; import { bindThisToMemberFunctions } from '../../internal/bind-this-to-member-functions'; +import { assertLocaleData } from '../../locale-proxy'; export enum Sex { Female = 'female', @@ -19,6 +20,7 @@ export type SexType = `${Sex}`; * @param param2.generic Non-sex definitions. * @param param2.female Female definitions. * @param param2.male Male definitions. + * @param type Type of the definition. * * @returns Definition based on given sex. */ @@ -26,12 +28,12 @@ function selectDefinition( faker: Faker, elementSelectorFn: (values: T[]) => string, sex: SexType | undefined, - // TODO @Shinigami92 2022-03-21: Remove fallback empty object when `strict: true` { generic, female, male, - }: { generic?: T[] | null; female?: T[] | null; male?: T[] | null } = {} + }: { generic?: T[] | null; female?: T[] | null; male?: T[] | null }, + type: string ): string { let values: T[] | undefined | null; @@ -56,11 +58,7 @@ function selectDefinition( values = generic; } - if (values == null) { - throw new FakerError( - 'Neither female, male or generic definitions are available.' - ); - } + assertLocaleData(values, `person.{${type}, female_${type}, male_${type}}`); } return elementSelectorFn(values); @@ -107,11 +105,17 @@ export class PersonModule { const { first_name, female_first_name, male_first_name } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: first_name, - female: female_first_name, - male: male_first_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: first_name, + female: female_first_name, + male: male_first_name, + }, + 'first_name' + ); } /** @@ -150,16 +154,23 @@ export class PersonModule { generic: last_name_pattern, female: female_last_name_pattern, male: male_last_name_pattern, - } + }, + 'last_name_pattern' ); return this.faker.helpers.fake(pattern); } - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: last_name, - female: female_last_name, - male: male_last_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: last_name, + female: female_last_name, + male: male_last_name, + }, + 'last_name' + ); } /** @@ -179,11 +190,17 @@ export class PersonModule { const { middle_name, female_middle_name, male_middle_name } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: middle_name, - female: female_middle_name, - male: male_middle_name, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: middle_name, + female: female_middle_name, + male: male_middle_name, + }, + 'middle_name' + ); } /** @@ -320,11 +337,17 @@ export class PersonModule { const { prefix, female_prefix, male_prefix } = this.faker.rawDefinitions.person ?? {}; - return selectDefinition(this.faker, this.faker.helpers.arrayElement, sex, { - generic: prefix, - female: female_prefix, - male: male_prefix, - }); + return selectDefinition( + this.faker, + this.faker.helpers.arrayElement, + sex, + { + generic: prefix, + female: female_prefix, + male: male_prefix, + }, + 'prefix' + ); } /** From a2a303dd2fe5d68ed101ce072f005c860805ae2a Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Sat, 7 Oct 2023 13:27:53 +0200 Subject: [PATCH 13/20] chore: apply suggestions --- src/locale-proxy.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/locale-proxy.ts b/src/locale-proxy.ts index 6c59ec291f3..e99ba655156 100644 --- a/src/locale-proxy.ts +++ b/src/locale-proxy.ts @@ -64,21 +64,17 @@ export function assertLocaleData( value: T, ...path: string[] ): asserts value is NonNullable { - if (value == null) { - if (value === null) { - throw new FakerError( - `The locale data for '${path.join( - '.' - )}' aren't applicable to this locale. + if (value === null) { + throw new FakerError( + `The locale data for '${path.join('.')}' aren't applicable to this locale. If you think this is a bug, please report it at: https://github.com/faker-js/faker` - ); - } else if (value === undefined) { - throw new FakerError( - `The locale data for '${path.join('.')}' are missing in this locale. + ); + } else if (value === undefined) { + throw new FakerError( + `The locale data for '${path.join('.')}' are missing in this locale. Please contribute the missing data to the project or use a locale/Faker instance that has these data. For more information see https://fakerjs.dev/guide/localization.html` - ); - } + ); } } From 6fe42533ea99891060c8f16cf8b5a00d480df0b0 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 20 Oct 2023 10:46:23 +0200 Subject: [PATCH 14/20] revert: helpers changes --- src/modules/helpers/index.ts | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/modules/helpers/index.ts b/src/modules/helpers/index.ts index 6c3f6ba04ee..dd4fdb3d284 100644 --- a/src/modules/helpers/index.ts +++ b/src/modules/helpers/index.ts @@ -422,7 +422,6 @@ export class SimpleHelpersModule { const quantifierMin: string = token[2]; const quantifierMax: string = token[3]; const quantifierSymbol: string = token[4]; - const tokenIndex: number = token.index; repetitions = getRepetitionsBasedOnQuantifierParameters( this.faker, @@ -432,11 +431,9 @@ export class SimpleHelpersModule { ); pattern = - pattern.slice(0, tokenIndex) + + pattern.slice(0, token.index) + token[1].repeat(repetitions) + - pattern.slice(tokenIndex + token[0].length); - - pattern.slice(token.index + token[0].length); + pattern.slice(token.index + token[0].length); token = SINGLE_CHAR_REG.exec(pattern); } @@ -451,7 +448,6 @@ export class SimpleHelpersModule { const quantifierMin: string = token[4]; const quantifierMax: string = token[5]; const quantifierSymbol: string = token[6]; - const tokenIndex: number = token.index; const rangeCodes: number[] = []; @@ -550,9 +546,9 @@ export class SimpleHelpersModule { ).join(''); pattern = - pattern.slice(0, tokenIndex) + + pattern.slice(0, token.index) + generatedString + - pattern.slice(tokenIndex + token[0].length); + pattern.slice(token.index + token[0].length); token = RANGE_ALPHANUMEMRIC_REG.exec(pattern); } @@ -562,7 +558,6 @@ export class SimpleHelpersModule { while (token != null) { min = parseInt(token[2]); max = parseInt(token[3]); - const tokenIndex = token.index; // throw error if min larger than max if (min > max) { throw new FakerError('Numbers out of order in {} quantifier.'); @@ -570,9 +565,9 @@ export class SimpleHelpersModule { repetitions = this.faker.number.int({ min, max }); pattern = - pattern.slice(0, tokenIndex) + + pattern.slice(0, token.index) + token[1].repeat(repetitions) + - pattern.slice(tokenIndex + token[0].length); + pattern.slice(token.index + token[0].length); token = RANGE_REP_REG.exec(pattern); } @@ -581,11 +576,10 @@ export class SimpleHelpersModule { token = REP_REG.exec(pattern); while (token != null) { repetitions = parseInt(token[2]); - const tokenIndex = token.index; pattern = - pattern.slice(0, tokenIndex) + + pattern.slice(0, token.index) + token[1].repeat(repetitions) + - pattern.slice(tokenIndex + token[0].length); + pattern.slice(token.index + token[0].length); token = REP_REG.exec(pattern); } From bf88c588d50118f857eec1409679f775846eb410 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Mon, 6 Nov 2023 10:06:18 +0100 Subject: [PATCH 15/20] chore: fix lint issues --- src/modules/commerce/index.ts | 10 +++++++++- test/modules/airline.spec.ts | 20 ++++++++++++-------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/modules/commerce/index.ts b/src/modules/commerce/index.ts index 1e37af3231e..2f22239c6e4 100644 --- a/src/modules/commerce/index.ts +++ b/src/modules/commerce/index.ts @@ -1,3 +1,4 @@ +import { FakerError } from '../../errors/faker-error'; import type { Faker } from '../../faker'; import { bindThisToMemberFunctions } from '../../internal/bind-this-to-member-functions'; import { deprecated } from '../../internal/deprecated'; @@ -386,7 +387,14 @@ export class CommerceModule { const registrantLength = groupRules.find( ([rangeMaximum]) => elementValue <= rangeMaximum - )![1]; + )?.[1]; + + if (!registrantLength) { + // This can only happen if the ISBN_LENGTH_RULES are corrupted + throw new FakerError( + `Unable to find a registrant length for the group ${group}` + ); + } const registrant = element.slice(0, registrantLength); const publication = element.slice(registrantLength); diff --git a/test/modules/airline.spec.ts b/test/modules/airline.spec.ts index df5f2fd7d42..bf674570c76 100644 --- a/test/modules/airline.spec.ts +++ b/test/modules/airline.spec.ts @@ -95,8 +95,8 @@ describe('airline', () => { const seatRegex = /^(\d{1,2})([A-K])$/; it('should return a random narrowbody seat when not passing an argument', () => { const seat = faker.airline.seat(); - const matchResult = seatRegex.exec(seat)!; - expect(matchResult).not.toBeNull(); + const matchResult = seatRegex.exec(seat); + expectNotNull(matchResult); const row = matchResult[1]; const seatLetter = matchResult[2]; expect(row).toSatisfy((row: number) => row >= 1 && row <= 35); @@ -106,8 +106,8 @@ describe('airline', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Narrowbody, }); - const matchResult = seatRegex.exec(seat)!; - expect(matchResult).not.toBeNull(); + const matchResult = seatRegex.exec(seat); + expectNotNull(matchResult); const row = matchResult[1]; const seatLetter = matchResult[2]; expect(row).toSatisfy((row: number) => row >= 1 && row <= 35); @@ -115,8 +115,8 @@ describe('airline', () => { }); it('should return a random regional seat', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Regional }); - const matchResult = seatRegex.exec(seat)!; - expect(matchResult).not.toBeNull(); + const matchResult = seatRegex.exec(seat); + expectNotNull(matchResult); const row = matchResult[1]; const seatLetter = matchResult[2]; expect(row).toSatisfy((row: number) => row >= 1 && row <= 20); @@ -124,8 +124,8 @@ describe('airline', () => { }); it('should return a random widebody seat', () => { const seat = faker.airline.seat({ aircraftType: Aircraft.Widebody }); - const matchResult = seatRegex.exec(seat)!; - expect(matchResult).not.toBeNull(); + const matchResult = seatRegex.exec(seat); + expectNotNull(matchResult); const row = matchResult[1]; const seatLetter = matchResult[2]; expect(row).toSatisfy((row: number) => row >= 1 && row <= 60); @@ -179,3 +179,7 @@ describe('airline', () => { } ); }); + +function expectNotNull(value: T): asserts value is NonNullable { + expect(value).not.toBeNull(); +} From 234c12fdf08fd31edc793c7ed25d101c823e5eb5 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Mon, 6 Nov 2023 10:16:51 +0100 Subject: [PATCH 16/20] chore: fix another lint warning --- src/modules/date/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index 9cb76015b21..d5f36ddf112 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -1081,6 +1081,7 @@ export class DateModule extends SimpleDateModule { context?: boolean; } = {} ): string { + // eslint-disable-next-line deprecation/deprecation const { abbr, abbreviated = abbr ?? false, context = false } = options; if (abbr != null) { @@ -1264,6 +1265,7 @@ export class DateModule extends SimpleDateModule { context?: boolean; } = {} ): string { + // eslint-disable-next-line deprecation/deprecation const { abbr, abbreviated = abbr ?? false, context = false } = options; if (abbr != null) { From 85e9096d782b8d6f7c071bb7d4880af2ff32a7d1 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Mon, 6 Nov 2023 10:32:37 +0100 Subject: [PATCH 17/20] chore: fix import issue --- src/modules/date/index.ts | 24 ++++++++++++++++++++++++ src/modules/person/index.ts | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index d5f36ddf112..eca0097cb2a 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -1292,3 +1292,27 @@ export class DateModule extends SimpleDateModule { return this.faker.helpers.arrayElement(values); } } + +/** + * + * @param options asd + * @param options.deprecated as + * @param options.replacement asd + */ +export function demo( + options: { + /** + * @deprecated + */ + deprecated?: boolean; + replacement?: boolean; + } = {} +): boolean { + const { + // eslint-disable-next-line deprecation/deprecation + deprecated = false, + // eslint-disable-next-line deprecation/deprecation + replacement = deprecated, + } = options; + return replacement; +} diff --git a/src/modules/person/index.ts b/src/modules/person/index.ts index af580b81d99..f5a2811cb13 100644 --- a/src/modules/person/index.ts +++ b/src/modules/person/index.ts @@ -1,5 +1,5 @@ import type { Faker } from '../..'; -import { FakerError } from '../..'; +import { FakerError } from '../../errors/faker-error'; import { ModuleBase } from '../../internal/module-base'; import { assertLocaleData } from '../../locale-proxy'; From 109738fd71f97a132455c4beb509f9f60033bb3c Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Mon, 6 Nov 2023 21:56:41 +0100 Subject: [PATCH 18/20] Update src/modules/date/index.ts --- src/modules/date/index.ts | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index eca0097cb2a..d5f36ddf112 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -1292,27 +1292,3 @@ export class DateModule extends SimpleDateModule { return this.faker.helpers.arrayElement(values); } } - -/** - * - * @param options asd - * @param options.deprecated as - * @param options.replacement asd - */ -export function demo( - options: { - /** - * @deprecated - */ - deprecated?: boolean; - replacement?: boolean; - } = {} -): boolean { - const { - // eslint-disable-next-line deprecation/deprecation - deprecated = false, - // eslint-disable-next-line deprecation/deprecation - replacement = deprecated, - } = options; - return replacement; -} From cb4383a91e731ce5223705c45e45d3813070ed46 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 10 Nov 2023 17:50:52 +0100 Subject: [PATCH 19/20] chore: fix lint warning --- src/modules/color/index.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts index 5962ef71b67..792b0c0b673 100644 --- a/src/modules/color/index.ts +++ b/src/modules/color/index.ts @@ -52,12 +52,14 @@ export type Casing = 'lower' | 'upper' | 'mixed'; */ function formatHexColor( hexColor: string, - options?: { + options: { prefix?: string; casing?: Casing; - } + } = {} ): string { - switch (options?.casing) { + const { prefix = '0x', casing = 'mixed' } = options; + + switch (casing) { case 'upper': hexColor = hexColor.toUpperCase(); break; @@ -68,7 +70,7 @@ function formatHexColor( // Do nothing } - if (options?.prefix) { + if (prefix) { hexColor = options.prefix + hexColor; } From 6efe430bbafcd94dc42d205671ea2e97e257ba62 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Fri, 10 Nov 2023 18:13:35 +0100 Subject: [PATCH 20/20] chore: remove wrong defaults and make the properties required --- src/modules/color/index.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/modules/color/index.ts b/src/modules/color/index.ts index 792b0c0b673..57b906a376d 100644 --- a/src/modules/color/index.ts +++ b/src/modules/color/index.ts @@ -47,17 +47,17 @@ export type Casing = 'lower' | 'upper' | 'mixed'; * * @param hexColor Hex color string to be formatted. * @param options Options object. - * @param options.prefix Prefix of the generated hex color. Defaults to `'0x'`. - * @param options.casing Letter type case of the generated hex color. Defaults to `'mixed'`. + * @param options.prefix Prefix of the generated hex color. + * @param options.casing Letter type case of the generated hex color. */ function formatHexColor( hexColor: string, options: { - prefix?: string; - casing?: Casing; - } = {} + prefix: string; + casing: Casing; + } ): string { - const { prefix = '0x', casing = 'mixed' } = options; + const { prefix, casing } = options; switch (casing) { case 'upper': @@ -71,7 +71,7 @@ function formatHexColor( } if (prefix) { - hexColor = options.prefix + hexColor; + hexColor = prefix + hexColor; } return hexColor; @@ -362,19 +362,20 @@ export class ColorModule extends ModuleBase { */ includeAlpha?: boolean; }): string | number[]; - rgb(options?: { - prefix?: string; - casing?: Casing; - format?: 'hex' | ColorFormat; - includeAlpha?: boolean; - }): string | number[] { + rgb( + options: { + prefix?: string; + casing?: Casing; + format?: 'hex' | ColorFormat; + includeAlpha?: boolean; + } = {} + ): string | number[] { const { format = 'hex', includeAlpha = false, prefix = '#', casing = 'lower', - } = options || {}; - options = { format, includeAlpha, prefix, casing }; + } = options; let color: string | number[]; let cssFunction: CssFunctionType = 'rgb'; if (format === 'hex') { @@ -382,7 +383,7 @@ export class ColorModule extends ModuleBase { length: includeAlpha ? 8 : 6, prefix: '', }); - color = formatHexColor(color, options); + color = formatHexColor(color, { prefix, casing }); return color; }