@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.
@@ -1,9 +1,12 @@
1
1
  import type { JSONSchema7 } from "json-schema";
2
+ import { findBestMapping } from "./field-name-matcher.js";
2
3
  import { isJSONSchema7, validateFakerMethod } from "./validation.js";
3
4
 
4
- /** JSONSchema7 extended with json-schema-faker's `faker` property */
5
+ /** JSONSchema7 extended with json-schema-faker's `faker` property and schmock markers */
5
6
  interface FakerSchema extends JSONSchema7 {
6
7
  faker?: string;
8
+ schmockNullable?: boolean;
9
+ schmockTrueProbability?: number;
7
10
  }
8
11
 
9
12
  export function enhanceSchemaWithSmartMapping(
@@ -13,10 +16,10 @@ export function enhanceSchemaWithSmartMapping(
13
16
  return schema;
14
17
  }
15
18
 
16
- const enhanced = { ...schema };
19
+ const enhanced = { ...schema } as FakerSchema;
17
20
 
18
21
  // Handle object properties
19
- if (enhanced.type === "object" && enhanced.properties) {
22
+ if (enhanced.properties) {
20
23
  enhanced.properties = { ...enhanced.properties };
21
24
 
22
25
  for (const [fieldName, fieldSchema] of Object.entries(
@@ -31,6 +34,38 @@ export function enhanceSchemaWithSmartMapping(
31
34
  }
32
35
  }
33
36
 
37
+ // Recurse into composition keywords
38
+ for (const keyword of ["allOf", "anyOf", "oneOf"] as const) {
39
+ const branches = enhanced[keyword];
40
+ if (Array.isArray(branches)) {
41
+ (enhanced as Record<string, unknown>)[keyword] = branches.map((branch) =>
42
+ isJSONSchema7(branch) ? enhanceSchemaWithSmartMapping(branch) : branch,
43
+ );
44
+ }
45
+ }
46
+
47
+ // Recurse into array items
48
+ if (enhanced.items) {
49
+ if (Array.isArray(enhanced.items)) {
50
+ enhanced.items = enhanced.items.map((item) =>
51
+ isJSONSchema7(item) ? enhanceSchemaWithSmartMapping(item) : item,
52
+ );
53
+ } else if (isJSONSchema7(enhanced.items)) {
54
+ enhanced.items = enhanceSchemaWithSmartMapping(enhanced.items);
55
+ }
56
+ }
57
+
58
+ // Recurse into additionalProperties
59
+ if (
60
+ enhanced.additionalProperties &&
61
+ typeof enhanced.additionalProperties === "object" &&
62
+ !Array.isArray(enhanced.additionalProperties)
63
+ ) {
64
+ enhanced.additionalProperties = enhanceSchemaWithSmartMapping(
65
+ enhanced.additionalProperties as JSONSchema7,
66
+ );
67
+ }
68
+
34
69
  return enhanced;
35
70
  }
36
71
 
@@ -46,60 +81,28 @@ function enhanceFieldSchema(
46
81
  return enhanced;
47
82
  }
48
83
 
49
- // Apply smart field name mapping
50
- const lowerFieldName = fieldName.toLowerCase();
51
-
52
- // Email fields
53
- if (lowerFieldName.includes("email")) {
54
- enhanced.format = "email";
55
- enhanced.faker = "internet.email";
56
- }
57
- // Name fields
58
- else if (lowerFieldName === "firstname" || lowerFieldName === "first_name") {
59
- enhanced.faker = "person.firstName";
60
- } else if (lowerFieldName === "lastname" || lowerFieldName === "last_name") {
61
- enhanced.faker = "person.lastName";
62
- } else if (lowerFieldName === "name" || lowerFieldName === "fullname") {
63
- enhanced.faker = "person.fullName";
84
+ // Recursively enhance nested schemas first
85
+ const hasComposition = enhanced.allOf || enhanced.anyOf || enhanced.oneOf;
86
+ if (enhanced.properties || hasComposition || enhanced.items) {
87
+ const recursed = enhanceSchemaWithSmartMapping(enhanced);
88
+ Object.assign(enhanced, recursed);
64
89
  }
65
- // Phone fields
66
- else if (lowerFieldName.includes("phone") || lowerFieldName === "mobile") {
67
- enhanced.faker = "phone.number";
68
- }
69
- // Address fields
70
- else if (lowerFieldName === "street" || lowerFieldName === "address") {
71
- enhanced.faker = "location.streetAddress";
72
- } else if (lowerFieldName === "city") {
73
- enhanced.faker = "location.city";
74
- } else if (lowerFieldName === "zipcode" || lowerFieldName === "zip") {
75
- enhanced.faker = "location.zipCode";
76
- }
77
- // UUID fields
78
- else if (
79
- lowerFieldName === "uuid" ||
80
- (lowerFieldName === "id" && enhanced.format === "uuid")
81
- ) {
82
- enhanced.faker = "string.uuid";
83
- }
84
- // Date fields
85
- else if (
86
- lowerFieldName.includes("createdat") ||
87
- lowerFieldName.includes("created_at") ||
88
- lowerFieldName.includes("updatedat") ||
89
- lowerFieldName.includes("updated_at")
90
- ) {
91
- enhanced.format = "date-time";
92
- enhanced.faker = "date.recent";
93
- }
94
- // Company fields
95
- else if (lowerFieldName.includes("company")) {
96
- enhanced.faker = "company.name";
97
- } else if (lowerFieldName === "position" || lowerFieldName === "jobtitle") {
98
- enhanced.faker = "person.jobTitle";
90
+
91
+ // Don't apply field-level faker mapping to composition schemas — the branches define their own types
92
+ if (hasComposition) {
93
+ return enhanced;
99
94
  }
100
- // Price/money fields
101
- else if (lowerFieldName === "price" || lowerFieldName === "amount") {
102
- enhanced.faker = "commerce.price";
95
+
96
+ // Apply smart field name mapping via the scoring matcher
97
+ const match = findBestMapping(fieldName, enhanced);
98
+ if (match) {
99
+ enhanced.faker = match.mapping.fakerMethod;
100
+ if (match.mapping.format) {
101
+ enhanced.format = match.mapping.format;
102
+ }
103
+ if (match.mapping.trueProbability !== undefined) {
104
+ enhanced.schmockTrueProbability = match.mapping.trueProbability;
105
+ }
103
106
  }
104
107
 
105
108
  return enhanced;
@@ -0,0 +1,20 @@
1
+ import type { JSONSchema7 } from "json-schema";
2
+ export declare function isJSONSchema7(value: unknown): value is JSONSchema7;
3
+ /**
4
+ * Validate JSON Schema structure and enforce resource limits
5
+ * Checks for malformed schemas, circular references, excessive nesting,
6
+ * and dangerous patterns that could cause memory issues
7
+ * @param schema - JSON Schema to validate
8
+ * @param path - Current path in schema tree (for error messages)
9
+ * @throws {SchemaValidationError} When schema structure is invalid
10
+ * @throws {ResourceLimitError} When schema exceeds safety limits
11
+ */
12
+ export declare function validateSchema(schema: JSONSchema7, path?: string): void;
13
+ /**
14
+ * Validate that faker method string references a valid Faker.js API
15
+ * Checks format (namespace.method) and validates against known namespaces
16
+ * @param fakerMethod - Faker method string (e.g., "person.fullName")
17
+ * @throws {SchemaValidationError} When faker method format or namespace is invalid
18
+ */
19
+ export declare function validateFakerMethod(fakerMethod: string): void;
20
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["validation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAY/C,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,WAAW,CAElE;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,SAAM,GAAG,IAAI,CAiJpE;AAwMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAmC7D"}