katanakit-js 5.1.0 → 5.1.1

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.
Files changed (36) hide show
  1. package/README.md +139 -0
  2. package/dist/core/index.d.ts +1 -0
  3. package/dist/core/index.d.ts.map +1 -1
  4. package/dist/core/index.js +1 -0
  5. package/dist/core/index.js.map +1 -1
  6. package/dist/core/services/faker.service.d.ts +160 -0
  7. package/dist/core/services/faker.service.d.ts.map +1 -0
  8. package/dist/core/services/faker.service.js +235 -0
  9. package/dist/core/services/faker.service.js.map +1 -0
  10. package/dist/infrastructure/filesystem/filesystem.service.d.ts +238 -0
  11. package/dist/infrastructure/filesystem/filesystem.service.d.ts.map +1 -0
  12. package/dist/infrastructure/filesystem/filesystem.service.js +403 -0
  13. package/dist/infrastructure/filesystem/filesystem.service.js.map +1 -0
  14. package/dist/infrastructure/filesystem/path.service.d.ts +115 -0
  15. package/dist/infrastructure/filesystem/path.service.d.ts.map +1 -0
  16. package/dist/infrastructure/filesystem/path.service.js +154 -0
  17. package/dist/infrastructure/filesystem/path.service.js.map +1 -0
  18. package/dist/infrastructure/index.d.ts +2 -0
  19. package/dist/infrastructure/index.d.ts.map +1 -1
  20. package/dist/infrastructure/index.js +2 -0
  21. package/dist/infrastructure/index.js.map +1 -1
  22. package/dist/schemas/faker.schema.d.ts +12 -0
  23. package/dist/schemas/faker.schema.d.ts.map +1 -0
  24. package/dist/schemas/faker.schema.js +12 -0
  25. package/dist/schemas/faker.schema.js.map +1 -0
  26. package/dist/schemas/filesystem.schema.d.ts +64 -0
  27. package/dist/schemas/filesystem.schema.d.ts.map +1 -0
  28. package/dist/schemas/filesystem.schema.js +54 -0
  29. package/dist/schemas/filesystem.schema.js.map +1 -0
  30. package/dist/schemas/index.d.ts +2 -0
  31. package/dist/schemas/index.d.ts.map +1 -1
  32. package/dist/schemas/index.js +2 -0
  33. package/dist/schemas/index.js.map +1 -1
  34. package/dist/types/index.d.ts +26 -0
  35. package/dist/types/index.d.ts.map +1 -1
  36. package/package.json +6 -1
