@schmock/faker 1.9.4 → 1.10.0

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.
@@ -0,0 +1,252 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ findBestMapping,
4
+ scoreMatch,
5
+ tokenizeFieldName,
6
+ } from "./field-name-matcher";
7
+
8
+ describe("tokenizeFieldName", () => {
9
+ it("splits camelCase", () => {
10
+ expect(tokenizeFieldName("userFirstName")).toEqual([
11
+ "user",
12
+ "first",
13
+ "name",
14
+ ]);
15
+ });
16
+
17
+ it("splits snake_case", () => {
18
+ expect(tokenizeFieldName("created_at")).toEqual(["created", "at"]);
19
+ });
20
+
21
+ it("splits kebab-case", () => {
22
+ expect(tokenizeFieldName("user-name")).toEqual(["user", "name"]);
23
+ });
24
+
25
+ it("handles consecutive uppercase (HTMLParser)", () => {
26
+ expect(tokenizeFieldName("HTMLParser")).toEqual(["html", "parser"]);
27
+ });
28
+
29
+ it("handles is_active", () => {
30
+ expect(tokenizeFieldName("is_active")).toEqual(["is", "active"]);
31
+ });
32
+
33
+ it("handles single word", () => {
34
+ expect(tokenizeFieldName("email")).toEqual(["email"]);
35
+ });
36
+
37
+ it("handles uppercase single word", () => {
38
+ expect(tokenizeFieldName("UUID")).toEqual(["uuid"]);
39
+ });
40
+
41
+ it("handles mixed formats", () => {
42
+ expect(tokenizeFieldName("userEmail_address")).toEqual([
43
+ "user",
44
+ "email",
45
+ "address",
46
+ ]);
47
+ });
48
+ });
49
+
50
+ describe("scoreMatch", () => {
51
+ it("returns 1.0 for exact match", () => {
52
+ expect(scoreMatch(["email"], ["email"])).toBe(1.0);
53
+ });
54
+
55
+ it("returns 1.0 for exact multi-token match", () => {
56
+ expect(scoreMatch(["first", "name"], ["first_name"])).toBe(1.0);
57
+ });
58
+
59
+ it("returns 0.7 for substring match with low keyword coverage", () => {
60
+ // "email" is 1/3 tokens → low coverage (0.65) but substring match (0.7) wins
61
+ expect(scoreMatch(["user", "email", "address"], ["email"])).toBe(0.7);
62
+ });
63
+
64
+ it("returns 0.9 when all keyword tokens found with high coverage", () => {
65
+ // ["created", "at"] are both found in ["user", "created", "at"] → 2/3 coverage > 50%
66
+ expect(scoreMatch(["user", "created", "at"], ["created_at"])).toBe(0.9);
67
+ });
68
+
69
+ it("returns 0.8 when field ends with keyword", () => {
70
+ // ["name"] is at the end of ["display", "name"] — ends-with score = 0.8
71
+ // coverage is 1/2 = 0.5, not > 0.5, so "all found" gives 0.65
72
+ // ends-with wins at 0.8
73
+ expect(scoreMatch(["display", "name"], ["name"])).toBe(0.8);
74
+ });
75
+
76
+ it("returns 0.7 for substring match", () => {
77
+ expect(scoreMatch(["myemailfield"], ["email"])).toBe(0.7);
78
+ });
79
+
80
+ it("returns 0 for no match", () => {
81
+ expect(scoreMatch(["foo", "bar"], ["email"])).toBe(0);
82
+ });
83
+ });
84
+
85
+ describe("findBestMapping", () => {
86
+ it("maps email field", () => {
87
+ const result = findBestMapping("email", { type: "string" });
88
+ expect(result).toBeDefined();
89
+ expect(result?.mapping.fakerMethod).toBe("internet.email");
90
+ });
91
+
92
+ it("maps userEmail field", () => {
93
+ const result = findBestMapping("userEmail", { type: "string" });
94
+ expect(result).toBeDefined();
95
+ expect(result?.mapping.fakerMethod).toBe("internet.email");
96
+ });
97
+
98
+ it("maps firstName field", () => {
99
+ const result = findBestMapping("firstName", { type: "string" });
100
+ expect(result).toBeDefined();
101
+ expect(result?.mapping.fakerMethod).toBe("person.firstName");
102
+ });
103
+
104
+ it("maps first_name field", () => {
105
+ const result = findBestMapping("first_name", { type: "string" });
106
+ expect(result).toBeDefined();
107
+ expect(result?.mapping.fakerMethod).toBe("person.firstName");
108
+ });
109
+
110
+ it("maps createdAt to date.recent", () => {
111
+ const result = findBestMapping("createdAt", { type: "string" });
112
+ expect(result).toBeDefined();
113
+ expect(result?.mapping.fakerMethod).toBe("date.recent");
114
+ expect(result?.mapping.format).toBe("date-time");
115
+ });
116
+
117
+ it("maps city field", () => {
118
+ const result = findBestMapping("city", { type: "string" });
119
+ expect(result).toBeDefined();
120
+ expect(result?.mapping.fakerMethod).toBe("location.city");
121
+ });
122
+
123
+ it("maps url field", () => {
124
+ const result = findBestMapping("url", { type: "string" });
125
+ expect(result).toBeDefined();
126
+ expect(result?.mapping.fakerMethod).toBe("internet.url");
127
+ });
128
+
129
+ it("maps avatar field", () => {
130
+ const result = findBestMapping("avatar", { type: "string" });
131
+ expect(result).toBeDefined();
132
+ expect(result?.mapping.fakerMethod).toBe("image.avatar");
133
+ });
134
+
135
+ it("maps latitude field to number", () => {
136
+ const result = findBestMapping("latitude", { type: "number" });
137
+ expect(result).toBeDefined();
138
+ expect(result?.mapping.fakerMethod).toBe("location.latitude");
139
+ });
140
+
141
+ it("maps description field", () => {
142
+ const result = findBestMapping("description", { type: "string" });
143
+ expect(result).toBeDefined();
144
+ expect(result?.mapping.fakerMethod).toBe("lorem.paragraph");
145
+ });
146
+
147
+ it("maps title field", () => {
148
+ const result = findBestMapping("title", { type: "string" });
149
+ expect(result).toBeDefined();
150
+ expect(result?.mapping.fakerMethod).toBe("lorem.sentence");
151
+ });
152
+
153
+ it("maps country field", () => {
154
+ const result = findBestMapping("country", { type: "string" });
155
+ expect(result).toBeDefined();
156
+ expect(result?.mapping.fakerMethod).toBe("location.country");
157
+ });
158
+
159
+ it("maps isActive boolean with probability", () => {
160
+ const result = findBestMapping("isActive", { type: "boolean" });
161
+ expect(result).toBeDefined();
162
+ expect(result?.mapping.trueProbability).toBe(0.9);
163
+ });
164
+
165
+ it("maps is_deleted boolean with low probability", () => {
166
+ const result = findBestMapping("is_deleted", { type: "boolean" });
167
+ expect(result).toBeDefined();
168
+ expect(result?.mapping.trueProbability).toBe(0.05);
169
+ });
170
+
171
+ describe("ID suffix detection", () => {
172
+ it("maps userId to UUID", () => {
173
+ const result = findBestMapping("userId", { type: "string" });
174
+ expect(result).toBeDefined();
175
+ expect(result?.mapping.fakerMethod).toBe("string.uuid");
176
+ });
177
+
178
+ it("maps order_id to UUID", () => {
179
+ const result = findBestMapping("order_id", { type: "string" });
180
+ expect(result).toBeDefined();
181
+ expect(result?.mapping.fakerMethod).toBe("string.uuid");
182
+ });
183
+
184
+ it("maps parent_id to UUID", () => {
185
+ const result = findBestMapping("parent_id", { type: "string" });
186
+ expect(result).toBeDefined();
187
+ expect(result?.mapping.fakerMethod).toBe("string.uuid");
188
+ });
189
+
190
+ it("does not map single id without format:uuid", () => {
191
+ const result = findBestMapping("id", { type: "string" });
192
+ // 'id' alone shouldn't trigger UUID — it's a single token so suffix rule doesn't apply
193
+ // But it could still match something else. Let's just check it doesn't falsely match
194
+ if (result) {
195
+ // Could match 'id' in some mapping, that's OK
196
+ expect(result.score).toBeGreaterThan(0);
197
+ }
198
+ });
199
+
200
+ it("does not map Id suffix on number fields", () => {
201
+ const result = findBestMapping("userId", { type: "number" });
202
+ // Number type should not get UUID mapping
203
+ if (result) {
204
+ expect(result.mapping.fakerMethod).not.toBe("string.uuid");
205
+ }
206
+ });
207
+ });
208
+
209
+ describe("skip conditions", () => {
210
+ it("skips when schema has pattern", () => {
211
+ const result = findBestMapping("email", {
212
+ type: "string",
213
+ pattern: "^[a-z]+$",
214
+ });
215
+ expect(result).toBeUndefined();
216
+ });
217
+
218
+ it("skips when schema has enum", () => {
219
+ const result = findBestMapping("email", {
220
+ type: "string",
221
+ enum: ["a@b.com", "c@d.com"],
222
+ });
223
+ expect(result).toBeUndefined();
224
+ });
225
+
226
+ it("skips when schema already has faker", () => {
227
+ const schema = { type: "string" as const, faker: "lorem.word" } as any;
228
+ const result = findBestMapping("email", schema);
229
+ expect(result).toBeUndefined();
230
+ });
231
+ });
232
+
233
+ it("does not map unrecognized fields", () => {
234
+ const result = findBestMapping("randomFieldXYZ123", { type: "string" });
235
+ expect(result).toBeUndefined();
236
+ });
237
+
238
+ it("respects type constraints", () => {
239
+ // latitude mapping requires number type
240
+ const result = findBestMapping("latitude", { type: "string" });
241
+ expect(result).toBeUndefined();
242
+ });
243
+
244
+ it("maps format:uuid even without name match", () => {
245
+ const result = findBestMapping("someField", {
246
+ type: "string",
247
+ format: "uuid",
248
+ });
249
+ expect(result).toBeDefined();
250
+ expect(result?.mapping.fakerMethod).toBe("string.uuid");
251
+ });
252
+ });
@@ -0,0 +1,172 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ import type { FieldMapping } from "./field-mappings.js";
3
+ import { ALL_FIELD_MAPPINGS } from "./field-mappings.js";
4
+
5
+ /**
6
+ * Split a field name (camelCase, snake_case, kebab-case) into lowercase tokens.
7
+ * "userFirstName" → ["user", "first", "name"]
8
+ * "created_at" → ["created", "at"]
9
+ * "HTMLParser" → ["html", "parser"]
10
+ * "is_active" → ["is", "active"]
11
+ */
12
+ export function tokenizeFieldName(name: string): string[] {
13
+ // Split on _ and -
14
+ const parts = name.split(/[_-]/);
15
+ const tokens: string[] = [];
16
+
17
+ for (const part of parts) {
18
+ if (!part) continue;
19
+ // Split camelCase and consecutive uppercase (e.g., HTMLParser → HTML, Parser)
20
+ const camelTokens = part
21
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
22
+ .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
23
+ .split("_");
24
+
25
+ for (const t of camelTokens) {
26
+ if (t) tokens.push(t.toLowerCase());
27
+ }
28
+ }
29
+
30
+ return tokens;
31
+ }
32
+
33
+ /**
34
+ * Score how well a set of keyword tokens matches field name tokens.
35
+ * Returns 0-1:
36
+ * 1.0 — exact full match (joined tokens equal joined keywords)
37
+ * 0.9 — all keyword tokens found in field tokens with high coverage (>50%)
38
+ * 0.8 — field ends with keyword tokens
39
+ * 0.7 — substring match (keyword appears in joined field name)
40
+ * 0.65 — all keyword tokens found but low coverage (<=50%)
41
+ */
42
+ export function scoreMatch(fieldTokens: string[], keywords: string[]): number {
43
+ const fieldJoined = fieldTokens.join("");
44
+
45
+ let bestScore = 0;
46
+
47
+ // Try each keyword variant, keep the highest score
48
+ for (const keyword of keywords) {
49
+ const kwTokens = tokenizeFieldName(keyword);
50
+ const kwJoined = kwTokens.join("");
51
+
52
+ // Exact match: joined tokens are identical
53
+ if (fieldJoined === kwJoined) return 1.0;
54
+
55
+ // All keyword tokens present in field tokens with high coverage
56
+ if (
57
+ kwTokens.length > 0 &&
58
+ kwTokens.every((kt) => fieldTokens.includes(kt))
59
+ ) {
60
+ const coverage = kwTokens.length / fieldTokens.length;
61
+ const score = coverage > 0.5 ? 0.9 : 0.65;
62
+ bestScore = Math.max(bestScore, score);
63
+ }
64
+
65
+ // Field ends with keyword tokens
66
+ if (kwTokens.length > 0 && kwTokens.length <= fieldTokens.length) {
67
+ const tail = fieldTokens.slice(-kwTokens.length);
68
+ if (tail.every((t, i) => t === kwTokens[i])) {
69
+ bestScore = Math.max(bestScore, 0.8);
70
+ }
71
+ }
72
+
73
+ // Substring match: keyword joined appears in field joined
74
+ if (kwJoined.length >= 3 && fieldJoined.includes(kwJoined)) {
75
+ bestScore = Math.max(bestScore, 0.7);
76
+ }
77
+ }
78
+
79
+ return bestScore;
80
+ }
81
+
82
+ interface MatchResult {
83
+ mapping: FieldMapping;
84
+ score: number;
85
+ }
86
+
87
+ /**
88
+ * Find the best field mapping for a given field name and schema.
89
+ * Returns the highest-scoring match above its threshold, or undefined.
90
+ */
91
+ export function findBestMapping(
92
+ fieldName: string,
93
+ schema: JSONSchema7,
94
+ mappings: FieldMapping[] = ALL_FIELD_MAPPINGS,
95
+ ): MatchResult | undefined {
96
+ const schemaAny = schema as Record<string, unknown>;
97
+ const schemaType = typeof schema.type === "string" ? schema.type : undefined;
98
+
99
+ // Priority: format:uuid always maps to string.uuid
100
+ if (schemaType === "string" && schema.format === "uuid") {
101
+ return {
102
+ mapping: {
103
+ keywords: ["uuid"],
104
+ fakerMethod: "string.uuid",
105
+ schemaType: "string",
106
+ minScore: 0.5,
107
+ },
108
+ score: 1.0,
109
+ };
110
+ }
111
+
112
+ // Skip if schema already has pattern, enum, or faker constraint
113
+ if (schemaAny.pattern || schemaAny.enum || schemaAny.faker) {
114
+ return undefined;
115
+ }
116
+
117
+ // Skip numeric faker mapping when schema already constrains the range
118
+ const hasNumericConstraints =
119
+ schema.minimum !== undefined ||
120
+ schema.maximum !== undefined ||
121
+ schema.exclusiveMinimum !== undefined ||
122
+ schema.exclusiveMaximum !== undefined;
123
+
124
+ const tokens = tokenizeFieldName(fieldName);
125
+
126
+ let best: MatchResult | undefined;
127
+
128
+ for (const mapping of mappings) {
129
+ // Skip numeric faker mappings when schema has explicit constraints
130
+ if (
131
+ hasNumericConstraints &&
132
+ (mapping.schemaType === "number" || mapping.schemaType === "integer")
133
+ ) {
134
+ continue;
135
+ }
136
+
137
+ // Check schema type constraint
138
+ if (mapping.schemaType && schemaType && mapping.schemaType !== schemaType) {
139
+ const isNumeric =
140
+ (mapping.schemaType === "number" && schemaType === "integer") ||
141
+ (mapping.schemaType === "integer" && schemaType === "number");
142
+ if (!isNumeric) continue;
143
+ }
144
+
145
+ const score = scoreMatch(tokens, mapping.keywords);
146
+ if (score >= mapping.minScore && (!best || score > best.score)) {
147
+ best = { mapping, score };
148
+ }
149
+ }
150
+
151
+ // ID suffix detection: fields ending in Id/_id with string type → UUID
152
+ // Only if no better match was found or the existing match is weak
153
+ if (schemaType === "string") {
154
+ const lastToken = tokens[tokens.length - 1];
155
+ if (lastToken === "id" && tokens.length > 1) {
156
+ const idScore = 0.8;
157
+ if (!best || best.score < idScore) {
158
+ best = {
159
+ mapping: {
160
+ keywords: ["id"],
161
+ fakerMethod: "string.uuid",
162
+ schemaType: "string",
163
+ minScore: 0.5,
164
+ },
165
+ score: idScore,
166
+ };
167
+ }
168
+ }
169
+ }
170
+
171
+ return best;
172
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ export interface SchemaGenerationContext {
3
+ schema: JSONSchema7;
4
+ count?: number;
5
+ overrides?: Record<string, any>;
6
+ params?: Record<string, string>;
7
+ state?: any;
8
+ query?: Record<string, string>;
9
+ seed?: number;
10
+ }
11
+ export interface FakerPluginOptions {
12
+ schema: JSONSchema7;
13
+ count?: number;
14
+ overrides?: Record<string, any>;
15
+ seed?: number;
16
+ }
17
+ export declare function fakerPlugin(options: FakerPluginOptions): Schmock.Plugin;
18
+ export declare function generateFromSchema(options: SchemaGenerationContext): any;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO/C,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CA+CvE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,uBAAuB,GAAG,GAAG,CA6CxE"}
package/src/index.ts CHANGED
@@ -6,11 +6,11 @@ import {
6
6
  SchemaValidationError,
7
7
  } from "@schmock/core";
8
8
  import type { JSONSchema7 } from "json-schema";
9
- import { MAX_ARRAY_SIZE } from "./constants.js";
9
+ import { MAX_ARRAY_SIZE, NULLABLE_NULL_PROBABILITY } from "./constants.js";
10
10
  import { getJsf } from "./jsf-config.js";
11
11
  import { applyOverrides, determineArrayCount } from "./overrides.js";
12
12
  import { enhanceSchemaWithSmartMapping } from "./schema-enhancement.js";
13
- import { validateSchema } from "./validation.js";
13
+ import { isJSONSchema7, validateSchema } from "./validation.js";
14
14
 
15
15
  export interface SchemaGenerationContext {
16
16
  schema: JSONSchema7;
@@ -106,12 +106,12 @@ export function generateFromSchema(options: SchemaGenerationContext): any {
106
106
  }
107
107
 
108
108
  const itemSchema = rawItemSchema;
109
+ const enhancedItemSchema = enhanceSchemaWithSmartMapping(itemSchema);
109
110
 
110
111
  generated = [];
111
112
  for (let i = 0; i < itemCount; i++) {
112
- let item = getJsf(seed).generate(
113
- enhanceSchemaWithSmartMapping(itemSchema),
114
- );
113
+ let item = getJsf(seed).generate(enhancedItemSchema);
114
+ item = postProcessGenerated(item, enhancedItemSchema);
115
115
  item = applyOverrides(item, overrides, params, state, query);
116
116
  generated.push(item);
117
117
  }
@@ -119,8 +119,61 @@ export function generateFromSchema(options: SchemaGenerationContext): any {
119
119
  // Handle object schemas
120
120
  const enhancedSchema = enhanceSchemaWithSmartMapping(schema);
121
121
  generated = getJsf(seed).generate(enhancedSchema);
122
+ generated = postProcessGenerated(generated, enhancedSchema);
122
123
  generated = applyOverrides(generated, overrides, params, state, query);
123
124
  }
124
125
 
125
126
  return generated;
126
127
  }
128
+
129
+ /**
130
+ * Post-process generated data to apply nullable probability and boolean weighting.
131
+ * Walks the schema and generated data in parallel, applying:
132
+ * - schmockNullable: ~5% chance of null
133
+ * - schmockTrueProbability: weighted boolean generation
134
+ */
135
+ function postProcessGenerated(data: any, schema: JSONSchema7): any {
136
+ if (
137
+ data === null ||
138
+ data === undefined ||
139
+ !schema ||
140
+ typeof schema !== "object"
141
+ ) {
142
+ return data;
143
+ }
144
+
145
+ const schemaAny = schema as Record<string, unknown>;
146
+
147
+ // Apply nullable probability at this level
148
+ if (schemaAny.schmockNullable === true) {
149
+ if (Math.random() < NULLABLE_NULL_PROBABILITY) {
150
+ return null;
151
+ }
152
+ }
153
+
154
+ // Apply boolean weighting at this level
155
+ if (
156
+ schema.type === "boolean" &&
157
+ typeof schemaAny.schmockTrueProbability === "number"
158
+ ) {
159
+ return Math.random() < schemaAny.schmockTrueProbability;
160
+ }
161
+
162
+ // Recurse into object properties
163
+ if (typeof data === "object" && !Array.isArray(data) && schema.properties) {
164
+ for (const [key, propSchema] of Object.entries(schema.properties)) {
165
+ if (key in data && isJSONSchema7(propSchema)) {
166
+ data[key] = postProcessGenerated(data[key], propSchema);
167
+ }
168
+ }
169
+ }
170
+
171
+ // Recurse into array items
172
+ if (Array.isArray(data) && schema.items && isJSONSchema7(schema.items)) {
173
+ for (let i = 0; i < data.length; i++) {
174
+ data[i] = postProcessGenerated(data[i], schema.items);
175
+ }
176
+ }
177
+
178
+ return data;
179
+ }
@@ -0,0 +1,10 @@
1
+ import { Faker } from "@faker-js/faker";
2
+ import jsf from "json-schema-faker";
3
+ /**
4
+ * Create isolated faker instance to avoid race conditions
5
+ * Each generation gets its own faker instance to ensure thread-safety
6
+ * @returns Fresh Faker instance with English locale
7
+ */
8
+ export declare function createFakerInstance(seed?: number): Faker;
9
+ export declare function getJsf(seed?: number): typeof jsf;
10
+ //# sourceMappingURL=jsf-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsf-config.d.ts","sourceRoot":"","sources":["jsf-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,GAAG,MAAM,mBAAmB,CAAC;AAEpC;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,SAMhD;AAoBD,wBAAgB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,CAuBhD"}
package/src/jsf-config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { en, Faker } from "@faker-js/faker";
1
+ import { base, en, Faker } from "@faker-js/faker";
2
2
  import jsf from "json-schema-faker";
3
3
 
4
4
  /**
@@ -7,7 +7,7 @@ import jsf from "json-schema-faker";
7
7
  * @returns Fresh Faker instance with English locale
8
8
  */
9
9
  export function createFakerInstance(seed?: number) {
10
- const faker = new Faker({ locale: [en] });
10
+ const faker = new Faker({ locale: [en, base] });
11
11
  if (seed !== undefined) {
12
12
  faker.seed(seed);
13
13
  }
@@ -0,0 +1,21 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ /**
3
+ * Determine number of items to generate for array schema
4
+ * Prefers explicit count, then schema minItems/maxItems, with sane defaults
5
+ * @param schema - Array schema with optional minItems/maxItems
6
+ * @param explicitCount - Explicit count override from plugin options
7
+ * @returns Number of array items to generate
8
+ */
9
+ export declare function determineArrayCount(schema: JSONSchema7, explicitCount?: number, random?: () => number): number;
10
+ /**
11
+ * Apply overrides to generated data with support for templates
12
+ * Supports nested paths (dot notation), templates with {{params.id}}, and state access
13
+ * @param data - Generated data to apply overrides to
14
+ * @param overrides - Override values (can use templates)
15
+ * @param params - Route parameters for template expansion
16
+ * @param state - Plugin state for template expansion
17
+ * @param query - Query parameters for template expansion
18
+ * @returns Data with overrides applied
19
+ */
20
+ export declare function applyOverrides(data: any, overrides?: Record<string, any>, params?: Record<string, string>, state?: any, query?: Record<string, string>): any;
21
+ //# sourceMappingURL=overrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overrides.d.ts","sourceRoot":"","sources":["overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,MAAM,GAAE,MAAM,MAAoB,GACjC,MAAM,CAyBR;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,GAAG,EACT,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,KAAK,CAAC,EAAE,GAAG,EACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,GAAG,CAuCL"}
@@ -0,0 +1,3 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ export declare function enhanceSchemaWithSmartMapping(schema: JSONSchema7): JSONSchema7;
3
+ //# sourceMappingURL=schema-enhancement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-enhancement.d.ts","sourceRoot":"","sources":["schema-enhancement.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAQ/C,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,WAAW,GAClB,WAAW,CAwBb"}