aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinigami92 <[email protected]>2022-01-10 21:34:27 +0100
committerDamien Retzinger <[email protected]>2022-01-14 18:37:49 -0500
commite0d0b5cc45cfde3dd6a351650becf9ea83b99ae2 (patch)
tree8014f68054db34065e1192ed61cd2e943ebe9bd5
parentb20f80bf7886e89045e369add9c5598d3586a225 (diff)
downloadfaker-e0d0b5cc45cfde3dd6a351650becf9ea83b99ae2.tar.xz
faker-e0d0b5cc45cfde3dd6a351650becf9ea83b99ae2.zip
feat: rewrite datatype to ts
-rw-r--r--src/datatype.ts253
-rw-r--r--src/index.ts36
-rw-r--r--src/mersenne.ts36
-rw-r--r--src/random.ts24
4 files changed, 349 insertions, 0 deletions
diff --git a/src/datatype.ts b/src/datatype.ts
new file mode 100644
index 00000000..9aa2dea9
--- /dev/null
+++ b/src/datatype.ts
@@ -0,0 +1,253 @@
+import type { Faker } from '.';
+
+export class Datatype {
+ constructor(private readonly faker: Faker, seed?: any[] | any) {
+ // Use a user provided seed if it is an array or number
+ if (Array.isArray(seed) && seed.length) {
+ this.faker.mersenne.seed_array(seed);
+ } else if (!isNaN(seed)) {
+ this.faker.mersenne.seed(seed);
+ }
+ }
+
+ /**
+ * Returns a single random number based on a max number or range.
+ *
+ * @method faker.datatype.number
+ * @param options
+ */
+ number(
+ options?: number | { min?: number; max?: number; precision?: number }
+ ): number {
+ if (typeof options === 'number') {
+ options = { max: options };
+ }
+
+ options = options ?? {};
+
+ if (typeof options.min === 'undefined') {
+ options.min = 0;
+ }
+
+ if (typeof options.max === 'undefined') {
+ options.max = 99999;
+ }
+
+ if (typeof options.precision === 'undefined') {
+ options.precision = 1;
+ }
+
+ // Make the range inclusive of the max value
+ let max = options.max;
+ if (max >= 0) {
+ max += options.precision;
+ }
+
+ let randomNumber = Math.floor(
+ this.faker.mersenne.rand(
+ max / options.precision,
+ options.min / options.precision
+ )
+ );
+ // Workaround problem in Float point arithmetics for e.g. 6681493 / 0.01
+ randomNumber = randomNumber / (1 / options.precision);
+
+ return randomNumber;
+ }
+
+ /**
+ * Returns a single random floating-point number based on a max number or range.
+ *
+ * @method faker.datatype.float
+ * @param options
+ */
+ float(
+ options?: number | { min?: number; max?: number; precision?: number }
+ ): number {
+ if (typeof options === 'number') {
+ options = {
+ precision: options,
+ };
+ }
+ options = options || {};
+ const opts: { precision?: number } = {};
+ for (const p in options) {
+ opts[p] = options[p];
+ }
+ if (typeof opts.precision === 'undefined') {
+ opts.precision = 0.01;
+ }
+ return this.faker.datatype.number(opts);
+ }
+
+ /**
+ * Returns a Date object using a random number of milliseconds since 1. Jan 1970 UTC
+ * Caveat: seeding is not working
+ *
+ * @method faker.datatype.datetime
+ * @param options pass min OR max as number of milliseconds since 1. Jan 1970 UTC
+ */
+ datetime(options): Date {
+ if (typeof options === 'number') {
+ options = {
+ max: options,
+ };
+ }
+
+ const minMax = 8640000000000000;
+
+ options = options || {};
+
+ if (typeof options.min === 'undefined' || options.min < minMax * -1) {
+ options.min = new Date().setFullYear(1990, 1, 1);
+ }
+
+ if (typeof options.max === 'undefined' || options.max > minMax) {
+ options.max = new Date().setFullYear(2100, 1, 1);
+ }
+
+ const random = this.faker.datatype.number(options);
+ return new Date(random);
+ }
+
+ /**
+ * Returns a string, containing UTF-16 chars between 33 and 125 ('!' to '}')
+ *
+ *
+ * @method faker.datatype.string
+ * @param length length of generated string, default = 10, max length = 2^20
+ */
+ string(length: number = 10): string {
+ const maxLength = Math.pow(2, 20);
+ if (length >= maxLength) {
+ length = maxLength;
+ }
+
+ const charCodeOption = {
+ min: 33,
+ max: 125,
+ };
+
+ let returnString = '';
+
+ for (var i = 0; i < length; i++) {
+ returnString += String.fromCharCode(
+ this.faker.datatype.number(charCodeOption)
+ );
+ }
+
+ return returnString;
+ }
+
+ /**
+ * uuid
+ *
+ * @method faker.datatype.uuid
+ */
+ uuid(): string {
+ const RFC4122_TEMPLATE = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
+ const replacePlaceholders = (placeholder) => {
+ const random = this.faker.datatype.number({ min: 0, max: 15 });
+ const value = placeholder == 'x' ? random : (random & 0x3) | 0x8;
+ return value.toString(16);
+ };
+ return RFC4122_TEMPLATE.replace(/[xy]/g, replacePlaceholders);
+ }
+
+ /**
+ * boolean
+ *
+ * @method faker.datatype.boolean
+ */
+ boolean(): boolean {
+ return !!this.faker.datatype.number(1);
+ }
+
+ /**
+ * hexaDecimal
+ *
+ * @method faker.datatype.hexaDecimal
+ * @param {number} count defaults to 1
+ */
+ hexaDecimal(count: number = 1): string {
+ let wholeString = '';
+ for (let i = 0; i < count; i++) {
+ wholeString += this.faker.random.arrayElement([
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'a',
+ 'b',
+ 'c',
+ 'd',
+ 'e',
+ 'f',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F',
+ ]);
+ }
+
+ return '0x' + wholeString;
+ }
+
+ /**
+ * Returns json object with 7 pre-defined properties
+ *
+ * @method faker.datatype.json
+ */
+ json(): string {
+ const properties = ['foo', 'bar', 'bike', 'a', 'b', 'name', 'prop'];
+
+ const returnObject: Record<string, string | number> = {};
+ properties.forEach((prop) => {
+ returnObject[prop] = this.faker.datatype.boolean()
+ ? this.faker.datatype.string()
+ : this.faker.datatype.number();
+ });
+
+ return JSON.stringify(returnObject);
+ }
+
+ /**
+ * Returns an array with values generated by faker.datatype.number and faker.datatype.string
+ *
+ * @method faker.datatype.array
+ * @param length length of the returned array
+ */
+
+ array(length: number = 10): Array<string | number> {
+ const returnArray = new Array(length);
+ for (var i = 0; i < length; i++) {
+ returnArray[i] = this.faker.datatype.boolean()
+ ? this.faker.datatype.string()
+ : this.faker.datatype.number();
+ }
+ return returnArray;
+ }
+
+ /**
+ * Returns a Big Integer with values generated by faker.datatype.bigInt
+ *
+ * @method faker.datatype.bigInt
+ * @param value
+ */
+ bigInt(value?: string | number | bigint | boolean): bigint {
+ if (value === undefined) {
+ value =
+ Math.floor(this.faker.datatype.number() * 99999999999) + 10000000000;
+ }
+
+ return BigInt(value);
+ }
+}
diff --git a/src/index.ts b/src/index.ts
new file mode 100644
index 00000000..ea724d04
--- /dev/null
+++ b/src/index.ts
@@ -0,0 +1,36 @@
+import { Datatype } from './datatype';
+import { Mersenne } from './mersenne';
+import { Random } from './random';
+
+export interface FakerOptions {
+ locales?: string[];
+ locale?: string;
+ localeFallback?: string;
+}
+
+export class Faker {
+ locales: string[] | {};
+ locale: string;
+ localeFallback: string;
+
+ seedValue?: any[] | any;
+
+ readonly mersenne: Mersenne = new Mersenne();
+ random = new Random(this);
+ datatype: Datatype = new Datatype(this);
+
+ constructor(opts: FakerOptions = {}) {
+ this.locales = this.locales || opts.locales || {};
+ this.locale = this.locale || opts.locale || 'en';
+ this.localeFallback = this.localeFallback || opts.localeFallback || 'en';
+ }
+
+ seed(value?: any[] | any) {
+ this.seedValue = value;
+ this.random = new Random(this, this.seedValue);
+ this.datatype = new Datatype(this, this.seedValue);
+ }
+}
+
+export default Faker;
+module.exports = Faker;
diff --git a/src/mersenne.ts b/src/mersenne.ts
new file mode 100644
index 00000000..e7ab78eb
--- /dev/null
+++ b/src/mersenne.ts
@@ -0,0 +1,36 @@
+const Gen = require('../vendor/mersenne').MersenneTwister19937;
+
+export class Mersenne {
+ private gen = new Gen();
+
+ constructor() {
+ this.gen.init_genrand(new Date().getTime() % 1000000000);
+ }
+
+ rand(max, min) {
+ if (max === undefined) {
+ min = 0;
+ max = 32768;
+ }
+
+ return Math.floor(this.gen.genrand_real2() * (max - min) + min);
+ }
+
+ seed(S) {
+ if (typeof S != 'number') {
+ throw new Error('seed(S) must take numeric argument; is ' + typeof S);
+ }
+
+ this.gen.init_genrand(S);
+ }
+
+ seed_array(A) {
+ if (typeof A != 'object') {
+ throw new Error(
+ 'seed_array(A) must take array of numbers; is ' + typeof A
+ );
+ }
+
+ this.gen.init_by_array(A, A.length);
+ }
+}
diff --git a/src/random.ts b/src/random.ts
new file mode 100644
index 00000000..8b4feb29
--- /dev/null
+++ b/src/random.ts
@@ -0,0 +1,24 @@
+import type { Faker } from '.';
+
+export class Random {
+ constructor(private readonly faker: Faker, seed?: any[] | any) {
+ // Use a user provided seed if it is an array or number
+ if (Array.isArray(seed) && seed.length) {
+ this.faker.mersenne.seed_array(seed);
+ } else if (!isNaN(seed)) {
+ this.faker.mersenne.seed(seed);
+ }
+ }
+
+ /**
+ * Takes an array and returns a random element of the array.
+ *
+ * @method faker.random.arrayElement
+ * @param array
+ */
+ arrayElement(array) {
+ array = array || ['a', 'b', 'c'];
+ var r = this.faker.datatype.number({ max: array.length - 1 });
+ return array[r];
+ }
+}