@ontemper/edi 1.1.4 → 1.1.6
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/README.md +23 -17
- package/dist/index.d.ts +1 -4
- package/dist/index.js +15 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,26 +142,32 @@ const acknowledgment = await edi.acknowledgeX12({
|
|
|
142
142
|
|
|
143
143
|
The EDI client throws two distinct error classes. The distinction matters for file routing:
|
|
144
144
|
a `TemperEdiClientError` is a verdict on the input document (bad file — don't retry) or a
|
|
145
|
-
persistent
|
|
146
|
-
|
|
147
|
-
transiently unavailable (network failure, timeout, 5xx, rate limit). It says nothing about
|
|
148
|
-
the document, so keep the file and retry (`error.retryable === true`).
|
|
145
|
+
persistent authentication failure, while an `EdiInfrastructureError` is retryable and does
|
|
146
|
+
not indicate that the document is invalid (`error.retryable === true`).
|
|
149
147
|
|
|
150
148
|
```typescript
|
|
151
149
|
import { isEdiInfrastructureError, isTemperEdiClientError } from '@ontemper/edi';
|
|
152
150
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
async function processFile(rawX12: string) {
|
|
152
|
+
try {
|
|
153
|
+
return await edi.fromX12({ input: rawX12 });
|
|
154
|
+
} catch (error) {
|
|
155
|
+
if (isEdiInfrastructureError(error)) {
|
|
156
|
+
// Keep the file and rethrow so the caller can retry.
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
if (isTemperEdiClientError(error)) {
|
|
160
|
+
if (error.code === 'edi_unauthorized_error') {
|
|
161
|
+
// Surface authentication failures instead of quarantining the file.
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
// A verdict on the document (see codes below) — handle it terminally (e.g.
|
|
165
|
+
// quarantine the file) and STOP. Do not rethrow into retry paths.
|
|
166
|
+
console.error('EDI Error:', error.code, error.message);
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
throw error; // unrecognized — surface to the caller
|
|
163
170
|
}
|
|
164
|
-
throw error;
|
|
165
171
|
}
|
|
166
172
|
```
|
|
167
173
|
|
|
@@ -178,11 +184,11 @@ try {
|
|
|
178
184
|
| `edi_unauthorized_error` | Unauthorized access to EDI service |
|
|
179
185
|
| `edi_unknown_error` | Legacy — no longer produced |
|
|
180
186
|
|
|
181
|
-
`EdiInfrastructureError` (
|
|
187
|
+
`EdiInfrastructureError` (`retryable: true`):
|
|
182
188
|
|
|
183
189
|
| Code | Description |
|
|
184
190
|
| ---------------------- | ------------------------------------------------------------------------------------ |
|
|
185
|
-
| `infrastructure_error` |
|
|
191
|
+
| `infrastructure_error` | Retryable failure unrelated to the input document |
|
|
186
192
|
|
|
187
193
|
## Type Definitions
|
|
188
194
|
|
package/dist/index.d.ts
CHANGED
|
@@ -16,10 +16,7 @@ export declare class TemperEdiClientError extends UnnboundError<TemperEdiClientE
|
|
|
16
16
|
}
|
|
17
17
|
export declare const isTemperEdiClientError: (error: unknown) => error is TemperEdiClientError;
|
|
18
18
|
/**
|
|
19
|
-
* A failure
|
|
20
|
-
* on the EDI payload. Deliberately NOT a TemperEdiClientError and NOT an `edi_*` code:
|
|
21
|
-
* workflows route `edi_*` errors as bad files, while these are transient platform
|
|
22
|
-
* faults the workflow should retry (T-3235).
|
|
19
|
+
* A retryable failure that does not indicate an invalid EDI document.
|
|
23
20
|
*/
|
|
24
21
|
export declare class EdiInfrastructureError extends UnnboundError<'infrastructure_error'> {
|
|
25
22
|
readonly retryable = true;
|
package/dist/index.js
CHANGED
|
@@ -66,10 +66,7 @@ exports.TemperEdiClientError = TemperEdiClientError;
|
|
|
66
66
|
const isTemperEdiClientError = (error) => error instanceof TemperEdiClientError;
|
|
67
67
|
exports.isTemperEdiClientError = isTemperEdiClientError;
|
|
68
68
|
/**
|
|
69
|
-
* A failure
|
|
70
|
-
* on the EDI payload. Deliberately NOT a TemperEdiClientError and NOT an `edi_*` code:
|
|
71
|
-
* workflows route `edi_*` errors as bad files, while these are transient platform
|
|
72
|
-
* faults the workflow should retry (T-3235).
|
|
69
|
+
* A retryable failure that does not indicate an invalid EDI document.
|
|
73
70
|
*/
|
|
74
71
|
class EdiInfrastructureError extends UnnboundError {
|
|
75
72
|
retryable = true;
|
|
@@ -83,10 +80,6 @@ const isEdiInfrastructureError = (error) => error instanceof EdiInfrastructureEr
|
|
|
83
80
|
exports.isEdiInfrastructureError = isEdiInfrastructureError;
|
|
84
81
|
const buildEdiPayload = (edi) => ({ type: 'edi', edi });
|
|
85
82
|
const buildEdiX12Payload = (operation, x12) => buildEdiPayload({ operation, type: 'x12', x12 });
|
|
86
|
-
// One traced instance for the whole process, created once at module load. Never trace
|
|
87
|
-
// the global axios export: in-place wrapping there accumulated a span layer per
|
|
88
|
-
// TemperEdiClient construction (stack overflow after enough polls) and leaked EDI
|
|
89
|
-
// payload capture into unrelated code sharing global axios (T-3235).
|
|
90
83
|
const ediAxios = (0, unnbound_logger_sdk_1.traceAxios)(axios_1.default.create(), { getPayload: internal_1.internal });
|
|
91
84
|
class TemperEdiClient {
|
|
92
85
|
X12;
|
|
@@ -112,22 +105,12 @@ class TemperEdiClient {
|
|
|
112
105
|
if (error instanceof EdiInfrastructureError)
|
|
113
106
|
throw error;
|
|
114
107
|
if ((0, axios_1.isAxiosError)(error)) {
|
|
115
|
-
|
|
108
|
+
const status = error.response?.status ?? error.status;
|
|
109
|
+
if (status === 401 || status === 403)
|
|
116
110
|
throw new TemperEdiClientError({
|
|
117
|
-
message: 'Unauthorized access to EDI service. Reach out to support.',
|
|
111
|
+
message: 'Unauthorized access to EDI service (credentials missing, expired, or invalid). Reach out to support.',
|
|
118
112
|
code: 'edi_unauthorized_error',
|
|
119
113
|
});
|
|
120
|
-
// Transport failures (no response: ECONNREFUSED/timeout/DNS), 5xx, and
|
|
121
|
-
// rate-limit/timeout statuses are transient service faults, not verdicts on
|
|
122
|
-
// the document — a brief EDI-service outage must never quarantine valid
|
|
123
|
-
// files in /error (T-3235).
|
|
124
|
-
const status = error.response?.status;
|
|
125
|
-
if (status === undefined || status >= 500 || status === 408 || status === 429) {
|
|
126
|
-
throw new EdiInfrastructureError({
|
|
127
|
-
message: `EDI service unreachable or transiently failing (${status ?? error.code ?? 'no response'}): ${error.message}`,
|
|
128
|
-
cause: error,
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
114
|
// Gateway normalises EdiFabric's camelCase to PascalCase before forwarding
|
|
132
115
|
const responseData = error.response?.data;
|
|
133
116
|
const details = typeof responseData === 'object' &&
|
|
@@ -136,18 +119,18 @@ class TemperEdiClient {
|
|
|
136
119
|
Array.isArray(responseData.Details)
|
|
137
120
|
? responseData.Details
|
|
138
121
|
: undefined;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
: error
|
|
144
|
-
|
|
122
|
+
if (status === 400 && details?.length) {
|
|
123
|
+
throw new TemperEdiClientError({
|
|
124
|
+
message: `EDI validation failed: ${details.join('; ')}`,
|
|
125
|
+
code,
|
|
126
|
+
cause: error,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
throw new EdiInfrastructureError({
|
|
130
|
+
message: `EDI service request failed (${status ?? error.code ?? 'no response'}): ${error.message}`,
|
|
131
|
+
cause: error,
|
|
132
|
+
});
|
|
145
133
|
}
|
|
146
|
-
// Not an axios error → the failure never reached the EDI HTTP exchange. It was
|
|
147
|
-
// raised by the SDK's own plumbing (span/logging instrumentation, request
|
|
148
|
-
// serialization), so it must not be reported as a verdict on the file: workflows
|
|
149
|
-
// route `edi_*` errors to /error, and that misrouted valid partner files when the
|
|
150
|
-
// instrumentation layer crashed (T-3235).
|
|
151
134
|
throw new EdiInfrastructureError({
|
|
152
135
|
message: `EDI client infrastructure failure (not caused by the input document): ${error instanceof Error ? error.message : String(error)}`,
|
|
153
136
|
cause: error,
|