universal-parcel-scraper 0.35.0-main.384 → 0.36.0
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/data/catalog.json +2 -2
- package/dist/browser/scraper.js +2 -2
- package/dist/carriers/tipsa/adapter.js +19 -12
- package/dist/carriers/tipsa/carrier.json +2 -2
- package/dist/carriers/tipsa/parser.d.ts +8 -5
- package/dist/carriers/tipsa/parser.js +13 -17
- package/dist/core/transport/trawl.d.ts +2 -0
- package/dist/core/transport/trawl.js +1 -0
- package/dist/data/catalog.json +2 -2
- package/dist/generated/catalog.d.ts +2 -2
- package/dist/generated/catalog.js +2 -2
- package/dist/providers/seventeentrack/adapter.d.ts +2 -2
- package/dist/providers/seventeentrack/adapter.js +37 -8
- package/dist/providers/universal.d.ts +1 -1
- package/dist/providers/universal.js +1 -1
- package/dist/server/openapi.json +1 -1
- package/package.json +1 -1
package/data/catalog.json
CHANGED
|
@@ -2439,13 +2439,13 @@
|
|
|
2439
2439
|
"recognitionRank": 24
|
|
2440
2440
|
},
|
|
2441
2441
|
"canaryUrl": "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php",
|
|
2442
|
-
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/
|
|
2442
|
+
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}",
|
|
2443
2443
|
"linkRules": [
|
|
2444
2444
|
{
|
|
2445
2445
|
"domains": [
|
|
2446
2446
|
"tip-sa.com"
|
|
2447
2447
|
],
|
|
2448
|
-
"path": "^/cliente/datos(?:_prestashop)?\\.php$",
|
|
2448
|
+
"path": "^/cliente/datos(?:_prestashop|_env)?\\.php$",
|
|
2449
2449
|
"params": [
|
|
2450
2450
|
"id"
|
|
2451
2451
|
]
|
package/dist/browser/scraper.js
CHANGED
|
@@ -1972,10 +1972,10 @@ var ce = {
|
|
|
1972
1972
|
recognitionRank: 24
|
|
1973
1973
|
},
|
|
1974
1974
|
canaryUrl: "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php",
|
|
1975
|
-
trackingUrlTemplate: "https://www.tip-sa.com/cliente/
|
|
1975
|
+
trackingUrlTemplate: "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}",
|
|
1976
1976
|
linkRules: [{
|
|
1977
1977
|
domains: ["tip-sa.com"],
|
|
1978
|
-
path: "^/cliente/datos(?:_prestashop)?\\.php$",
|
|
1978
|
+
path: "^/cliente/datos(?:_prestashop|_env)?\\.php$",
|
|
1979
1979
|
params: ["id"]
|
|
1980
1980
|
}],
|
|
1981
1981
|
detectionRules: [{
|
|
@@ -3,9 +3,10 @@ import { BudgetExceededError, NotFoundError, SchemaError } from '../../core/erro
|
|
|
3
3
|
import { runSteps } from '../../core/runner/index.js';
|
|
4
4
|
import { NOOP_RECORDER } from '../../core/telemetry/index.js';
|
|
5
5
|
import { decodeText, fetchBounded } from '../../core/transport/index.js';
|
|
6
|
-
import { normalizeTipsaNumber, parseTipsaDetail, tipsaDetailUrl } from './parser.js';
|
|
7
|
-
// The shop link (www.tip-sa.com/cliente/
|
|
8
|
-
|
|
6
|
+
import { normalizeTipsaNumber, parseTipsaDetail, tipsaDetailUrl, tipsaLookupNotFound } from './parser.js';
|
|
7
|
+
// The shop link (www.tip-sa.com/cliente/datos_env.php) redirects here. Unlike
|
|
8
|
+
// datos_prestashop.php, it does not ask for the destination postcode.
|
|
9
|
+
const LOOKUP = 'https://aplicaciones.tip-sa.com/cliente/datos_env.php';
|
|
9
10
|
const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36';
|
|
10
11
|
const LOOKUP_MAX_BYTES = 20_000;
|
|
11
12
|
const DETAIL_MAX_BYTES = 1_000_000;
|
|
@@ -21,12 +22,12 @@ export class TipsaTracker {
|
|
|
21
22
|
return runSteps({ carrier: 'tipsa', budgetMs, signal: context.signal,
|
|
22
23
|
recorder: this.options.recorder ?? NOOP_RECORDER }, [{ id: 'direct', run: async ({ signal, remainingMs }) => {
|
|
23
24
|
const deadline = performance.now() + remainingMs;
|
|
24
|
-
const read = async (url, maxBytes
|
|
25
|
+
const read = async (url, maxBytes) => {
|
|
25
26
|
signal.throwIfAborted();
|
|
26
27
|
const left = deadline - performance.now();
|
|
27
28
|
if (left <= 0)
|
|
28
29
|
throw new BudgetExceededError('TIPSA', budgetMs);
|
|
29
|
-
const
|
|
30
|
+
const fetched = await fetchBounded(url, { signal, headers: {
|
|
30
31
|
'User-Agent': USER_AGENT,
|
|
31
32
|
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
|
32
33
|
'Accept-Language': 'es-ES,es;q=0.9,en;q=0.8',
|
|
@@ -34,14 +35,20 @@ export class TipsaTracker {
|
|
|
34
35
|
allowHttpStatuses: REDIRECTS, fetcher: this.options.fetcher });
|
|
35
36
|
if (performance.now() >= deadline)
|
|
36
37
|
throw new BudgetExceededError('TIPSA', budgetMs);
|
|
37
|
-
|
|
38
|
-
throw new SchemaError('TIPSA', 'TIPSA tracking page moved');
|
|
39
|
-
return decodeText(bytes, encoding);
|
|
38
|
+
return fetched;
|
|
40
39
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
// A known reference redirects to its shipment page; an unknown one
|
|
41
|
+
// answers a page that refreshes to TIPSA's not-located page.
|
|
42
|
+
const lookup = await read(`${LOOKUP}?id=${number}`, LOOKUP_MAX_BYTES);
|
|
43
|
+
if (!REDIRECTS.includes(lookup.response.status)) {
|
|
44
|
+
if (tipsaLookupNotFound(decodeText(lookup.bytes, 'utf-8')))
|
|
45
|
+
throw new NotFoundError('TIPSA');
|
|
46
|
+
throw new SchemaError('TIPSA', 'TIPSA lookup did not name a shipment page');
|
|
47
|
+
}
|
|
48
|
+
const detail = await read(tipsaDetailUrl(lookup.response.headers.get('location') ?? ''), DETAIL_MAX_BYTES);
|
|
49
|
+
if (REDIRECTS.includes(detail.response.status))
|
|
50
|
+
throw new SchemaError('TIPSA', 'TIPSA tracking page moved');
|
|
51
|
+
return parseTipsaDetail(decodeText(detail.bytes, 'iso-8859-1'), number);
|
|
45
52
|
} }]);
|
|
46
53
|
}
|
|
47
54
|
}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"location"
|
|
30
30
|
],
|
|
31
31
|
"portal": {
|
|
32
|
-
"url": "https://www.tip-sa.com/cliente/
|
|
32
|
+
"url": "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}",
|
|
33
33
|
"canaryUrl": "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php",
|
|
34
34
|
"shows": [
|
|
35
35
|
"status",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"domains": [
|
|
71
71
|
"tip-sa.com"
|
|
72
72
|
],
|
|
73
|
-
"path": "^/cliente/datos(?:_prestashop)?\\.php$",
|
|
73
|
+
"path": "^/cliente/datos(?:_prestashop|_env)?\\.php$",
|
|
74
74
|
"params": [
|
|
75
75
|
"id"
|
|
76
76
|
]
|
|
@@ -3,12 +3,15 @@ export declare const TIPSA_ZONE = "Europe/Madrid";
|
|
|
3
3
|
/** The 22-digit reference: charge agency, origin agency and waybill, six, six and ten digits. */
|
|
4
4
|
export declare function normalizeTipsaNumber(raw: string): string;
|
|
5
5
|
/**
|
|
6
|
-
* The shipment page
|
|
7
|
-
*
|
|
8
|
-
* parameters). Only TIPSA's own detail page with a service id and a
|
|
9
|
-
* `dd/MM/yy` date is followed.
|
|
6
|
+
* The shipment page a lookup redirects to. Only TIPSA's own detail page with
|
|
7
|
+
* a service id and a `dd/MM/yy` date is followed.
|
|
10
8
|
*/
|
|
11
|
-
export declare function tipsaDetailUrl(
|
|
9
|
+
export declare function tipsaDetailUrl(location: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether a lookup that did not redirect is TIPSA's answer for a reference it
|
|
12
|
+
* cannot locate: a page that refreshes to its "envío no localizado" page.
|
|
13
|
+
*/
|
|
14
|
+
export declare function tipsaLookupNotFound(html: string): boolean;
|
|
12
15
|
/**
|
|
13
16
|
* The history table of TIPSA's shipment page. Its clock is Madrid's for every
|
|
14
17
|
* agency, Portuguese ones included. Recipient, sender, reference and proof of
|
|
@@ -19,36 +19,32 @@ export function normalizeTipsaNumber(raw) {
|
|
|
19
19
|
throw new InvalidInputError(PROVIDER, 'TIPSA requires the full 22-digit reference');
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* The shipment page
|
|
23
|
-
*
|
|
24
|
-
* parameters). Only TIPSA's own detail page with a service id and a
|
|
25
|
-
* `dd/MM/yy` date is followed.
|
|
22
|
+
* The shipment page a lookup redirects to. Only TIPSA's own detail page with
|
|
23
|
+
* a service id and a `dd/MM/yy` date is followed.
|
|
26
24
|
*/
|
|
27
|
-
export function tipsaDetailUrl(
|
|
28
|
-
const target = /<meta\s+http-equiv=["']refresh["']\s+content=["']\s*0\s*;\s*URL=([^"'\s]{1,512})["']/i.exec(html)?.[1];
|
|
29
|
-
if (!target)
|
|
30
|
-
throw new SchemaError(PROVIDER, 'TIPSA lookup did not name a shipment page');
|
|
25
|
+
export function tipsaDetailUrl(location) {
|
|
31
26
|
let url;
|
|
32
27
|
try {
|
|
33
|
-
url = new URL(
|
|
28
|
+
url = new URL(location);
|
|
34
29
|
}
|
|
35
30
|
catch {
|
|
36
31
|
throw new SchemaError(PROVIDER, 'TIPSA shipment page address is invalid');
|
|
37
32
|
}
|
|
38
33
|
const keys = [...url.searchParams.keys()];
|
|
39
34
|
if (url.origin !== DETAIL_ORIGIN || url.pathname.toLowerCase() !== DETAIL_PATH || url.username || url.password || url.hash
|
|
40
|
-
|| keys.length !== 2 || !keys.includes('servicio') || !keys.includes('fecha')
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
const service = url.searchParams.get('servicio');
|
|
44
|
-
const date = url.searchParams.get('fecha');
|
|
45
|
-
if (!service && !date)
|
|
46
|
-
return null;
|
|
47
|
-
if (!SERVICE.test(service) || !/^\d{2}\/\d{2}\/\d{2}$/.test(date)) {
|
|
35
|
+
|| keys.length !== 2 || !keys.includes('servicio') || !keys.includes('fecha')
|
|
36
|
+
|| !SERVICE.test(url.searchParams.get('servicio')) || !/^\d{2}\/\d{2}\/\d{2}$/.test(url.searchParams.get('fecha'))) {
|
|
48
37
|
throw new SchemaError(PROVIDER, 'TIPSA shipment page address changed');
|
|
49
38
|
}
|
|
50
39
|
return url.toString();
|
|
51
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Whether a lookup that did not redirect is TIPSA's answer for a reference it
|
|
43
|
+
* cannot locate: a page that refreshes to its "envío no localizado" page.
|
|
44
|
+
*/
|
|
45
|
+
export function tipsaLookupNotFound(html) {
|
|
46
|
+
return /<meta\s+http-equiv=["']refresh["']\s+content=["']\s*\d+\s*;\s*URL=error_env\.html["']/i.test(html);
|
|
47
|
+
}
|
|
52
48
|
/**
|
|
53
49
|
* The history table of TIPSA's shipment page. Its clock is Madrid's for every
|
|
54
50
|
* agency, Portuguese ones included. Recipient, sender, reference and proof of
|
|
@@ -30,6 +30,8 @@ export interface TrawlCapturedResponse {
|
|
|
30
30
|
truncated: boolean;
|
|
31
31
|
base64Encoded: boolean;
|
|
32
32
|
error: string | null;
|
|
33
|
+
/** 17TRACK's matching browser request included the supplied delivery postcode. */
|
|
34
|
+
postcodeSubmitted?: boolean;
|
|
33
35
|
}
|
|
34
36
|
export interface TrawlScrapeResponse {
|
|
35
37
|
url: string;
|
|
@@ -70,6 +70,7 @@ function captured(value) {
|
|
|
70
70
|
truncated: entry.truncated === true,
|
|
71
71
|
base64Encoded: entry.base64Encoded === true,
|
|
72
72
|
error: typeof entry.error === 'string' ? entry.error : entry.error ? 'error' : null,
|
|
73
|
+
...(entry.postcodeSubmitted === true ? { postcodeSubmitted: true } : {}),
|
|
73
74
|
}));
|
|
74
75
|
}
|
|
75
76
|
/**
|
package/dist/data/catalog.json
CHANGED
|
@@ -2439,13 +2439,13 @@
|
|
|
2439
2439
|
"recognitionRank": 24
|
|
2440
2440
|
},
|
|
2441
2441
|
"canaryUrl": "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php",
|
|
2442
|
-
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/
|
|
2442
|
+
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}",
|
|
2443
2443
|
"linkRules": [
|
|
2444
2444
|
{
|
|
2445
2445
|
"domains": [
|
|
2446
2446
|
"tip-sa.com"
|
|
2447
2447
|
],
|
|
2448
|
-
"path": "^/cliente/datos(?:_prestashop)?\\.php$",
|
|
2448
|
+
"path": "^/cliente/datos(?:_prestashop|_env)?\\.php$",
|
|
2449
2449
|
"params": [
|
|
2450
2450
|
"id"
|
|
2451
2451
|
]
|
|
@@ -1620,10 +1620,10 @@ export declare const CARRIER_CATALOG: {
|
|
|
1620
1620
|
readonly recognitionRank: 24;
|
|
1621
1621
|
};
|
|
1622
1622
|
readonly canaryUrl: "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php";
|
|
1623
|
-
readonly trackingUrlTemplate: "https://www.tip-sa.com/cliente/
|
|
1623
|
+
readonly trackingUrlTemplate: "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}";
|
|
1624
1624
|
readonly linkRules: readonly [{
|
|
1625
1625
|
readonly domains: readonly ["tip-sa.com"];
|
|
1626
|
-
readonly path: "^/cliente/datos(?:_prestashop)?\\.php$";
|
|
1626
|
+
readonly path: "^/cliente/datos(?:_prestashop|_env)?\\.php$";
|
|
1627
1627
|
readonly params: readonly ["id"];
|
|
1628
1628
|
}];
|
|
1629
1629
|
readonly detectionRules: readonly [{
|
|
@@ -2440,13 +2440,13 @@ export const CARRIER_CATALOG = {
|
|
|
2440
2440
|
"recognitionRank": 24
|
|
2441
2441
|
},
|
|
2442
2442
|
"canaryUrl": "https://dinapaqweb.tipsa-dinapaq.com/dinapaqweb/detalle_envio.php",
|
|
2443
|
-
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/
|
|
2443
|
+
"trackingUrlTemplate": "https://www.tip-sa.com/cliente/datos_env.php?id={trackingNumber}",
|
|
2444
2444
|
"linkRules": [
|
|
2445
2445
|
{
|
|
2446
2446
|
"domains": [
|
|
2447
2447
|
"tip-sa.com"
|
|
2448
2448
|
],
|
|
2449
|
-
"path": "^/cliente/datos(?:_prestashop)?\\.php$",
|
|
2449
|
+
"path": "^/cliente/datos(?:_prestashop|_env)?\\.php$",
|
|
2450
2450
|
"params": [
|
|
2451
2451
|
"id"
|
|
2452
2452
|
]
|
|
@@ -25,7 +25,7 @@ export declare class SeventeenTrackVerificationError extends ChallengeError {
|
|
|
25
25
|
}
|
|
26
26
|
/** Structured replies without usable history; polling may still produce a later success. */
|
|
27
27
|
export declare function isSeventeenTrackLookupError(error: unknown): error is SeventeenTrackLookupError | SeventeenTrackNoHistoryError | SeventeenTrackVerificationError;
|
|
28
|
-
export declare function parse17TrackResponse(payload: unknown, trackingNumber: string): CarrierResult;
|
|
28
|
+
export declare function parse17TrackResponse(payload: unknown, trackingNumber: string, postcode?: string | null): CarrierResult;
|
|
29
29
|
export interface SeventeenTrackOptions {
|
|
30
30
|
trawl?: TrawlClient | null;
|
|
31
31
|
fetcher?: typeof fetch;
|
|
@@ -35,6 +35,6 @@ export interface SeventeenTrackOptions {
|
|
|
35
35
|
export declare class SeventeenTrackTracker {
|
|
36
36
|
readonly options: SeventeenTrackOptions;
|
|
37
37
|
constructor(options?: SeventeenTrackOptions);
|
|
38
|
-
fetch(trackingNumber: string, budgetMs?: number, signal?: AbortSignal): Promise<CarrierResult>;
|
|
38
|
+
fetch(trackingNumber: string, budgetMs?: number, signal?: AbortSignal, postcode?: string | null): Promise<CarrierResult>;
|
|
39
39
|
}
|
|
40
40
|
export declare const adapter: AdapterFactory;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* verification wall from an outage.
|
|
10
10
|
*/
|
|
11
11
|
import { DateTime } from 'luxon';
|
|
12
|
-
import { ChallengeError, NoHistoryError, NotFoundError, SchemaError, TransportError } from '../../core/errors/index.js';
|
|
12
|
+
import { ChallengeError, InputRequiredError, InvalidInputError, NoHistoryError, NotFoundError, SchemaError, TransportError } from '../../core/errors/index.js';
|
|
13
13
|
import { runSteps } from '../../core/runner/index.js';
|
|
14
14
|
import { isRecord } from '../../core/types.js';
|
|
15
15
|
import { universalCarrierHints } from '../shared/hints.js';
|
|
@@ -75,7 +75,13 @@ function facilityWall(raw) {
|
|
|
75
75
|
return clock && typeof clock.date === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(clock.date)
|
|
76
76
|
&& typeof clock.time === 'string' && /^\d{2}:\d{2}:\d{2}$/.test(clock.time) ? `${clock.date}T${clock.time}` : null;
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
function requestsPostcode(shipment) {
|
|
79
|
+
if (Array.isArray(shipment.params_v2))
|
|
80
|
+
return shipment.params_v2.some(p => isRecord(p) && p.key === 'postal_code');
|
|
81
|
+
return (isRecord(shipment.param) && shipment.param.type === 'PostalCode')
|
|
82
|
+
|| (Array.isArray(shipment.params) && shipment.params.some(p => isRecord(p) && p.type === 'PostalCode'));
|
|
83
|
+
}
|
|
84
|
+
export function parse17TrackResponse(payload, trackingNumber, postcode = null) {
|
|
79
85
|
const number = numberOf(trackingNumber);
|
|
80
86
|
if (!isRecord(payload) || !isRecord(payload.meta) || !Number.isInteger(payload.meta.code)) {
|
|
81
87
|
throw new SchemaError(SOURCE, '17TRACK lookup unavailable');
|
|
@@ -94,8 +100,11 @@ export function parse17TrackResponse(payload, trackingNumber) {
|
|
|
94
100
|
const code = Number(matches[0].code);
|
|
95
101
|
// Observed repeatedly for valid references whose other providers have history.
|
|
96
102
|
// Scope this to the matching shipment; envelope errors and unknown shapes remain failures.
|
|
97
|
-
if (code === 400 && matches[0].shipment === null)
|
|
103
|
+
if (code === 400 && matches[0].shipment === null) {
|
|
104
|
+
if (!postcode && requestsPostcode(matches[0]))
|
|
105
|
+
throw new InputRequiredError(SOURCE, 'postcode');
|
|
98
106
|
throw new SeventeenTrackNoHistoryError();
|
|
107
|
+
}
|
|
99
108
|
throw new SeventeenTrackLookupError(code === 100 ? 'lookup_pending' : 'lookup_unavailable', code);
|
|
100
109
|
}
|
|
101
110
|
if (matches.length !== 1 || !isRecord(matches[0]) || matches[0].code !== 200 || !isRecord(matches[0].shipment)) {
|
|
@@ -156,10 +165,14 @@ export class SeventeenTrackTracker {
|
|
|
156
165
|
constructor(options = {}) {
|
|
157
166
|
this.options = options;
|
|
158
167
|
}
|
|
159
|
-
async fetch(trackingNumber, budgetMs = this.options.timeoutMs ?? 30_000, signal) {
|
|
168
|
+
async fetch(trackingNumber, budgetMs = this.options.timeoutMs ?? 30_000, signal, postcode = null) {
|
|
160
169
|
const number = numberOf(trackingNumber);
|
|
170
|
+
postcode = postcode?.trim().replace(/\s+/g, ' ').toUpperCase() || null;
|
|
171
|
+
if (postcode && (postcode.length < 2 || postcode.length > 15 || !/^[A-Z0-9]+(?:[ -][A-Z0-9]+)*$/.test(postcode))) {
|
|
172
|
+
throw new InvalidInputError(SOURCE, '17TRACK delivery postcode has an invalid format');
|
|
173
|
+
}
|
|
161
174
|
const spec = (remainingMs, signal) => ({
|
|
162
|
-
source: SOURCE, url: `https://t.17track.net/en#nums=${number}`, apiUrl: API_URL,
|
|
175
|
+
source: SOURCE, url: `https://t.17track.net/en#nums=${number}${postcode ? `&trawl-postcode=${encodeURIComponent(postcode)}` : ''}`, apiUrl: API_URL,
|
|
163
176
|
budgetMs: remainingMs, fetcher: this.options.fetcher, signal,
|
|
164
177
|
});
|
|
165
178
|
return runSteps({ carrier: SOURCE, budgetMs, signal, recorder: this.options.recorder }, [{
|
|
@@ -170,12 +183,28 @@ export class SeventeenTrackTracker {
|
|
|
170
183
|
let pending;
|
|
171
184
|
for (const body of capturedBodies(page, capture)) {
|
|
172
185
|
try {
|
|
173
|
-
|
|
186
|
+
const payload = JSON.parse(body);
|
|
187
|
+
// Old browser-service builds ignore the private input marker. Never
|
|
188
|
+
// report that a supplied postcode was tried without a bound request.
|
|
189
|
+
const submitted = page.capturedResponses.some(entry => entry.body === body && entry.postcodeSubmitted === true);
|
|
190
|
+
if (postcode && !submitted) {
|
|
191
|
+
try {
|
|
192
|
+
return parse17TrackResponse(payload, number);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
if (error instanceof InputRequiredError || error instanceof SeventeenTrackNoHistoryError) {
|
|
196
|
+
throw new TransportError(SOURCE, '17TRACK browser service did not submit the delivery postcode', { reason: 'postcode_not_submitted' });
|
|
197
|
+
}
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return parse17TrackResponse(payload, number, postcode);
|
|
174
202
|
}
|
|
175
203
|
catch (error) {
|
|
176
204
|
// Continue past polling replies and unrelated/demo numbers, but retain
|
|
177
205
|
// the latest structured failure if no matching history follows.
|
|
178
|
-
if (isSeventeenTrackLookupError(error) || error instanceof NotFoundError || error instanceof SchemaError
|
|
206
|
+
if (isSeventeenTrackLookupError(error) || error instanceof NotFoundError || error instanceof SchemaError
|
|
207
|
+
|| error instanceof InputRequiredError || error instanceof TransportError)
|
|
179
208
|
pending ??= error;
|
|
180
209
|
}
|
|
181
210
|
}
|
|
@@ -191,6 +220,6 @@ export const adapter = (environment) => {
|
|
|
191
220
|
return {
|
|
192
221
|
id: SOURCE,
|
|
193
222
|
steps: ['trawl'],
|
|
194
|
-
track: (input, context) => tracker.fetch(input.number, context?.budgetMs, context?.signal),
|
|
223
|
+
track: (input, context) => tracker.fetch(input.number, context?.budgetMs, context?.signal, input.postcode),
|
|
195
224
|
};
|
|
196
225
|
};
|
|
@@ -55,7 +55,7 @@ export declare class UniversalTracker {
|
|
|
55
55
|
* Look up one number through the whole chain. `postcode` is the parcel's
|
|
56
56
|
* stored delivery postcode, if the user supplied one: it is forwarded into
|
|
57
57
|
* every provider's track input. ParcelsApp submits it as extra[zipcode] on
|
|
58
|
-
* its direct API request;
|
|
58
|
+
* its direct API request; 17TRACK submits it through the browser's postcode form.
|
|
59
59
|
* `countryHint` lets ParcelsApp retry an empty answer with that country.
|
|
60
60
|
* The caller's budget covers the whole chain and its signal ends it.
|
|
61
61
|
*/
|
|
@@ -48,7 +48,7 @@ export class UniversalTracker {
|
|
|
48
48
|
* Look up one number through the whole chain. `postcode` is the parcel's
|
|
49
49
|
* stored delivery postcode, if the user supplied one: it is forwarded into
|
|
50
50
|
* every provider's track input. ParcelsApp submits it as extra[zipcode] on
|
|
51
|
-
* its direct API request;
|
|
51
|
+
* its direct API request; 17TRACK submits it through the browser's postcode form.
|
|
52
52
|
* `countryHint` lets ParcelsApp retry an empty answer with that country.
|
|
53
53
|
* The caller's budget covers the whole chain and its signal ends it.
|
|
54
54
|
*/
|
package/dist/server/openapi.json
CHANGED
package/package.json
CHANGED