@deenruv/inpost 1.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.
Files changed (141) hide show
  1. package/LICENSE +23 -0
  2. package/dist/api/organizations/index.d.ts +18 -0
  3. package/dist/api/organizations/index.js +34 -0
  4. package/dist/api/organizations/shipments.d.ts +17 -0
  5. package/dist/api/organizations/shipments.js +33 -0
  6. package/dist/api/organizations.d.ts +18 -0
  7. package/dist/api/organizations.js +33 -0
  8. package/dist/api/shipments/index.d.ts +14 -0
  9. package/dist/api/shipments/index.js +26 -0
  10. package/dist/api/shipments.d.ts +19 -0
  11. package/dist/api/shipments.js +37 -0
  12. package/dist/error.d.ts +6 -0
  13. package/dist/error.js +14 -0
  14. package/dist/index.d.ts +16 -0
  15. package/dist/index.js +43 -0
  16. package/dist/index.test.d.ts +1 -0
  17. package/dist/index.test.js +99 -0
  18. package/dist/middleware/auth.d.ts +2 -0
  19. package/dist/middleware/auth.js +12 -0
  20. package/dist/middleware/endpoint.d.ts +2 -0
  21. package/dist/middleware/endpoint.js +10 -0
  22. package/dist/middleware/expect_200.d.ts +2 -0
  23. package/dist/middleware/expect_200.js +26 -0
  24. package/dist/middleware/get.d.ts +2 -0
  25. package/dist/middleware/get.js +8 -0
  26. package/dist/middleware/index.d.ts +9 -0
  27. package/dist/middleware/index.js +25 -0
  28. package/dist/middleware/json_request.d.ts +2 -0
  29. package/dist/middleware/json_request.js +14 -0
  30. package/dist/middleware/json_response.d.ts +5 -0
  31. package/dist/middleware/json_response.js +14 -0
  32. package/dist/middleware/middleware.d.ts +4 -0
  33. package/dist/middleware/middleware.js +2 -0
  34. package/dist/middleware/post.d.ts +2 -0
  35. package/dist/middleware/post.js +8 -0
  36. package/dist/middleware/values.d.ts +4 -0
  37. package/dist/middleware/values.js +14 -0
  38. package/dist/models/address.d.ts +13 -0
  39. package/dist/models/address.js +2 -0
  40. package/dist/models/carrier.d.ts +1 -0
  41. package/dist/models/carrier.js +2 -0
  42. package/dist/models/country_code.d.ts +4 -0
  43. package/dist/models/country_code.js +2 -0
  44. package/dist/models/currency_code.d.ts +3 -0
  45. package/dist/models/currency_code.js +2 -0
  46. package/dist/models/index.d.ts +11 -0
  47. package/dist/models/index.js +27 -0
  48. package/dist/models/money.d.ts +5 -0
  49. package/dist/models/money.js +2 -0
  50. package/dist/models/offer.d.ts +4 -0
  51. package/dist/models/offer.js +2 -0
  52. package/dist/models/organization.d.ts +19 -0
  53. package/dist/models/organization.js +2 -0
  54. package/dist/models/parcel.d.ts +69 -0
  55. package/dist/models/parcel.js +2 -0
  56. package/dist/models/person.d.ts +10 -0
  57. package/dist/models/person.js +2 -0
  58. package/dist/models/service.d.ts +1 -0
  59. package/dist/models/service.js +2 -0
  60. package/dist/models/shipment.d.ts +32 -0
  61. package/dist/models/shipment.js +2 -0
  62. package/dist/models/transaction.d.ts +7 -0
  63. package/dist/models/transaction.js +2 -0
  64. package/dist/validators/address.d.ts +2 -0
  65. package/dist/validators/address.js +18 -0
  66. package/dist/validators/array.d.ts +1 -0
  67. package/dist/validators/array.js +5 -0
  68. package/dist/validators/carrier.d.ts +2 -0
  69. package/dist/validators/carrier.js +13 -0
  70. package/dist/validators/is_country_code.d.ts +2 -0
  71. package/dist/validators/is_country_code.js +13 -0
  72. package/dist/validators/is_currency_code.d.ts +2 -0
  73. package/dist/validators/is_currency_code.js +12 -0
  74. package/dist/validators/is_money.d.ts +2 -0
  75. package/dist/validators/is_money.js +8 -0
  76. package/dist/validators/is_parcel.d.ts +2 -0
  77. package/dist/validators/is_parcel.js +8 -0
  78. package/dist/validators/is_shipment.d.ts +2 -0
  79. package/dist/validators/is_shipment.js +7 -0
  80. package/dist/validators/number.d.ts +1 -0
  81. package/dist/validators/number.js +5 -0
  82. package/dist/validators/object.d.ts +1 -0
  83. package/dist/validators/object.js +5 -0
  84. package/dist/validators/optional.d.ts +1 -0
  85. package/dist/validators/optional.js +5 -0
  86. package/dist/validators/organization.d.ts +2 -0
  87. package/dist/validators/organization.js +28 -0
  88. package/dist/validators/person.d.ts +2 -0
  89. package/dist/validators/person.js +17 -0
  90. package/dist/validators/services.d.ts +2 -0
  91. package/dist/validators/services.js +24 -0
  92. package/dist/validators/string.d.ts +1 -0
  93. package/dist/validators/string.js +5 -0
  94. package/package.json +30 -0
  95. package/src/api/organizations/index.ts +51 -0
  96. package/src/api/organizations/shipments.ts +53 -0
  97. package/src/api/organizations.ts +44 -0
  98. package/src/api/shipments/index.ts +44 -0
  99. package/src/api/shipments.ts +59 -0
  100. package/src/error.ts +10 -0
  101. package/src/index.test.ts +127 -0
  102. package/src/index.ts +33 -0
  103. package/src/middleware/auth.ts +12 -0
  104. package/src/middleware/endpoint.ts +12 -0
  105. package/src/middleware/expect_200.ts +28 -0
  106. package/src/middleware/get.ts +6 -0
  107. package/src/middleware/index.ts +9 -0
  108. package/src/middleware/json_request.ts +15 -0
  109. package/src/middleware/json_response.ts +18 -0
  110. package/src/middleware/middleware.ts +7 -0
  111. package/src/middleware/post.ts +7 -0
  112. package/src/middleware/values.ts +23 -0
  113. package/src/models/address.ts +16 -0
  114. package/src/models/carrier.ts +1 -0
  115. package/src/models/country_code.ts +4 -0
  116. package/src/models/currency_code.ts +3 -0
  117. package/src/models/index.ts +11 -0
  118. package/src/models/money.ts +5 -0
  119. package/src/models/offer.ts +4 -0
  120. package/src/models/organization.ts +19 -0
  121. package/src/models/parcel.ts +75 -0
  122. package/src/models/person.ts +11 -0
  123. package/src/models/service.ts +15 -0
  124. package/src/models/shipment.ts +39 -0
  125. package/src/models/transaction.ts +7 -0
  126. package/src/validators/address.ts +19 -0
  127. package/src/validators/array.ts +4 -0
  128. package/src/validators/carrier.ts +13 -0
  129. package/src/validators/is_country_code.ts +11 -0
  130. package/src/validators/is_currency_code.ts +10 -0
  131. package/src/validators/is_money.ts +8 -0
  132. package/src/validators/is_parcel.ts +11 -0
  133. package/src/validators/is_shipment.ts +5 -0
  134. package/src/validators/number.ts +1 -0
  135. package/src/validators/object.ts +2 -0
  136. package/src/validators/optional.ts +4 -0
  137. package/src/validators/organization.ts +29 -0
  138. package/src/validators/person.ts +18 -0
  139. package/src/validators/services.ts +24 -0
  140. package/src/validators/string.ts +1 -0
  141. package/tsconfig.json +13 -0
