@agentica/core 0.36.2 → 0.36.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/lib/index.mjs +156 -157
- package/lib/index.mjs.map +1 -1
- package/lib/orchestrate/call.js +2 -3
- package/lib/orchestrate/call.js.map +1 -1
- package/lib/utils/JsonUtil.d.ts +3 -0
- package/lib/utils/JsonUtil.js +201 -4
- package/lib/utils/JsonUtil.js.map +1 -1
- package/lib/utils/stringifyValidateFailure.spec.js +41 -41
- package/lib/utils/stringifyValidateFailure.spec.js.map +1 -1
- package/package.json +2 -2
- package/src/orchestrate/call.ts +2 -3
- package/src/utils/JsonUtil.ts +255 -4
- package/src/utils/stringifyValidateFailure.spec.ts +41 -41
- package/lib/utils/JsonUtil.spec.d.ts +0 -1
- package/lib/utils/JsonUtil.spec.js +0 -151
- package/lib/utils/JsonUtil.spec.js.map +0 -1
- package/lib/utils/stringifyValidateFailure.d.ts +0 -2
- package/lib/utils/stringifyValidateFailure.js +0 -201
- package/lib/utils/stringifyValidateFailure.js.map +0 -1
- package/src/utils/JsonUtil.spec.ts +0 -190
- package/src/utils/stringifyValidateFailure.ts +0 -251
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.stringifyValidateFailure = stringifyValidateFailure;
|
|
4
|
-
const Escaper_1 = require("typia/lib/utils/Escaper");
|
|
5
|
-
function stringifyValidateFailure(failure) {
|
|
6
|
-
return stringify({
|
|
7
|
-
value: failure.data,
|
|
8
|
-
errors: failure.errors,
|
|
9
|
-
path: "$input",
|
|
10
|
-
tab: 0,
|
|
11
|
-
inArray: false,
|
|
12
|
-
inToJson: false,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
function stringify(props) {
|
|
16
|
-
var _a;
|
|
17
|
-
const { value, errors, path, tab, inArray, inToJson } = props;
|
|
18
|
-
const indent = " ".repeat(tab);
|
|
19
|
-
const errorComment = getErrorComment(path, errors);
|
|
20
|
-
// Handle undefined in arrays
|
|
21
|
-
if (inArray && value === undefined) {
|
|
22
|
-
return `${indent}undefined${errorComment}`;
|
|
23
|
-
}
|
|
24
|
-
// Array
|
|
25
|
-
if (Array.isArray(value)) {
|
|
26
|
-
if (value.length === 0) {
|
|
27
|
-
return `${indent}[]${errorComment}`;
|
|
28
|
-
}
|
|
29
|
-
const lines = [];
|
|
30
|
-
lines.push(`${indent}[${errorComment}`);
|
|
31
|
-
value.forEach((item, index) => {
|
|
32
|
-
const itemPath = `${path}[${index}]`;
|
|
33
|
-
let itemStr = stringify({
|
|
34
|
-
value: item,
|
|
35
|
-
errors,
|
|
36
|
-
path: itemPath,
|
|
37
|
-
tab: tab + 1,
|
|
38
|
-
inArray: true,
|
|
39
|
-
inToJson: false,
|
|
40
|
-
});
|
|
41
|
-
// Add comma before the error comment if not the last element
|
|
42
|
-
if (index < value.length - 1) {
|
|
43
|
-
const itemLines = itemStr.split("\n");
|
|
44
|
-
const lastLine = itemLines[itemLines.length - 1];
|
|
45
|
-
const commentIndex = lastLine.indexOf(" //");
|
|
46
|
-
if (commentIndex !== -1) {
|
|
47
|
-
itemLines[itemLines.length - 1]
|
|
48
|
-
= `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
itemLines[itemLines.length - 1] += ",";
|
|
52
|
-
}
|
|
53
|
-
itemStr = itemLines.join("\n");
|
|
54
|
-
}
|
|
55
|
-
lines.push(itemStr);
|
|
56
|
-
});
|
|
57
|
-
lines.push(`${indent}]`);
|
|
58
|
-
return lines.join("\n");
|
|
59
|
-
}
|
|
60
|
-
// Object
|
|
61
|
-
if (typeof value === "object" && value !== null) {
|
|
62
|
-
// Check for toJSON method
|
|
63
|
-
if (!inToJson && typeof value.toJSON === "function") {
|
|
64
|
-
const jsonValue = value.toJSON();
|
|
65
|
-
return stringify({
|
|
66
|
-
value: jsonValue,
|
|
67
|
-
errors,
|
|
68
|
-
path,
|
|
69
|
-
tab,
|
|
70
|
-
inArray,
|
|
71
|
-
inToJson: true,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
// Get existing entries (filter out undefined values from actual data)
|
|
75
|
-
const existingEntries = Object.entries(value).filter(([_, val]) => val !== undefined);
|
|
76
|
-
// Find missing properties that have validation errors
|
|
77
|
-
const missingKeys = getMissingProperties(path, value, errors);
|
|
78
|
-
// Combine existing and missing properties
|
|
79
|
-
const allKeys = [
|
|
80
|
-
...existingEntries.map(([key]) => key),
|
|
81
|
-
...missingKeys,
|
|
82
|
-
];
|
|
83
|
-
if (allKeys.length === 0) {
|
|
84
|
-
return `${indent}{}${errorComment}`;
|
|
85
|
-
}
|
|
86
|
-
const lines = [];
|
|
87
|
-
lines.push(`${indent}{${errorComment}`);
|
|
88
|
-
allKeys.forEach((key, index, array) => {
|
|
89
|
-
const propPath = Escaper_1.Escaper.variable(key)
|
|
90
|
-
? `${path}.${key}`
|
|
91
|
-
: `${path}[${JSON.stringify(key)}]`;
|
|
92
|
-
const propIndent = " ".repeat(tab + 1);
|
|
93
|
-
// Get the value (undefined for missing properties)
|
|
94
|
-
const val = missingKeys.includes(key) ? undefined : value[key];
|
|
95
|
-
// Primitive property value (including undefined for missing properties)
|
|
96
|
-
if (val === undefined
|
|
97
|
-
|| val === null
|
|
98
|
-
|| typeof val === "boolean"
|
|
99
|
-
|| typeof val === "number"
|
|
100
|
-
|| typeof val === "string") {
|
|
101
|
-
const propErrorComment = getErrorComment(propPath, errors);
|
|
102
|
-
const valueStr = val === undefined
|
|
103
|
-
? `${propIndent}"${key}": undefined`
|
|
104
|
-
: `${propIndent}"${key}": ${JSON.stringify(val)}`;
|
|
105
|
-
const withComma = index < array.length - 1 ? `${valueStr},` : valueStr;
|
|
106
|
-
const line = withComma + propErrorComment;
|
|
107
|
-
lines.push(line);
|
|
108
|
-
}
|
|
109
|
-
// Complex property value (object or array)
|
|
110
|
-
else {
|
|
111
|
-
const keyLine = `${propIndent}"${key}": `;
|
|
112
|
-
let valStr = stringify({
|
|
113
|
-
value: val,
|
|
114
|
-
errors,
|
|
115
|
-
path: propPath,
|
|
116
|
-
tab: tab + 1,
|
|
117
|
-
inArray: false,
|
|
118
|
-
inToJson: false,
|
|
119
|
-
});
|
|
120
|
-
const valStrWithoutIndent = valStr.trimStart();
|
|
121
|
-
// Add comma before the error comment if not the last property
|
|
122
|
-
if (index < array.length - 1) {
|
|
123
|
-
const valLines = valStrWithoutIndent.split("\n");
|
|
124
|
-
const lastLine = valLines[valLines.length - 1];
|
|
125
|
-
const commentIndex = lastLine.indexOf(" //");
|
|
126
|
-
if (commentIndex !== -1) {
|
|
127
|
-
valLines[valLines.length - 1]
|
|
128
|
-
= `${lastLine.slice(0, commentIndex)},${lastLine.slice(commentIndex)}`;
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
valLines[valLines.length - 1] += ",";
|
|
132
|
-
}
|
|
133
|
-
valStr = valLines.join("\n");
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
valStr = valStrWithoutIndent;
|
|
137
|
-
}
|
|
138
|
-
const combined = keyLine + valStr;
|
|
139
|
-
lines.push(combined);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
lines.push(`${indent}}`);
|
|
143
|
-
return lines.join("\n");
|
|
144
|
-
}
|
|
145
|
-
// Primitive types (null, boolean, number, string, undefined, etc.)
|
|
146
|
-
const valStr = value === undefined
|
|
147
|
-
? "undefined"
|
|
148
|
-
: ((_a = JSON.stringify(value)) !== null && _a !== void 0 ? _a : String(value));
|
|
149
|
-
return `${indent}${valStr}${errorComment}`;
|
|
150
|
-
}
|
|
151
|
-
/** Get error comment for a given path */
|
|
152
|
-
function getErrorComment(path, errors) {
|
|
153
|
-
const pathErrors = errors.filter((e) => e.path === path);
|
|
154
|
-
if (pathErrors.length === 0) {
|
|
155
|
-
return "";
|
|
156
|
-
}
|
|
157
|
-
return ` // ❌ ${JSON.stringify(pathErrors.map(e => ({
|
|
158
|
-
path: e.path,
|
|
159
|
-
expected: e.expected,
|
|
160
|
-
description: e.description,
|
|
161
|
-
})))}`;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Find missing properties that have validation errors but don't exist in the data
|
|
165
|
-
* Returns array of property keys that should be displayed as undefined
|
|
166
|
-
*/
|
|
167
|
-
function getMissingProperties(path, value, errors) {
|
|
168
|
-
const missingKeys = new Set();
|
|
169
|
-
for (const e of errors) {
|
|
170
|
-
// Check if error.path is a direct child of current path
|
|
171
|
-
const childKey = extractDirectChildKey(path, e.path);
|
|
172
|
-
if (childKey !== null) {
|
|
173
|
-
// Check if this property actually exists in the value
|
|
174
|
-
if (!(childKey in value)) {
|
|
175
|
-
missingKeys.add(childKey);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
return Array.from(missingKeys);
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Extract direct child property key if errorPath is a direct child of parentPath
|
|
183
|
-
* Returns null if not a direct child
|
|
184
|
-
*
|
|
185
|
-
* Examples:
|
|
186
|
-
* - extractDirectChildKey("$input", "$input.email") => "email"
|
|
187
|
-
* - extractDirectChildKey("$input", "$input.user.email") => null (grandchild)
|
|
188
|
-
* - extractDirectChildKey("$input.user", "$input.user.email") => "email"
|
|
189
|
-
* - extractDirectChildKey("$input", "$input[0]") => null (array index, not object property)
|
|
190
|
-
*/
|
|
191
|
-
function extractDirectChildKey(parentPath, errorPath) {
|
|
192
|
-
if (!errorPath.startsWith(parentPath)) {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
const suffix = errorPath.slice(parentPath.length);
|
|
196
|
-
// Match ".propertyName" pattern (direct child property)
|
|
197
|
-
// Should not contain additional dots or brackets after the property name
|
|
198
|
-
const match = suffix.match(/^\.([^.[\]]+)$/);
|
|
199
|
-
return match !== null ? match[1] : null;
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=stringifyValidateFailure.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"stringifyValidateFailure.js","sourceRoot":"","sources":["../../src/utils/stringifyValidateFailure.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { JsonUtil } from "./JsonUtil";
|
|
2
|
-
|
|
3
|
-
describe("jsonUtil", () => {
|
|
4
|
-
describe("parse", () => {
|
|
5
|
-
describe("normal Operations", () => {
|
|
6
|
-
it("should parse standard valid JSON", () => {
|
|
7
|
-
const jsonString = "{\"normal\": \"json\"}";
|
|
8
|
-
const result = JsonUtil.parse(jsonString);
|
|
9
|
-
|
|
10
|
-
expect(result).toEqual({ normal: "json" });
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should handle object with '{}' prefix", () => {
|
|
14
|
-
const jsonString = "{}{\"name\": \"test\", \"value\": 42}";
|
|
15
|
-
const result = JsonUtil.parse(jsonString);
|
|
16
|
-
|
|
17
|
-
expect(result).toEqual({ name: "test", value: 42 });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("should handle array with '{}' prefix", () => {
|
|
21
|
-
const jsonString = "{}[1, 2, 3, \"test\"]";
|
|
22
|
-
const result = JsonUtil.parse(jsonString);
|
|
23
|
-
|
|
24
|
-
expect(result).toEqual([1, 2, 3, "test"]);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("should handle primitive values with '{}' prefix", () => {
|
|
28
|
-
expect(JsonUtil.parse("{}42")).toBe(42);
|
|
29
|
-
expect(JsonUtil.parse("{}\"hello\"")).toBe("hello");
|
|
30
|
-
expect(JsonUtil.parse("{}true")).toBe(true);
|
|
31
|
-
expect(JsonUtil.parse("{}null")).toBeNull();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("should remove trailing comma in object", () => {
|
|
35
|
-
const jsonString = "{\"name\": \"test\", \"value\": 42,}";
|
|
36
|
-
const result = JsonUtil.parse(jsonString);
|
|
37
|
-
|
|
38
|
-
expect(result).toEqual({ name: "test", value: 42 });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("should remove trailing comma in array", () => {
|
|
42
|
-
const jsonString = "[1, 2, 3, \"test\",]";
|
|
43
|
-
const result = JsonUtil.parse(jsonString);
|
|
44
|
-
|
|
45
|
-
expect(result).toEqual([1, 2, 3, "test"]);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("should add missing closing brace in object", () => {
|
|
49
|
-
const jsonString = "{\"name\": \"test\", \"value\": 42";
|
|
50
|
-
const result = JsonUtil.parse(jsonString);
|
|
51
|
-
|
|
52
|
-
expect(result).toEqual({ name: "test", value: 42 });
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("should add missing closing bracket in array", () => {
|
|
56
|
-
const jsonString = "[1, 2, 3, \"test\"";
|
|
57
|
-
const result = JsonUtil.parse(jsonString);
|
|
58
|
-
|
|
59
|
-
expect(result).toEqual([1, 2, 3, "test"]);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe("combined Features", () => {
|
|
64
|
-
it("should handle '{}' prefix and missing closing brace together", () => {
|
|
65
|
-
const jsonString = "{}{\"name\": \"test\", \"value\": 42";
|
|
66
|
-
const result = JsonUtil.parse(jsonString);
|
|
67
|
-
|
|
68
|
-
expect(result).toEqual({ name: "test", value: 42 });
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it("should handle '{}' prefix and missing closing bracket together", () => {
|
|
72
|
-
const jsonString = "{}[1, 2, 3, \"test\"";
|
|
73
|
-
const result = JsonUtil.parse(jsonString);
|
|
74
|
-
|
|
75
|
-
expect(result).toEqual([1, 2, 3, "test"]);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("should handle trailing comma in nested objects", () => {
|
|
79
|
-
const jsonString = "{\"user\": {\"id\": 1, \"name\": \"John\",}, \"active\": true,}";
|
|
80
|
-
const result = JsonUtil.parse(jsonString);
|
|
81
|
-
|
|
82
|
-
expect(result).toEqual({
|
|
83
|
-
user: { id: 1, name: "John" },
|
|
84
|
-
active: true,
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("should handle missing closing brace in nested objects", () => {
|
|
89
|
-
const jsonString = "{\"user\": {\"id\": 1, \"name\": \"John\"}";
|
|
90
|
-
const result = JsonUtil.parse(jsonString);
|
|
91
|
-
|
|
92
|
-
expect(result).toEqual({
|
|
93
|
-
user: { id: 1, name: "John" },
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it("should handle missing closing brace in complex nested structure", () => {
|
|
98
|
-
const jsonString = "{\"users\": [{\"id\": 1, \"name\": \"John\"}, {\"id\": 2, \"name\": \"Jane\"}], \"count\": 2";
|
|
99
|
-
const result = JsonUtil.parse(jsonString);
|
|
100
|
-
|
|
101
|
-
expect(result).toEqual({
|
|
102
|
-
users: [
|
|
103
|
-
{ id: 1, name: "John" },
|
|
104
|
-
{ id: 2, name: "Jane" },
|
|
105
|
-
],
|
|
106
|
-
count: 2,
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("should apply all correction features together", () => {
|
|
111
|
-
const jsonString = "{}{\"name\": \"test\", \"items\": [1, 2, 3,], \"user\": {\"id\": 1, \"name\": \"John\",}";
|
|
112
|
-
const result = JsonUtil.parse(jsonString);
|
|
113
|
-
|
|
114
|
-
expect(result).toEqual({
|
|
115
|
-
name: "test",
|
|
116
|
-
items: [1, 2, 3],
|
|
117
|
-
user: { id: 1, name: "John" },
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it("should handle all issues simultaneously in complex nested structure", () => {
|
|
122
|
-
const jsonString = "{}{\"data\": {\"users\": [{\"id\": 1, \"name\": \"John\",}, {\"id\": 2, \"name\": \"Jane\",}], \"meta\": {\"total\": 2, \"page\": 1,}}, \"status\": \"ok\",";
|
|
123
|
-
const result = JsonUtil.parse(jsonString);
|
|
124
|
-
|
|
125
|
-
expect(result).toEqual({
|
|
126
|
-
data: {
|
|
127
|
-
users: [
|
|
128
|
-
{ id: 1, name: "John" },
|
|
129
|
-
{ id: 2, name: "Jane" },
|
|
130
|
-
],
|
|
131
|
-
meta: { total: 2, page: 1 },
|
|
132
|
-
},
|
|
133
|
-
status: "ok",
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
describe("edge Cases", () => {
|
|
139
|
-
it("should handle empty object with '{}' prefix", () => {
|
|
140
|
-
const jsonString = "{}{}";
|
|
141
|
-
const result = JsonUtil.parse(jsonString);
|
|
142
|
-
|
|
143
|
-
expect(result).toEqual({});
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it("should handle empty array with '{}' prefix", () => {
|
|
147
|
-
const jsonString = "{}[]";
|
|
148
|
-
const result = JsonUtil.parse(jsonString);
|
|
149
|
-
|
|
150
|
-
expect(result).toEqual([]);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it("should handle nested object with '{}' prefix", () => {
|
|
154
|
-
const jsonString = "{}{\"user\": {\"id\": 1, \"name\": \"John\"}}";
|
|
155
|
-
const result = JsonUtil.parse(jsonString);
|
|
156
|
-
|
|
157
|
-
expect(result).toEqual({
|
|
158
|
-
user: { id: 1, name: "John" },
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it("should handle multiple trailing commas", () => {
|
|
163
|
-
const jsonString = "{\"items\": [1, 2, 3,,,], \"count\": 3,,,}";
|
|
164
|
-
const result = JsonUtil.parse(jsonString);
|
|
165
|
-
|
|
166
|
-
expect(result).toEqual({
|
|
167
|
-
items: [1, 2, 3],
|
|
168
|
-
count: 3,
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("should handle JSON with whitespace and formatting issues", () => {
|
|
173
|
-
const jsonString = "{} { \"name\" : \"test\" , \"value\" : 42 , } ";
|
|
174
|
-
const result = JsonUtil.parse(jsonString);
|
|
175
|
-
|
|
176
|
-
expect(result).toEqual({ name: "test", value: 42 });
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it("should throw error for completely invalid JSON", () => {
|
|
180
|
-
const invalidJson = "{invalid: json without quotes}";
|
|
181
|
-
|
|
182
|
-
expect(() => JsonUtil.parse(invalidJson)).toThrow();
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("should throw error for empty string", () => {
|
|
186
|
-
expect(() => JsonUtil.parse("")).toThrow();
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
});
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
import type { IValidation } from "typia";
|
|
2
|
-
|
|
3
|
-
import { Escaper } from "typia/lib/utils/Escaper";
|
|
4
|
-
|
|
5
|
-
export function stringifyValidateFailure(
|
|
6
|
-
failure: IValidation.IFailure,
|
|
7
|
-
): string {
|
|
8
|
-
return stringify({
|
|
9
|
-
value: failure.data,
|
|
10
|
-
errors: failure.errors,
|
|
11
|
-
path: "$input",
|
|
12
|
-
tab: 0,
|
|
13
|
-
inArray: false,
|
|
14
|
-
inToJson: false,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function stringify(props: {
|
|
19
|
-
value: unknown;
|
|
20
|
-
errors: IValidation.IError[];
|
|
21
|
-
path: string;
|
|
22
|
-
tab: number;
|
|
23
|
-
inArray: boolean;
|
|
24
|
-
inToJson: boolean;
|
|
25
|
-
}): string {
|
|
26
|
-
const { value, errors, path, tab, inArray, inToJson } = props;
|
|
27
|
-
const indent: string = " ".repeat(tab);
|
|
28
|
-
const errorComment: string = getErrorComment(path, errors);
|
|
29
|
-
|
|
30
|
-
// Handle undefined in arrays
|
|
31
|
-
if (inArray && value === undefined) {
|
|
32
|
-
return `${indent}undefined${errorComment}`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// Array
|
|
36
|
-
if (Array.isArray(value)) {
|
|
37
|
-
if (value.length === 0) {
|
|
38
|
-
return `${indent}[]${errorComment}`;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const lines: string[] = [];
|
|
42
|
-
lines.push(`${indent}[${errorComment}`);
|
|
43
|
-
|
|
44
|
-
value.forEach((item: unknown, index: number) => {
|
|
45
|
-
const itemPath: string = `${path}[${index}]`;
|
|
46
|
-
let itemStr: string = stringify({
|
|
47
|
-
value: item,
|
|
48
|
-
errors,
|
|
49
|
-
path: itemPath,
|
|
50
|
-
tab: tab + 1,
|
|
51
|
-
inArray: true,
|
|
52
|
-
inToJson: false,
|
|
53
|
-
});
|
|
54
|
-
// Add comma before the error comment if not the last element
|
|
55
|
-
if (index < value.length - 1) {
|
|
56
|
-
const itemLines: string[] = itemStr.split("\n");
|
|
57
|
-
const lastLine: string = itemLines[itemLines.length - 1]!;
|
|
58
|
-
const commentIndex: number = lastLine.indexOf(" //");
|
|
59
|
-
if (commentIndex !== -1) {
|
|
60
|
-
itemLines[itemLines.length - 1]
|
|
61
|
-
= `${lastLine.slice(0, commentIndex)
|
|
62
|
-
},${
|
|
63
|
-
lastLine.slice(commentIndex)}`;
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
itemLines[itemLines.length - 1] += ",";
|
|
67
|
-
}
|
|
68
|
-
itemStr = itemLines.join("\n");
|
|
69
|
-
}
|
|
70
|
-
lines.push(itemStr);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
lines.push(`${indent}]`);
|
|
74
|
-
return lines.join("\n");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Object
|
|
78
|
-
if (typeof value === "object" && value !== null) {
|
|
79
|
-
// Check for toJSON method
|
|
80
|
-
if (!inToJson && typeof (value as any).toJSON === "function") {
|
|
81
|
-
const jsonValue: unknown = (value as any).toJSON();
|
|
82
|
-
return stringify({
|
|
83
|
-
value: jsonValue,
|
|
84
|
-
errors,
|
|
85
|
-
path,
|
|
86
|
-
tab,
|
|
87
|
-
inArray,
|
|
88
|
-
inToJson: true,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Get existing entries (filter out undefined values from actual data)
|
|
93
|
-
const existingEntries: [string, unknown][] = Object.entries(value).filter(
|
|
94
|
-
([_, val]) => val !== undefined,
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
// Find missing properties that have validation errors
|
|
98
|
-
const missingKeys: string[] = getMissingProperties(path, value, errors);
|
|
99
|
-
|
|
100
|
-
// Combine existing and missing properties
|
|
101
|
-
const allKeys: string[] = [
|
|
102
|
-
...existingEntries.map(([key]) => key),
|
|
103
|
-
...missingKeys,
|
|
104
|
-
];
|
|
105
|
-
|
|
106
|
-
if (allKeys.length === 0) {
|
|
107
|
-
return `${indent}{}${errorComment}`;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const lines: string[] = [];
|
|
111
|
-
lines.push(`${indent}{${errorComment}`);
|
|
112
|
-
|
|
113
|
-
allKeys.forEach((key, index, array) => {
|
|
114
|
-
const propPath: string = Escaper.variable(key)
|
|
115
|
-
? `${path}.${key}`
|
|
116
|
-
: `${path}[${JSON.stringify(key)}]`;
|
|
117
|
-
const propIndent: string = " ".repeat(tab + 1);
|
|
118
|
-
|
|
119
|
-
// Get the value (undefined for missing properties)
|
|
120
|
-
const val: unknown = missingKeys.includes(key) ? undefined : (value as any)[key];
|
|
121
|
-
|
|
122
|
-
// Primitive property value (including undefined for missing properties)
|
|
123
|
-
if (
|
|
124
|
-
val === undefined
|
|
125
|
-
|| val === null
|
|
126
|
-
|| typeof val === "boolean"
|
|
127
|
-
|| typeof val === "number"
|
|
128
|
-
|| typeof val === "string"
|
|
129
|
-
) {
|
|
130
|
-
const propErrorComment: string = getErrorComment(propPath, errors);
|
|
131
|
-
const valueStr: string = val === undefined
|
|
132
|
-
? `${propIndent}"${key}": undefined`
|
|
133
|
-
: `${propIndent}"${key}": ${JSON.stringify(val)}`;
|
|
134
|
-
const withComma: string
|
|
135
|
-
= index < array.length - 1 ? `${valueStr},` : valueStr;
|
|
136
|
-
const line: string = withComma + propErrorComment;
|
|
137
|
-
lines.push(line);
|
|
138
|
-
}
|
|
139
|
-
// Complex property value (object or array)
|
|
140
|
-
else {
|
|
141
|
-
const keyLine: string = `${propIndent}"${key}": `;
|
|
142
|
-
let valStr: string = stringify({
|
|
143
|
-
value: val,
|
|
144
|
-
errors,
|
|
145
|
-
path: propPath,
|
|
146
|
-
tab: tab + 1,
|
|
147
|
-
inArray: false,
|
|
148
|
-
inToJson: false,
|
|
149
|
-
});
|
|
150
|
-
const valStrWithoutIndent: string = valStr.trimStart();
|
|
151
|
-
// Add comma before the error comment if not the last property
|
|
152
|
-
if (index < array.length - 1) {
|
|
153
|
-
const valLines: string[] = valStrWithoutIndent.split("\n");
|
|
154
|
-
const lastLine: string = valLines[valLines.length - 1]!;
|
|
155
|
-
const commentIndex: number = lastLine.indexOf(" //");
|
|
156
|
-
if (commentIndex !== -1) {
|
|
157
|
-
valLines[valLines.length - 1]
|
|
158
|
-
= `${lastLine.slice(0, commentIndex)
|
|
159
|
-
},${
|
|
160
|
-
lastLine.slice(commentIndex)}`;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
valLines[valLines.length - 1] += ",";
|
|
164
|
-
}
|
|
165
|
-
valStr = valLines.join("\n");
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
valStr = valStrWithoutIndent;
|
|
169
|
-
}
|
|
170
|
-
const combined: string = keyLine + valStr;
|
|
171
|
-
lines.push(combined);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
lines.push(`${indent}}`);
|
|
176
|
-
return lines.join("\n");
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Primitive types (null, boolean, number, string, undefined, etc.)
|
|
180
|
-
const valStr: string
|
|
181
|
-
= value === undefined
|
|
182
|
-
? "undefined"
|
|
183
|
-
: (JSON.stringify(value) ?? String(value));
|
|
184
|
-
return `${indent}${valStr}${errorComment}`;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/** Get error comment for a given path */
|
|
188
|
-
function getErrorComment(path: string, errors: IValidation.IError[]): string {
|
|
189
|
-
const pathErrors: IValidation.IError[] = errors.filter(
|
|
190
|
-
(e: IValidation.IError) => e.path === path,
|
|
191
|
-
);
|
|
192
|
-
if (pathErrors.length === 0) {
|
|
193
|
-
return "";
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return ` // ❌ ${JSON.stringify(
|
|
197
|
-
pathErrors.map(e => ({
|
|
198
|
-
path: e.path,
|
|
199
|
-
expected: e.expected,
|
|
200
|
-
description: e.description,
|
|
201
|
-
})),
|
|
202
|
-
)}`;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Find missing properties that have validation errors but don't exist in the data
|
|
207
|
-
* Returns array of property keys that should be displayed as undefined
|
|
208
|
-
*/
|
|
209
|
-
function getMissingProperties(
|
|
210
|
-
path: string,
|
|
211
|
-
value: object,
|
|
212
|
-
errors: IValidation.IError[],
|
|
213
|
-
): string[] {
|
|
214
|
-
const missingKeys: Set<string> = new Set();
|
|
215
|
-
|
|
216
|
-
for (const e of errors) {
|
|
217
|
-
// Check if error.path is a direct child of current path
|
|
218
|
-
const childKey = extractDirectChildKey(path, e.path);
|
|
219
|
-
if (childKey !== null) {
|
|
220
|
-
// Check if this property actually exists in the value
|
|
221
|
-
if (!(childKey in value)) {
|
|
222
|
-
missingKeys.add(childKey);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return Array.from(missingKeys);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Extract direct child property key if errorPath is a direct child of parentPath
|
|
232
|
-
* Returns null if not a direct child
|
|
233
|
-
*
|
|
234
|
-
* Examples:
|
|
235
|
-
* - extractDirectChildKey("$input", "$input.email") => "email"
|
|
236
|
-
* - extractDirectChildKey("$input", "$input.user.email") => null (grandchild)
|
|
237
|
-
* - extractDirectChildKey("$input.user", "$input.user.email") => "email"
|
|
238
|
-
* - extractDirectChildKey("$input", "$input[0]") => null (array index, not object property)
|
|
239
|
-
*/
|
|
240
|
-
function extractDirectChildKey(parentPath: string, errorPath: string): string | null {
|
|
241
|
-
if (!errorPath.startsWith(parentPath)) {
|
|
242
|
-
return null;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const suffix = errorPath.slice(parentPath.length);
|
|
246
|
-
|
|
247
|
-
// Match ".propertyName" pattern (direct child property)
|
|
248
|
-
// Should not contain additional dots or brackets after the property name
|
|
249
|
-
const match = suffix.match(/^\.([^.[\]]+)$/);
|
|
250
|
-
return match !== null ? match[1]! : null;
|
|
251
|
-
}
|