@schmock/faker 2.2.3 → 2.3.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 (65) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +45 -0
  3. package/dist/constants.d.ts +82 -1
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/field-mappings.d.ts.map +1 -1
  6. package/dist/field-name-matcher.d.ts +19 -0
  7. package/dist/field-name-matcher.d.ts.map +1 -1
  8. package/dist/index.d.ts +3 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +4 -1
  11. package/dist/jsf-config.d.ts +27 -2
  12. package/dist/jsf-config.d.ts.map +1 -1
  13. package/dist/output-limits.d.ts +3 -0
  14. package/dist/output-limits.d.ts.map +1 -0
  15. package/dist/overrides.d.ts +2 -1
  16. package/dist/overrides.d.ts.map +1 -1
  17. package/dist/schema-children.d.ts +14 -0
  18. package/dist/schema-children.d.ts.map +1 -0
  19. package/dist/schema-enhancement.d.ts +1 -0
  20. package/dist/schema-enhancement.d.ts.map +1 -1
  21. package/dist/validation.d.ts +24 -5
  22. package/dist/validation.d.ts.map +1 -1
  23. package/package.json +19 -9
  24. package/dist/constants.js +0 -8
  25. package/dist/field-mappings.js +0 -1107
  26. package/dist/field-name-matcher.js +0 -149
  27. package/dist/jsf-config.js +0 -35
  28. package/dist/overrides.js +0 -131
  29. package/dist/schema-enhancement.js +0 -89
  30. package/dist/test-utils.d.ts +0 -57
  31. package/dist/test-utils.d.ts.map +0 -1
  32. package/dist/test-utils.js +0 -271
  33. package/dist/validation.js +0 -300
  34. package/src/advanced-features.test.ts +0 -912
  35. package/src/audit-faker-args.test.ts +0 -97
  36. package/src/constants.d.ts.map +0 -1
  37. package/src/constants.ts +0 -9
  38. package/src/data-quality.test.ts +0 -415
  39. package/src/error-handling.test.ts +0 -504
  40. package/src/field-mappings.test.ts +0 -351
  41. package/src/field-mappings.ts +0 -1141
  42. package/src/field-name-matcher.test.ts +0 -292
  43. package/src/field-name-matcher.ts +0 -188
  44. package/src/index.d.ts.map +0 -1
  45. package/src/index.test.ts +0 -1218
  46. package/src/index.ts +0 -168
  47. package/src/integration.test.ts +0 -634
  48. package/src/jsf-config.d.ts.map +0 -1
  49. package/src/jsf-config.ts +0 -48
  50. package/src/overrides.d.ts.map +0 -1
  51. package/src/overrides.property.test.ts +0 -172
  52. package/src/overrides.test.ts +0 -38
  53. package/src/overrides.ts +0 -176
  54. package/src/performance.test.ts +0 -494
  55. package/src/plugin-integration.test.ts +0 -575
  56. package/src/post-process.test.ts +0 -151
  57. package/src/real-world.test.ts +0 -636
  58. package/src/schema-enhancement.d.ts.map +0 -1
  59. package/src/schema-enhancement.test.ts +0 -216
  60. package/src/schema-enhancement.ts +0 -128
  61. package/src/steps/deterministic-seeds.steps.ts +0 -35
  62. package/src/steps/faker-plugin.steps.ts +0 -109
  63. package/src/test-utils.ts +0 -365
  64. package/src/validation.d.ts.map +0 -1
  65. package/src/validation.ts +0 -417