package/README.md CHANGED
@@ -329,6 +329,145 @@ const stop = useKatanaWatch(newProduct, () => checkValidations(), { deep: true }
329
329
  - **Hexagonal architecture** — pure core, infrastructure adapters, framework adapters
330
330
  - **Tree-shakeable** — destructured re-exports from Singleton facades
331
331
  - **SSR-safe** — all infrastructure adapters guard or fall back gracefully in server environments
332
+ - **Filesystem (Node/Bun)** — `useReadFile`, `useWriteFile`, `useReadJsonFile`, `useReadModuleJson` and friends return Safe Results with native errno codes, loaded lazily through dynamic `import()` and guarded by `useIsNode()`
333
+ - **Fake data (optional)** — `useFakeVehicle`, `useFakeEmail`, `useFakeList`, … via an optional, lazy-loaded `@faker-js/faker` peer
334
+
335
+ ## Filesystem (Node/Bun)
336
+
337
+ Node-only helpers that wrap `node:fs/promises` and `node:path` with the Safe
338
+ Result contract. Built-ins load through dynamic `import()`, so importing them is
339
+ browser-safe; outside Node/Bun every fallible call returns `ERR_FS_UNAVAILABLE`
340
+ instead of throwing.
341
+
342
+ ```ts
343
+ import {
344
+ useEnsureDir,
345
+ useReadDir,
346
+ useReadJsonFile,
347
+ useReadModuleJson,
348
+ useWriteJsonFile,
349
+ } from "katanakit-js";
350
+ import { z } from "zod";
351
+
352
+ const BooksSchema = z.array(z.object({ title: z.string() }));
353
+
354
+ // Read relative to the current module (the __dirname pattern, without __dirname)
355
+ const result = await useReadModuleJson(import.meta.url, "../data/books.json", BooksSchema);
356
+
357
+ if (result.ok) {
358
+ console.log(result.data);
359
+ } else {
360
+ console.error(result.error.code, result.error.message); // ENOENT | ERR_VALIDATION | ...
361
+ }
362
+
363
+ // Or with an explicit path (relative paths resolve against process.cwd())
364
+ await useEnsureDir("data/cache");
365
+ await useWriteJsonFile("data/cache/books.json", [{ title: "Kata" }]);
366
+ const books = await useReadJsonFile("data/cache/books.json", BooksSchema);
367
+ const files = await useReadDir("data/cache", { recursive: true });
368
+ ```
369
+
370
+ | Group | Helpers |
371
+ | ----- | ------- |
372
+ | Read | `useReadFile`, `useReadFileBuffer`, `useReadJsonFile`, `useReadModuleFile`, `useReadModuleJson` |
373
+ | Write | `useWriteFile`, `useAppendFile`, `useWriteJsonFile`, `useEnsureDir` |
374
+ | Inspect | `useFileExists`, `useGetFileStats`, `useReadDir` |
375
+ | Move / delete | `useCopyFile`, `useMoveFile`, `useRemoveFile`, `useRemoveDir` |
376
+ | Paths | `useGetDirname`, `useResolvePath`, `useJoinPath`, `useGetRelativePath`, `useGetBasename`, `useGetFileExtension`, `useGetCwd`, `useIsNode` |
377
+
378
+ ## Fake data (optional)
379
+
380
+ `@faker-js/faker` is an **optional peer dependency**: these helpers load it
381
+ through dynamic `import()` on first call, so install it only if you use them
382
+ (`bun add @faker-js/faker` / `npm install @faker-js/faker`).
383
+
384
+ | Group | Helpers |
385
+ | ----------------- | -------------------------------------------------------------------------------------------------------------- |
386
+ | People / internet | `useFakeFullName`, `useFakeFirstName`, `useFakeLastName`, `useFakeEmail`, `useFakePhone`, `useFakeCompanyName`, `useFakeUrl` |
387
+ | Values | `useFakeUuid`, `useFakeText`, `useFakeNumber`, `useFakeBoolean`, `useFakeDate`, `useFakeVehicle` |
388
+ | Collections | `useFakeList(factory, count)` — the factory receives the zero-based index |
389
+ | Reproducibility | `useFakeSeed(seed?)`, `useFakeSetDefaultRefDate(refDate?)` |
390
+
391
+ ### Reproducible seeds
392
+
393
+ `useFakeSeed(42)` sets the seed **and returns it**. Call it with no arguments to
394
+ roll a fresh random seed (also returned) — log it in CI and pass it back later
395
+ to replay the exact run. `useFakeSetDefaultRefDate("2026-01-01")` pins the
396
+ reference date used by date helpers. Same seed + same reference date + same
397
+ call order + same faker major = identical output.
398
+
399
+ ```ts
400
+ import { useFakeSeed, useFakeSetDefaultRefDate, useFakeUuid } from "katanakit-js";
401
+
402
+ const seed = await useFakeSeed(); // e.g. 1696121567592875 — log it in CI
403
+ await useFakeSetDefaultRefDate("2026-01-01");
404
+
405
+ await useFakeSeed(seed); // replay the exact same sequence
406
+ const id = await useFakeUuid();
407
+ ```
408
+
409
+ ### Seed data (users, products, orders)
410
+
411
+ Compose the helpers with `useFakeList` to build realistic fixtures, then write
412
+ them anywhere with the [filesystem helpers](#filesystem-nodebun):
413
+
414
+ ```ts
415
+ import {
416
+ useEnsureDir,
417
+ useFakeDate,
418
+ useFakeEmail,
419
+ useFakeFullName,
420
+ useFakeList,
421
+ useFakeNumber,
422
+ useFakeSeed,
423
+ useFakeSetDefaultRefDate,
424
+ useFakeText,
425
+ useFakeUuid,
426
+ useWriteJsonFile,
427
+ } from "katanakit-js";
428
+
429
+ await useFakeSeed(42);
430
+ await useFakeSetDefaultRefDate("2026-01-01");
431
+
432
+ const users = await useFakeList(
433
+ async () => ({
434
+ id: await useFakeUuid(),
435
+ fullName: await useFakeFullName(),
436
+ email: await useFakeEmail(),
437
+ createdAt: (await useFakeDate("2024-01-01")).toISOString(),
438
+ }),
439
+ 5,
440
+ );
441
+
442
+ const products = await useFakeList(
443
+ async () => ({
444
+ id: await useFakeUuid(),
445
+ name: await useFakeText(3),
446
+ price: await useFakeNumber(5, 250),
447
+ stock: await useFakeNumber(0, 120),
448
+ }),
449
+ 8,
450
+ );
451
+
452
+ // Relations: the factory receives the index
453
+ const orders = await useFakeList(
454
+ async (index) => ({
455
+ id: await useFakeUuid(),
456
+ userId: users[index % users.length].id,
457
+ productId: products[index % products.length].id,
458
+ quantity: await useFakeNumber(1, 6),
459
+ placedAt: (await useFakeDate("2025-01-01")).toISOString(),
460
+ }),
461
+ 12,
462
+ );
463
+
464
+ await useEnsureDir("data/seed");
465
+ await useWriteJsonFile("data/seed/users.json", users);
466
+ // feed the arrays to your seeder: prisma.user.createMany({ data: users }), ...
467
+ ```
468
+
469
+ A runnable version (users, products and orders with relations, written as JSON)
470
+ lives in [`examples/seed/`](./examples/seed/README.md).
332
471
 
333
472
  ## AI assistant (Kitt)
334
473
 
@@ -3,6 +3,7 @@ export * from "./services/agent.service.js";
3
3
  export * from "./services/assistant.service.js";
4
4
  export * from "./services/dates.service.js";
5
5
  export * from "./services/error.service.js";
6
+ export * from "./services/faker.service.js";
6
7
  export * from "./services/formatter.service.js";
7
8
  export * from "./services/generator.service.js";
8
9
  export * from "./services/geometry.service.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
@@ -3,6 +3,7 @@ export * from "./services/agent.service.js";
3
3
  export * from "./services/assistant.service.js";
4
4
  export * from "./services/dates.service.js";
5
5
  export * from "./services/error.service.js";
6
+ export * from "./services/faker.service.js";
6
7
  export * from "./services/formatter.service.js";
7
8
  export * from "./services/generator.service.js";
8
9
  export * from "./services/geometry.service.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iCAAiC,CAAC;AAChD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC"}
@@ -0,0 +1,160 @@
1
+ import type { FakeVehicle } from "../../types/index.js";
2
+ /**
3
+ * Seeds the faker instance for reproducible output, or rolls a new random seed.
4
+ *
5
+ * The sequence depends on the seed, the number of calls made since it was set
6
+ * and the faker major version — keep the call order stable for stable output.
7
+ *
8
+ * @param seed - Optional numeric seed. Omit it to generate a fresh random seed
9
+ * (log the returned value and pass it back later to replay the exact run).
10
+ * @returns The seed that was set.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { useFakeSeed, useFakeUuid } from "katanakit-js";
15
+ *
16
+ * const seed = await useFakeSeed(); // random, but loggable/replayable
17
+ * await useFakeSeed(seed); // replays the same sequence
18
+ * await useFakeUuid();
19
+ * ```
20
+ */
21
+ export declare function useFakeSeed(seed?: number): Promise<number>;
22
+ /**
23
+ * Pins the reference date faker uses for relative date helpers, so
24
+ * date-dependent output stays reproducible next to {@link useFakeSeed}.
25
+ *
26
+ * @param refDate - Static date (`Date`, ISO string or epoch ms) or a factory
27
+ * returning a fresh `Date` on every call. Omit it to reset to the current time.
28
+ * @returns The reference date now in effect.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { useFakeSeed, useFakeSetDefaultRefDate, useFakeDate } from "katanakit-js";
33
+ *
34
+ * await useFakeSeed(42);
35
+ * await useFakeSetDefaultRefDate("2026-01-01");
36
+ * await useFakeDate(); // reproducible between 1970-01-01 and 2026-01-01
37
+ * ```
38
+ */
39
+ export declare function useFakeSetDefaultRefDate(refDate?: Date | number | string | (() => Date)): Promise<Date>;
40
+ /**
41
+ * Generates a v4 UUID.
42
+ *
43
+ * @returns A random UUID string.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const id = await useFakeUuid();
48
+ * ```
49
+ */
50
+ export declare function useFakeUuid(): Promise<string>;
51
+ /**
52
+ * Generates a fake email address.
53
+ *
54
+ * @returns An email address.
55
+ */
56
+ export declare function useFakeEmail(): Promise<string>;
57
+ /**
58
+ * Generates a fake full name.
59
+ *
60
+ * @returns A full name, e.g. `"Ada Lovelace"`.
61
+ */
62
+ export declare function useFakeFullName(): Promise<string>;
63
+ /**
64
+ * Generates a fake first name.
65
+ *
66
+ * @returns A first name.
67
+ */
68
+ export declare function useFakeFirstName(): Promise<string>;
69
+ /**
70
+ * Generates a fake last name.
71
+ *
72
+ * @returns A last name.
73
+ */
74
+ export declare function useFakeLastName(): Promise<string>;
75
+ /**
76
+ * Generates a fake phone number.
77
+ *
78
+ * @returns A phone number string.
79
+ */
80
+ export declare function useFakePhone(): Promise<string>;
81
+ /**
82
+ * Generates a fake company name.
83
+ *
84
+ * @returns A company name.
85
+ */
86
+ export declare function useFakeCompanyName(): Promise<string>;
87
+ /**
88
+ * Generates a fake URL.
89
+ *
90
+ * @returns An absolute URL.
91
+ */
92
+ export declare function useFakeUrl(): Promise<string>;
93
+ /**
94
+ * Generates lorem-ipsum text.
95
+ *
96
+ * @param words - Number of words (default: `12`).
97
+ * @returns A space-separated string of words.
98
+ */
99
+ export declare function useFakeText(words?: number): Promise<string>;
100
+ /**
101
+ * Generates an integer within an inclusive range.
102
+ *
103
+ * @param min - Lower bound (default: `0`).
104
+ * @param max - Upper bound (default: `100`).
105
+ * @returns A random integer between `min` and `max`.
106
+ *
107
+ * @example
108
+ * ```ts
109
+ * const age = await useFakeNumber(18, 65);
110
+ * ```
111
+ */
112
+ export declare function useFakeNumber(min?: number, max?: number): Promise<number>;
113
+ /**
114
+ * Generates a random boolean.
115
+ *
116
+ * @returns `true` or `false`.
117
+ */
118
+ export declare function useFakeBoolean(): Promise<boolean>;
119
+ /**
120
+ * Generates a random date within an optional range.
121
+ *
122
+ * @param from - Lower bound (default: `1970-01-01`).
123
+ * @param to - Upper bound (default: faker's reference date, see
124
+ * {@link useFakeSetDefaultRefDate} — the current time when unset).
125
+ * @returns A `Date` instance.
126
+ *
127
+ * @example
128
+ * ```ts
129
+ * const hiredAt = await useFakeDate(new Date("2020-01-01"), new Date("2025-12-31"));
130
+ * ```
131
+ */
132
+ export declare function useFakeDate(from?: Date | number | string, to?: Date | number | string): Promise<Date>;
133
+ /**
134
+ * Generates a generic fake vehicle (brand, model, type, fuel, color, vin, plate).
135
+ *
136
+ * @returns A {@link FakeVehicle} object.
137
+ *
138
+ * @example
139
+ * ```ts
140
+ * const vehicle = await useFakeVehicle();
141
+ * // { brand: "Jeep", model: "Wrangler", plate: "HJ47FNP", ... }
142
+ * ```
143
+ */
144
+ export declare function useFakeVehicle(): Promise<FakeVehicle>;
145
+ /**
146
+ * Builds an array of fake items from a factory (sync or async).
147
+ *
148
+ * @typeParam T - Item type produced by the factory.
149
+ * @param factory - Called once per item; receives the zero-based index.
150
+ * @param count - Number of items to generate (non-negative integer).
151
+ * @returns A promise resolving to the generated array.
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * const vehicles = await useFakeList(() => useFakeVehicle(), 5);
156
+ * const relations = await useFakeList((index) => ({ user: users[index % users.length] }), 10);
157
+ * ```
158
+ */
159
+ export declare function useFakeList<T>(factory: (index: number) => T | Promise<T>, count: number): Promise<T[]>;
160
+ //# sourceMappingURL=faker.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faker.service.d.ts","sourceRoot":"","sources":["../../../src/core/services/faker.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BxD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,wBAAwB,CAC7C,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;;;;;;GASG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAGnD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAGpD;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAGvD;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGxD;AAED;;;;GAIG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAGvD;AAED;;;;GAIG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAGpD;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAG1D;AAED;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAGlD;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,GAAG,SAAI,EAAE,GAAG,SAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGvE;AAED;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAGvD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,WAAW,CAChC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,EAC7B,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GACzB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC,CAW3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC1C,KAAK,EAAE,MAAM,GACX,OAAO,CAAC,CAAC,EAAE,CAAC,CAKd"}
@@ -0,0 +1,235 @@
1
+ /** Cached lazy faker instance (reset on failure so a later call can retry). */
2
+ let fakerPromise = null;
3
+ /** Loads faker on first use, or rejects with an actionable install error. */
4
+ async function loadFaker() {
5
+ if (!fakerPromise) {
6
+ fakerPromise = import("@faker-js/faker")
7
+ .then((module) => module.faker)
8
+ .catch((error) => {
9
+ fakerPromise = null;
10
+ throw new Error('[Faker] The optional peer dependency "@faker-js/faker" is not installed. Run "bun add @faker-js/faker" (or "npm install @faker-js/faker").', { cause: error });
11
+ });
12
+ }
13
+ return fakerPromise;
14
+ }
15
+ /**
16
+ * Seeds the faker instance for reproducible output, or rolls a new random seed.
17
+ *
18
+ * The sequence depends on the seed, the number of calls made since it was set
19
+ * and the faker major version — keep the call order stable for stable output.
20
+ *
21
+ * @param seed - Optional numeric seed. Omit it to generate a fresh random seed
22
+ * (log the returned value and pass it back later to replay the exact run).
23
+ * @returns The seed that was set.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { useFakeSeed, useFakeUuid } from "katanakit-js";
28
+ *
29
+ * const seed = await useFakeSeed(); // random, but loggable/replayable
30
+ * await useFakeSeed(seed); // replays the same sequence
31
+ * await useFakeUuid();
32
+ * ```
33
+ */
34
+ export async function useFakeSeed(seed) {
35
+ const faker = await loadFaker();
36
+ return seed === undefined ? faker.seed() : faker.seed(seed);
37
+ }
38
+ /**
39
+ * Pins the reference date faker uses for relative date helpers, so
40
+ * date-dependent output stays reproducible next to {@link useFakeSeed}.
41
+ *
42
+ * @param refDate - Static date (`Date`, ISO string or epoch ms) or a factory
43
+ * returning a fresh `Date` on every call. Omit it to reset to the current time.
44
+ * @returns The reference date now in effect.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * import { useFakeSeed, useFakeSetDefaultRefDate, useFakeDate } from "katanakit-js";
49
+ *
50
+ * await useFakeSeed(42);
51
+ * await useFakeSetDefaultRefDate("2026-01-01");
52
+ * await useFakeDate(); // reproducible between 1970-01-01 and 2026-01-01
53
+ * ```
54
+ */
55
+ export async function useFakeSetDefaultRefDate(refDate) {
56
+ const faker = await loadFaker();
57
+ faker.setDefaultRefDate(refDate);
58
+ return faker.defaultRefDate();
59
+ }
60
+ /**
61
+ * Generates a v4 UUID.
62
+ *
63
+ * @returns A random UUID string.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * const id = await useFakeUuid();
68
+ * ```
69
+ */
70
+ export async function useFakeUuid() {
71
+ const faker = await loadFaker();
72
+ return faker.string.uuid();
73
+ }
74
+ /**
75
+ * Generates a fake email address.
76
+ *
77
+ * @returns An email address.
78
+ */
79
+ export async function useFakeEmail() {
80
+ const faker = await loadFaker();
81
+ return faker.internet.email();
82
+ }
83
+ /**
84
+ * Generates a fake full name.
85
+ *
86
+ * @returns A full name, e.g. `"Ada Lovelace"`.
87
+ */
88
+ export async function useFakeFullName() {
89
+ const faker = await loadFaker();
90
+ return faker.person.fullName();
91
+ }
92
+ /**
93
+ * Generates a fake first name.
94
+ *
95
+ * @returns A first name.
96
+ */
97
+ export async function useFakeFirstName() {
98
+ const faker = await loadFaker();
99
+ return faker.person.firstName();
100
+ }
101
+ /**
102
+ * Generates a fake last name.
103
+ *
104
+ * @returns A last name.
105
+ */
106
+ export async function useFakeLastName() {
107
+ const faker = await loadFaker();
108
+ return faker.person.lastName();
109
+ }
110
+ /**
111
+ * Generates a fake phone number.
112
+ *
113
+ * @returns A phone number string.
114
+ */
115
+ export async function useFakePhone() {
116
+ const faker = await loadFaker();
117
+ return faker.phone.number();
118
+ }
119
+ /**
120
+ * Generates a fake company name.
121
+ *
122
+ * @returns A company name.
123
+ */
124
+ export async function useFakeCompanyName() {
125
+ const faker = await loadFaker();
126
+ return faker.company.name();
127
+ }
128
+ /**
129
+ * Generates a fake URL.
130
+ *
131
+ * @returns An absolute URL.
132
+ */
133
+ export async function useFakeUrl() {
134
+ const faker = await loadFaker();
135
+ return faker.internet.url();
136
+ }
137
+ /**
138
+ * Generates lorem-ipsum text.
139
+ *
140
+ * @param words - Number of words (default: `12`).
141
+ * @returns A space-separated string of words.
142
+ */
143
+ export async function useFakeText(words = 12) {
144
+ const faker = await loadFaker();
145
+ return faker.lorem.words(words);
146
+ }
147
+ /**
148
+ * Generates an integer within an inclusive range.
149
+ *
150
+ * @param min - Lower bound (default: `0`).
151
+ * @param max - Upper bound (default: `100`).
152
+ * @returns A random integer between `min` and `max`.
153
+ *
154
+ * @example
155
+ * ```ts
156
+ * const age = await useFakeNumber(18, 65);
157
+ * ```
158
+ */
159
+ export async function useFakeNumber(min = 0, max = 100) {
160
+ const faker = await loadFaker();
161
+ return faker.number.int({ max, min });
162
+ }
163
+ /**
164
+ * Generates a random boolean.
165
+ *
166
+ * @returns `true` or `false`.
167
+ */
168
+ export async function useFakeBoolean() {
169
+ const faker = await loadFaker();
170
+ return faker.datatype.boolean();
171
+ }
172
+ /**
173
+ * Generates a random date within an optional range.
174
+ *
175
+ * @param from - Lower bound (default: `1970-01-01`).
176
+ * @param to - Upper bound (default: faker's reference date, see
177
+ * {@link useFakeSetDefaultRefDate} — the current time when unset).
178
+ * @returns A `Date` instance.
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * const hiredAt = await useFakeDate(new Date("2020-01-01"), new Date("2025-12-31"));
183
+ * ```
184
+ */
185
+ export async function useFakeDate(from, to) {
186
+ const faker = await loadFaker();
187
+ return faker.date.between({
188
+ from: from ?? "1970-01-01",
189
+ to: to ?? faker.defaultRefDate(),
190
+ });
191
+ }
192
+ /**
193
+ * Generates a generic fake vehicle (brand, model, type, fuel, color, vin, plate).
194
+ *
195
+ * @returns A {@link FakeVehicle} object.
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * const vehicle = await useFakeVehicle();
200
+ * // { brand: "Jeep", model: "Wrangler", plate: "HJ47FNP", ... }
201
+ * ```
202
+ */
203
+ export async function useFakeVehicle() {
204
+ const faker = await loadFaker();
205
+ return {
206
+ brand: faker.vehicle.manufacturer(),
207
+ color: faker.vehicle.color(),
208
+ fuel: faker.vehicle.fuel(),
209
+ model: faker.vehicle.model(),
210
+ plate: faker.vehicle.vrm(),
211
+ type: faker.vehicle.type(),
212
+ vin: faker.vehicle.vin(),
213
+ };
214
+ }
215
+ /**
216
+ * Builds an array of fake items from a factory (sync or async).
217
+ *
218
+ * @typeParam T - Item type produced by the factory.
219
+ * @param factory - Called once per item; receives the zero-based index.
220
+ * @param count - Number of items to generate (non-negative integer).
221
+ * @returns A promise resolving to the generated array.
222
+ *
223
+ * @example
224
+ * ```ts
225
+ * const vehicles = await useFakeList(() => useFakeVehicle(), 5);
226
+ * const relations = await useFakeList((index) => ({ user: users[index % users.length] }), 10);
227
+ * ```
228
+ */
229
+ export async function useFakeList(factory, count) {
230
+ if (!Number.isInteger(count) || count < 0) {
231
+ throw new Error("[Faker] count must be a non-negative integer.");
232
+ }
233
+ return Promise.all(Array.from({ length: count }, (_, index) => factory(index)));
234
+ }
235
+ //# sourceMappingURL=faker.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faker.service.js","sourceRoot":"","sources":["../../../src/core/services/faker.service.ts"],"names":[],"mappings":"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"}