@futdevpro/fsm-dynamo 1.11.31 → 1.11.33

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 (42) hide show
  1. package/.github/workflows/main.yml +20 -21
  2. package/build/_collections/utils/json-error-helper.util.d.ts +8 -0
  3. package/build/_collections/utils/json-error-helper.util.d.ts.map +1 -1
  4. package/build/_collections/utils/json-error-helper.util.js +118 -39
  5. package/build/_collections/utils/json-error-helper.util.js.map +1 -1
  6. package/build/_collections/utils/object.util.d.ts +6 -0
  7. package/build/_collections/utils/object.util.d.ts.map +1 -1
  8. package/build/_collections/utils/object.util.js +37 -1
  9. package/build/_collections/utils/object.util.js.map +1 -1
  10. package/build/_collections/utils/object.util.spec.js +393 -0
  11. package/build/_collections/utils/object.util.spec.js.map +1 -1
  12. package/build/_collections/utils/string.util.d.ts +130 -0
  13. package/build/_collections/utils/string.util.d.ts.map +1 -1
  14. package/build/_collections/utils/string.util.js +354 -0
  15. package/build/_collections/utils/string.util.js.map +1 -1
  16. package/build/_collections/utils/string.util.spec.js +694 -0
  17. package/build/_collections/utils/string.util.spec.js.map +1 -1
  18. package/build/_modules/crypto/_collections/crypto-2-non-stable.util.d.ts.map +1 -1
  19. package/build/_modules/crypto/_collections/crypto-2-non-stable.util.js +3 -2
  20. package/build/_modules/crypto/_collections/crypto-2-non-stable.util.js.map +1 -1
  21. package/build/_modules/crypto/_collections/crypto.util.d.ts.map +1 -1
  22. package/build/_modules/crypto/_collections/crypto.util.js +22 -9
  23. package/build/_modules/crypto/_collections/crypto.util.js.map +1 -1
  24. package/build/_modules/crypto/_collections/crypto.util.spec.js +3 -3
  25. package/build/_modules/crypto/_collections/crypto.util.spec.js.map +1 -1
  26. package/build/_modules/crypto/index.js +7 -6
  27. package/build/_modules/crypto/index.js.map +1 -1
  28. package/build/_modules/open-ai/index.js +7 -6
  29. package/build/_modules/open-ai/index.js.map +1 -1
  30. package/futdevpro-fsm-dynamo-01.11.33.tgz +0 -0
  31. package/package.json +1 -1
  32. package/src/_collections/utils/json-error-helper.util.ts +135 -45
  33. package/src/_collections/utils/object.util.spec.ts +503 -0
  34. package/src/_collections/utils/object.util.ts +40 -10
  35. package/src/_collections/utils/string.util.spec.ts +773 -1
  36. package/src/_collections/utils/string.util.ts +426 -0
  37. package/src/_modules/crypto/_collections/crypto-2-non-stable.util.ts +3 -2
  38. package/src/_modules/crypto/_collections/crypto.util.spec.ts +3 -3
  39. package/src/_modules/crypto/_collections/crypto.util.ts +20 -8
  40. package/src/_modules/crypto/index.ts +2 -2
  41. package/src/_modules/open-ai/index.ts +2 -2
  42. package/futdevpro-fsm-dynamo-01.11.31.tgz +0 -0
