@deliverart/sdk-js-core 0.0.7 → 0.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @deliverart/sdk-js-core
2
2
 
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 20b57df: Expose errors
8
+
9
+ ## 0.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - dd33eb4: Implement Request Response call
14
+
3
15
  ## 0.0.7
4
16
 
5
17
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -30,16 +30,92 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AbstractApiRequest: () => AbstractApiRequest,
34
+ InputValidationError: () => InputValidationError,
35
+ OutputValidationError: () => OutputValidationError,
33
36
  createApiClient: () => createApiClient
34
37
  });
35
38
  module.exports = __toCommonJS(index_exports);
36
39
 
37
40
  // src/ApiClient.ts
38
41
  var import_axios = __toESM(require("axios"), 1);
42
+
43
+ // src/errors.ts
44
+ var InputValidationError = class extends Error {
45
+ // eslint-disable-next-line no-unused-vars
46
+ constructor(issues) {
47
+ super("Invalid input");
48
+ this.issues = issues;
49
+ this.name = "InputValidationError";
50
+ }
51
+ };
52
+ var OutputValidationError = class extends Error {
53
+ // eslint-disable-next-line no-unused-vars
54
+ constructor(issues) {
55
+ super("Invalid response");
56
+ this.issues = issues;
57
+ this.name = "OutputValidationError";
58
+ }
59
+ };
60
+
61
+ // src/ApiClient.ts
62
+ var AbstractApiRequest = class {
63
+ constructor(input, options) {
64
+ this.input = input;
65
+ this.options = options;
66
+ }
67
+ validateInput() {
68
+ const result = this.inputSchema.safeParse(this.input);
69
+ if (!result.success) {
70
+ throw new InputValidationError(result.error.issues);
71
+ }
72
+ return result.data;
73
+ }
74
+ validateQuery() {
75
+ if (!this.querySchema || !this.options?.query) return void 0;
76
+ const result = this.querySchema.safeParse(this.options.query);
77
+ if (!result.success) {
78
+ throw new InputValidationError(result.error.issues);
79
+ }
80
+ return result.data;
81
+ }
82
+ validateHeaders() {
83
+ if (!this.headersSchema || !this.options?.headers) return void 0;
84
+ const result = this.headersSchema.safeParse(this.options.headers);
85
+ if (!result.success) {
86
+ throw new InputValidationError(result.error.issues);
87
+ }
88
+ return result.data;
89
+ }
90
+ validateOutput(data) {
91
+ const result = this.outputSchema.safeParse(data);
92
+ if (!result.success) {
93
+ throw new OutputValidationError(result.error.issues);
94
+ }
95
+ return result.data;
96
+ }
97
+ };
39
98
  function createApiClient(config) {
40
99
  const http = import_axios.default.create({ baseURL: config.baseUrl });
41
100
  const base = {
42
101
  http,
102
+ async call(request) {
103
+ const input = request.validateInput();
104
+ const query = request.validateQuery();
105
+ const headers = request.validateHeaders();
106
+ const res = await http.request({
107
+ url: request.getPath(),
108
+ method: request.method,
109
+ headers: {
110
+ "Content-Type": request.contentType,
111
+ Accept: request.accept,
112
+ ...headers ?? {}
113
+ },
114
+ params: query,
115
+ data: request.method !== "GET" ? input : void 0
116
+ });
117
+ return request.validateOutput(res.data);
118
+ },
43
119
  addPlugin(plugin) {
44
120
  const extension = plugin.setup(this);
45
121
  return { ...this, ...extension };
@@ -49,5 +125,8 @@ function createApiClient(config) {
49
125
  }
50
126
  // Annotate the CommonJS export names for ESM import in node:
51
127
  0 && (module.exports = {
128
+ AbstractApiRequest,
129
+ InputValidationError,
130
+ OutputValidationError,
52
131
  createApiClient
53
132
  });
package/dist/index.d.cts CHANGED
@@ -1,17 +1,51 @@
1
1
  import { AxiosInstance } from 'axios';
2
+ import { ZodSchema, ZodIssue } from 'zod';
2
3
 
3
4
  type ApiExtension = Record<string, unknown>;
4
5
  interface ApiClientPlugin<T extends ApiExtension = Record<string, unknown>> {
5
6
  setup: (client: ApiClient<Record<string, unknown>>) => T;
6
7
  }
7
8
 
8
- declare function createApiClient<Extensions extends ApiExtension = NonNullable<unknown>>(config: {
9
- baseUrl: string;
10
- }): ApiClient<Extensions>;
9
+ declare abstract class AbstractApiRequest<Input, Output, Query = unknown, Headers = unknown> {
10
+ readonly input: Input;
11
+ readonly options?: {
12
+ query?: Query;
13
+ headers?: Headers;
14
+ } | undefined;
15
+ abstract readonly method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
16
+ abstract readonly contentType: 'application/json' | 'multipart/form-data' | 'application/merge-patch+json';
17
+ abstract readonly accept: 'application/json';
18
+ abstract readonly inputSchema: ZodSchema<Input>;
19
+ abstract readonly outputSchema: ZodSchema<Output>;
20
+ abstract readonly querySchema?: ZodSchema<Query>;
21
+ abstract readonly headersSchema?: ZodSchema<Headers>;
22
+ protected constructor(input: Input, options?: {
23
+ query?: Query;
24
+ headers?: Headers;
25
+ } | undefined);
26
+ abstract getPath(): string;
27
+ validateInput(): Input;
28
+ validateQuery(): Query | undefined;
29
+ validateHeaders(): Headers | undefined;
30
+ validateOutput(data: unknown): Output;
31
+ }
11
32
  interface ApiClientBase {
12
33
  http: AxiosInstance;
13
34
  addPlugin: <T extends ApiExtension>(plugin: ApiClientPlugin<T>) => ApiClient<T>;
35
+ call<I, O, Q, H>(request: AbstractApiRequest<I, O, Q, H>): Promise<O>;
14
36
  }
37
+ declare function createApiClient<Extensions extends ApiExtension = NonNullable<unknown>>(config: {
38
+ baseUrl: string;
39
+ }): ApiClient<Extensions>;
15
40
  type ApiClient<Extensions extends ApiExtension = NonNullable<unknown>> = ApiClientBase & Extensions;
16
41
 
17
- export { type ApiClient, type ApiClientPlugin, type ApiExtension, createApiClient };
42
+ declare class InputValidationError extends Error {
43
+ readonly issues: ZodIssue[];
44
+ constructor(issues: ZodIssue[]);
45
+ }
46
+ declare class OutputValidationError extends Error {
47
+ readonly issues: ZodIssue[];
48
+ constructor(issues: ZodIssue[]);
49
+ }
50
+
51
+ export { AbstractApiRequest, type ApiClient, type ApiClientPlugin, type ApiExtension, InputValidationError, OutputValidationError, createApiClient };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,51 @@
1
1
  import { AxiosInstance } from 'axios';
2
+ import { ZodSchema, ZodIssue } from 'zod';
2
3
 
3
4
  type ApiExtension = Record<string, unknown>;
4
5
  interface ApiClientPlugin<T extends ApiExtension = Record<string, unknown>> {
5
6
  setup: (client: ApiClient<Record<string, unknown>>) => T;
6
7
  }
7
8
 
8
- declare function createApiClient<Extensions extends ApiExtension = NonNullable<unknown>>(config: {
9
- baseUrl: string;
10
- }): ApiClient<Extensions>;
9
+ declare abstract class AbstractApiRequest<Input, Output, Query = unknown, Headers = unknown> {
10
+ readonly input: Input;
11
+ readonly options?: {
12
+ query?: Query;
13
+ headers?: Headers;
14
+ } | undefined;
15
+ abstract readonly method: 'GET' | 'POST' | 'PATCH' | 'DELETE';
16
+ abstract readonly contentType: 'application/json' | 'multipart/form-data' | 'application/merge-patch+json';
17
+ abstract readonly accept: 'application/json';
18
+ abstract readonly inputSchema: ZodSchema<Input>;
19
+ abstract readonly outputSchema: ZodSchema<Output>;
20
+ abstract readonly querySchema?: ZodSchema<Query>;
21
+ abstract readonly headersSchema?: ZodSchema<Headers>;
22
+ protected constructor(input: Input, options?: {
23
+ query?: Query;
24
+ headers?: Headers;
25
+ } | undefined);
26
+ abstract getPath(): string;
27
+ validateInput(): Input;
28
+ validateQuery(): Query | undefined;
29
+ validateHeaders(): Headers | undefined;
30
+ validateOutput(data: unknown): Output;
31
+ }
11
32
  interface ApiClientBase {
12
33
  http: AxiosInstance;
13
34
  addPlugin: <T extends ApiExtension>(plugin: ApiClientPlugin<T>) => ApiClient<T>;
35
+ call<I, O, Q, H>(request: AbstractApiRequest<I, O, Q, H>): Promise<O>;
14
36
  }
37
+ declare function createApiClient<Extensions extends ApiExtension = NonNullable<unknown>>(config: {
38
+ baseUrl: string;
39
+ }): ApiClient<Extensions>;
15
40
  type ApiClient<Extensions extends ApiExtension = NonNullable<unknown>> = ApiClientBase & Extensions;
16
41
 
17
- export { type ApiClient, type ApiClientPlugin, type ApiExtension, createApiClient };
42
+ declare class InputValidationError extends Error {
43
+ readonly issues: ZodIssue[];
44
+ constructor(issues: ZodIssue[]);
45
+ }
46
+ declare class OutputValidationError extends Error {
47
+ readonly issues: ZodIssue[];
48
+ constructor(issues: ZodIssue[]);
49
+ }
50
+
51
+ export { AbstractApiRequest, type ApiClient, type ApiClientPlugin, type ApiExtension, InputValidationError, OutputValidationError, createApiClient };
package/dist/index.js CHANGED
@@ -1,9 +1,82 @@
1
1
  // src/ApiClient.ts
2
2
  import axios from "axios";
3
+
4
+ // src/errors.ts
5
+ var InputValidationError = class extends Error {
6
+ // eslint-disable-next-line no-unused-vars
7
+ constructor(issues) {
8
+ super("Invalid input");
9
+ this.issues = issues;
10
+ this.name = "InputValidationError";
11
+ }
12
+ };
13
+ var OutputValidationError = class extends Error {
14
+ // eslint-disable-next-line no-unused-vars
15
+ constructor(issues) {
16
+ super("Invalid response");
17
+ this.issues = issues;
18
+ this.name = "OutputValidationError";
19
+ }
20
+ };
21
+
22
+ // src/ApiClient.ts
23
+ var AbstractApiRequest = class {
24
+ constructor(input, options) {
25
+ this.input = input;
26
+ this.options = options;
27
+ }
28
+ validateInput() {
29
+ const result = this.inputSchema.safeParse(this.input);
30
+ if (!result.success) {
31
+ throw new InputValidationError(result.error.issues);
32
+ }
33
+ return result.data;
34
+ }
35
+ validateQuery() {
36
+ if (!this.querySchema || !this.options?.query) return void 0;
37
+ const result = this.querySchema.safeParse(this.options.query);
38
+ if (!result.success) {
39
+ throw new InputValidationError(result.error.issues);
40
+ }
41
+ return result.data;
42
+ }
43
+ validateHeaders() {
44
+ if (!this.headersSchema || !this.options?.headers) return void 0;
45
+ const result = this.headersSchema.safeParse(this.options.headers);
46
+ if (!result.success) {
47
+ throw new InputValidationError(result.error.issues);
48
+ }
49
+ return result.data;
50
+ }
51
+ validateOutput(data) {
52
+ const result = this.outputSchema.safeParse(data);
53
+ if (!result.success) {
54
+ throw new OutputValidationError(result.error.issues);
55
+ }
56
+ return result.data;
57
+ }
58
+ };
3
59
  function createApiClient(config) {
4
60
  const http = axios.create({ baseURL: config.baseUrl });
5
61
  const base = {
6
62
  http,
63
+ async call(request) {
64
+ const input = request.validateInput();
65
+ const query = request.validateQuery();
66
+ const headers = request.validateHeaders();
67
+ const res = await http.request({
68
+ url: request.getPath(),
69
+ method: request.method,
70
+ headers: {
71
+ "Content-Type": request.contentType,
72
+ Accept: request.accept,
73
+ ...headers ?? {}
74
+ },
75
+ params: query,
76
+ data: request.method !== "GET" ? input : void 0
77
+ });
78
+ return request.validateOutput(res.data);
79
+ },
7
80
  addPlugin(plugin) {
8
81
  const extension = plugin.setup(this);
9
82
  return { ...this, ...extension };
@@ -12,5 +85,8 @@ function createApiClient(config) {
12
85
  return base;
13
86
  }
14
87
  export {
88
+ AbstractApiRequest,
89
+ InputValidationError,
90
+ OutputValidationError,
15
91
  createApiClient
16
92
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deliverart/sdk-js-core",
3
3
  "description": "Core SDK for DeliverArt, providing essential functionalities and utilities.",
4
- "version": "0.0.7",
4
+ "version": "0.1.1",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -12,7 +12,8 @@
12
12
  }
13
13
  },
14
14
  "dependencies": {
15
- "axios": "1.9.0"
15
+ "axios": "1.9.0",
16
+ "zod": "3.25.67"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@changesets/cli": "^2.29.4",
package/src/ApiClient.ts CHANGED
@@ -1,7 +1,78 @@
1
1
  import axios, { AxiosInstance } from 'axios'
2
+ import { ZodSchema } from 'zod'
2
3
 
4
+ import { InputValidationError, OutputValidationError } from './errors'
3
5
  import type { ApiClientPlugin, ApiExtension } from './types'
4
6
 
7
+ export abstract class AbstractApiRequest<Input, Output, Query = unknown, Headers = unknown> {
8
+ abstract readonly method: 'GET' | 'POST' | 'PATCH' | 'DELETE'
9
+ abstract readonly contentType:
10
+ | 'application/json'
11
+ | 'multipart/form-data'
12
+ | 'application/merge-patch+json'
13
+ abstract readonly accept: 'application/json'
14
+ abstract readonly inputSchema: ZodSchema<Input>
15
+ abstract readonly outputSchema: ZodSchema<Output>
16
+ abstract readonly querySchema?: ZodSchema<Query>
17
+ abstract readonly headersSchema?: ZodSchema<Headers>
18
+
19
+ protected constructor(
20
+ // eslint-disable-next-line no-unused-vars
21
+ public readonly input: Input,
22
+ // eslint-disable-next-line no-unused-vars
23
+ public readonly options?: {
24
+ query?: Query
25
+ headers?: Headers
26
+ },
27
+ ) {}
28
+
29
+ abstract getPath(): string
30
+
31
+ validateInput(): Input {
32
+ const result = this.inputSchema.safeParse(this.input)
33
+ if (!result.success) {
34
+ throw new InputValidationError(result.error.issues)
35
+ }
36
+ return result.data
37
+ }
38
+
39
+ validateQuery(): Query | undefined {
40
+ if (!this.querySchema || !this.options?.query) return undefined
41
+
42
+ const result = this.querySchema.safeParse(this.options.query)
43
+ if (!result.success) {
44
+ throw new InputValidationError(result.error.issues)
45
+ }
46
+ return result.data
47
+ }
48
+
49
+ validateHeaders(): Headers | undefined {
50
+ if (!this.headersSchema || !this.options?.headers) return undefined
51
+
52
+ const result = this.headersSchema.safeParse(this.options.headers)
53
+ if (!result.success) {
54
+ throw new InputValidationError(result.error.issues)
55
+ }
56
+ return result.data
57
+ }
58
+
59
+ validateOutput(data: unknown): Output {
60
+ const result = this.outputSchema.safeParse(data)
61
+ if (!result.success) {
62
+ throw new OutputValidationError(result.error.issues)
63
+ }
64
+ return result.data
65
+ }
66
+ }
67
+
68
+ interface ApiClientBase {
69
+ http: AxiosInstance
70
+ // eslint-disable-next-line no-unused-vars
71
+ addPlugin: <T extends ApiExtension>(plugin: ApiClientPlugin<T>) => ApiClient<T>
72
+ // eslint-disable-next-line no-unused-vars
73
+ call<I, O, Q, H>(request: AbstractApiRequest<I, O, Q, H>): Promise<O>
74
+ }
75
+
5
76
  export function createApiClient<Extensions extends ApiExtension = NonNullable<unknown>>(config: {
6
77
  baseUrl: string
7
78
  }): ApiClient<Extensions> {
@@ -9,6 +80,27 @@ export function createApiClient<Extensions extends ApiExtension = NonNullable<un
9
80
 
10
81
  const base: ApiClientBase = {
11
82
  http,
83
+
84
+ async call<I, O, Q, H>(request: AbstractApiRequest<I, O, Q, H>): Promise<O> {
85
+ const input = request.validateInput()
86
+ const query = request.validateQuery()
87
+ const headers = request.validateHeaders()
88
+
89
+ const res = await http.request({
90
+ url: request.getPath(),
91
+ method: request.method,
92
+ headers: {
93
+ 'Content-Type': request.contentType,
94
+ Accept: request.accept,
95
+ ...(headers ?? {}),
96
+ },
97
+ params: query,
98
+ data: request.method !== 'GET' ? input : undefined,
99
+ })
100
+
101
+ return request.validateOutput(res.data)
102
+ },
103
+
12
104
  addPlugin<T extends ApiExtension>(plugin: ApiClientPlugin<T>) {
13
105
  const extension = plugin.setup(this as ApiClient<Extensions & T>)
14
106
  return { ...this, ...extension } as ApiClient<Extensions & T>
@@ -18,11 +110,5 @@ export function createApiClient<Extensions extends ApiExtension = NonNullable<un
18
110
  return base as ApiClient<Extensions>
19
111
  }
20
112
 
21
- interface ApiClientBase {
22
- http: AxiosInstance
23
- // eslint-disable-next-line no-unused-vars
24
- addPlugin: <T extends ApiExtension>(plugin: ApiClientPlugin<T>) => ApiClient<T>
25
- }
26
-
27
113
  export type ApiClient<Extensions extends ApiExtension = NonNullable<unknown>> = ApiClientBase &
28
114
  Extensions
package/src/errors.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { ZodIssue } from 'zod'
2
+
3
+ export class InputValidationError extends Error {
4
+ // eslint-disable-next-line no-unused-vars
5
+ constructor(public readonly issues: ZodIssue[]) {
6
+ super('Invalid input')
7
+ this.name = 'InputValidationError'
8
+ }
9
+ }
10
+
11
+ export class OutputValidationError extends Error {
12
+ // eslint-disable-next-line no-unused-vars
13
+ constructor(public readonly issues: ZodIssue[]) {
14
+ super('Invalid response')
15
+ this.name = 'OutputValidationError'
16
+ }
17
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './ApiClient'
2
+ export * from './errors'
2
3
  export * from './types'