@devua-lab/error-serialization 1.0.2 → 1.0.5

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/dist/index.cjs CHANGED
@@ -27,7 +27,7 @@ __export(index_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(index_exports);
29
29
 
30
- // src/contants.ts
30
+ // src/constants.ts
31
31
  var ErrorPriority = {
32
32
  /**
33
33
  * Fallback priority for unhandled errors
@@ -144,20 +144,48 @@ var AxiosErrorPlugin = class extends ErrorPlugin {
144
144
  return (0, import_axios.isAxiosError)(error);
145
145
  }
146
146
  /**
147
- * Maps HTTP response details to the global schema
147
+ * Maps HTTP response details to the global schema.
148
+ * Flattens any nested validation error structures into a single-level object.
148
149
  */
149
150
  serialize(error) {
150
151
  const responseData = error.response?.data;
151
152
  const backendMessage = responseData?.message || responseData?.error?.message;
152
153
  const backendCode = responseData?.code || responseData?.errorCode;
154
+ const rawValidation = responseData?.validationErrors || responseData?.errors;
155
+ const validation = rawValidation ? this.flatten(rawValidation) : void 0;
153
156
  const finalMessage = backendMessage || error.message || "Network Error";
154
157
  const finalCodes = backendCode ? Array.isArray(backendCode) ? backendCode : [String(backendCode)] : [`HTTP_${error.response?.status || 0}`];
155
158
  return this.createResponse(error, {
156
159
  global: finalMessage,
157
160
  code: finalCodes,
158
- status: error.response?.status || 0
161
+ status: error.response?.status || 0,
162
+ validation
159
163
  });
160
164
  }
165
+ /**
166
+ * Recursively flattens a nested object into a flat record with dot-separated keys.
167
+ * Traverses nested objects but keeps arrays as leaf values.
168
+ * If an array has exactly one element, it returns the element itself.
169
+ */
170
+ flatten(obj, prefix = "") {
171
+ return Object.keys(obj).reduce((acc, k) => {
172
+ const path = prefix ? `${prefix}.${k}` : k;
173
+ const value = obj[k];
174
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
175
+ Object.assign(
176
+ acc,
177
+ this.flatten(value, path)
178
+ );
179
+ } else {
180
+ if (Array.isArray(value) && value.length === 1) {
181
+ acc[path] = value[0];
182
+ } else {
183
+ acc[path] = value;
184
+ }
185
+ }
186
+ return acc;
187
+ }, {});
188
+ }
161
189
  };
162
190
 
163
191
  // src/plugins/StandardErrorPlugin.ts
package/dist/index.d.cts CHANGED
@@ -154,6 +154,11 @@ declare class ErrorSerializer {
154
154
 
155
155
  /**
156
156
  * Plugin for handling Axios errors and extracting server-side data.
157
+ * Supports extraction of messages, error codes, and recursive validation errors
158
+ * which are automatically flattened into a dot-notation structure.
159
+ *
160
+ * Special behavior: If a validation field contains an array with a single value,
161
+ * it will be extracted as a direct value instead of an array.
157
162
  */
158
163
  declare class AxiosErrorPlugin extends ErrorPlugin<AxiosError> {
159
164
  /**
@@ -166,9 +171,16 @@ declare class AxiosErrorPlugin extends ErrorPlugin<AxiosError> {
166
171
  */
167
172
  match(error: unknown): error is AxiosError;
168
173
  /**
169
- * Maps HTTP response details to the global schema
174
+ * Maps HTTP response details to the global schema.
175
+ * Flattens any nested validation error structures into a single-level object.
170
176
  */
171
177
  serialize(error: AxiosError): AppErrorResponse;
178
+ /**
179
+ * Recursively flattens a nested object into a flat record with dot-separated keys.
180
+ * Traverses nested objects but keeps arrays as leaf values.
181
+ * If an array has exactly one element, it returns the element itself.
182
+ */
183
+ private flatten;
172
184
  }
173
185
 
174
186
  /**
package/dist/index.d.ts CHANGED
@@ -154,6 +154,11 @@ declare class ErrorSerializer {
154
154
 
155
155
  /**
156
156
  * Plugin for handling Axios errors and extracting server-side data.
157
+ * Supports extraction of messages, error codes, and recursive validation errors
158
+ * which are automatically flattened into a dot-notation structure.
159
+ *
160
+ * Special behavior: If a validation field contains an array with a single value,
161
+ * it will be extracted as a direct value instead of an array.
157
162
  */
158
163
  declare class AxiosErrorPlugin extends ErrorPlugin<AxiosError> {
159
164
  /**
@@ -166,9 +171,16 @@ declare class AxiosErrorPlugin extends ErrorPlugin<AxiosError> {
166
171
  */
167
172
  match(error: unknown): error is AxiosError;
168
173
  /**
169
- * Maps HTTP response details to the global schema
174
+ * Maps HTTP response details to the global schema.
175
+ * Flattens any nested validation error structures into a single-level object.
170
176
  */
171
177
  serialize(error: AxiosError): AppErrorResponse;
178
+ /**
179
+ * Recursively flattens a nested object into a flat record with dot-separated keys.
180
+ * Traverses nested objects but keeps arrays as leaf values.
181
+ * If an array has exactly one element, it returns the element itself.
182
+ */
183
+ private flatten;
172
184
  }
173
185
 
174
186
  /**
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // src/contants.ts
1
+ // src/constants.ts
2
2
  var ErrorPriority = {
3
3
  /**
4
4
  * Fallback priority for unhandled errors
@@ -115,20 +115,48 @@ var AxiosErrorPlugin = class extends ErrorPlugin {
115
115
  return isAxiosError(error);
116
116
  }
117
117
  /**
118
- * Maps HTTP response details to the global schema
118
+ * Maps HTTP response details to the global schema.
119
+ * Flattens any nested validation error structures into a single-level object.
119
120
  */
120
121
  serialize(error) {
121
122
  const responseData = error.response?.data;
122
123
  const backendMessage = responseData?.message || responseData?.error?.message;
123
124
  const backendCode = responseData?.code || responseData?.errorCode;
125
+ const rawValidation = responseData?.validationErrors || responseData?.errors;
126
+ const validation = rawValidation ? this.flatten(rawValidation) : void 0;
124
127
  const finalMessage = backendMessage || error.message || "Network Error";
125
128
  const finalCodes = backendCode ? Array.isArray(backendCode) ? backendCode : [String(backendCode)] : [`HTTP_${error.response?.status || 0}`];
126
129
  return this.createResponse(error, {
127
130
  global: finalMessage,
128
131
  code: finalCodes,
129
- status: error.response?.status || 0
132
+ status: error.response?.status || 0,
133
+ validation
130
134
  });
131
135
  }
136
+ /**
137
+ * Recursively flattens a nested object into a flat record with dot-separated keys.
138
+ * Traverses nested objects but keeps arrays as leaf values.
139
+ * If an array has exactly one element, it returns the element itself.
140
+ */
141
+ flatten(obj, prefix = "") {
142
+ return Object.keys(obj).reduce((acc, k) => {
143
+ const path = prefix ? `${prefix}.${k}` : k;
144
+ const value = obj[k];
145
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
146
+ Object.assign(
147
+ acc,
148
+ this.flatten(value, path)
149
+ );
150
+ } else {
151
+ if (Array.isArray(value) && value.length === 1) {
152
+ acc[path] = value[0];
153
+ } else {
154
+ acc[path] = value;
155
+ }
156
+ }
157
+ return acc;
158
+ }, {});
159
+ }
132
160
  };
