@ghostry/fabricator-extension-faker-v10 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/Error.js +2 -2
- package/dist/esm/FakerModules/Build.js +39 -37
- package/dist/esm/FakerModules/Words.js +151 -0
- package/dist/esm/index.js +1 -1
- package/dist/types/Construct.d.ts +1 -1
- package/dist/types/Error.d.ts +2 -1
- package/dist/types/FakerModules/Build.d.ts +10 -4
- package/dist/types/FakerModules/Types.d.ts +3 -0
- package/dist/types/FakerModules/Words.d.ts +71 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +8 -7
package/dist/esm/Error.js
CHANGED
|
@@ -2,14 +2,14 @@ import { FabricatorError } from "@ghostry/fabricator";
|
|
|
2
2
|
class Error_FakerExtensionError extends FabricatorError {
|
|
3
3
|
constructor(){
|
|
4
4
|
super();
|
|
5
|
-
this.name = "FakerExtensionError";
|
|
5
|
+
this.name = "@ghostry/fabricator-extension-faker-v10:FakerExtensionError";
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
(function(FakerExtensionError) {
|
|
9
9
|
class NoActiveScopeError extends FakerExtensionError {
|
|
10
10
|
constructor(){
|
|
11
11
|
super();
|
|
12
|
-
this.name = "NoActiveScopeError";
|
|
12
|
+
this.name = "@ghostry/fabricator-extension-faker-v10:NoActiveScopeError";
|
|
13
13
|
this.message = "A faker builder was invoked outside of fabricate(). Faker builders only draw randomness while the schema they belong to is being fabricated.";
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { toWords } from "./Words.js";
|
|
1
2
|
function build(T, faker, draw) {
|
|
2
|
-
const [f, d] = [
|
|
3
|
+
const [f, d, w] = [
|
|
3
4
|
faker,
|
|
4
|
-
draw
|
|
5
|
+
draw,
|
|
6
|
+
toWords(faker)
|
|
5
7
|
];
|
|
6
8
|
const string = T.string.as(()=>"");
|
|
7
9
|
return {
|
|
@@ -171,7 +173,7 @@ function build(T, faker, draw) {
|
|
|
171
173
|
collation: (...args)=>T.string.as(d(()=>f.database.collation(...args))),
|
|
172
174
|
column: (...args)=>T.string.as(d(()=>f.database.column(...args))),
|
|
173
175
|
engine: (...args)=>T.string.as(d(()=>f.database.engine(...args))),
|
|
174
|
-
mongodbObjectId: (...args)=>T.string.as(d(()=>f.database.mongodbObjectId(...args))
|
|
176
|
+
mongodbObjectId: (...args)=>T.string.as(d(()=>f.database.mongodbObjectId(...args))).admits({
|
|
175
177
|
pattern: "^[0-9a-fA-F]{24}$"
|
|
176
178
|
}),
|
|
177
179
|
type: (...args)=>T.string.as(d(()=>f.database.type(...args)))
|
|
@@ -196,11 +198,11 @@ function build(T, faker, draw) {
|
|
|
196
198
|
accountName: (...args)=>T.string.as(d(()=>f.finance.accountName(...args))),
|
|
197
199
|
accountNumber: (...args)=>T.string.as(d(()=>f.finance.accountNumber(...args))),
|
|
198
200
|
amount: (...args)=>T.string.as(d(()=>f.finance.amount(...args))),
|
|
199
|
-
bic: (...args)=>T.string.as(d(()=>f.finance.bic(...args))
|
|
201
|
+
bic: (...args)=>T.string.as(d(()=>f.finance.bic(...args))).admits({
|
|
200
202
|
pattern: "^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$"
|
|
201
203
|
}),
|
|
202
204
|
bitcoinAddress: (...args)=>T.string.as(d(()=>f.finance.bitcoinAddress(...args))),
|
|
203
|
-
creditCardCVV: (...args)=>T.string.as(d(()=>f.finance.creditCardCVV(...args))
|
|
205
|
+
creditCardCVV: (...args)=>T.string.as(d(()=>f.finance.creditCardCVV(...args))).admits({
|
|
204
206
|
pattern: "^[0-9]{3,4}$"
|
|
205
207
|
}),
|
|
206
208
|
creditCardIssuer: (...args)=>T.string.as(d(()=>f.finance.creditCardIssuer(...args))),
|
|
@@ -250,38 +252,38 @@ function build(T, faker, draw) {
|
|
|
250
252
|
verb: (...args)=>T.string.as(d(()=>f.hacker.verb(...args)))
|
|
251
253
|
},
|
|
252
254
|
image: {
|
|
253
|
-
avatar: (...args)=>T.string.as(d(()=>f.image.avatar(...args))
|
|
255
|
+
avatar: (...args)=>T.string.as(d(()=>f.image.avatar(...args))).admits({
|
|
254
256
|
format: "uri"
|
|
255
257
|
}),
|
|
256
|
-
avatarGitHub: (...args)=>T.string.as(d(()=>f.image.avatarGitHub(...args))
|
|
258
|
+
avatarGitHub: (...args)=>T.string.as(d(()=>f.image.avatarGitHub(...args))).admits({
|
|
257
259
|
format: "uri"
|
|
258
260
|
}),
|
|
259
|
-
dataUri: (...args)=>T.string.as(d(()=>f.image.dataUri(...args))
|
|
261
|
+
dataUri: (...args)=>T.string.as(d(()=>f.image.dataUri(...args))).admits({
|
|
260
262
|
format: "uri"
|
|
261
263
|
}),
|
|
262
|
-
personPortrait: (...args)=>T.string.as(d(()=>f.image.personPortrait(...args))
|
|
264
|
+
personPortrait: (...args)=>T.string.as(d(()=>f.image.personPortrait(...args))).admits({
|
|
263
265
|
format: "uri"
|
|
264
266
|
}),
|
|
265
|
-
url: (...args)=>T.string.as(d(()=>f.image.url(...args))
|
|
267
|
+
url: (...args)=>T.string.as(d(()=>f.image.url(...args))).admits({
|
|
266
268
|
format: "uri"
|
|
267
269
|
}),
|
|
268
270
|
urlLoremFlickr: (...args)=>T.string.as(d(()=>f.image.urlLoremFlickr(...args))),
|
|
269
|
-
urlPicsumPhotos: (...args)=>T.string.as(d(()=>f.image.urlPicsumPhotos(...args))
|
|
271
|
+
urlPicsumPhotos: (...args)=>T.string.as(d(()=>f.image.urlPicsumPhotos(...args))).admits({
|
|
270
272
|
format: "uri"
|
|
271
273
|
})
|
|
272
274
|
},
|
|
273
275
|
internet: {
|
|
274
276
|
displayName: (...args)=>T.string.as(d(()=>f.internet.displayName(...args))),
|
|
275
|
-
domainName: (...args)=>T.string.as(d(()=>f.internet.domainName(...args))
|
|
277
|
+
domainName: (...args)=>T.string.as(d(()=>f.internet.domainName(...args))).admits({
|
|
276
278
|
format: "hostname"
|
|
277
279
|
}),
|
|
278
280
|
domainSuffix: (...args)=>T.string.as(d(()=>f.internet.domainSuffix(...args))),
|
|
279
281
|
domainWord: (...args)=>T.string.as(d(()=>f.internet.domainWord(...args))),
|
|
280
|
-
email: (...args)=>T.string.as(d(()=>f.internet.email(...args))
|
|
282
|
+
email: (...args)=>T.string.as(d(()=>f.internet.email(...args))).admits({
|
|
281
283
|
format: "email"
|
|
282
284
|
}),
|
|
283
285
|
emoji: (...args)=>T.string.as(d(()=>f.internet.emoji(...args))),
|
|
284
|
-
exampleEmail: (...args)=>T.string.as(d(()=>f.internet.exampleEmail(...args))
|
|
286
|
+
exampleEmail: (...args)=>T.string.as(d(()=>f.internet.exampleEmail(...args))).admits({
|
|
285
287
|
format: "email"
|
|
286
288
|
}),
|
|
287
289
|
httpMethod: (...args)=>T.enum.uniform([
|
|
@@ -293,10 +295,10 @@ function build(T, faker, draw) {
|
|
|
293
295
|
]).as(d(()=>f.internet.httpMethod(...args))),
|
|
294
296
|
httpStatusCode: (...args)=>T.number.as(d(()=>f.internet.httpStatusCode(...args))),
|
|
295
297
|
ip: (...args)=>T.string.as(d(()=>f.internet.ip(...args))),
|
|
296
|
-
ipv4: (...args)=>T.string.as(d(()=>f.internet.ipv4(...args))
|
|
298
|
+
ipv4: (...args)=>T.string.as(d(()=>f.internet.ipv4(...args))).admits({
|
|
297
299
|
format: "ipv4"
|
|
298
300
|
}),
|
|
299
|
-
ipv6: (...args)=>T.string.as(d(()=>f.internet.ipv6(...args))
|
|
301
|
+
ipv6: (...args)=>T.string.as(d(()=>f.internet.ipv6(...args))).admits({
|
|
300
302
|
format: "ipv6"
|
|
301
303
|
}),
|
|
302
304
|
jwt: (...args)=>T.string.as(d(()=>f.internet.jwt(...args))),
|
|
@@ -308,7 +310,7 @@ function build(T, faker, draw) {
|
|
|
308
310
|
"http",
|
|
309
311
|
"https"
|
|
310
312
|
]).as(d(()=>f.internet.protocol(...args))),
|
|
311
|
-
url: (...args)=>T.string.as(d(()=>f.internet.url(...args))
|
|
313
|
+
url: (...args)=>T.string.as(d(()=>f.internet.url(...args))).admits({
|
|
312
314
|
format: "uri"
|
|
313
315
|
}),
|
|
314
316
|
userAgent: (...args)=>T.string.as(d(()=>f.internet.userAgent(...args))),
|
|
@@ -344,15 +346,15 @@ function build(T, faker, draw) {
|
|
|
344
346
|
zipCode: (...args)=>T.string.as(d(()=>f.location.zipCode(...args)))
|
|
345
347
|
},
|
|
346
348
|
lorem: {
|
|
347
|
-
lines: (...args)=>T.string.as(d(
|
|
348
|
-
paragraph: (...args)=>T.string.as(d(
|
|
349
|
-
paragraphs: (...args)=>T.string.as(d(
|
|
350
|
-
sentence: (...args)=>T.string.as(d(
|
|
351
|
-
sentences: (...args)=>T.string.as(d(
|
|
352
|
-
slug: (...args)=>T.string.as(d(
|
|
353
|
-
text: (...args)=>T.string.as(d(
|
|
354
|
-
word: (...args)=>T.string.as(d(
|
|
355
|
-
words: (...args)=>T.string.as(d(
|
|
349
|
+
lines: (...args)=>T.string.as(d(w.lorem.lines(...args))),
|
|
350
|
+
paragraph: (...args)=>T.string.as(d(w.lorem.paragraph(...args))),
|
|
351
|
+
paragraphs: (...args)=>T.string.as(d(w.lorem.paragraphs(...args))),
|
|
352
|
+
sentence: (...args)=>T.string.as(d(w.lorem.sentence(...args))),
|
|
353
|
+
sentences: (...args)=>T.string.as(d(w.lorem.sentences(...args))),
|
|
354
|
+
slug: (...args)=>T.string.as(d(w.lorem.slug(...args))),
|
|
355
|
+
text: (...args)=>T.string.as(d(w.lorem.text(...args))),
|
|
356
|
+
word: (...args)=>T.string.as(d(w.lorem.word(...args))),
|
|
357
|
+
words: (...args)=>T.string.as(d(w.lorem.words(...args)))
|
|
356
358
|
},
|
|
357
359
|
music: {
|
|
358
360
|
album: (...args)=>T.string.as(d(()=>f.music.album(...args))),
|
|
@@ -417,7 +419,7 @@ function build(T, faker, draw) {
|
|
|
417
419
|
sample: (...args)=>T.string.as(d(()=>f.string.sample(...args))),
|
|
418
420
|
symbol: (...args)=>T.string.as(d(()=>f.string.symbol(...args))),
|
|
419
421
|
ulid: (...args)=>T.string.as(d(()=>f.string.ulid(...args))),
|
|
420
|
-
uuid: (...args)=>T.string.as(d(()=>f.string.uuid(...args))
|
|
422
|
+
uuid: (...args)=>T.string.as(d(()=>f.string.uuid(...args))).admits({
|
|
421
423
|
format: "uuid"
|
|
422
424
|
})
|
|
423
425
|
},
|
|
@@ -429,7 +431,7 @@ function build(T, faker, draw) {
|
|
|
429
431
|
directoryPath: (...args)=>T.string.as(d(()=>f.system.directoryPath(...args))),
|
|
430
432
|
fileExt: (...args)=>T.string.as(d(()=>f.system.fileExt(...args))),
|
|
431
433
|
fileName: (...args)=>T.string.as(d(()=>f.system.fileName(...args))),
|
|
432
|
-
filePath: (...args)=>T.string.as(d(()=>f.system.filePath(...args))
|
|
434
|
+
filePath: (...args)=>T.string.as(d(()=>f.system.filePath(...args))).admits({
|
|
433
435
|
format: "uri-reference"
|
|
434
436
|
}),
|
|
435
437
|
fileType: (...args)=>T.string.as(d(()=>f.system.fileType(...args))),
|
|
@@ -449,15 +451,15 @@ function build(T, faker, draw) {
|
|
|
449
451
|
vrm: (...args)=>T.string.as(d(()=>f.vehicle.vrm(...args)))
|
|
450
452
|
},
|
|
451
453
|
word: {
|
|
452
|
-
adjective: (...args)=>T.string.as(d(
|
|
453
|
-
adverb: (...args)=>T.string.as(d(
|
|
454
|
-
conjunction: (...args)=>T.string.as(d(
|
|
455
|
-
interjection: (...args)=>T.string.as(d(
|
|
456
|
-
noun: (...args)=>T.string.as(d(
|
|
457
|
-
preposition: (...args)=>T.string.as(d(
|
|
458
|
-
sample: (...args)=>T.string.as(d(
|
|
459
|
-
verb: (...args)=>T.string.as(d(
|
|
460
|
-
words: (...args)=>T.string.as(d(
|
|
454
|
+
adjective: (...args)=>T.string.as(d(w.word.adjective(...args))),
|
|
455
|
+
adverb: (...args)=>T.string.as(d(w.word.adverb(...args))),
|
|
456
|
+
conjunction: (...args)=>T.string.as(d(w.word.conjunction(...args))),
|
|
457
|
+
interjection: (...args)=>T.string.as(d(w.word.interjection(...args))),
|
|
458
|
+
noun: (...args)=>T.string.as(d(w.word.noun(...args))),
|
|
459
|
+
preposition: (...args)=>T.string.as(d(w.word.preposition(...args))),
|
|
460
|
+
sample: (...args)=>T.string.as(d(w.word.sample(...args))),
|
|
461
|
+
verb: (...args)=>T.string.as(d(w.word.verb(...args))),
|
|
462
|
+
words: (...args)=>T.string.as(d(w.word.words(...args)))
|
|
461
463
|
}
|
|
462
464
|
};
|
|
463
465
|
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { FakerError } from "@faker-js/faker";
|
|
2
|
+
const categories = [
|
|
3
|
+
"adjective",
|
|
4
|
+
"adverb",
|
|
5
|
+
"conjunction",
|
|
6
|
+
"interjection",
|
|
7
|
+
"noun",
|
|
8
|
+
"preposition",
|
|
9
|
+
"verb"
|
|
10
|
+
];
|
|
11
|
+
function filterByLength(list, options = {}) {
|
|
12
|
+
const { length, strategy = "fail" } = "number" == typeof options ? {
|
|
13
|
+
length: options
|
|
14
|
+
} : options;
|
|
15
|
+
if (void 0 === length) {
|
|
16
|
+
if ("shortest" === strategy || "longest" === strategy) return extreme(list, strategy);
|
|
17
|
+
return list;
|
|
18
|
+
}
|
|
19
|
+
const range = "number" == typeof length ? {
|
|
20
|
+
min: length,
|
|
21
|
+
max: length
|
|
22
|
+
} : length;
|
|
23
|
+
const matching = list.filter((word)=>word.length >= range.min && word.length <= range.max);
|
|
24
|
+
if (matching.length > 0) return matching;
|
|
25
|
+
switch(strategy){
|
|
26
|
+
case "fail":
|
|
27
|
+
throw new FakerError("No words found that match the given length.");
|
|
28
|
+
case "closest":
|
|
29
|
+
return closest(list, range);
|
|
30
|
+
case "shortest":
|
|
31
|
+
case "longest":
|
|
32
|
+
return extreme(list, strategy);
|
|
33
|
+
case "any-length":
|
|
34
|
+
return list;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function extreme(list, strategy) {
|
|
38
|
+
const lengths = list.map((word)=>word.length);
|
|
39
|
+
const target = "shortest" === strategy ? Math.min(...lengths) : Math.max(...lengths);
|
|
40
|
+
return list.filter((word)=>word.length === target);
|
|
41
|
+
}
|
|
42
|
+
function closest(list, range) {
|
|
43
|
+
let below = -1 / 0;
|
|
44
|
+
let above = 1 / 0;
|
|
45
|
+
for (const { length } of list){
|
|
46
|
+
if (length < range.min && length > below) below = length;
|
|
47
|
+
if (length > range.max && length < above) above = length;
|
|
48
|
+
}
|
|
49
|
+
const offset = Math.min(range.min - below, above - range.max);
|
|
50
|
+
return list.filter(({ length })=>length === range.min - offset || length === range.max + offset);
|
|
51
|
+
}
|
|
52
|
+
function listOf(read, options) {
|
|
53
|
+
let resolved;
|
|
54
|
+
return ()=>{
|
|
55
|
+
if (void 0 === resolved) resolved = filterByLength(read(), options);
|
|
56
|
+
return resolved;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function pick(random, list) {
|
|
60
|
+
if (0 === list.length) throw new FakerError("Cannot get value from empty dataset.");
|
|
61
|
+
return list[list.length > 1 ? Math.floor(random.next() * list.length) : 0];
|
|
62
|
+
}
|
|
63
|
+
function toWords(faker) {
|
|
64
|
+
const repeat = (count, separator, next)=>faker.helpers.multiple(next, {
|
|
65
|
+
count
|
|
66
|
+
}).join(separator);
|
|
67
|
+
const words = (word, count = 3)=>repeat(count, " ", word);
|
|
68
|
+
const sentence = (word, count = {
|
|
69
|
+
min: 3,
|
|
70
|
+
max: 10
|
|
71
|
+
})=>{
|
|
72
|
+
const text = words(word, count);
|
|
73
|
+
return `${text.charAt(0).toUpperCase()}${text.substring(1)}.`;
|
|
74
|
+
};
|
|
75
|
+
const sentences = (word, count = {
|
|
76
|
+
min: 2,
|
|
77
|
+
max: 6
|
|
78
|
+
}, separator = " ")=>repeat(count, separator, ()=>sentence(word));
|
|
79
|
+
const paragraph = (word, count = 3)=>sentences(word, count);
|
|
80
|
+
const paragraphs = (word, count = 3, separator = "\n")=>repeat(count, separator, ()=>paragraph(word));
|
|
81
|
+
const lines = (word, count = {
|
|
82
|
+
min: 1,
|
|
83
|
+
max: 5
|
|
84
|
+
})=>sentences(word, count, "\n");
|
|
85
|
+
const texts = [
|
|
86
|
+
sentence,
|
|
87
|
+
sentences,
|
|
88
|
+
paragraph,
|
|
89
|
+
paragraphs,
|
|
90
|
+
lines
|
|
91
|
+
];
|
|
92
|
+
const lorem = (compose)=>{
|
|
93
|
+
const list = listOf(()=>faker.definitions.lorem.word, void 0);
|
|
94
|
+
return ({ random })=>compose(()=>pick(random, list()), random);
|
|
95
|
+
};
|
|
96
|
+
const category = (name)=>(options)=>{
|
|
97
|
+
const list = listOf(()=>faker.definitions.word[name], options);
|
|
98
|
+
return ({ random })=>pick(random, list());
|
|
99
|
+
};
|
|
100
|
+
const sampler = (options)=>{
|
|
101
|
+
const lists = categories.map((name)=>listOf(()=>faker.definitions.word[name], options));
|
|
102
|
+
return (random)=>{
|
|
103
|
+
for (const list of faker.helpers.shuffle(lists))try {
|
|
104
|
+
return pick(random, list());
|
|
105
|
+
} catch {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
throw new FakerError("No matching word data available for the current locale");
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
return {
|
|
112
|
+
lorem: {
|
|
113
|
+
lines: (count)=>lorem((word)=>lines(word, count)),
|
|
114
|
+
paragraph: (count)=>lorem((word)=>paragraph(word, count)),
|
|
115
|
+
paragraphs: (count, separator)=>lorem((word)=>paragraphs(word, count, separator)),
|
|
116
|
+
sentence: (count)=>lorem((word)=>sentence(word, count)),
|
|
117
|
+
sentences: (count, separator)=>lorem((word)=>sentences(word, count, separator)),
|
|
118
|
+
slug: (count)=>lorem((word)=>faker.helpers.slugify(words(word, count))),
|
|
119
|
+
text: ()=>lorem((word, random)=>pick(random, texts)(word)),
|
|
120
|
+
word: (options)=>{
|
|
121
|
+
const list = listOf(()=>faker.definitions.lorem.word, options);
|
|
122
|
+
return ({ random })=>pick(random, list());
|
|
123
|
+
},
|
|
124
|
+
words: (count)=>lorem((word)=>words(word, count))
|
|
125
|
+
},
|
|
126
|
+
word: {
|
|
127
|
+
adjective: category("adjective"),
|
|
128
|
+
adverb: category("adverb"),
|
|
129
|
+
conjunction: category("conjunction"),
|
|
130
|
+
interjection: category("interjection"),
|
|
131
|
+
noun: category("noun"),
|
|
132
|
+
preposition: category("preposition"),
|
|
133
|
+
sample: (options)=>{
|
|
134
|
+
const sample = sampler(options);
|
|
135
|
+
return ({ random })=>sample(random);
|
|
136
|
+
},
|
|
137
|
+
verb: category("verb"),
|
|
138
|
+
words: (options = {})=>{
|
|
139
|
+
const { count = {
|
|
140
|
+
min: 1,
|
|
141
|
+
max: 3
|
|
142
|
+
} } = "number" == typeof options ? {
|
|
143
|
+
count: options
|
|
144
|
+
} : options;
|
|
145
|
+
const sample = sampler(void 0);
|
|
146
|
+
return ({ random })=>repeat(count, " ", ()=>sample(random));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export { toWords };
|
package/dist/esm/index.js
CHANGED
|
@@ -22,4 +22,4 @@ import type { FakerExtension, Registry } from "./Types";
|
|
|
22
22
|
* runtime floor on the builder count: the type-level guards read the surface
|
|
23
23
|
* alone and cannot see a spread that drops a module.
|
|
24
24
|
*/
|
|
25
|
-
export declare function construct(T: Registry, faker: Faker, draw: <$T>(produce: () => $T) => (context: ProduceContext) => $T): FakerExtension;
|
|
25
|
+
export declare function construct(T: Registry, faker: Faker, draw: <$T>(produce: (context: ProduceContext) => $T) => (context: ProduceContext) => $T): FakerExtension;
|
package/dist/types/Error.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* exports that name, and importing both into one scope would collide. Follows
|
|
4
4
|
* core's `FabricatorError` shape (abstract base plus a merged namespace of
|
|
5
5
|
* subclasses) so `e instanceof FabricatorError` still catches everything either
|
|
6
|
-
* package throws.
|
|
6
|
+
* package throws. A `name` is prefixed with this package's name, as core's are
|
|
7
|
+
* with its own.
|
|
7
8
|
*/
|
|
8
9
|
import { FabricatorError } from "@ghostry/fabricator";
|
|
9
10
|
export declare abstract class FakerExtensionError extends FabricatorError {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the faker-bump workflow; an entry added or changed here needs the matching
|
|
10
10
|
* edit there, and vice versa.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Shapes before editing:
|
|
13
13
|
*
|
|
14
14
|
* - Every builder spreads faker's `Parameters<...>` rather than taking a single
|
|
15
15
|
* `options?`. Faker's zero-parameter methods (`animal.bear()`) and its
|
|
@@ -30,10 +30,16 @@
|
|
|
30
30
|
* whose _first_ overload takes `format?: StringColorFormat` and returns
|
|
31
31
|
* `string`. `'decimal'` is `NumberColorFormat`'s sole member, so naming it is
|
|
32
32
|
* exact.
|
|
33
|
+
* - `lorem`'s and `word`'s builders never call faker's own method: faker's
|
|
34
|
+
* per-word path copies the word list and parses an options object for every
|
|
35
|
+
* word drawn, so they draw through `./Words.ts`, which reproduces faker's
|
|
36
|
+
* output exactly from the same stream.
|
|
33
37
|
*
|
|
34
38
|
* Every node is a plain object or a bare builder function, never a function
|
|
35
39
|
* carrying properties — the invariant `deepMerge` needs to recurse through an
|
|
36
40
|
* extended registry, guarded by `test/Mergeable.test.ts`.
|
|
41
|
+
*
|
|
42
|
+
* @module
|
|
37
43
|
*/
|
|
38
44
|
import type { Faker } from "@faker-js/faker";
|
|
39
45
|
import type { ProduceContext } from "@ghostry/fabricator";
|
|
@@ -41,9 +47,9 @@ import type { Registry } from "../Types";
|
|
|
41
47
|
import type { FakerModules } from "./Types";
|
|
42
48
|
/**
|
|
43
49
|
* `src/index.ts`'s `draw`, by type — the save/restore wrapper that binds a
|
|
44
|
-
* producer to the leaf's own `random`/`clock`. Named here rather than imported
|
|
45
|
-
*
|
|
50
|
+
* producer to the leaf's own `random`/`clock`. Named here rather than imported,
|
|
51
|
+
* since `src/index.ts` imports this file.
|
|
46
52
|
*/
|
|
47
|
-
type Draw = <$T>(produce: () => $T) => (context: ProduceContext) => $T;
|
|
53
|
+
type Draw = <$T>(produce: (context: ProduceContext) => $T) => (context: ProduceContext) => $T;
|
|
48
54
|
export declare function build(T: Registry, faker: Faker, draw: Draw): FakerModules;
|
|
49
55
|
export {};
|
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
* union rather than a bare `string`.
|
|
42
42
|
* 4. A reordered overload set changes `Parameters<...>` here, which the matching
|
|
43
43
|
* builder's `...args` forwarding then fails to accept.
|
|
44
|
+
* 5. A change to how `lorem` or `word` draws fails `test/Parity.test.ts`, at `bun
|
|
45
|
+
* test` rather than `check`: those builders reimplement faker's method
|
|
46
|
+
* bodies in `./Words.ts`, which must then be brought back in line.
|
|
44
47
|
*
|
|
45
48
|
* Fix the entry in **both** files; the annotation on `build` fails until they
|
|
46
49
|
* agree.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Faker 10's `lorem` and `word` method bodies, minus the word-list copy.
|
|
3
|
+
*
|
|
4
|
+
* Faker's per-word path has two costs. With no `length`, its shared
|
|
5
|
+
* `filterWordListByLength` returns `[...wordList]`, copying a whole locale list
|
|
6
|
+
* (up to 1,000 entries in `en`) to index one element. That copy is close to
|
|
7
|
+
* free where the engine shares a literal array's storage on spread (Node 22–26
|
|
8
|
+
* and Bun 1.4.4 with faker's bundled locales), but costs about a microsecond
|
|
9
|
+
* per word on Bun 1.2.14, and on any engine when a locale's lists are built at
|
|
10
|
+
* runtime. Each word then goes through `helpers.arrayElement` → `number.int`,
|
|
11
|
+
* which parses an options object per draw and is most of what remains where the
|
|
12
|
+
* copy is free. `lorem.sentence`/`paragraph`/`text` pay both once per word.
|
|
13
|
+
* Every builder in `./Build.ts`'s `lorem`/`word` modules draws through this
|
|
14
|
+
* file instead and never calls faker's own method.
|
|
15
|
+
*
|
|
16
|
+
* The copy is reported upstream as
|
|
17
|
+
* https://github.com/faker-js/faker/issues/4242. A faker release that drops it
|
|
18
|
+
* is the point to weigh calling faker's methods again, not an automatic
|
|
19
|
+
* removal: the per-draw options parsing and definitions lookup would remain.
|
|
20
|
+
*
|
|
21
|
+
* **The output is faker's exactly, not an approximation.** `pick` reads
|
|
22
|
+
* `random.next()` and indexes with `arrayElement`'s own arithmetic,
|
|
23
|
+
* `Math.floor(u * length)`, from the same stream faker's randomizer reads
|
|
24
|
+
* (`src/index.ts`'s `draw` installs one `context` for both). Every draw made
|
|
25
|
+
* once per group rather than once per word — a `count` resolved through
|
|
26
|
+
* `rangeToNumber`, `word.sample`'s shuffle, `slug`'s `slugify` — goes through
|
|
27
|
+
* faker's own helpers, which keeps their semantics (an inverted range's error,
|
|
28
|
+
* a fractional count's truncation) without restating them, at a cost that is
|
|
29
|
+
* off the hot path. So a seed's data is unchanged, the surface keeps faker's
|
|
30
|
+
* `Parameters<...>`, and nothing about this is a deviation in the sense of
|
|
31
|
+
* `AGENTS.md`'s deviation policy. `test/Parity.test.ts` is the guard: it
|
|
32
|
+
* compares every builder here against faker's own method on an identical
|
|
33
|
+
* stream, so a faker release that changes how these draw fails there.
|
|
34
|
+
*
|
|
35
|
+
* Each filtered list is resolved once per builder call, lazily on the first
|
|
36
|
+
* draw, and a throw is never cached: missing locale data (thrown by faker's
|
|
37
|
+
* definitions proxy) and `strategy: "fail"` still throw from `fabricate()` on
|
|
38
|
+
* every call, as faker's own methods do, rather than from the builder call.
|
|
39
|
+
*
|
|
40
|
+
* @module
|
|
41
|
+
*/
|
|
42
|
+
import type { Faker } from "@faker-js/faker";
|
|
43
|
+
import type { ProduceContext } from "@ghostry/fabricator";
|
|
44
|
+
type Producer = (context: ProduceContext) => string;
|
|
45
|
+
type WordOptions = Parameters<Faker["word"]["noun"]>[0];
|
|
46
|
+
type Count = NonNullable<Parameters<Faker["lorem"]["words"]>[0]>;
|
|
47
|
+
export declare function toWords(faker: Faker): {
|
|
48
|
+
lorem: {
|
|
49
|
+
lines: (count?: Count) => Producer;
|
|
50
|
+
paragraph: (count?: Count) => Producer;
|
|
51
|
+
paragraphs: (count?: Count, separator?: string) => Producer;
|
|
52
|
+
sentence: (count?: Count) => Producer;
|
|
53
|
+
sentences: (count?: Count, separator?: string) => Producer;
|
|
54
|
+
slug: (count?: Count) => Producer;
|
|
55
|
+
text: () => Producer;
|
|
56
|
+
word: (options?: WordOptions) => Producer;
|
|
57
|
+
words: (count?: Count) => Producer;
|
|
58
|
+
};
|
|
59
|
+
word: {
|
|
60
|
+
adjective: (options?: WordOptions) => Producer;
|
|
61
|
+
adverb: (options?: WordOptions) => Producer;
|
|
62
|
+
conjunction: (options?: WordOptions) => Producer;
|
|
63
|
+
interjection: (options?: WordOptions) => Producer;
|
|
64
|
+
noun: (options?: WordOptions) => Producer;
|
|
65
|
+
preposition: (options?: WordOptions) => Producer;
|
|
66
|
+
sample: (options?: WordOptions) => Producer;
|
|
67
|
+
verb: (options?: WordOptions) => Producer;
|
|
68
|
+
words: (options?: Parameters<Faker["word"]["words"]>[0]) => Producer;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -66,8 +66,8 @@ export type Options = {
|
|
|
66
66
|
* declaration emission (`tsgo`, not `tsc --noEmit`; see `AGENTS.md`'s
|
|
67
67
|
* declaration-emit trap) refuses to print an anonymous expansion of one. Even
|
|
68
68
|
* where it printed it would be the wrong contract: inference would surface each
|
|
69
|
-
* builder's incidental narrowness (`Schema<{ produce
|
|
70
|
-
*
|
|
69
|
+
* builder's incidental narrowness (`Schema<{ produce }>`) where the declared
|
|
70
|
+
* surface states `Primitive.string.Schema`.
|
|
71
71
|
*
|
|
72
72
|
* Every node is a plain object or a leaf builder function, never a function
|
|
73
73
|
* carrying properties: `deepMerge` recurses only where `isPlainObject` holds on
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghostry/fabricator-extension-faker-v10",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "@faker-js/faker integration for @ghostry/fabricator — faker's data generators, seeded and reproducible through the fabricator instance that calls them.",
|
|
6
6
|
"keywords": [
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"url": "git+https://github.com/ghostry-dev/fabricator",
|
|
22
22
|
"directory": "pkg/fabricator-extension-faker-v10"
|
|
23
23
|
},
|
|
24
|
-
"homepage": "https://docs.ghostry.dev/fabricator
|
|
24
|
+
"homepage": "https://docs.ghostry.dev/fabricator",
|
|
25
25
|
"bugs": "https://github.com/ghostry-dev/fabricator/issues",
|
|
26
26
|
"type": "module",
|
|
27
27
|
"sideEffects": false,
|
|
@@ -53,20 +53,21 @@
|
|
|
53
53
|
"check": "tsc --noEmit",
|
|
54
54
|
"check:ts5": "bun --bun ../../node_modules/typescript-5/lib/tsc.js --noEmit",
|
|
55
55
|
"check:jsr": "DENO_BIN_PATH=$PWD/../../node_modules/.bin/deno bunx --no-install jsr publish --dry-run --allow-dirty",
|
|
56
|
-
"format": "
|
|
56
|
+
"format": "bun fmt",
|
|
57
57
|
"test": "bun run check && bun run check:ts5 && bun run check:jsr && bun test"
|
|
58
58
|
},
|
|
59
59
|
"files": [
|
|
60
60
|
"dist"
|
|
61
61
|
],
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@ghostry/fabricator": ">=0.0.
|
|
63
|
+
"@ghostry/fabricator": ">=0.0.14 <0.1.0",
|
|
64
64
|
"@faker-js/faker": "^10.5.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@ghostry/fabricator": "0.0.
|
|
68
|
-
"@ghostry/fabricator-adapter-typebox-v0": "0.0.
|
|
69
|
-
"@faker-js/faker": "^10.
|
|
67
|
+
"@ghostry/fabricator": "0.0.14",
|
|
68
|
+
"@ghostry/fabricator-adapter-typebox-v0": "0.0.4",
|
|
69
|
+
"@faker-js/faker": "^10.6.0",
|
|
70
|
+
"@ghostry/harness": "^0.0.6",
|
|
70
71
|
"@sinclair/typebox": "^0.34.52"
|
|
71
72
|
}
|
|
72
73
|
}
|