Skip to content

Commit 5c7e58c

Browse files
committed
Merge branch 'next' into unicorn/prefer-date-now
2 parents fb44f87 + 97b0c8b commit 5c7e58c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+3743
-538
lines changed

.eslintrc.js

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = defineConfig({
1818
'plugin:@typescript-eslint/recommended',
1919
'plugin:@typescript-eslint/recommended-type-checked',
2020
'plugin:prettier/recommended',
21+
'plugin:jsdoc/recommended-typescript-error',
2122
'plugin:unicorn/recommended',
2223
],
2324
parser: '@typescript-eslint/parser',
@@ -26,7 +27,7 @@ module.exports = defineConfig({
2627
sourceType: 'module',
2728
warnOnUnsupportedTypeScriptVersion: false,
2829
},
29-
plugins: ['@typescript-eslint', 'prettier', 'deprecation'],
30+
plugins: ['@typescript-eslint', 'prettier', 'deprecation', 'jsdoc'],
3031
rules: {
3132
// We may want to use this in the future
3233
'no-useless-escape': 'off',
@@ -37,19 +38,17 @@ module.exports = defineConfig({
3738

3839
'deprecation/deprecation': 'error',
3940

40-
'unicorn/no-array-reduce': 'off',
41-
'unicorn/no-nested-ternary': 'off',
42-
'unicorn/no-null': 'off',
43-
'unicorn/no-useless-switch-case': 'off',
44-
'unicorn/number-literal-case': 'off',
45-
// TODO @Shinigami92 2023-09-23: prefer-at should be turned on when we drop support for Node 14
41+
'unicorn/no-nested-ternary': 'off', // incompatible with prettier
42+
'unicorn/no-null': 'off', // incompatible with TypeScript
43+
'unicorn/number-literal-case': 'off', // incompatible with prettier
44+
45+
// TODO @Shinigami92 2023-09-23: prefer-at should be turned on when we drop support for Node 14.
4646
'unicorn/prefer-at': 'off',
47-
// TODO @Shinigami92 2023-09-23: prefer-string-replace-all should be turned on when we drop support for Node 14
47+
// TODO @Shinigami92 2023-09-23: prefer-string-replace-all should be turned on when we drop support for Node 14.
4848
'unicorn/prefer-string-replace-all': 'off',
4949

50-
// TODO @Shinigami92 2023-09-23: All following unicorn rules are turned on by default through the unicorn/recommended set
51-
// they should be turned on individually, removed or potentially configured to our needs
52-
// But read https://github.com/faker-js/faker/pull/2417 for more
50+
// TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code.
51+
// Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently.
5352
'unicorn/better-regex': 'off',
5453
'unicorn/catch-error-name': 'off',
5554
'unicorn/consistent-destructuring': 'off',
@@ -61,6 +60,7 @@ module.exports = defineConfig({
6160
'unicorn/no-array-callback-reference': 'off',
6261
'unicorn/no-array-for-each': 'off',
6362
'unicorn/no-array-push-push': 'off',
63+
'unicorn/no-array-reduce': 'off',
6464
'unicorn/no-await-expression-member': 'off',
6565
'unicorn/no-console-spaces': 'off',
6666
'unicorn/no-for-loop': 'off',
@@ -70,6 +70,7 @@ module.exports = defineConfig({
7070
'unicorn/no-new-array': 'off',
7171
'unicorn/no-object-as-default-parameter': 'off',
7272
'unicorn/no-process-exit': 'off',
73+
'unicorn/no-useless-switch-case': 'off',
7374
'unicorn/no-zero-fractions': 'off',
7475
'unicorn/numeric-separators-style': 'off',
7576
'unicorn/prefer-array-flat-map': 'off',
@@ -134,40 +135,39 @@ module.exports = defineConfig({
134135
{ allowNumber: true, allowBoolean: true },
135136
],
136137
'@typescript-eslint/unbound-method': 'off',
138+
139+
'jsdoc/no-types': 'error',
140+
'jsdoc/require-jsdoc': 'off',
141+
'jsdoc/require-returns': 'off',
142+
'jsdoc/sort-tags': [
143+
'error',
144+
{
145+
tagSequence: [
146+
{ tags: ['template'] },
147+
{ tags: ['internal'] },
148+
{ tags: ['param'] },
149+
{ tags: ['returns'] },
150+
{ tags: ['throws'] },
151+
{ tags: ['see'] },
152+
{ tags: ['example'] },
153+
{ tags: ['since'] },
154+
{ tags: ['default'] },
155+
{ tags: ['deprecated'] },
156+
],
157+
},
158+
],
159+
'jsdoc/tag-lines': 'off',
160+
},
161+
settings: {
162+
jsdoc: {
163+
mode: 'typescript',
164+
},
137165
},
138166
overrides: [
139167
{
140168
files: ['src/**/*.ts'],
141-
plugins: ['jsdoc'],
142-
extends: ['plugin:jsdoc/recommended-error'],
143169
rules: {
144-
'jsdoc/no-types': 'error',
145-
'jsdoc/require-param-type': 'off',
146-
'jsdoc/require-returns-type': 'off',
147-
'jsdoc/require-returns': 'off',
148-
'jsdoc/tag-lines': 'off',
149-
'jsdoc/sort-tags': [
150-
'error',
151-
{
152-
tagSequence: [
153-
{ tags: ['template'] },
154-
{ tags: ['internal'] },
155-
{ tags: ['param'] },
156-
{ tags: ['returns'] },
157-
{ tags: ['throws'] },
158-
{ tags: ['see'] },
159-
{ tags: ['example'] },
160-
{ tags: ['since'] },
161-
{ tags: ['default'] },
162-
{ tags: ['deprecated'] },
163-
],
164-
},
165-
],
166-
},
167-
settings: {
168-
jsdoc: {
169-
mode: 'typescript',
170-
},
170+
'jsdoc/require-jsdoc': 'error',
171171
},
172172
},
173173
{

docs/.vitepress/api-pages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ export const apiPages = [
3030
{ text: 'System', link: '/api/system.html' },
3131
{ text: 'Vehicle', link: '/api/vehicle.html' },
3232
{ text: 'Word', link: '/api/word.html' },
33+
{ text: 'Randomizer', link: '/api/randomizer.html' },
3334
{ text: 'Utilities', link: '/api/utils.html' },
3435
];

docs/.vitepress/config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ const config = defineConfig({
200200
text: 'Frameworks',
201201
link: '/guide/frameworks',
202202
},
203+
{
204+
text: 'Randomizer',
205+
link: '/guide/randomizer',
206+
},
203207
{
204208
text: 'Upgrading to v8',
205209
link: '/guide/upgrading',

docs/api/ApiIndex.vue

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- This content is mostly copied over from https://github.com/vuejs/docs/blob/main/src/api/ApiIndex.vue -->
22

33
<script setup lang="ts">
4-
import { computed, onMounted, onUnmounted, ref } from 'vue';
4+
import { computed, ref } from 'vue';
55
import { slugify } from '../.vitepress/shared/utils/slugify';
66
import apiSearchIndex from './api-search-index.json';
77
import { APIGroup } from './api-types';
@@ -43,37 +43,6 @@ const filtered = computed(() => {
4343
})
4444
.filter((i) => i) as APIGroup[];
4545
});
46-
47-
const apiFilter = ref<HTMLInputElement>();
48-
49-
function apiSearchFocusHandler(event: KeyboardEvent): void {
50-
if (event.key === 'Escape') {
51-
if (apiFilter.value !== document.activeElement) {
52-
query.value = '';
53-
} else {
54-
apiFilter.value!.blur();
55-
}
56-
} else if (event.key === 'Enter') {
57-
if (apiFilter.value !== document.activeElement) return;
58-
if (query.value === '') return;
59-
const item = filtered.value[0].items[0];
60-
if (!item) return;
61-
const header = item.headers[0];
62-
if (!header) return;
63-
window.location.href = item.link + '#' + slugify(header.anchor);
64-
} else if (
65-
/^[a-z]$/.test(event.key) &&
66-
!event.altKey &&
67-
!event.ctrlKey &&
68-
!event.shiftKey &&
69-
!event.metaKey
70-
) {
71-
apiFilter.value!.focus();
72-
}
73-
}
74-
75-
onMounted(() => window.addEventListener('keydown', apiSearchFocusHandler));
76-
onUnmounted(() => window.removeEventListener('keydown', apiSearchFocusHandler));
7746
</script>
7847

7948
<template>
@@ -85,7 +54,6 @@ onUnmounted(() => window.removeEventListener('keydown', apiSearchFocusHandler));
8554
<input
8655
type="search"
8756
placeholder="Enter keyword"
88-
ref="apiFilter"
8957
id="api-filter"
9058
v-model="query"
9159
/>

docs/guide/randomizer.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Randomizer
2+
3+
The [`Randomizer`](/api/randomizer) interface allows you to use a custom randomness source within Faker.
4+
5+
::: warning Important
6+
Faker's default `Randomizer` is sufficient in most cases.
7+
Change this only if you want to use it to achieve a specific goal, such as sharing the same random generator with other instances/tools.
8+
:::
9+
10+
There are two connected use cases we have considered where this might be needed:
11+
12+
1. Re-Use of the same `Randomizer` within multiple `Faker` instances.
13+
2. The use of a random number generator from a third party library.
14+
15+
## Using `Randomizer`s
16+
17+
A `Randomizer` has to be set during construction of the instance:
18+
19+
```ts
20+
import { Faker, Randomizer } from '@faker-js/faker';
21+
22+
const customFaker = new Faker({
23+
locale: ...,
24+
randomizer: ...,
25+
});
26+
```
27+
28+
The following methods take a `Randomizer` as argument:
29+
30+
- [new SimpleFaker(...)](/api/simpleFaker#constructor)
31+
- [new Faker(...)](/api/faker#constructor)
32+
33+
## Re-Using a `Randomizer`
34+
35+
Sometimes it might be required to generate values in two different locales.
36+
E.g. a Chinese person might have an English identity to simplify the communication with foreigners.
37+
While this could also be achieved with two independent `Faker` instances like this:
38+
39+
```ts
40+
import { fakerEN, fakerZH_TW } from '@faker-js/faker';
41+
42+
fakerZH_TW.seed(5);
43+
fakerEN.seed(5);
44+
45+
const firstName = fakerZH_TW.person.firstName(); // 炫明
46+
const alias = fakerEN.person.firstName(); // Arthur
47+
```
48+
49+
There might be issues regarding reproducibility, when seeding only one of them.
50+
51+
By sharing a `Randomizer` between the two instances, you omit this issue by affecting all instances simultaneously.
52+
53+
::: tip Note
54+
This gets more important if the seeding happens at a different location than the data generation (e.g. due to nesting).
55+
:::
56+
57+
```ts
58+
import { en, Faker, Randomizer, zh_TW } from '@faker-js/faker';
59+
60+
const randomizer: Randomizer = ...;
61+
62+
const customFakerEN = new Faker({
63+
locale: en,
64+
randomizer,
65+
});
66+
67+
const customFakerZH_TW = new Faker({
68+
locale: [zh_TW, en],
69+
randomizer,
70+
});
71+
72+
randomizer.seed(5);
73+
// customFakerEN.seed(5); // Redundant
74+
// customFakerZH_TW.seed(5); // Redundant
75+
76+
const firstName = fakerZH_TW.person.firstName(); // 炫明
77+
const alias = fakerEN.person.firstName(); // John (different from before, because it is now the second call)
78+
```
79+
80+
This is also relevant when trying to use faker's random number generator in third party libraries.
81+
E.g. some libraries that can generate `string`s from a `RegExp` can be customized with a custom random number generator as well,
82+
and since they will be used in the same context it makes sense to rely on the same randomness source to ensure the values are reproducible.
83+
84+
## Third-Party `Randomizer`s
85+
86+
Sometimes you might want to use a custom/third-party random number generator.
87+
This can be achieved by implementing your own `Randomizer` and passing it to [supported methods](#using-randomizers).
88+
89+
::: tip Note
90+
Faker does not ship `Randomizers` for third-party libraries and does not provide support for bridging the gap between libraries.
91+
The following examples show how the interface can be implemented, but they are not tested for correctness.
92+
Feel free to submit more `Randomizer` examples for other popular packages.
93+
:::
94+
95+
### Pure-Rand
96+
97+
The following is an example for a [pure-rand](https://github.com/dubzzz/pure-rand) based `Randomizer`:
98+
99+
```ts
100+
import { Faker, Randomizer, SimpleFaker } from '@faker-js/faker';
101+
import { RandomGenerator, xoroshiro128plus } from 'pure-rand';
102+
103+
export function generatePureRandRandomizer(
104+
seed: number | number[] = Date.now() ^ (Math.random() * 0x100000000),
105+
factory: (seed: number) => RandomGenerator = xoroshiro128plus
106+
): Randomizer {
107+
const self = {
108+
next: () => (self.generator.unsafeNext() >>> 0) / 0x100000000,
109+
seed: (seed: number | number[]) => {
110+
self.generator = factory(typeof seed === 'number' ? seed : seed[0]);
111+
},
112+
} as Randomizer & { generator: RandomGenerator };
113+
self.seed(seed);
114+
return self;
115+
}
116+
```

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -89,43 +89,43 @@
8989
"devDependencies": {
9090
"@actions/github": "~5.1.1",
9191
"@algolia/client-search": "~4.19.1",
92-
"@types/markdown-it": "~13.0.1",
93-
"@types/node": "~20.6.2",
94-
"@types/sanitize-html": "~2.9.0",
95-
"@types/semver": "~7.5.2",
96-
"@types/validator": "~13.11.1",
97-
"@typescript-eslint/eslint-plugin": "~6.7.0",
98-
"@typescript-eslint/parser": "~6.7.0",
99-
"@vitest/coverage-v8": "~0.34.4",
100-
"@vitest/ui": "~0.34.4",
92+
"@types/markdown-it": "~13.0.2",
93+
"@types/node": "~20.8.0",
94+
"@types/sanitize-html": "~2.9.1",
95+
"@types/semver": "~7.5.3",
96+
"@types/validator": "~13.11.2",
97+
"@typescript-eslint/eslint-plugin": "~6.7.3",
98+
"@typescript-eslint/parser": "~6.7.3",
99+
"@vitest/coverage-v8": "~0.34.6",
100+
"@vitest/ui": "~0.34.7",
101101
"@vueuse/core": "~10.4.1",
102102
"conventional-changelog-cli": "~4.1.0",
103-
"cypress": "~13.2.0",
104-
"esbuild": "~0.19.3",
105-
"eslint": "~8.49.0",
103+
"cypress": "~13.3.0",
104+
"esbuild": "~0.19.4",
105+
"eslint": "~8.50.0",
106106
"eslint-config-prettier": "~9.0.0",
107107
"eslint-define-config": "~1.23.0",
108108
"eslint-gitignore": "~0.1.0",
109109
"eslint-plugin-deprecation": "~2.0.0",
110-
"eslint-plugin-jsdoc": "~46.8.1",
110+
"eslint-plugin-jsdoc": "~46.8.2",
111111
"eslint-plugin-prettier": "~5.0.0",
112112
"eslint-plugin-unicorn": "~48.0.1",
113113
"eslint-plugin-vitest": "~0.3.1",
114-
"glob": "~10.3.4",
114+
"glob": "~10.3.10",
115115
"npm-run-all": "~4.1.5",
116116
"prettier": "3.0.3",
117117
"prettier-plugin-organize-imports": "~3.2.3",
118-
"rimraf": "~5.0.1",
118+
"rimraf": "~5.0.5",
119119
"sanitize-html": "~2.11.0",
120120
"semver": "~7.5.4",
121121
"standard-version": "~9.5.0",
122-
"tsx": "~3.12.10",
122+
"tsx": "~3.13.0",
123123
"typedoc": "~0.24.8",
124124
"typescript": "~4.9.5",
125125
"validator": "~13.11.0",
126126
"vite": "~4.4.9",
127127
"vitepress": "1.0.0-beta.7",
128-
"vitest": "~0.34.4",
128+
"vitest": "~0.34.6",
129129
"vue": "~3.3.4"
130130
},
131131
"packageManager": "pnpm@8.5.1",

0 commit comments

Comments
 (0)