133
161
 
134
162
  // src/plugins/StandardErrorPlugin.ts
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
- "name": "@devua-lab/error-serialization",
3
- "version": "1.0.2",
4
- "type": "module",
5
- "main": "./dist/index.cjs",
6
- "module": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "import": {
11
- "types": "./dist/index.d.ts",
12
- "default": "./dist/index.js"
13
- },
14
- "require": {
15
- "types": "./dist/index.d.cts",
16
- "default": "./dist/index.cjs"
17
- }
18
- }
19
- },
20
- "scripts": {
21
- "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
- "dev": "tsup src/index.ts --format cjs,esm --watch --dts",
23
- "format": "biome format --write .",
24
- "lint": "biome lint .",
25
- "check": "biome check --write .",
26
- "ci": "biome ci .",
27
- "test": "vitest",
28
- "test:run": "vitest run",
29
- "test:cov": "vitest run --coverage"
30
- },
31
- "devDependencies": {
32
- "@biomejs/biome": "2.3.14",
33
- "@types/node": "^25.2.2",
34
- "axios": "^1.13.5",
35
- "tsup": "^8.5.1",
36
- "typescript": "^5.9.3",
37
- "vite": "^7.3.1",
38
- "vitest": "^4.0.18",
39
- "zod": "^4.3.6"
40
- },
41
- "peerDependencies": {
42
- "axios": ">=1.0.0",
43
- "zod": ">=3.0.0"
44
- },
45
- "peerDependenciesMeta": {
46
- "axios": {
47
- "optional": true
48
- },
49
- "zod": {
50
- "optional": true
51
- }
52
- },
53
- "files": [
54
- "dist",
55
- "README.md"
56
- ]
2
+ "name": "@devua-lab/error-serialization",
3
+ "version": "1.0.5",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ }
19
+ },
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
+ "dev": "tsup src/index.ts --format cjs,esm --watch --dts",
23
+ "format": "biome format --write .",
24
+ "lint": "biome lint .",
25
+ "check": "biome check --write .",
26
+ "ci": "biome ci .",
27
+ "test": "vitest",
28
+ "test:run": "vitest run",
29
+ "test:cov": "vitest run --coverage"
30
+ },
31
+ "devDependencies": {
32
+ "@biomejs/biome": "2.3.14",
33
+ "@types/node": "^25.2.2",
34
+ "axios": "^1.13.5",
35
+ "tsup": "^8.5.1",
36
+ "typescript": "^5.9.3",
37
+ "vite": "^7.3.1",
38
+ "vitest": "^4.0.18",
39
+ "zod": "^4.3.6"
40
+ },
41
+ "peerDependencies": {
42
+ "axios": ">=1.0.0",
43
+ "zod": ">=3.0.0"
44
+ },
45
+ "peerDependenciesMeta": {
46
+ "axios": {
47
+ "optional": true
48
+ },
49
+ "zod": {
50
+ "optional": true
51
+ }
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "README.md"
56
+ ]
57
57
  }