@@ -39,13 +39,30 @@ export class DyFM_JsonErrorHelper {
39
39
  contextLines: number = 5
40
40
  ): JsonErrorLineInfo | null {
41
41
  try {
42
- // Extract position from error message (e.g., "at position 10" or "Unexpected end of JSON input at position 17")
42
+ // Extract position from various error message formats
43
43
  let positionMatch = errorMessage.match(/at position (\d+)/);
44
44
  if (!positionMatch) {
45
45
  // Handle "Unexpected end of JSON input at position 17" format
46
46
  positionMatch = errorMessage.match(/Unexpected end of JSON input at position (\d+)/);
47
47
  }
48
48
  if (!positionMatch) {
49
+ // Handle "Unexpected token" format which might include position
50
+ positionMatch = errorMessage.match(/position (\d+)/);
51
+ }
52
+
53
+ if (!positionMatch) {
54
+ // For "Unexpected token" errors without explicit position, try to find it from the token
55
+ const tokenMatch = errorMessage.match(/Unexpected token '(.)'|Unexpected token (.)/);
56
+ if (tokenMatch && jsonInput.includes('\n')) {
57
+ const token = tokenMatch[1] || tokenMatch[2];
58
+ if (token) {
59
+ // Find the first occurrence of this token (this is a simple heuristic)
60
+ const tokenPosition = jsonInput.indexOf(token);
61
+ if (tokenPosition !== -1) {
62
+ return this.createLineInfoFromPosition(jsonInput, tokenPosition, contextLines);
63
+ }
64
+ }
65
+ }
49
66
  return null;
50
67
  }
51
68
 
@@ -60,54 +77,74 @@ export class DyFM_JsonErrorHelper {
60
77
  return null;
61
78
  }
62
79
 
63
- // Split input into lines to find the line number
64
- const lines = jsonInput.split('\n');
65
- let currentPosition = 0;
66
- let lineNumber = 1;
67
- let characterPosition = 0;
68
-
69
- for (let i = 0; i < lines.length; i++) {
70
- const lineLength = lines[i].length;
71
- if (currentPosition + lineLength >= position) {
72
- lineNumber = i + 1;
73
- characterPosition = position - currentPosition;
74
- break;
75
- }
76
- currentPosition += lineLength + 1; // +1 for newline character
77
- }
78
-
79
- // If we didn't find the line in the loop, it's at the end
80
- if (characterPosition === 0) {
81
- lineNumber = lines.length;
82
- characterPosition = position - currentPosition;
83
- }
84
-
85
- // Ensure character position is not negative
86
- if (characterPosition < 0) {
87
- characterPosition = 0;
88
- }
89
-
90
- // Ensure line number is within bounds
91
- if (lineNumber > lines.length) {
92
- lineNumber = lines.length;
93
- }
94
-
95
- // Get surrounding context (±contextLines)
96
- const contextStart = Math.max(0, lineNumber - contextLines - 1);
97
- const contextEnd = Math.min(lines.length, lineNumber + contextLines);
98
- const contextLinesArray = lines.slice(contextStart, contextEnd);
99
-
100
- return {
101
- lineNumber,
102
- contextLines: contextLinesArray,
103
- characterPosition
104
- };
80
+ return this.createLineInfoFromPosition(jsonInput, position, contextLines);
105
81
  } catch (error) {
106
82
  // If we can't parse the error, return null to fall back to simple preview
107
83
  return null;
108
84
  }
109
85
  }
110
86
 