@@ -0,0 +1,51 @@
1
+ import {
2
+ FetchFn,
3
+ endpoint,
4
+ get,
5
+ jsonResponse,
6
+ is2xx,
7
+ } from "../../middleware/index.js";
8
+ import { Shipment } from "../../models/index.js";
9
+ import { isArray } from "../../validators/array.js";
10
+ import { isNumber } from "../../validators/number.js";
11
+ import { isObject } from "../../validators/object.js";
12
+ import { isOrganization } from "../../validators/organization.js";
13
+ import { isShipment } from "../../validators/is_shipment.js";
14
+ import { isString } from "../../validators/string.js";
15
+ import { Shipments } from "./shipments.js";
16
+
17
+ export interface ShipmentListResponse {
18
+ href: string;
19
+ count: number;
20
+ page: number;
21
+ per_page: number;
22
+ items: Shipment[];
23
+ }
24
+
25
+ const mustShipmentList = (v: ShipmentListResponse) =>
26
+ isString(v.href) &&
27
+ isNumber(v.count) &&
28
+ isNumber(v.page) &&
29
+ isNumber(v.per_page) &&
30
+ isArray(isShipment)(v.items);
31
+
32
+ export const isShipmentList = (v: unknown): v is ShipmentListResponse =>
33
+ isObject(v) && mustShipmentList(v as ShipmentListResponse);
34
+
35
+ export class Organization {
36
+ constructor(
37
+ private apiBase: URL,
38
+ private fetchFn: FetchFn,
39
+ ) {}
40
+
41
+ async fetch() {
42
+ const res = await jsonResponse(isOrganization)(get(is2xx(this.fetchFn)))(
43
+ this.apiBase,
44
+ );
45
+ return res.jsonResponse;
46
+ }
47
+
48
+ shipments() {
49
+ return new Shipments(this.apiBase, endpoint("shipments")(this.fetchFn));
50
+ }
51
+ }
@@ -0,0 +1,53 @@
1
+ import {
2
+ FetchFn,
3
+ get,
4
+ jsonRequest,
5
+ jsonResponse,
6
+ post,
7
+ is2xx,
8
+ } from '../../middleware/index.js';
9
+ import { Shipment } from '../../models/index.js';
10
+ import { isArray } from '../../validators/array.js';
11
+ import { isNumber } from '../../validators/number.js';
12
+ import { isObject } from '../../validators/object.js';
13
+ import { isShipment } from '../../validators/is_shipment.js';
14
+ import { isString } from '../../validators/string.js';
15
+
16
+ export interface ShipmentListResponse {
17
+ href: string;
18
+ count: number;
19
+ page: number;
20
+ per_page: number;
21
+ items: Shipment[];
22
+ }
23
+
24
+ const mustShipmentList = (v: ShipmentListResponse) =>
25
+ isString(v.href) &&
26
+ isNumber(v.count) &&
27
+ isNumber(v.page) &&
28
+ isNumber(v.per_page) &&
29
+ isArray(isShipment)(v.items);
30
+
31
+ export const isShipmentList = (v: unknown): v is ShipmentListResponse =>
32
+ isObject(v) && mustShipmentList(v as ShipmentListResponse);
33
+
34
+ export class Shipments {
35
+ constructor(
36
+ private apiBase: URL,
37
+ private fetchFn: FetchFn,
38
+ ) {}
39
+
40
+ async list() {
41
+ const res = await jsonResponse(isShipmentList)(get(is2xx(this.fetchFn)))(
42
+ this.apiBase,
43
+ );
44
+ return res.jsonResponse;
45
+ }
46
+
47
+ async create(data: Shipment): Promise<Shipment> {
48
+ const res = await jsonResponse(isShipment)(
49
+ post(jsonRequest(data)(is2xx(this.fetchFn))),
50
+ )(this.apiBase);
51
+ return res.jsonResponse;
52
+ }
53
+ }
@@ -0,0 +1,44 @@
1
+ import { FetchFn, endpoint, get, jsonResponse, is2xx } from '../middleware/index.js';
2
+ import { Organization } from '../models/index.js';
3
+ import { isArray } from '../validators/array.js';
4
+ import { isNumber } from '../validators/number.js';
5
+ import { isObject } from '../validators/object.js';
6
+ import { isOrganization } from '../validators/organization.js';
7
+ import { isString } from '../validators/string.js';
8
+ import { Organization as OrganizationAPI } from './organizations/index.js';
9
+
10
+ export interface OrganizationListResponse {
11
+ href: string;
12
+ count: number;
13
+ page: number;
14
+ per_page: number;
15
+ items: Organization[];
16
+ }
17
+
18
+ const mustOrganizationList = (v: OrganizationListResponse) =>
19
+ isString(v.href) &&
20
+ isNumber(v.count) &&
21
+ isNumber(v.page) &&
22
+ isNumber(v.per_page) &&
23
+ isArray(isOrganization)(v.items);
24
+
25
+ export const isOrganizationList = (v: unknown): v is OrganizationListResponse =>
26
+ isObject(v) && mustOrganizationList(v as OrganizationListResponse);
27
+
28
+ export class Organizations {
29
+ constructor(
30
+ private apiBase: URL,
31
+ private fetch: FetchFn,
32
+ ) {}
33
+
34
+ async list() {
35
+ const res = await jsonResponse(isOrganizationList)(get(is2xx(this.fetch)))(
36
+ this.apiBase,
37
+ );
38
+ return res.jsonResponse;
39
+ }
40
+
41
+ get(id: number) {
42
+ return new OrganizationAPI(this.apiBase, endpoint(`${id}`)(this.fetch));
43
+ }
44
+ }
@@ -0,0 +1,44 @@
1
+ import {
2
+ endpoint,
3
+ is2xx,
4
+ values,
5
+ FetchFn,
6
+ get,
7
+ jsonResponse,
8
+ jsonRequest,
9
+ post,
10
+ } from '../../middleware/index.js';
11
+ import { isShipment } from '../../validators/is_shipment.js';
12
+
13
+ export class Shipment {
14
+ constructor(
15
+ private apiBase: URL,
16
+ private fetchFn: FetchFn,
17
+ ) {}
18
+
19
+ async fetch() {
20
+ const res = await jsonResponse(isShipment)(get(is2xx(this.fetchFn)))(
21
+ this.apiBase,
22
+ );
23
+ return res.jsonResponse;
24
+ }
25
+
26
+ async label(
27
+ args: {
28
+ format?: 'Pdf' | 'Zpl' | 'Epl';
29
+ type?: 'normal' | 'A6' | 'dpi300';
30
+ } = {},
31
+ ) {
32
+ const res = await endpoint('label')(values(args)(get(is2xx(this.fetchFn))))(
33
+ this.apiBase,
34
+ );
35
+ return res.body;
36
+ }
37
+
38
+ async buy(body: { offer_id: number }) {
39
+ const res = await jsonResponse(isShipment)(
40
+ endpoint('buy')(jsonRequest(body)(post(is2xx(this.fetchFn)))),
41
+ )(this.apiBase);
42
+ return res.jsonResponse;
43
+ }
44
+ }
@@ -0,0 +1,59 @@
1
+ import {
2
+ FetchFn,
3
+ endpoint,
4
+ get,
5
+ jsonRequest,
6
+ jsonResponse,
7
+ post,
8
+ is2xx,
9
+ } from '../middleware/index.js';
10
+ import { Shipment } from '../models/index.js';
11
+ import { isArray } from '../validators/array.js';
12
+ import { isNumber } from '../validators/number.js';
13
+ import { isObject } from '../validators/object.js';
14
+ import { isShipment } from '../validators/is_shipment.js';
15
+ import { isString } from '../validators/string.js';
16
+ import { Shipment as ShipmentAPI } from './shipments/index.js';
17
+
18
+ export interface ShipmentListResponse {
19
+ href: string;
20
+ count: number;
21
+ page: number;
22
+ per_page: number;
23
+ items: Shipment[];
24
+ }
25
+
26
+ const mustShipmentList = (v: ShipmentListResponse) =>
27
+ isString(v.href) &&
28
+ isNumber(v.count) &&
29
+ isNumber(v.page) &&
30
+ isNumber(v.per_page) &&
31
+ isArray(isShipment)(v.items);
32
+
33
+ export const isShipmentList = (v: unknown): v is ShipmentListResponse =>
34
+ isObject(v) && mustShipmentList(v as ShipmentListResponse);
35
+
36
+ export class Shipments {
37
+ constructor(
38
+ private apiBase: URL,
39
+ private fetchFn: FetchFn,
40
+ ) {}
41
+
42
+ async list() {
43
+ const res = await jsonResponse(isShipmentList)(get(is2xx(this.fetchFn)))(
44
+ this.apiBase,
45
+ );
46
+ return res.jsonResponse;
47
+ }
48
+
49
+ async create(data: Shipment): Promise<Shipment> {
50
+ const res = await jsonResponse(isShipment)(
51
+ post(jsonRequest(data)(is2xx(this.fetchFn))),
52
+ )(this.apiBase);
53
+ return res.jsonResponse;
54
+ }
55
+
56
+ get(id: number) {
57
+ return new ShipmentAPI(this.apiBase, endpoint(`${id}`)(this.fetchFn));
58
+ }
59
+ }
package/src/error.ts ADDED
@@ -0,0 +1,10 @@
1
+ export class InvalidBody extends Error {}
2
+
3
+ export class InvalidResponseStatus extends Error {
4
+ constructor(
5
+ msg: string,
6
+ public res: Response,
7
+ ) {
8
+ super(msg);
9
+ }
10
+ }
@@ -0,0 +1,127 @@
1
+ import { describe, it } from "node:test";
2
+ import { doesNotReject, notEqual } from "node:assert";
3
+ import { Client, CountryCode } from "./index.js";
4
+ import { createWriteStream } from "fs";
5
+ import { tmpdir } from "node:os";
6
+ import { mkdtemp, rm } from "fs/promises";
7
+ import { join } from "node:path";
8
+ import { Writable } from "node:stream";
9
+
10
+ const {
11
+ INPOST_HOST: host = "sandbox-api-shipx-pl.easypack24.net",
12
+ INPOST_API_KEY: apiKey,
13
+ } = process.env as {
14
+ INPOST_HOST: string;
15
+ INPOST_API_KEY: string;
16
+ };
17
+
18
+ describe("inpost client tests", { skip: !apiKey }, () => {
19
+ const client = new Client({ host, apiKey });
20
+ it("lists organizations", () => doesNotReject(client.organizations().list()));
21
+ it("fetches organization", () =>
22
+ doesNotReject(
23
+ client
24
+ .organizations()
25
+ .list()
26
+ .then((orgs) => client.organizations().get(orgs.items[0].id).fetch()),
27
+ ));
28
+ it("fetches shipments", () =>
29
+ doesNotReject(
30
+ client
31
+ .organizations()
32
+ .list()
33
+ .then((orgs) =>
34
+ client.organizations().get(orgs.items[0].id).shipments().list(),
35
+ ),
36
+ ));
37
+ it("test shipment flow", () =>
38
+ doesNotReject(async () => {
39
+ const orgs = await client.organizations().list();
40
+ const org = orgs.items[0];
41
+ // is not falsy
42
+ notEqual(!!org, false);
43
+ let shipment = await client
44
+ .organizations()
45
+ .get(org.id)
46
+ .shipments()
47
+ .create({
48
+ receiver: {
49
+ first_name: "Test",
50
+ last_name: "Test",
51
+ email: "email@example.org",
52
+ phone: "321321321",
53
+ address: {
54
+ street: "Czerniakowska",
55
+ building_number: "87A",
56
+ city: "Warszawa",
57
+ post_code: "00-718",
58
+ country_code: CountryCode.pl,
59
+ },
60
+ },
61
+ sender: {
62
+ company_name: "Company_name",
63
+ first_name: "Test",
64
+ last_name: "Test",
65
+ email: "email@example.com",
66
+ phone: "888000000",
67
+ address: {
68
+ line1: "Cybernetyki 10",
69
+ city: "Warszawa",
70
+ post_code: "02-677",
71
+ country_code: CountryCode.pl,
72
+ },
73
+ },
74
+ parcels: [{ template: "small" }],
75
+ service: "inpost_locker_standard",
76
+ custom_attributes: {
77
+ target_point: "KRA010",
78
+ },
79
+ });
80
+
81
+ while (!shipment.status || shipment.status === "created") {
82
+ console.log("Waiting for shipment to be created...");
83
+ await new Promise((resolve) => setTimeout(resolve, 500));
84
+ shipment = await client.shipments().get(shipment.id).fetch();
85
+ }
86
+
87
+ shipment = await client
88
+ .shipments()
89
+ .get(shipment.id)
90
+ .buy({ offer_id: shipment.offers[0].id });
91
+
92
+ let found = shipment.transactions?.find(
93
+ (t) => t.status === "success" && t.offer_id === shipment.offers?.[0].id,
94
+ );
95
+
96
+ while (!found) {
97
+ console.log("Waiting for transaction to succeed...");
98
+ await new Promise((resolve) => setTimeout(resolve, 500));
99
+ shipment = await client.shipments().get(shipment.id).fetch();
100
+ found = shipment.transactions?.find((t) => t.status === "success");
101
+ if (!found) {
102
+ await client
103
+ .shipments()
104
+ .get(shipment.id)
105
+ .buy({ offer_id: shipment.offers[0].id });
106
+ }
107
+ }
108
+
109
+ while (
110
+ !shipment.status ||
111
+ shipment.status === "created" ||
112
+ shipment.status === "offer_selected"
113
+ ) {
114
+ console.log("Waiting for shipment to be ready...");
115
+ await new Promise((resolve) => setTimeout(resolve, 500));
116
+ shipment = await client.shipments().get(shipment.id).fetch();
117
+ }
118
+ const tmp = await mkdtemp(join(tmpdir(), "test-inpost-label"));
119
+ const label = await client.shipments().get(shipment.id).label();
120
+ await label.pipeTo(
121
+ Writable.toWeb(
122
+ createWriteStream(join(tmp, "label.pdf")),
123
+ ) as WritableStream<Uint8Array>,
124
+ );
125
+ await rm(tmp, { force: true, recursive: true });
126
+ }));
127
+ });
package/src/index.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { Organizations } from "./api/organizations.js";
2
+ import { Shipments } from "./api/shipments.js";
3
+ import { Middleware, auth, endpoint } from "./middleware/index.js";
4
+ export class Client {
5
+ private auth: Middleware;
6
+ private base: URL;
7
+ constructor(
8
+ private opts: {
9
+ host: string;
10
+ version?: string;
11
+ apiKey: string;
12
+ },
13
+ ) {
14
+ this.auth = auth(this.opts.apiKey);
15
+ this.base = new URL(`https://${this.opts.host}`);
16
+ }
17
+ private doRequest() {
18
+ return (info: string | URL, init?: RequestInit) => {
19
+ return endpoint(this.opts.version || "v1")(this.auth(fetch))(info, init);
20
+ };
21
+ }
22
+ organizations() {
23
+ return new Organizations(
24
+ this.base,
25
+ endpoint("organizations")(this.doRequest()),
26
+ );
27
+ }
28
+
29
+ shipments() {
30
+ return new Shipments(this.base, endpoint("shipments")(this.doRequest()));
31
+ }
32
+ }
33
+ export * from "./models/index.js";
@@ -0,0 +1,12 @@
1
+ import { Middleware } from './middleware.js';
2
+ export const auth =
3
+ (token: string): Middleware =>
4
+ (next) =>
5
+ (info, init) => {
6
+ const headers = new Headers(init?.headers);
7
+ headers.set('authorization', `Bearer ${token}`);
8
+ return next(info, {
9
+ ...init,
10
+ headers,
11
+ });
12
+ };
@@ -0,0 +1,12 @@
1
+ import { Middleware } from './middleware.js';
2
+ const buildEndpoint = (url: string | URL, endpoint: string) => {
3
+ url = new URL(url);
4
+ url.pathname = `${endpoint.replace(/\/+$/, '')}/${url.pathname.replace(/^\/+/, '')}`;
5
+ return url;
6
+ };
7
+
8
+ export const endpoint =
9
+ (endpoint: string): Middleware =>
10
+ (next) =>
11
+ (info, init) =>
12
+ next(buildEndpoint(info, endpoint), init);
@@ -0,0 +1,28 @@
1
+ import { FetchFn, Middleware } from "./middleware.js";
2
+ import { InvalidResponseStatus } from "../error.js";
3
+
4
+ export const is2xx: Middleware =
5
+ <U>(next: FetchFn<U>) =>
6
+ async (info, init) => {
7
+ const res = await next(info, init);
8
+ if (res.status < 200 || res.status > 299) {
9
+ if ((process.env.LOG_LEVEL || "").toLowerCase() === "debug") {
10
+ console.log(await res.text());
11
+ }
12
+ // Let user know message from the response if available
13
+ let error: { message: string; details: string };
14
+ try {
15
+ error = await res.json();
16
+ } catch {
17
+ error = {
18
+ message: "Unknown error",
19
+ details: "No additional details available",
20
+ };
21
+ }
22
+ throw new InvalidResponseStatus(
23
+ `${error.message}: ${error.details}, (status: ${res.status})`,
24
+ res,
25
+ );
26
+ }
27
+ return res;
28
+ };
@@ -0,0 +1,6 @@
1
+ import { Middleware } from './middleware.js';
2
+ export const get: Middleware = (next) => (info, init) =>
3
+ next(info, {
4
+ ...init,
5
+ method: 'GET',
6
+ });
@@ -0,0 +1,9 @@
1
+ export * from './middleware.js';
2
+ export * from './get.js';
3
+ export * from './post.js';
4
+ export * from './endpoint.js';
5
+ export * from './json_request.js';
6
+ export * from './json_response.js';
7
+ export * from './auth.js';
8
+ export * from './expect_200.js';
9
+ export * from './values.js';
@@ -0,0 +1,15 @@
1
+ import { Middleware } from './middleware.js';
2
+
3
+ export const jsonRequest =
4
+ (rawBody: unknown): Middleware =>
5
+ (next) =>
6
+ async (info, init) => {
7
+ const headers = new Headers(init?.headers);
8
+ headers.set('content-type', `application/json`);
9
+ const body = JSON.stringify(rawBody);
10
+ return next(info, {
11
+ ...init,
12
+ headers,
13
+ body,
14
+ });
15
+ };
@@ -0,0 +1,18 @@
1
+ import { FetchFn, Middleware } from './middleware.js';
2
+ import { InvalidBody } from '../error.js';
3
+ export type JSONResponse<T> = {
4
+ jsonResponse: T;
5
+ };
6
+ export const jsonResponse =
7
+ <T>(validate: (v: unknown) => v is T): Middleware<JSONResponse<T>> =>
8
+ <U>(next: FetchFn<U>) =>
9
+ async (info, init) => {
10
+ const res = await next(info, init);
11
+ type ResponseType = Response & JSONResponse<T> & U;
12
+ const data = await res.json();
13
+ if (!validate(data)) {
14
+ throw new InvalidBody('invalid response body');
15
+ }
16
+ (res as ResponseType).jsonResponse = data;
17
+ return res as ResponseType;
18
+ };
@@ -0,0 +1,7 @@
1
+ export type FetchFn<T = unknown> = (
2
+ info: string | URL,
3
+ init?: RequestInit,
4
+ ) => Promise<T & Response>;
5
+ export interface Middleware<T = unknown> {
6
+ <U = unknown>(next: FetchFn<U>): FetchFn<T & U>;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { Middleware } from './middleware.js';
2
+
3
+ export const post: Middleware = (next) => (info, init) =>
4
+ next(info, {
5
+ ...init,
6
+ method: 'POST',
7
+ });
@@ -0,0 +1,23 @@
1
+ import { Middleware } from "./middleware.js";
2
+
3
+ type Values =
4
+ | string
5
+ | [string, string][]
6
+ | Record<string, string>
7
+ | URLSearchParams;
8
+
9
+ const buildValues = (url: string | URL, values: Values) => {
10
+ url = new URL(url);
11
+ const params = new URLSearchParams(url.searchParams);
12
+ for (const [key, value] of new URLSearchParams(values)) {
13
+ params.set(key, value);
14
+ }
15
+ url.search = params.toString();
16
+ return url;
17
+ };
18
+
19
+ export const values =
20
+ (values: Values): Middleware =>
21
+ (next) =>
22
+ (info, init) =>
23
+ next(buildValues(info, values), init);
@@ -0,0 +1,16 @@
1
+ import { CountryCode } from './country_code.js';
2
+ export type Address = {
3
+ id?: number;
4
+ city: string;
5
+ country_code: CountryCode;
6
+ post_code: string;
7
+ } & (
8
+ | {
9
+ line1: string;
10
+ line2?: string;
11
+ }
12
+ | {
13
+ street: string;
14
+ building_number: string;
15
+ }
16
+ );
@@ -0,0 +1 @@
1
+ export type Carrier = 'inpost_locker' | 'inpost_letter' | 'inpost_courier';
@@ -0,0 +1,4 @@
1
+ export const enum CountryCode {
2
+ pl = 'PL',
3
+ en = 'EN',
4
+ }
@@ -0,0 +1,3 @@
1
+ export const enum CurrencyCode {
2
+ PLN = 'PLN',
3
+ }
@@ -0,0 +1,11 @@
1
+ export * from "./address.js";
2
+ export * from "./carrier.js";
3
+ export * from "./country_code.js";
4
+ export * from "./currency_code.js";
5
+ export * from "./money.js";
6
+ export * from "./offer.js";
7
+ export * from "./organization.js";
8
+ export * from "./parcel.js";
9
+ export * from "./person.js";
10
+ export * from "./shipment.js";
11
+ export * from "./service.js";
@@ -0,0 +1,5 @@
1
+ import { CurrencyCode } from './currency_code.js';
2
+ export interface Money {
3
+ amount: number;
4
+ currency: CurrencyCode;
5
+ }
@@ -0,0 +1,4 @@
1
+ export interface Offer {
2
+ id: number;
3
+ status: string;
4
+ }
@@ -0,0 +1,19 @@
1
+ import { Address } from './address.js';
2
+ import { Carrier } from './carrier.js';
3
+ import { Person } from './person.js';
4
+ import { Service } from './service.js';
5
+ export interface Organization {
6
+ address: Address;
7
+ bank_account_number?: string;
8
+ carriers: Carrier[];
9
+ contact_person?: Person;
10
+ created_at: string;
11
+ href: string;
12
+ id: number;
13
+ invoice_address?: Address;
14
+ name: string;
15
+ owner_id: number;
16
+ services: Service[];
17
+ tax_id: string;
18
+ updated_at: string;
19
+ }