@@ -1,149 +0,0 @@
1
- import { ALL_FIELD_MAPPINGS } from "./field-mappings.js";
2
- /**
3
- * Split a field name (camelCase, snake_case, kebab-case) into lowercase tokens.
4
- * "userFirstName" → ["user", "first", "name"]
5
- * "created_at" → ["created", "at"]
6
- * "HTMLParser" → ["html", "parser"]
7
- * "is_active" → ["is", "active"]
8
- */
9
- export function tokenizeFieldName(name) {
10
- // Split on _ and -
11
- const parts = name.split(/[_-]/);
12
- const tokens = [];
13
- for (const part of parts) {
14
- if (!part)
15
- continue;
16
- // Split camelCase and consecutive uppercase (e.g., HTMLParser → HTML, Parser)
17
- const camelTokens = part
18
- .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
19
- .replace(/([a-z0-9])([A-Z])/g, "$1_$2")
20
- .split("_");
21
- for (const t of camelTokens) {
22
- if (t)
23
- tokens.push(t.toLowerCase());
24
- }
25
- }
26
- return tokens;
27
- }
28
- /**
29
- * Score how well a set of keyword tokens matches field name tokens.
30
- * Returns 0-1:
31
- * 1.0 — exact full match (joined tokens equal joined keywords)
32
- * 0.9 — all keyword tokens found in field tokens with high coverage (>50%)
33
- * 0.8 — field ends with keyword tokens
34
- * 0.7 — substring match (keyword appears in joined field name)
35
- * 0.65 — all keyword tokens found but low coverage (<=50%)
36
- */
37
- export function scoreMatch(fieldTokens, keywords) {
38
- const fieldJoined = fieldTokens.join("");
39
- let bestScore = 0;
40
- // Try each keyword variant, keep the highest score
41
- for (const keyword of keywords) {
42
- const kwTokens = tokenizeFieldName(keyword);
43
- const kwJoined = kwTokens.join("");
44
- // Exact match: joined tokens are identical
45
- if (fieldJoined === kwJoined)
46
- return 1.0;
47
- // All keyword tokens present in field tokens with high coverage
48
- if (kwTokens.length > 0 &&
49
- kwTokens.every((kt) => fieldTokens.includes(kt))) {
50
- const coverage = kwTokens.length / fieldTokens.length;
51
- const score = coverage > 0.5 ? 0.9 : 0.65;
52
- bestScore = Math.max(bestScore, score);
53
- }
54
- // Field ends with keyword tokens
55
- if (kwTokens.length > 0 && kwTokens.length <= fieldTokens.length) {
56
- const tail = fieldTokens.slice(-kwTokens.length);
57
- if (tail.every((t, i) => t === kwTokens[i])) {
58
- bestScore = Math.max(bestScore, 0.8);
59
- }
60
- }
61
- // Substring match: keyword joined appears in field joined
62
- if (kwJoined.length >= 3 && fieldJoined.includes(kwJoined)) {
63
- bestScore = Math.max(bestScore, 0.7);
64
- }
65
- }
66
- return bestScore;
67
- }
68
- /**
69
- * Find the best field mapping for a given field name and schema.
70
- * Returns the highest-scoring match above its threshold, or undefined.
71
- */
72
- export function findBestMapping(fieldName, schema, mappings = ALL_FIELD_MAPPINGS) {
73
- const schemaAny = schema;
74
- const schemaType = typeof schema.type === "string" ? schema.type : undefined;
75
- // Priority: format:uuid always maps to string.uuid
76
- if (schemaType === "string" && schema.format === "uuid") {
77
- return {
78
- mapping: {
79
- keywords: ["uuid"],
80
- fakerMethod: "string.uuid",
81
- schemaType: "string",
82
- minScore: 0.5,
83
- },
84
- score: 1.0,
85
- };
86
- }
87
- // Skip if schema already has pattern, enum, faker, or $ref constraint
88
- // Also skip string mappings when minLength/maxLength is set — name-based
89
- // mappings (e.g. lorem.word for "label") don't honor JSON Schema length
90
- // constraints, so they'd produce out-of-range strings ~20% of the time.
91
- // Mirrors the numeric constraint skip just below.
92
- if (schemaAny.pattern ||
93
- schemaAny.enum ||
94
- schemaAny.faker ||
95
- schemaAny.$ref ||
96
- (schemaType === "string" &&
97
- (schema.minLength !== undefined || schema.maxLength !== undefined))) {
98
- return undefined;
99
- }
100
- // Skip numeric faker mapping when schema already constrains the range
101
- const hasNumericConstraints = schema.minimum !== undefined ||
102
- schema.maximum !== undefined ||
103
- schema.exclusiveMinimum !== undefined ||
104
- schema.exclusiveMaximum !== undefined;
105
- const tokens = tokenizeFieldName(fieldName);
106
- let best;
107
- for (const mapping of mappings) {
108
- // Skip numeric faker mappings when schema has explicit constraints
109
- if (hasNumericConstraints &&
110
- (mapping.schemaType === "number" || mapping.schemaType === "integer")) {
111
- continue;
112
- }
113
- // Skip faker mappings for object/array schemas — they generate primitive values
114
- if (schemaType === "object" || schemaType === "array") {
115
- continue;
116
- }
117
- // Check schema type constraint
118
- if (mapping.schemaType && schemaType && mapping.schemaType !== schemaType) {
119
- const isNumeric = (mapping.schemaType === "number" && schemaType === "integer") ||
120
- (mapping.schemaType === "integer" && schemaType === "number");
121
- if (!isNumeric)
122
- continue;
123
- }
124
- const score = scoreMatch(tokens, mapping.keywords);
125
- if (score >= mapping.minScore && (!best || score > best.score)) {
126
- best = { mapping, score };
127
- }
128
- }
129
- // ID suffix detection: fields ending in Id/_id with string type → UUID
130
- // Only if no better match was found or the existing match is weak
131
- if (schemaType === "string") {
132
- const lastToken = tokens[tokens.length - 1];
133
- if (lastToken === "id" && tokens.length > 1) {
134
- const idScore = 0.8;
135
- if (!best || best.score < idScore) {
136
- best = {
137
- mapping: {
138
- keywords: ["id"],
139
- fakerMethod: "string.uuid",
140
- schemaType: "string",
141
- minScore: 0.5,
142
- },
143
- score: idScore,
144
- };
145
- }
146
- }
147
- }
148
- return best;
149
- }
@@ -1,35 +0,0 @@
1
- import { base, en, Faker } from "@faker-js/faker";
2
- import { generate, } 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
- */
7
- export function createFakerInstance(seed) {
8
- const faker = new Faker({ locale: [en, base] });
9
- if (seed !== undefined) {
10
- faker.seed(seed);
11
- }
12
- return faker;
13
- }
14
- /**
15
- * Generate data from a JSON schema using json-schema-faker 0.6.0 async API.
16
- * Stateless — each call is self-contained with its own faker instance and options.
17
- */
18
- export async function generateWithJsf(schema, seed) {
19
- // When no seed is specified, generate a random seed to ensure different
20
- // results on each call. JSF 0.6.0 treats seed=undefined as deterministic.
21
- const effectiveSeed = seed ?? Math.floor(Math.random() * 2147483647);
22
- return generate(
23
- // JSONSchema7.items allows arrays but JsonSchema.items does not — structural
24
- // mismatch requires routing through `unknown`.
25
- schema, {
26
- seed: effectiveSeed,
27
- optionalsProbability: 1.0,
28
- alwaysFakeOptionals: true,
29
- useDefaultValue: true,
30
- ignoreMissingRefs: true,
31
- failOnInvalidTypes: false,
32
- failOnInvalidFormat: false,
33
- extensions: { faker: createFakerInstance(seed) },
34
- });
35
- }
package/dist/overrides.js DELETED
@@ -1,131 +0,0 @@
1
- import { DEFAULT_ARRAY_COUNT } from "./constants.js";
2
- const DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
3
- /**
4
- * Determine number of items to generate for array schema
5
- * Prefers explicit count, then schema minItems/maxItems, with sane defaults
6
- * @param schema - Array schema with optional minItems/maxItems
7
- * @param explicitCount - Explicit count override from plugin options
8
- * @returns Number of array items to generate
9
- */
10
- export function determineArrayCount(schema, explicitCount, random = Math.random) {
11
- if (explicitCount !== undefined) {
12
- // Handle negative or invalid counts
13
- if (explicitCount < 0) {
14
- return 0;
15
- }
16
- return explicitCount;
17
- }
18
- if (schema.minItems !== undefined && schema.maxItems !== undefined) {
19
- const min = schema.minItems;
20
- const max = Math.max(min, schema.maxItems);
21
- return Math.floor(random() * (max - min + 1)) + min;
22
- }
23
- if (schema.minItems !== undefined) {
24
- return Math.max(schema.minItems, DEFAULT_ARRAY_COUNT);
25
- }
26
- if (schema.maxItems !== undefined) {
27
- return Math.min(schema.maxItems, DEFAULT_ARRAY_COUNT);
28
- }
29
- return DEFAULT_ARRAY_COUNT;
30
- }
31
- /**
32
- * Apply overrides to generated data with support for templates
33
- * Supports nested paths (dot notation), templates with {{params.id}}, and state access
34
- * @param data - Generated data to apply overrides to
35
- * @param overrides - Override values (can use templates)
36
- * @param params - Route parameters for template expansion
37
- * @param state - Plugin state for template expansion
38
- * @param query - Query parameters for template expansion
39
- * @returns Data with overrides applied
40
- */
41
- export function applyOverrides(data, overrides, params, state, query) {
42
- if (!overrides)
43
- return data;
44
- if (typeof data !== "object" || data === null)
45
- return data;
46
- const result = structuredClone(data);
47
- for (const [key, value] of Object.entries(overrides)) {
48
- if (DANGEROUS_KEYS.has(key))
49
- continue;
50
- // Handle nested paths like "data.id" or "pagination.page"
51
- if (key.includes(".")) {
52
- setNestedProperty(result, key, value, { params, state, query });
53
- }
54
- else {
55
- // Handle flat keys and nested objects
56
- if (typeof value === "object" &&
57
- value !== null &&
58
- !Array.isArray(value)) {
59
- const nested = value;
60
- // Recursively apply nested overrides
61
- if (result[key] && typeof result[key] === "object") {
62
- result[key] = applyOverrides(result[key], nested, params, state, query);
63
- }
64
- else {
65
- result[key] = applyOverrides({}, nested, params, state, query);
66
- }
67
- }
68
- else if (typeof value === "string" && value.includes("{{")) {
69
- // Template processing
70
- result[key] = processTemplate(value, { params, state, query });
71
- }
72
- else {
73
- result[key] = value;
74
- }
75
- }
76
- }
77
- return result;
78
- }
79
- function setNestedProperty(obj, path, value, context) {
80
- const parts = path.split(".");
81
- let current = obj;
82
- // Navigate to the parent of the target property
83
- for (let i = 0; i < parts.length - 1; i++) {
84
- const part = parts[i];
85
- if (DANGEROUS_KEYS.has(part))
86
- return;
87
- if (!(part in current) ||
88
- typeof current[part] !== "object" ||
89
- current[part] === null) {
90
- current[part] = {};
91
- }
92
- current = current[part];
93
- }
94
- // Set the final property
95
- const finalKey = parts[parts.length - 1];
96
- if (DANGEROUS_KEYS.has(finalKey))
97
- return;
98
- if (typeof value === "string" && value.includes("{{")) {
99
- current[finalKey] = processTemplate(value, context);
100
- }
101
- else {
102
- current[finalKey] = value;
103
- }
104
- }
105
- function resolveTemplatePath(context, expression) {
106
- const parts = expression.trim().split(".");
107
- let result = context;
108
- for (const part of parts) {
109
- if (result && typeof result === "object") {
110
- result = result[part];
111
- }
112
- else {
113
- return undefined;
114
- }
115
- }
116
- return result;
117
- }
118
- function processTemplate(template, context) {
119
- // Check if the template is just a single template expression
120
- const singleTemplateMatch = template.match(/^\{\{\s*([^}]+)\s*\}\}$/);
121
- if (singleTemplateMatch) {
122
- // For single templates, return the actual value without string conversion
123
- const result = resolveTemplatePath(context, singleTemplateMatch[1]);
124
- return result !== undefined ? result : template;
125
- }
126
- // For templates mixed with other text, do string replacement
127
- return template.replace(/\{\{\s*([^}]+)\s*\}\}/g, (match, expression) => {
128
- const result = resolveTemplatePath(context, expression);
129
- return result !== undefined ? String(result) : match;
130
- });
131
- }
@@ -1,89 +0,0 @@
1
- import { findBestMapping } from "./field-name-matcher.js";
2
- import { isJSONSchema7, validateFakerMethod } from "./validation.js";
3
- export function enhanceSchemaWithSmartMapping(schema) {
4
- if (!schema || typeof schema !== "object") {
5
- return schema;
6
- }
7
- const enhanced = { ...schema };
8
- // Handle object properties
9
- if (enhanced.properties) {
10
- enhanced.properties = { ...enhanced.properties };
11
- for (const [fieldName, fieldSchema] of Object.entries(enhanced.properties)) {
12
- if (isJSONSchema7(fieldSchema)) {
13
- enhanced.properties[fieldName] = enhanceFieldSchema(fieldName, fieldSchema);
14
- }
15
- }
16
- }
17
- // Recurse into composition keywords
18
- for (const keyword of ["allOf", "anyOf", "oneOf"]) {
19
- const branches = enhanced[keyword];
20
- if (Array.isArray(branches)) {
21
- enhanced[keyword] = branches.map((branch) => isJSONSchema7(branch) ? enhanceSchemaWithSmartMapping(branch) : branch);
22
- }
23
- }
24
- // Recurse into array items
25
- if (enhanced.items) {
26
- if (Array.isArray(enhanced.items)) {
27
- enhanced.items = enhanced.items.map((item) => isJSONSchema7(item) ? enhanceSchemaWithSmartMapping(item) : item);
28
- }
29
- else if (isJSONSchema7(enhanced.items)) {
30
- enhanced.items = enhanceSchemaWithSmartMapping(enhanced.items);
31
- }
32
- }
33
- // Recurse into additionalProperties
34
- if (enhanced.additionalProperties &&
35
- typeof enhanced.additionalProperties === "object" &&
36
- !Array.isArray(enhanced.additionalProperties)) {
37
- enhanced.additionalProperties = enhanceSchemaWithSmartMapping(enhanced.additionalProperties);
38
- }
39
- return enhanced;
40
- }
41
- function enhanceFieldSchema(fieldName, fieldSchema) {
42
- const enhanced = { ...fieldSchema };
43
- // If already has faker extension, validate it and don't override.
44
- // User-supplied faker values are always strings; the object form is only
45
- // produced internally by this function when fakerArgs are present.
46
- if (enhanced.faker) {
47
- if (typeof enhanced.faker === "string") {
48
- validateFakerMethod(enhanced.faker);
49
- }
50
- return enhanced;
51
- }
52
- // Recursively enhance nested schemas first
53
- const hasComposition = enhanced.allOf || enhanced.anyOf || enhanced.oneOf;
54
- if (enhanced.properties || hasComposition || enhanced.items) {
55
- const recursed = enhanceSchemaWithSmartMapping(enhanced);
56
- Object.assign(enhanced, recursed);
57
- }
58
- // Don't apply field-level faker mapping to composition schemas — the branches define their own types
59
- if (hasComposition) {
60
- return enhanced;
61
- }
62
- // Don't apply smart mapping when const or enum is defined — these have fixed values
63
- if (enhanced.const !== undefined || enhanced.enum) {
64
- return enhanced;
65
- }
66
- // Apply smart field name mapping via the scoring matcher
67
- const match = findBestMapping(fieldName, enhanced);
68
- if (match) {
69
- const { fakerMethod, format, trueProbability, fakerArgs } = match.mapping;
70
- // Use the JSF object form when fakerArgs are present so the options object
71
- // is forwarded to the faker method (e.g. number.int({ min, max })).
72
- // JSF calls Q(...J) where J is the value, so we must wrap fakerArgs in an
73
- // array: { "number.int": [{ min, max }] } → faker.number.int({ min, max }).
74
- // Fall back to the plain string form when there are no args.
75
- if (fakerArgs) {
76
- enhanced.faker = { [fakerMethod]: [fakerArgs] };
77
- }
78
- else {
79
- enhanced.faker = fakerMethod;
80
- }
81
- if (format) {
82
- enhanced.format = format;
83
- }
84
- if (trueProbability !== undefined) {
85
- enhanced.schmockTrueProbability = trueProbability;
86
- }
87
- }
88
- return enhanced;
89
- }
@@ -1,57 +0,0 @@
1
- import type { JSONSchema7 } from "json-schema";
2
- interface FakerSchema extends JSONSchema7 {
3
- faker?: string;
4
- }
5
- export declare const schemas: {
6
- simple: {
7
- string: () => JSONSchema7;
8
- number: () => JSONSchema7;
9
- object: (properties?: Record<string, JSONSchema7>) => JSONSchema7;
10
- array: (items: JSONSchema7, constraints?: {
11
- minItems?: number;
12
- maxItems?: number;
13
- }) => JSONSchema7;
14
- };
15
- withFaker: (type: JSONSchema7["type"], fakerMethod: string) => FakerSchema;
16
- nested: {
17
- deep: (depth: number, leafSchema?: JSONSchema7) => JSONSchema7;
18
- wide: (width: number, propertySchema?: JSONSchema7) => JSONSchema7;
19
- };
20
- complex: {
21
- user: () => JSONSchema7;
22
- apiResponse: () => JSONSchema7;
23
- };
24
- };
25
- export declare const validators: {
26
- isFieldMapped: (fieldName: string, fieldType?: JSONSchema7["type"]) => Promise<boolean>;
27
- uniquenessRatio: (samples: any[]) => number;
28
- allMatch: (samples: any[], validator: (sample: any) => boolean) => boolean;
29
- appearsToBeFromCategory: (samples: string[], category: "email" | "name" | "phone" | "address" | "uuid" | "date") => boolean;
30
- };
31
- export declare const performance: {
32
- measure: <T>(fn: () => T | Promise<T>) => Promise<{
33
- result: T;
34
- duration: number;
35
- }>;
36
- measureMemory: (fn: () => void) => number;
37
- benchmark: (_name: string, fn: () => any, iterations?: number) => Promise<{
38
- mean: number;
39
- min: number;
40
- max: number;
41
- }>;
42
- };
43
- export declare const generate: {
44
- samples: <T>(schema: JSONSchema7, count?: number, options?: any) => Promise<T[]>;
45
- withSeed: (schema: JSONSchema7, _seed?: number) => Promise<any>;
46
- };
47
- export declare const stats: {
48
- distribution: (samples: any[]) => Map<any, number>;
49
- entropy: (samples: any[]) => number;
50
- };
51
- export declare const schemaTests: {
52
- expectValid: (schema: JSONSchema7) => Promise<void>;
53
- expectInvalid: (schema: any, errorMessage?: string | RegExp) => Promise<void>;
54
- expectSchemaError: (schema: any, path: string, issue?: string) => Promise<void>;
55
- };
56
- export {};
57
- //# sourceMappingURL=test-utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../src/test-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C,UAAU,WAAY,SAAQ,WAAW;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,eAAO,MAAM,OAAO;;sBAEJ,WAAW;sBAIX,WAAW;8BAIF,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAQ,WAAW;uBAM1D,WAAW,gBACJ;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,KACrD,WAAW;;sBAOE,WAAW,CAAC,MAAM,CAAC,eAAe,MAAM,KAAG,WAAW;;sBAO7D,MAAM,eACD,WAAW,KACtB,WAAW;sBAWL,MAAM,mBACG,WAAW,KAC1B,WAAW;;;oBASJ,WAAW;2BAYJ,WAAW;;CAkB/B,CAAC;AAGF,eAAO,MAAM,UAAU;+BAGR,MAAM,cACN,WAAW,CAAC,MAAM,CAAC,KAC7B,OAAO,CAAC,OAAO,CAAC;+BAyCQ,GAAG,EAAE,KAAG,MAAM;wBAMrB,GAAG,EAAE,aAAa,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,KAAG,OAAO;uCAM7D,MAAM,EAAE,YACP,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,KACjE,OAAO;CAgDX,CAAC;AAGF,eAAO,MAAM,WAAW;cACN,CAAC,MACX,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KACvB,OAAO,CAAC;QAAE,MAAM,EAAE,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;wBAOvB,MAAM,IAAI,KAAG,MAAM;uBAW9B,MAAM,MACT,MAAM,GAAG,0BAEZ,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAgBvD,CAAC;AAGF,eAAO,MAAM,QAAQ;cACH,CAAC,UACP,WAAW,4BAET,GAAG,KACZ,OAAO,CAAC,CAAC,EAAE,CAAC;uBAQU,WAAW,UAAU,MAAM,KAAG,OAAO,CAAC,GAAG,CAAC;CAKpE,CAAC;AAGF,eAAO,MAAM,KAAK;4BACQ,GAAG,EAAE,KAAG,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC;uBAS7B,GAAG,EAAE,KAAG,MAAM;CAclC,CAAC;AAGF,eAAO,MAAM,WAAW;0BACM,WAAW,KAAG,OAAO,CAAC,IAAI,CAAC;4BAK7C,GAAG,iBACI,MAAM,GAAG,MAAM,KAC7B,OAAO,CAAC,IAAI,CAAC;gCAWN,GAAG,QACL,MAAM,UACJ,MAAM,KACb,OAAO,CAAC,IAAI,CAAC;CAejB,CAAC"}