@deliverart/sdk-js-core 0.0.7 → 0.1.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @deliverart/sdk-js-core
2
2
 
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - dd33eb4: Implement Request Response call
8
+
3
9
  ## 0.0.7
4
10
 
5
11
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -30,16 +30,90 @@ 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,
33
34
  createApiClient: () => createApiClient
34
35
  });
35
36
  module.exports = __toCommonJS(index_exports);
36
37
 
37
38
  // src/ApiClient.ts
38
39
  var import_axios = __toESM(require("axios"), 1);
40
+
41
+ // src/errors.ts
42
+ var InputValidationError = class extends Error {
43
+ // eslint-disable-next-line no-unused-vars
44
+ constructor(issues) {
45
+ super("Invalid input");
46
+ this.issues = issues;
47
+ this.name = "InputValidationError";
48
+ }
49
+ };
50
+ var OutputValidationError = class extends Error {
51
+ // eslint-disable-next-line no-unused-vars
52
+ constructor(issues) {
53
+ super("Invalid response");
54
+ this.issues = issues;
55
+ this.name = "OutputValidationError";
56
+ }
57
+ };
58
+
59
+ // src/ApiClient.ts
60
+ var AbstractApiRequest = class {
61
+ constructor(input, options) {
62
+ this.input = input;
63
+ this.options = options;
64
+ }
65
+ validateInput() {
66
+ const result = this.inputSchema.safeParse(this.input);
67
+ if (!result.success) {
68
+ throw new InputValidationError(result.error.issues);
69
+ }
70
+ return result.data;
71
+ }
72
+ validateQuery() {
73
+ if (!this.querySchema || !this.options?.query) return void 0;
74
+ const result = this.querySchema.safeParse(this.options.query);
75
+ if (!result.success) {
76
+ throw new InputValidationError(result.error.issues);
77
+ }
78
+ return result.data;
79
+ }
80
+ validateHeaders() {
81
+ if (!this.headersSchema || !this.options?.headers) return void 0;
82
+ const result = this.headersSchema.safeParse(this.options.headers);
83
+ if (!result.success) {
84
+ throw new InputValidationError(result.error.issues);
85
+ }
86
+ return result.data;
87
+ }
88
+ validateOutput(data) {
89
+ const result = this.outputSchema.safeParse(data);
90
+ if (!result.success) {
91
+ throw new OutputValidationError(result.error.issues);
92
+ }
93
+ return result.data;
94
+ }
95
+ };
39
96
  function createApiClient(config) {
40
97
  const http = import_axios.default.create({ baseURL: config.baseUrl });
41
98
  const base = {
42
99
  http,
100
+ async call(request) {
101
+ const input = request.validateInput();
102
+ const query = request.validateQuery();
103
+ const headers = request.validateHeaders();
104
+ const res = await http.request({
105
+ url: request.getPath(),
106
+ method: request.method,
107
+ headers: {
108
+ "Content-Type": request.contentType,
109
+ Accept: request.accept,
110
+ ...headers ?? {}
111
+ },
112
+ params: query,
113
+ data: request.method !== "GET" ? input : void 0
114
+ });
115
+ return request.validateOutput(res.data);
116
+ },
43
117
  addPlugin(plugin) {
44
118
  const extension = plugin.setup(this);
45
119
  return { ...this, ...extension };
@@ -49,5 +123,6 @@ function createApiClient(config) {
49
123
  }
50
124
  // Annotate the CommonJS export names for ESM import in node:
51
125
  0 && (module.exports = {
126
+ AbstractApiRequest,
52
127
  createApiClient
53
128
  });
package/dist/index.d.cts CHANGED
@@ -1,17 +1,42 @@
1
1
  import { AxiosInstance } from 'axios';
2
+ import { ZodSchema } 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
+ export { AbstractApiRequest, type ApiClient, type ApiClientPlugin, type ApiExtension, createApiClient };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,42 @@
1
1
  import { AxiosInstance } from 'axios';
2
+ import { ZodSchema } 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
+ export { AbstractApiRequest, type ApiClient, type ApiClientPlugin, type ApiExtension, 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,6 @@ function createApiClient(config) {
12
85
  return base;
13
86
  }
14
87
  export {
88
+ AbstractApiRequest,
15
89
  createApiClient
16
90
  };
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.0",
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
+ }