@emulates/easypost 0.0.0-stage → 3.0.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/CHANGELOG.md +19 -0
- package/DISCOVERY.md +55 -0
- package/README.md +118 -2
- package/SUPPORT.md +13 -0
- package/dist/chunk-7GJN6ROH.js +3708 -0
- package/dist/chunk-7GJN6ROH.js.map +7 -0
- package/dist/chunk-X5XEHMAK.js +838 -0
- package/dist/chunk-X5XEHMAK.js.map +7 -0
- package/dist/cli.js +19 -0
- package/dist/cli.js.map +7 -0
- package/dist/index.d.ts +1014 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +7 -0
- package/dist/server.d.ts +1434 -0
- package/dist/server.js +12 -0
- package/dist/server.js.map +7 -0
- package/openapi.yaml +286 -0
- package/package.json +115 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog — @emulates/easypost
|
|
2
|
+
|
|
3
|
+
## 3.0.0 (2026-10-07)
|
|
4
|
+
|
|
5
|
+
### ⚠️ Breaking changes
|
|
6
|
+
|
|
7
|
+
- point the repo at crvouga/emulates ([cdb5e53](https://github.com/crvouga/emulates/commit/cdb5e536ed8c1f52345e3984f089001c25fdb08a))
|
|
8
|
+
|
|
9
|
+
### Fixes and improvements
|
|
10
|
+
|
|
11
|
+
- format the emulates records query ([8698872](https://github.com/crvouga/emulates/commit/8698872509d06002be5a8fcdc85d79f8462320c3))
|
|
12
|
+
|
|
13
|
+
### Dependencies
|
|
14
|
+
|
|
15
|
+
- `@emulates/sqlite`
|
|
16
|
+
|
|
17
|
+
## 2.3.1 (2026-10-06)
|
|
18
|
+
|
|
19
|
+
Initial release.
|
package/DISCOVERY.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @emulates/easypost discovery
|
|
2
|
+
|
|
3
|
+
This is the installed-package index for coding agents and tooling. All relative links resolve
|
|
4
|
+
inside `node_modules/@emulates/easypost/`; no repository checkout is needed to discover the emulator's
|
|
5
|
+
supported surface or documented behavior.
|
|
6
|
+
|
|
7
|
+
## Capability and behavior sources
|
|
8
|
+
|
|
9
|
+
| Question | Authoritative file | What it contains |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| Behaviour and integration | [`README.md`](README.md) | Routes, state transitions, auth, webhooks, controls, presets and deliberate omissions. |
|
|
12
|
+
| Exact capabilities | [`SUPPORT.md`](SUPPORT.md) | Supported, unsupported and parity-covered operations or commands, including reasons for gaps. |
|
|
13
|
+
| Wire contract | [`openapi.yaml`](openapi.yaml) | Machine-readable paths, methods, schemas, responses and parity annotations. |
|
|
14
|
+
| Public API | [`dist/index.d.ts`](dist/index.d.ts) | The installed package's exact TypeScript exports and signatures. |
|
|
15
|
+
| Package metadata | [`package.json`](package.json) | Runtime/entry-point claims, vendor links, parity scope/tier and `emulates.discovery`. |
|
|
16
|
+
|
|
17
|
+
Read these together: the contract/capability matrix says *what* is available, while the README
|
|
18
|
+
defines stateful behavior, lifecycle rules, test controls, and intentional oracle differences.
|
|
19
|
+
If prose and an executable surface disagree, report a parity mismatch instead of adding a
|
|
20
|
+
consumer-side workaround.
|
|
21
|
+
|
|
22
|
+
## Parity and oracle
|
|
23
|
+
|
|
24
|
+
- Declared parity surface: **Trackers**.
|
|
25
|
+
- Parity tier: **cold** (the repository controls when live checks run).
|
|
26
|
+
- Oracle: **Live vendor API or sandbox**.
|
|
27
|
+
- Repository command: `bun run parity:service -- easypost`.
|
|
28
|
+
- Evidence model: Run from an Emulates checkout; credentials come only from .env.local or GitHub Actions secrets. Missing credentials exit 2.
|
|
29
|
+
|
|
30
|
+
The npm package contains evidence summaries and the exact contract, not credentials or the
|
|
31
|
+
repository-only parity harness. Self-parity/property and acceptance tests run in the Emulates
|
|
32
|
+
repository; live parity is an additional oracle check, not a substitute for the packaged matrix.
|
|
33
|
+
|
|
34
|
+
## Runtime introspection
|
|
35
|
+
|
|
36
|
+
- `GET /__admin/health`
|
|
37
|
+
- `GET /__admin`
|
|
38
|
+
- `GET /__admin/state`
|
|
39
|
+
- `GET /__admin/requests`
|
|
40
|
+
- `GET /__admin/metrics`
|
|
41
|
+
- `GET /__admin/faults/presets`
|
|
42
|
+
- `GET /__admin/ui`
|
|
43
|
+
|
|
44
|
+
For HTTP services, use `x-emulates-namespace` (or the documented credential/path carrier) so
|
|
45
|
+
parallel tests do not share state. Admin state, journal, metrics and fault-preset endpoints are
|
|
46
|
+
designed for assertions and diagnosis by consuming test suites.
|
|
47
|
+
|
|
48
|
+
## Report a mismatch or missing capability
|
|
49
|
+
|
|
50
|
+
Follow the [agent reporting contract](https://github.com/crvouga/emulates/blob/main/docs/REPORTING_ISSUES.md). Include package version,
|
|
51
|
+
operation/command, a minimal redacted request, actual emulator result, expected oracle result or vendor
|
|
52
|
+
documentation, and whether the mismatch appears in the matrix. Never include keys, tokens,
|
|
53
|
+
customer data, prompts, PHI, card data, or unredacted recordings.
|
|
54
|
+
|
|
55
|
+
Service key: `easypost`.
|
package/README.md
CHANGED
|
@@ -1,3 +1,119 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @emulates/easypost
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Part of [Emulates](https://github.com/crvouga/emulates): high-fidelity, in-process emulators for APIs and databases.
|
|
4
|
+
|
|
5
|
+
Stateful emulator of the **EasyPost** trackers API for test suites: `POST /v2/trackers` (create or
|
|
6
|
+
re-use a tracker for a tracking code), `GET /v2/trackers/{id}` and `GET /v2/trackers`. EasyPost's
|
|
7
|
+
documented test tracking codes answer their fixed statuses, and any other code moves through
|
|
8
|
+
admin transitions, so the genomics admin's shipping-leg states can be driven deterministically.
|
|
9
|
+
|
|
10
|
+
- Operation coverage: [SUPPORT.md](https://github.com/crvouga/emulates/blob/main/packages/service/easypost/SUPPORT.md)
|
|
11
|
+
- The contract (`openapi.yaml`) is trimmed from EasyPost's published reference to what our
|
|
12
|
+
tracking lookup (`packages/lib/src/shipment-tracking-status/easypost-client.ts`) calls.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -D @emulates/easypost
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
ESM only. Node >= 22 or Bun >= 1.2. No native dependencies. Serve it with
|
|
21
|
+
`npx emulates-easypost serve`, `createServer` from `./server` (Node), or `createRuntime` with
|
|
22
|
+
any Fetch server.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
The app hardcodes `https://api.easypost.com/v2/trackers` (seam **G-Y1**: add a base-URL env to
|
|
27
|
+
`easypost-client.ts`). Point that base URL at the emulator; `EASYPOST_API_KEY` can be any value
|
|
28
|
+
(`--api-key` restricts it).
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx emulates-easypost serve --port 8818
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { createRuntime } from "@emulates/easypost"
|
|
36
|
+
|
|
37
|
+
const easypost = createRuntime()
|
|
38
|
+
const auth = { authorization: `Basic ${btoa("EZTK_test:")}` }
|
|
39
|
+
|
|
40
|
+
// Seed a status before the app looks the code up (or move an existing tracker).
|
|
41
|
+
await easypost.fetch(
|
|
42
|
+
new Request("http://easypost.test/__admin/trackers/1Z999AA10123456784/transition", {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { "content-type": "application/json" },
|
|
45
|
+
body: JSON.stringify({ status: "out_for_delivery" }),
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
const tracker = await easypost.fetch(
|
|
49
|
+
new Request("http://easypost.test/v2/trackers", {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers: { ...auth, "content-type": "application/x-www-form-urlencoded" },
|
|
52
|
+
body: "tracker[tracking_code]=1Z999AA10123456784&tracker[carrier]=UPS",
|
|
53
|
+
}),
|
|
54
|
+
)
|
|
55
|
+
// → 201 {id: "trk_…", status: "out_for_delivery", carrier: "UPS", status_detail: "out_for_delivery", …}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Routes
|
|
59
|
+
|
|
60
|
+
| Route | Behaviour |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `POST /v2/trackers` | Form (`tracker[tracking_code]`, `tracker[carrier]`) or JSON (`{tracker: {…}}`), `Authorization: Basic base64(key:)`. Answers 201 with the Tracker (`id`, `object`, `mode`, `tracking_code`, `status`, `status_detail`, `carrier`, `tracking_details`, `public_url`, `signed_by`, `est_delivery_date`, …). The same code and carrier re-use the existing tracker, as EasyPost does. Carrier: the given one (`DHL` is normalised to `DHLExpress`), else detected from the code's shape, else `USPS`. A blank code is 422 `PARAMETER.REQUIRED`; a bad carrier 422 `PARAMETER.INVALID`. |
|
|
63
|
+
| `GET /v2/trackers/{id}` | The tracker, or 404 `NOT_FOUND`. |
|
|
64
|
+
| `GET /v2/trackers` | `?tracking_code=&carrier=&page_size=` → `{trackers, has_more}`, newest first. |
|
|
65
|
+
|
|
66
|
+
Every error is EasyPost's envelope `{error: {code, message, errors}}`; our client reads
|
|
67
|
+
`error.message`. A missing key is 401 `APIKEY.REQUIRED`, a key outside `apiKeys` 401
|
|
68
|
+
`APIKEY.INACTIVE`. Keys starting `EZAK` are production mode (test codes are not special there);
|
|
69
|
+
anything else is test mode.
|
|
70
|
+
|
|
71
|
+
**Test tracking codes** (test mode, carrier `USPS`): `EZ1000000001` pre_transit,
|
|
72
|
+
`EZ2000000002` in_transit, `EZ3000000003` out_for_delivery, `EZ4000000004` delivered,
|
|
73
|
+
`EZ5000000005` return_to_sender, `EZ6000000006` failure, `EZ7000000007` unknown. Any other code
|
|
74
|
+
starts `unknown` / `unknown`.
|
|
75
|
+
|
|
76
|
+
### Admin (beyond the standard contract)
|
|
77
|
+
|
|
78
|
+
| Route | Effect |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `POST /__admin/trackers/:idOrCode/transition` | `{status, status_detail?, message?, signed_by?, carrier?}`. Moves the tracker (by id or tracking code) and appends a tracking detail. With no tracker for that code yet, registers one first, so the app's next lookup sees the status. `status` is one of `unknown`, `pre_transit`, `in_transit`, `out_for_delivery`, `delivered`, `available_for_pickup`, `return_to_sender`, `failure`, `cancelled`, `error`. |
|
|
81
|
+
| `GET /__admin/trackers` | The namespace's trackers. |
|
|
82
|
+
| `GET/PUT /__admin/settings` | `{apiKeys?: string[]}`: accept only these keys (default: any). |
|
|
83
|
+
|
|
84
|
+
Fault presets (`POST /__admin/faults {"preset": "<name>", "count"?: n}`): `rate_limited` (429),
|
|
85
|
+
`server_error` (500), `invalid_api_key` (401), `gateway_html` (502 HTML, our client falls back
|
|
86
|
+
to `EasyPost tracker request failed (502)`), `connection_drop` (fetch rejects; our batch lookup
|
|
87
|
+
records `unknown` and warns), `slow` (5 s).
|
|
88
|
+
|
|
89
|
+
### Namespaces
|
|
90
|
+
|
|
91
|
+
`x-emulates-namespace`, a `/__admin/ns/<name>` prefix on the base URL, or by API key:
|
|
92
|
+
`PUT /__admin/credentials {"credentials": {"<EASYPOST_API_KEY>": "<namespace>"}}`.
|
|
93
|
+
|
|
94
|
+
### Deliberately not modelled
|
|
95
|
+
|
|
96
|
+
- Tracker webhooks (`tracker.updated`, `X-Hmac-Signature`): our app has no receiver.
|
|
97
|
+
- Carrier lookups: a real-shaped code never moves on its own; statuses come from admin
|
|
98
|
+
transitions.
|
|
99
|
+
- Shipments, rates, labels, addresses, batches and every other EasyPost resource.
|
|
100
|
+
- Pagination cursors (`before_id` / `after_id`) on the list: `page_size` and `has_more` only.
|
|
101
|
+
|
|
102
|
+
## API
|
|
103
|
+
|
|
104
|
+
| Export | Kind | Description |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| `EasyPostAPI` | class | The in-process emulator: `fetch(request)`, `reset()`, `transition(idOrCode, {status, …}, carrier?)`, `trackers()`. Options: `sqlite`, `now`, `namespace`, `settings`. |
|
|
107
|
+
| `createRuntime` | function | The emulator with the full service contract (health, admin, namespaces, credentials, presets). Options: `settings`, `clock`, `seed`, `adminKey`, `onLog`, `sqlite`. |
|
|
108
|
+
| `EASYPOST_PRESETS` | object | Every named fault preset. |
|
|
109
|
+
| `EASYPOST_NAMESPACE` | string | The service name, `"easypost"`. |
|
|
110
|
+
| `TEST_TRACKING_CODES` | object | EasyPost's test codes and the status / detail each answers. |
|
|
111
|
+
| `TRACKER_STATUSES` | array | Every Tracker `status`. |
|
|
112
|
+
| `apiKeyCredential` | function | The API key from `Basic base64(key:)` (how credentials map to namespaces). |
|
|
113
|
+
| `detectCarrier` | function | The carrier the emulator assigns a code with no carrier given. |
|
|
114
|
+
| `easyPostError` | function | Build an EasyPost error response `{error: {code, message, errors}}`. |
|
|
115
|
+
| `isTrackerStatus` | function | Whether a value is a Tracker status. |
|
|
116
|
+
| `document`, `operationIds`, `supportedOperationIds` | values | The vendored OpenAPI contract and its operation ids. |
|
|
117
|
+
| `createServer`, `serveTarget`, `DEFAULT_PORT` (`./server`) | Node | Serve over `node:http`; the `serve` CLI target; port 8818. |
|
|
118
|
+
|
|
119
|
+
Part of [Emulates](https://github.com/crvouga/emulates).
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# EasyPost Trackers API (Emulates subset) — operation support
|
|
2
|
+
|
|
3
|
+
Generated from `openapi.yaml`; do not edit by hand.
|
|
4
|
+
|
|
5
|
+
- operations in spec: **3**
|
|
6
|
+
- supported by the emulator: **3**
|
|
7
|
+
- parity enabled: **3**
|
|
8
|
+
|
|
9
|
+
| operationId | route | emulator | parity | notes |
|
|
10
|
+
| --- | --- | --- | --- | --- |
|
|
11
|
+
| `ListTrackers` | `GET /v2/trackers` | ✅ supported | ✅ | |
|
|
12
|
+
| `CreateTracker` | `POST /v2/trackers` | ✅ supported | ✅ | |
|
|
13
|
+
| `RetrieveTracker` | `GET /v2/trackers/{id}` | ✅ supported | ✅ | |
|