@sovecom/client-js 1.0.0-rc.1

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.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * @sovecom/client-js — thin typed fetch wrapper over the OpenAPI-generated `paths`.
3
+ *
4
+ * No runtime dependency beyond the platform `fetch`. The generated spec (Zod DTOs via nestjs-zod)
5
+ * types request path/query/header params and bodies, but does not carry response body schemas, so
6
+ * `request()` returns a caller-supplied generic (default `unknown`). Auth is layered as headers:
7
+ * a customer bearer (via `getToken`), the cart cookie token, and the guest-order `X-Order-Token`
8
+ * (never in the URL).
9
+ */
10
+ import type { paths } from './generated/api.js';
11
+ export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
12
+ /** Paths in the spec that define operation `M` (e.g. every path with a `post`). */
13
+ export type PathFor<M extends HttpMethod> = {
14
+ [P in keyof paths]: paths[P] extends Record<M, infer O> ? [O] extends [never] ? never : O extends undefined ? never : P : never;
15
+ }[keyof paths];
16
+ type Op<P extends keyof paths, M extends HttpMethod> = M extends keyof paths[P] ? paths[P][M] : never;
17
+ type ParamsOf<O> = O extends {
18
+ parameters: infer Pr;
19
+ } ? Pr : Record<never, never>;
20
+ type PathParamsOf<O> = ParamsOf<O> extends {
21
+ path: infer X;
22
+ } ? (X extends undefined | never ? never : X) : never;
23
+ type QueryOf<O> = ParamsOf<O> extends {
24
+ query?: infer X;
25
+ } ? (X extends undefined | never ? never : X) : never;
26
+ type HeaderOf<O> = ParamsOf<O> extends {
27
+ header?: infer X;
28
+ } ? (X extends undefined | never ? never : X) : never;
29
+ type BodyOf<O> = O extends {
30
+ requestBody?: infer R;
31
+ } ? R extends {
32
+ content: {
33
+ 'application/json': infer B;
34
+ };
35
+ } ? B : never : never;
36
+ /** Present a key in the options object only when the operation actually defines it. */
37
+ type Opt<K extends string, V> = [V] extends [never] ? Record<never, never> : {
38
+ [P in K]: V;
39
+ };
40
+ export type RequestOptions<P extends keyof paths, M extends HttpMethod> = Opt<'path', PathParamsOf<Op<P, M>>> & Opt<'query', QueryOf<Op<P, M>>> & Opt<'headers', HeaderOf<Op<P, M>>> & Opt<'body', BodyOf<Op<P, M>>> & {
41
+ /** A per-request signal for cancellation/timeouts. */
42
+ signal?: AbortSignal;
43
+ };
44
+ export interface SovEcomClientOptions {
45
+ /** API origin, e.g. `https://api.example.com` (no trailing slash required). */
46
+ baseUrl: string;
47
+ /** Returns the customer bearer token (JWT) to send as `Authorization`, if any. Sync or async. */
48
+ getToken?: () => string | undefined | null | Promise<string | undefined | null>;
49
+ /** Default headers merged into every request (e.g. a cart token your app manages). */
50
+ headers?: Record<string, string>;
51
+ /** Override the fetch implementation (tests, non-browser runtimes). Defaults to global `fetch`. */
52
+ fetch?: typeof fetch;
53
+ }
54
+ /** Thrown for any non-2xx response. Carries the status + parsed body (never a secret in the URL). */
55
+ export declare class SovEcomApiError extends Error {
56
+ readonly status: number;
57
+ readonly statusText: string;
58
+ readonly body: unknown;
59
+ constructor(status: number, statusText: string, body: unknown);
60
+ }
61
+ export interface SovEcomClient {
62
+ /** Low-level typed request. `TResponse` defaults to `unknown` (the spec carries no response bodies). */
63
+ request<P extends PathFor<M>, M extends HttpMethod, TResponse = unknown>(method: M, path: P, options?: RequestOptions<P, M>): Promise<TResponse>;
64
+ /** Create an order from a cart (cart cookie token must be supplied via `headers`/`getToken`). */
65
+ checkout<TResponse = unknown>(cartId: string): Promise<TResponse>;
66
+ /** Guest order lookup — the token travels in the `X-Order-Token` header, never the URL. */
67
+ getOrderByNumber<TResponse = unknown>(orderNumber: string, orderToken: string): Promise<TResponse>;
68
+ }
69
+ export declare function createSovEcomClient(options: SovEcomClientOptions): SovEcomClient;
70
+ export {};
71
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,102 @@
1
+ /** Thrown for any non-2xx response. Carries the status + parsed body (never a secret in the URL). */
2
+ export class SovEcomApiError extends Error {
3
+ status;
4
+ statusText;
5
+ body;
6
+ constructor(status, statusText, body) {
7
+ super(`SovEcom API ${status} ${statusText}`);
8
+ this.status = status;
9
+ this.statusText = statusText;
10
+ this.body = body;
11
+ this.name = 'SovEcomApiError';
12
+ }
13
+ }
14
+ function fillPath(path, params) {
15
+ return path.replace(/\{([^}]+)\}/g, (_m, key) => {
16
+ const value = params?.[key];
17
+ if (value === undefined || value === null) {
18
+ throw new Error(`Missing path parameter "${key}" for ${path}`);
19
+ }
20
+ return encodeURIComponent(String(value));
21
+ });
22
+ }
23
+ function buildQuery(query) {
24
+ if (!query)
25
+ return '';
26
+ const usp = new URLSearchParams();
27
+ for (const [key, value] of Object.entries(query)) {
28
+ if (value === undefined || value === null)
29
+ continue;
30
+ if (Array.isArray(value)) {
31
+ for (const v of value)
32
+ usp.append(key, String(v));
33
+ }
34
+ else {
35
+ usp.append(key, String(value));
36
+ }
37
+ }
38
+ const qs = usp.toString();
39
+ return qs ? `?${qs}` : '';
40
+ }
41
+ export function createSovEcomClient(options) {
42
+ const baseUrl = options.baseUrl.replace(/\/+$/, '');
43
+ const doFetch = options.fetch ?? globalThis.fetch;
44
+ if (typeof doFetch !== 'function') {
45
+ throw new Error('No fetch implementation available; pass `fetch` in SovEcomClientOptions.');
46
+ }
47
+ async function request(method, path, opts) {
48
+ const o = (opts ?? {});
49
+ const url = `${baseUrl}${fillPath(path, o.path)}${buildQuery(o.query)}`;
50
+ // A `Headers` instance is case-INSENSITIVE, so a caller-supplied `content-type` /
51
+ // `authorization` (any casing) is recognised rather than silently duplicated. Per-request
52
+ // headers override the client defaults; an explicit caller `Authorization` is NOT clobbered
53
+ // by `getToken` (the bearer only fills in when the caller didn't set one).
54
+ const headers = new Headers(options.headers);
55
+ if (o.headers) {
56
+ for (const [k, v] of Object.entries(o.headers))
57
+ headers.set(k, v);
58
+ }
59
+ const token = options.getToken ? await options.getToken() : undefined;
60
+ if (token && !headers.has('authorization'))
61
+ headers.set('authorization', `Bearer ${token}`);
62
+ const hasBody = o.body !== undefined;
63
+ if (hasBody && !headers.has('content-type'))
64
+ headers.set('content-type', 'application/json');
65
+ const res = await doFetch(url, {
66
+ method: method.toUpperCase(),
67
+ headers,
68
+ body: hasBody ? JSON.stringify(o.body) : undefined,
69
+ signal: o.signal,
70
+ });
71
+ const text = await res.text();
72
+ const parsed = text ? safeJson(text) : undefined;
73
+ if (!res.ok) {
74
+ throw new SovEcomApiError(res.status, res.statusText, parsed);
75
+ }
76
+ return parsed;
77
+ }
78
+ return {
79
+ request,
80
+ // NB: these convenience methods pass UNCAST option objects on purpose — if the spec drifts
81
+ // (a path/param/header renamed), regeneration changes `paths` and these stop compiling, which
82
+ // (with the CI regen-diff guard) surfaces the drift instead of silently sending a wrong request.
83
+ checkout(cartId) {
84
+ return request('post', '/store/v1/carts/{cartId}/checkout', { path: { cartId } });
85
+ },
86
+ getOrderByNumber(orderNumber, orderToken) {
87
+ return request('get', '/store/v1/orders/by-number/{orderNumber}', {
88
+ path: { orderNumber },
89
+ headers: { 'x-order-token': orderToken },
90
+ });
91
+ },
92
+ };
93
+ }
94
+ function safeJson(text) {
95
+ try {
96
+ return JSON.parse(text);
97
+ }
98
+ catch {
99
+ return text;
100
+ }
101
+ }
102
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}