From 9537dfddba882bd93d9a429697fd44bc72428426 Mon Sep 17 00:00:00 2001 From: DivisionByZero Date: Thu, 26 Sep 2024 17:50:05 +0200 Subject: infra: update file structure for util/internal (#3141) --- src/faker.ts | 4 +- src/index.ts | 8 +-- src/internal/locale-proxy.ts | 115 +++++++++++++++++++++++++++++++++++++++++++ src/internal/mersenne.ts | 48 ------------------ src/internal/types.ts | 39 +++++++++++++++ src/locale-proxy.ts | 115 ------------------------------------------- src/modules/date/index.ts | 2 +- src/modules/string/index.ts | 2 +- src/simple-faker.ts | 2 +- src/utils/mersenne.ts | 48 ++++++++++++++++++ src/utils/types.ts | 39 --------------- 11 files changed, 211 insertions(+), 211 deletions(-) create mode 100644 src/internal/locale-proxy.ts create mode 100644 src/internal/types.ts delete mode 100644 src/locale-proxy.ts create mode 100644 src/utils/mersenne.ts delete mode 100644 src/utils/types.ts (limited to 'src') diff --git a/src/faker.ts b/src/faker.ts index 5f5e14ce..7b7f5e16 100644 --- a/src/faker.ts +++ b/src/faker.ts @@ -1,8 +1,8 @@ import type { LocaleDefinition, MetadataDefinition } from './definitions'; import { FakerError } from './errors/faker-error'; import { deprecated } from './internal/deprecated'; -import type { LocaleProxy } from './locale-proxy'; -import { createLocaleProxy } from './locale-proxy'; +import type { LocaleProxy } from './internal/locale-proxy'; +import { createLocaleProxy } from './internal/locale-proxy'; import { AirlineModule } from './modules/airline'; import { AnimalModule } from './modules/animal'; import { ColorModule } from './modules/color'; diff --git a/src/index.ts b/src/index.ts index 0b590340..f94b3aa0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,10 +30,6 @@ export type { export { FakerError } from './errors/faker-error'; export { Faker } from './faker'; export type { FakerOptions } from './faker'; -export { - generateMersenne32Randomizer, - generateMersenne53Randomizer, -} from './internal/mersenne'; export * from './locale'; export { fakerEN as faker } from './locale'; export * from './locales'; @@ -85,3 +81,7 @@ export type { WordModule } from './modules/word'; export type { Randomizer } from './randomizer'; export { SimpleFaker, simpleFaker } from './simple-faker'; export { mergeLocales } from './utils/merge-locales'; +export { + generateMersenne32Randomizer, + generateMersenne53Randomizer, +} from './utils/mersenne'; diff --git a/src/internal/locale-proxy.ts b/src/internal/locale-proxy.ts new file mode 100644 index 00000000..dbb9f277 --- /dev/null +++ b/src/internal/locale-proxy.ts @@ -0,0 +1,115 @@ +import type { LocaleDefinition } from '../definitions'; +import { FakerError } from '../errors/faker-error'; + +/** + * A proxy for LocaleDefinition that marks all properties as required and throws an error when an entry is accessed that is not defined. + */ +export type LocaleProxy = Readonly<{ + [key in keyof LocaleDefinition]-?: LocaleProxyCategory; +}>; + +type LocaleProxyCategory = Readonly<{ + [key in keyof T]-?: LocaleProxyEntry; +}>; + +type LocaleProxyEntry = unknown extends T ? T : Readonly>; + +const throwReadOnlyError: () => never = () => { + throw new FakerError('You cannot edit the locale data on the faker instance'); +}; + +/** + * Creates a proxy for LocaleDefinition that throws an error if an undefined property is accessed. + * + * @param locale The locale definition to create the proxy for. + */ +export function createLocaleProxy(locale: LocaleDefinition): LocaleProxy { + const proxies = {} as LocaleDefinition; + return new Proxy(locale, { + has(): true { + // Categories are always present (proxied), that's why we return true. + return true; + }, + + get( + target: LocaleDefinition, + categoryName: keyof LocaleDefinition + ): LocaleDefinition[keyof LocaleDefinition] { + if (typeof categoryName === 'symbol' || categoryName === 'nodeType') { + return target[categoryName]; + } + + if (categoryName in proxies) { + return proxies[categoryName]; + } + + return (proxies[categoryName] = createCategoryProxy( + categoryName, + target[categoryName] + )); + }, + + set: throwReadOnlyError, + deleteProperty: throwReadOnlyError, + }) 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) { + 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. + * + * @param categoryName The name of the category. + * @param categoryData The module to create the proxy for. + */ +function createCategoryProxy< + TCategoryData extends Record, +>( + categoryName: string, + categoryData: TCategoryData = {} as TCategoryData +): Required { + return new Proxy(categoryData, { + has(target: TCategoryData, entryName: keyof TCategoryData): boolean { + const value = target[entryName]; + return value != null; + }, + + get( + target: TCategoryData, + entryName: keyof TCategoryData + ): TCategoryData[keyof TCategoryData] { + const value = target[entryName]; + if (typeof entryName === 'symbol' || entryName === 'nodeType') { + return value; + } + + assertLocaleData(value, categoryName, entryName.toString()); + return value; + }, + + set: throwReadOnlyError, + deleteProperty: throwReadOnlyError, + }) as Required; +} diff --git a/src/internal/mersenne.ts b/src/internal/mersenne.ts index d01b5ee9..351faa4e 100644 --- a/src/internal/mersenne.ts +++ b/src/internal/mersenne.ts @@ -1,5 +1,3 @@ -import type { Randomizer } from '../randomizer'; - /** * Copyright (c) 2022-2023 Faker * @@ -325,49 +323,3 @@ export class MersenneTwister19937 { } // These real versions are due to Isaku Wada, 2002/01/09 } - -/** - * Generates a MersenneTwister19937 randomizer with 32 bits of precision. - * This is the default randomizer used by faker prior to v9.0. - */ -export function generateMersenne32Randomizer(): Randomizer { - const twister = new MersenneTwister19937(); - - twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); - - return { - next(): number { - return twister.genrandReal2(); - }, - seed(seed: number | number[]): void { - if (typeof seed === 'number') { - twister.initGenrand(seed); - } else if (Array.isArray(seed)) { - twister.initByArray(seed, seed.length); - } - }, - }; -} - -/** - * Generates a MersenneTwister19937 randomizer with 53 bits of precision. - * This is the default randomizer used by faker starting with v9.0. - */ -export function generateMersenne53Randomizer(): Randomizer { - const twister = new MersenneTwister19937(); - - twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); - - return { - next(): number { - return twister.genrandRes53(); - }, - seed(seed: number | number[]): void { - if (typeof seed === 'number') { - twister.initGenrand(seed); - } else if (Array.isArray(seed)) { - twister.initByArray(seed, seed.length); - } - }, - }; -} diff --git a/src/internal/types.ts b/src/internal/types.ts new file mode 100644 index 00000000..affdda7e --- /dev/null +++ b/src/internal/types.ts @@ -0,0 +1,39 @@ +/** + * Type that provides auto-suggestions but also any string. + * + * @see https://github.com/microsoft/TypeScript/issues/29729#issuecomment-471566609 + */ +export type LiteralUnion = + | TSuggested + | (TBase & { zz_IGNORE_ME?: never }); + +/** + * A function that returns a value. + * + * `Function` cannot be used instead because it doesn't accept class declarations. + * These would fail when invoked since they are invoked without the `new` keyword. + */ +export type Callable = ( + // TODO @Shinigami92 2023-02-14: This `any` type can be fixed by anyone if they want to. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...args: any[] +) => unknown; + +/** + * Type that represents a single method/function name of the given type. + */ +export type MethodOf = { + [Key in keyof TObjectType]: TObjectType[Key] extends TSignature + ? Key extends string + ? Key + : never + : never; +}[keyof TObjectType]; + +/** + * Type that represents all method/function names of the given type. + */ +export type MethodsOf< + TObjectType, + TSignature extends Callable = Callable, +> = ReadonlyArray>; diff --git a/src/locale-proxy.ts b/src/locale-proxy.ts deleted file mode 100644 index e99ba655..00000000 --- a/src/locale-proxy.ts +++ /dev/null @@ -1,115 +0,0 @@ -import type { LocaleDefinition } from './definitions'; -import { FakerError } from './errors/faker-error'; - -/** - * A proxy for LocaleDefinition that marks all properties as required and throws an error when an entry is accessed that is not defined. - */ -export type LocaleProxy = Readonly<{ - [key in keyof LocaleDefinition]-?: LocaleProxyCategory; -}>; - -type LocaleProxyCategory = Readonly<{ - [key in keyof T]-?: LocaleProxyEntry; -}>; - -type LocaleProxyEntry = unknown extends T ? T : Readonly>; - -const throwReadOnlyError: () => never = () => { - throw new FakerError('You cannot edit the locale data on the faker instance'); -}; - -/** - * Creates a proxy for LocaleDefinition that throws an error if an undefined property is accessed. - * - * @param locale The locale definition to create the proxy for. - */ -export function createLocaleProxy(locale: LocaleDefinition): LocaleProxy { - const proxies = {} as LocaleDefinition; - return new Proxy(locale, { - has(): true { - // Categories are always present (proxied), that's why we return true. - return true; - }, - - get( - target: LocaleDefinition, - categoryName: keyof LocaleDefinition - ): LocaleDefinition[keyof LocaleDefinition] { - if (typeof categoryName === 'symbol' || categoryName === 'nodeType') { - return target[categoryName]; - } - - if (categoryName in proxies) { - return proxies[categoryName]; - } - - return (proxies[categoryName] = createCategoryProxy( - categoryName, - target[categoryName] - )); - }, - - set: throwReadOnlyError, - deleteProperty: throwReadOnlyError, - }) 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) { - 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. - * - * @param categoryName The name of the category. - * @param categoryData The module to create the proxy for. - */ -function createCategoryProxy< - TCategoryData extends Record, ->( - categoryName: string, - categoryData: TCategoryData = {} as TCategoryData -): Required { - return new Proxy(categoryData, { - has(target: TCategoryData, entryName: keyof TCategoryData): boolean { - const value = target[entryName]; - return value != null; - }, - - get( - target: TCategoryData, - entryName: keyof TCategoryData - ): TCategoryData[keyof TCategoryData] { - const value = target[entryName]; - if (typeof entryName === 'symbol' || entryName === 'nodeType') { - return value; - } - - assertLocaleData(value, categoryName, entryName.toString()); - return value; - }, - - set: throwReadOnlyError, - deleteProperty: throwReadOnlyError, - }) as Required; -} diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index f2eac1cf..53204a03 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -1,8 +1,8 @@ import type { Faker } from '../..'; import type { DateEntryDefinition } from '../../definitions'; import { FakerError } from '../../errors/faker-error'; +import { assertLocaleData } from '../../internal/locale-proxy'; import { SimpleModuleBase } from '../../internal/module-base'; -import { assertLocaleData } from '../../locale-proxy'; /** * Converts a date passed as a `string`, `number` or `Date` to a valid `Date` object. diff --git a/src/modules/string/index.ts b/src/modules/string/index.ts index cfee0dc1..7df31fc7 100644 --- a/src/modules/string/index.ts +++ b/src/modules/string/index.ts @@ -1,6 +1,6 @@ import { FakerError } from '../../errors/faker-error'; import { SimpleModuleBase } from '../../internal/module-base'; -import type { LiteralUnion } from '../../utils/types'; +import type { LiteralUnion } from '../../internal/types'; export type Casing = 'upper' | 'lower' | 'mixed'; diff --git a/src/simple-faker.ts b/src/simple-faker.ts index e775cbc7..743df923 100644 --- a/src/simple-faker.ts +++ b/src/simple-faker.ts @@ -1,10 +1,10 @@ -import { generateMersenne53Randomizer } from './internal/mersenne'; import { DatatypeModule } from './modules/datatype'; import { SimpleDateModule } from './modules/date'; import { SimpleHelpersModule } from './modules/helpers'; import { NumberModule } from './modules/number'; import { StringModule } from './modules/string'; import type { Randomizer } from './randomizer'; +import { generateMersenne53Randomizer } from './utils/mersenne'; /** * This is a simplified Faker class that doesn't need any localized data to generate its output. diff --git a/src/utils/mersenne.ts b/src/utils/mersenne.ts new file mode 100644 index 00000000..de415f91 --- /dev/null +++ b/src/utils/mersenne.ts @@ -0,0 +1,48 @@ +import { MersenneTwister19937 } from '../internal/mersenne'; +import type { Randomizer } from '../randomizer'; + +/** + * Generates a MersenneTwister19937 randomizer with 32 bits of precision. + * This is the default randomizer used by faker prior to v9.0. + */ +export function generateMersenne32Randomizer(): Randomizer { + const twister = new MersenneTwister19937(); + + twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); + + return { + next(): number { + return twister.genrandReal2(); + }, + seed(seed: number | number[]): void { + if (typeof seed === 'number') { + twister.initGenrand(seed); + } else if (Array.isArray(seed)) { + twister.initByArray(seed, seed.length); + } + }, + }; +} + +/** + * Generates a MersenneTwister19937 randomizer with 53 bits of precision. + * This is the default randomizer used by faker starting with v9.0. + */ +export function generateMersenne53Randomizer(): Randomizer { + const twister = new MersenneTwister19937(); + + twister.initGenrand(Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER)); + + return { + next(): number { + return twister.genrandRes53(); + }, + seed(seed: number | number[]): void { + if (typeof seed === 'number') { + twister.initGenrand(seed); + } else if (Array.isArray(seed)) { + twister.initByArray(seed, seed.length); + } + }, + }; +} diff --git a/src/utils/types.ts b/src/utils/types.ts deleted file mode 100644 index affdda7e..00000000 --- a/src/utils/types.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Type that provides auto-suggestions but also any string. - * - * @see https://github.com/microsoft/TypeScript/issues/29729#issuecomment-471566609 - */ -export type LiteralUnion = - | TSuggested - | (TBase & { zz_IGNORE_ME?: never }); - -/** - * A function that returns a value. - * - * `Function` cannot be used instead because it doesn't accept class declarations. - * These would fail when invoked since they are invoked without the `new` keyword. - */ -export type Callable = ( - // TODO @Shinigami92 2023-02-14: This `any` type can be fixed by anyone if they want to. - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ...args: any[] -) => unknown; - -/** - * Type that represents a single method/function name of the given type. - */ -export type MethodOf = { - [Key in keyof TObjectType]: TObjectType[Key] extends TSignature - ? Key extends string - ? Key - : never - : never; -}[keyof TObjectType]; - -/** - * Type that represents all method/function names of the given type. - */ -export type MethodsOf< - TObjectType, - TSignature extends Callable = Callable, -> = ReadonlyArray>; -- cgit v1.2.3