87
+ /**
88
+ * Helper method to create line info from a character position
89
+ */
90
+ private static createLineInfoFromPosition(
91
+ jsonInput: string,
92
+ position: number,
93
+ contextLines: number
94
+ ): JsonErrorLineInfo {
95
+ // Handle undefined or invalid input
96
+ if (!jsonInput || typeof jsonInput !== 'string') {
97
+ return {
98
+ lineNumber: 1,
99
+ contextLines: ['(invalid or empty input)'],
100
+ characterPosition: 0
101
+ };
102
+ }
103
+
104
+ // Split input into lines to find the line number
105
+ const lines = jsonInput.split('\n');
106
+ let currentPosition = 0;
107
+ let lineNumber = 1;
108
+ let characterPosition = 0;
109
+
110
+ for (let i = 0; i < lines.length; i++) {
111
+ const lineLength = lines[i].length;
112
+ if (currentPosition + lineLength >= position) {
113
+ lineNumber = i + 1;
114
+ characterPosition = position - currentPosition;
115
+ break;
116
+ }
117
+ currentPosition += lineLength + 1; // +1 for newline character
118
+ }
119
+
120
+ // If we didn't find the line in the loop, it's at the end
121
+ if (characterPosition === 0 && lineNumber === 1) {
122
+ lineNumber = lines.length;
123
+ characterPosition = position - currentPosition;
124
+ }
125
+
126
+ // Ensure character position is not negative
127
+ if (characterPosition < 0) {
128
+ characterPosition = 0;
129
+ }
130
+
131
+ // Ensure line number is within bounds
132
+ if (lineNumber > lines.length) {
133
+ lineNumber = lines.length;
134
+ }
135
+
136
+ // Get surrounding context (±contextLines)
137
+ const contextStart = Math.max(0, lineNumber - contextLines - 1);
138
+ const contextEnd = Math.min(lines.length, lineNumber + contextLines);
139
+ const contextLinesArray = lines.slice(contextStart, contextEnd);
140
+
141
+ return {
142
+ lineNumber,
143
+ contextLines: contextLinesArray,
144
+ characterPosition
145
+ };
146
+ }
147
+
111
148
  /**
112
149
  * Formats JSON error information for logging
113
150
  * Creates a formatted string showing the error location and context
@@ -152,13 +189,39 @@ export class DyFM_JsonErrorHelper {
152
189
  static parseJsonWithEnhancedError(
153
190
  jsonString: string,
154
191
  reviver?: (key: string, value: any) => any,
155
- contextLines: number = 5
192
+ contextLines: number = 2
156
193
  ): any {
194
+ // Prevent infinite recursion and handle invalid input
195
+ if (!jsonString || typeof jsonString !== 'string') {
196
+ throw new Error(`Invalid JSON input: expected string, got ${typeof jsonString}`);
197
+ }
198
+
157
199
  try {
158
200
  return JSON.parse(jsonString, reviver);
159
201
  } catch (error) {
160
202
  const errorMessage = error instanceof Error ? error.message : String(error);
161
- const lineInfo = this.extractLineInfoFromJsonError(errorMessage, jsonString, contextLines);
203
+ const originalJsonString = jsonString;
204
+
205
+ // First try to extract line info from the original JSON
206
+ let lineInfo = this.extractLineInfoFromJsonError(errorMessage, originalJsonString, contextLines);
207
+
208
+ // If no line info was found and the JSON is on a single line, try formatting it
209
+ if (!lineInfo && !originalJsonString.includes('\n')) {
210
+ try {
211
+ const formattedJson = this.formatJsonForBetterErrors(originalJsonString);
212
+
213
+ // Try parsing the formatted JSON to get a new error with position info
214
+ try {
215
+ JSON.parse(formattedJson, reviver);
216
+ } catch (formattedError) {
217
+ const formattedErrorMessage = formattedError instanceof Error ? formattedError.message : String(formattedError);
218
+ lineInfo = this.extractLineInfoFromJsonError(formattedErrorMessage, formattedJson, contextLines);
219
+ }
220
+ } catch (formatError) {
221
+ // If formatting fails, skip enhanced error reporting
222
+ lineInfo = null;
223
+ }
224
+ }
162
225
 
163
226
  if (lineInfo) {
164
227
  const formattedError = this.formatJsonErrorForLogging(lineInfo, errorMessage);
@@ -169,4 +232,31 @@ export class DyFM_JsonErrorHelper {
169
232
  }
170
233
  }
171
234
  }
235
+
236
+ /**
237
+ * Formats single-line JSON with line breaks for better error reporting
238
+ */
239
+ private static formatJsonForBetterErrors(jsonString: string): string {
240
+ if (!jsonString || typeof jsonString !== 'string') {
241
+ return jsonString || '';
242
+ }
243
+
244
+ return jsonString
245
+ .replace(/,/g, ',\n ')
246
+ .replace(/{/g, '{\n ')
247
+ .replace(/}/g, '\n}')
248
+ .replace(/\[/g, '[\n ')
249
+ .replace(/\]/g, '\n]')
250
+ .replace(/\n\s*\n/g, '\n') // Remove double newlines
251
+ .replace(/^\s+|\s+$/gm, function(match, offset, string) {
252
+ // Trim but preserve indentation structure
253
+ if (!string || typeof string !== 'string') {
254
+ return match;
255
+ }
256
+ const lines = string.slice(0, offset).split('\n');
257
+ const depth = (string.slice(0, offset).match(/{|\[/g) || []).length -
258
+ (string.slice(0, offset).match(/}|\]/g) || []).length;
259
+ return ' '.repeat(Math.max(0, depth));
260
+ });
261
+ }
172
262
  }