sizebay-core-sdk 1.0.0 → 1.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,3 +1,16 @@
1
+ ## [1.1.0](https://github.com/sizebay/events-sdk/compare/v1.0.1...v1.1.0) (2025-04-01)
2
+
3
+ ### Features
4
+
5
+ * **tracker:** update TrackData types and documentation ([e7187f2](https://github.com/sizebay/events-sdk/commit/e7187f2ca7b5d0ecee3404b19bf3fa21f8c14953))
6
+
7
+ ## [1.0.1](https://github.com/sizebay/events-sdk/compare/v1.0.0...v1.0.1) (2025-04-01)
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ai-image-service:** correct endpoint configuration ([cc7c8f4](https://github.com/sizebay/events-sdk/commit/cc7c8f41b4961e6fdca62d87ef3de152351064cd))
12
+ * **tracker:** update URL construction logic ([7be913c](https://github.com/sizebay/events-sdk/commit/7be913c8b81dfdd1543d4d843a83753955f5b83a))
13
+
1
14
  ## 1.0.0 (2025-03-31)
2
15
 
3
16
  ### Features
package/README.md CHANGED
@@ -35,25 +35,63 @@ const client = createClient({
35
35
 
36
36
  ---
37
37
 
38
- ### Tracker Module
38
+ ## Tracker Module
39
39
 
40
- #### `track(eventName: string, payload: EventPayload): Promise<any>`
41
- Sends an event to the designated API endpoint.
40
+ #### `track(eventName: string, payload: TrackData): Promise<TrackResponse>`
41
+ Sends an event to the designated API endpoint, returning a standardized response.
42
42
 
43
43
  **Parameters**
44
44
 
45
- | Parameter | Type | Required | Description |
46
- |--------------|----------------|----------|--------------------------------------------------|
47
- | `eventName` | `string` | Yes | The name of the event (e.g., "ADD_TO_CART", "ORDER"). |
48
- | `payload` | `EventPayload` | Yes | An object containing event data. |
45
+ | Parameter | Type | Required | Description |
46
+ |-------------|-------------|----------|-----------------------------------------------------------------------|
47
+ | `eventName` | `string` | Yes | The name of the event (e.g., "ADD_TO_CART", "ORDER"). |
48
+ | `payload` | `TrackData` | Yes | An object containing event data. See the structure of `TrackData` below. |
49
+
50
+ **TrackData Structure**
51
+
52
+ | Property | Type | Required | Description |
53
+ |-------------|-------------------------------|----------|-----------------------------------------------------------------------|
54
+ | **sid** | `string` | Yes | Unique session identifier. |
55
+ | **tenantId**| `number` | Yes | Identifier of the tenant (client) sending the event. |
56
+ | **sessionId**| `number` | Yes | Internal session identifier. |
57
+ | **permalink**| `string` (optional) | No | Product URL associated with the event. When the event is linked to product (e.g., ADD_TO_CART RECOMMENDATION_DONE), it is required. |
58
+ | **properties**| `Record<string, JSONValue>` | Yes | Object containing additional properties as key-value pairs. |
59
+ **Returns**
60
+
61
+ - **201** – Event successfully created.
62
+ ```json
63
+ {
64
+ "statusCode": 201,
65
+ "message": "Event successfully created."
66
+ }
67
+ ```
68
+ - **400** – Invalid or missing fields.
69
+ ```json
70
+ {
71
+ "statusCode": 400,
72
+ "error": "Bad Request",
73
+ "message": [
74
+ "tenantId must be an integer number"
75
+ ]
76
+ }
77
+ ```
78
+ - **500** – Internal server error.
79
+ ```json
80
+ {
81
+ "statusCode": 500,
82
+ "error": "Internal server error",
83
+ "message": [
84
+ "Unexpected error on server side"
85
+ ]
86
+ }
87
+ ```
49
88
 
50
89
  **Example**
51
90
 
52
91
  ```typescript
53
- const eventPayload = {
92
+ const eventPayload: TrackData = {
54
93
  sid: 'a0cf8559-926a-4a75-b4ca-7c4c13fed69c',
55
94
  tenantId: 123,
56
- eventName: 'ADD_TO_CART',
57
95
  sessionId: 123,
58
96
  permalink: 'https://www.example.com/2IC-7370',
59
97
  properties: {
@@ -66,40 +104,63 @@ const eventPayload = {
66
104
  async function trackEvent() {
67
105
  try {
68
106
  const response = await client.track('ADD_TO_CART', eventPayload);
69
- console.log('Event tracked successfully:', response);
107
+
108
+ if (response.statusCode === 201) {
109
+ console.log('Event tracked successfully:', response.message);
110
+ } else {
111
+ console.error(
112
+ `Error tracking event (${response.statusCode}):`,
113
+ response.error,
114
+ response.message
115
+ );
116
+ }
70
117
  } catch (error: any) {
71
- console.error('Error tracking event:', error.message);
118
+ console.error('Unexpected error tracking event:', error.message);
72
119
  }
73
120
  }
74
121
 
75
122
  trackEvent();
76
123
  ```
77
124
 
78
- ---
125
+ ## AI Image Service Module
79
126
 
80
- ### AI Image Service Module
127
+ ### `getSimilarProducts(params: GetSimilarProductsParams): Promise<GetSimilarProductsResponse>`
81
128
 
82
- #### `getSimilarProducts(params: GetSimilarProductsParams): Promise<GetSimilarProductsResponse>`
83
- Fetches similar products based on the provided image parameters.
129
+ Fetches similar products based on the given parameters, returning a paginated result.
84
130
 
85
- **Parameters**
131
+ #### Parameters
86
132
 
87
- | Parameter | Type | Required | Description |
88
- |-----------|----------------------------|----------|------------------------------------------------------------|
89
- | `params` | `GetSimilarProductsParams` | Yes | An object containing parameters for fetching similar products. |
133
+ | Parameter | Type | Required | Description |
134
+ |------------------|--------------------------------|:--------:|------------------------------------------------------------------------------------------|
135
+ | `tenantId` | `number` | **Yes** | The tenant ID that initiated the request. |
136
+ | `collectionName` | `string` | **Yes** | The name of the relevant product collection. |
137
+ | `sessionId` | `number` | **Yes** | The session ID, typically required for internal event tracking. |
138
+ | `permalink` | `string` | **Yes** | A permanent link representing the main product. |
139
+ | `page` | `number` (optional) | No | Page number for pagination. |
140
+ | `perPage` | `number` (optional) | No | Number of items per page. |
90
141
 
91
- **Example**
142
+ #### Returns
143
+
144
+ **`Promise<GetSimilarProductsResponse>`**
145
+ An object containing:
146
+
147
+ - `data`: An array of `Product` objects.
148
+ - `page`: The current page number.
149
+ - `perPage`: The number of items per page.
150
+ - `total`: The total number of items available.
151
+
152
+ #### Example
92
153
 
93
154
  ```typescript
94
- import { GetSimilarProductsParams } from 'sizebay-core-sdk/types/ai-image-service';
155
+ import { GetSimilarProductsParams } from 'sizebay-core-sdk';
95
156
 
96
157
  const params: GetSimilarProductsParams = {
97
158
  tenantId: 123,
98
159
  permalink: 'https://example.com/product',
99
- collectionName: 'summer-collection', // optional
100
- sessionId: 456, // optional
101
- page: 1, // optional
102
- perPage: 10, // optional
160
+ collectionName: 'summer-collection',
161
+ sessionId: 456,
162
+ page: 1,
163
+ perPage: 10,
103
164
  };
104
165
 
105
166
  async function fetchSimilarProducts() {
@@ -112,4 +173,57 @@ async function fetchSimilarProducts() {
112
173
  }
113
174
 
114
175
  fetchSimilarProducts();
115
- ```
176
+ ```
177
+
178
+ ---
179
+
180
+ ### `GetRecommendedSizeByProducts(payload: GetRecommendedSizeByProductsParams): Promise<GetRecommendedSizeByProductsResponse[]>`
181
+
182
+ Retrieves the recommended sizes for one or more products based on the provided parameters.
183
+
184
+ #### Parameters
185
+
186
+ | Parameter | Type | Required | Description |
187
+ |-------------:|-------------------------|:--------:|----------------------------------------------------------------------------------------------------------------|
188
+ | `tenantId` | `number` | **Yes** | The tenant ID that initiated the request. |
189
+ | `sid` | `string` (optional) | No | The session ID for internal events, if needed. |
190
+ | `sizeSystem` | `string` | **Yes** | The size system (e.g., 'BR', 'US', 'EU'). |
191
+ | `permalinks` | `string[]` | **Yes** | A list of product permalinks for which size recommendations are requested. |
192
+
193
+ #### Returns
194
+
195
+ **`Promise<GetRecommendedSizeByProductsResponse[]>`**
196
+ An array of objects, each containing:
197
+
198
+ - `id`: The internal identifier for the product.
199
+ - `permalink`: The product permalink from the request.
200
+ - `recommendedSize`: The recommended size (`string`) or `null` if no recommendation is available.
201
+
202
+ #### Example
203
+
204
+ ```typescript
205
+ import { GetRecommendedSizeByProductsParams } from 'sizebay-core-sdk';
206
+
207
+ const payload: GetRecommendedSizeByProductsParams = {
208
+ tenantId: 123,
209
+ sid: '0c7f5233b325',
210
+ sizeSystem: 'BR',
211
+ permalinks: [
212
+ 'https://example.com/product1',
213
+ 'https://example.com/product2',
214
+ ],
215
+ };
216
+
217
+ async function fetchRecommendedSizes() {
218
+ try {
219
+ const response = await client.GetRecommendedSizeByProducts(payload);
220
+ response.forEach((item) => {
221
+ console.log(`Product ID: ${item.id}, Recommended Size: ${item.recommendedSize}`);
222
+ });
223
+ } catch (error: any) {
224
+ console.error('Error fetching recommended product sizes:', error.message);
225
+ }
226
+ }
227
+
228
+ fetchRecommendedSizes();
229
+ ```
@@ -1,101 +1,101 @@
1
1
  const c = {
2
2
  tracker: {
3
- production: "https://data-event-service.internalsizebay.com/events",
4
- development: "https://data-event-service.internalsizebay.com/events"
3
+ production: "https://data-event-service.internalsizebay.com",
4
+ development: "https://data-event-service.internalsizebay.com"
5
5
  },
6
6
  aiImageService: {
7
- production: "https://ai-image-service.example.com/production",
8
- development: "https://ai-image-service.example.com/development"
7
+ production: "https://ai-image-service.internalsizebay.com/",
8
+ development: "https://ai-image-service-dev.internalsizebay.com/"
9
9
  }
10
10
  // Adicione outros serviços conforme necessário
11
11
  };
12
12
  class a {
13
- constructor(r) {
14
- const o = r.env || "development";
15
- this.serviceOverrides = r.services || {}, this.endpoints = {};
13
+ constructor(e) {
14
+ const n = e.env || "development";
15
+ this.serviceOverrides = e.services || {}, this.endpoints = {};
16
16
  for (const t in c)
17
17
  if (Object.prototype.hasOwnProperty.call(c, t)) {
18
- const i = c[t][o];
19
- if (!i)
18
+ const o = c[t][n];
19
+ if (!o)
20
20
  continue;
21
- this.endpoints[t] = i;
21
+ this.endpoints[t] = o;
22
22
  }
23
23
  }
24
- getEndpoint(r) {
25
- const o = this.endpoints[r];
26
- if (!o)
24
+ getEndpoint(e) {
25
+ const n = this.endpoints[e];
26
+ if (!n)
27
27
  throw new Error(
28
- `Endpoint for service '${r}' is not configured.`
28
+ `Endpoint for service '${e}' is not configured.`
29
29
  );
30
- return o;
30
+ return n;
31
31
  }
32
- getServiceConfig(r) {
33
- return this.serviceOverrides[r] || {};
32
+ getServiceConfig(e) {
33
+ return this.serviceOverrides[e] || {};
34
34
  }
35
35
  }
36
36
  class p {
37
- constructor(r) {
38
- this.endpoint = r.getEndpoint("tracker");
37
+ constructor(e) {
38
+ this.endpoint = e.getEndpoint("tracker");
39
39
  }
40
- async track(r, o) {
40
+ async track(e, n) {
41
41
  const t = {
42
- eventName: r,
43
- ...o
44
- };
42
+ eventName: e,
43
+ ...n
44
+ }, r = new URL(`${this.endpoint}/events`);
45
45
  try {
46
- const e = await fetch(this.endpoint, {
46
+ const o = await fetch(r, {
47
47
  method: "POST",
48
48
  headers: { "Content-Type": "application/json" },
49
49
  body: JSON.stringify(t)
50
50
  });
51
- if (!e.ok) {
52
- const i = await e.text();
53
- throw new Error(`Request error: ${e.status} - ${i}`);
51
+ if (!o.ok) {
52
+ const i = await o.text();
53
+ throw new Error(`Request error: ${o.status} - ${i}`);
54
54
  }
55
- return await e.json();
56
- } catch (e) {
57
- throw e;
55
+ return await o.json();
56
+ } catch (o) {
57
+ throw o;
58
58
  }
59
59
  }
60
60
  }
61
61
  class d {
62
- constructor(r) {
63
- this.endpoint = r.getEndpoint("aiImageService");
62
+ constructor(e) {
63
+ this.endpoint = e.getEndpoint("aiImageService");
64
64
  }
65
- async getSimilarProducts(r) {
66
- const o = new URL(`${this.endpoint}/recommendations/similar`);
67
- Object.entries(r).forEach(([t, e]) => {
68
- e !== void 0 && o.searchParams.append(t, String(e));
65
+ async getSimilarProducts(e) {
66
+ const n = new URL(`${this.endpoint}/recommendations/similar`);
67
+ Object.entries(e).forEach(([t, r]) => {
68
+ r !== void 0 && n.searchParams.append(t, String(r));
69
69
  });
70
70
  try {
71
- const t = await fetch(o.toString(), {
71
+ const t = await fetch(n.toString(), {
72
72
  method: "GET",
73
73
  headers: {
74
74
  "Content-Type": "application/json"
75
75
  }
76
76
  });
77
77
  if (!t.ok) {
78
- const e = await t.text();
79
- throw new Error(`Request error: ${t.status} - ${e}`);
78
+ const r = await t.text();
79
+ throw new Error(`Request error: ${t.status} - ${r}`);
80
80
  }
81
81
  return await t.json();
82
82
  } catch (t) {
83
83
  throw new Error(`Error fetching similar products: ${t.message}`);
84
84
  }
85
85
  }
86
- async getRecommendedProductSize(r) {
87
- const o = new URL(`${this.endpoint}/recommendations/size-by-products`);
86
+ async getRecommendedSizeByProducts(e) {
87
+ const n = new URL(`${this.endpoint}/recommendations/size-by-products`);
88
88
  try {
89
- const t = await fetch(o.toString(), {
89
+ const t = await fetch(n.toString(), {
90
90
  method: "POST",
91
91
  headers: {
92
92
  "Content-Type": "application/json"
93
93
  },
94
- body: JSON.stringify(r)
94
+ body: JSON.stringify(e)
95
95
  });
96
96
  if (!t.ok) {
97
- const e = await t.text();
98
- throw new Error(`Request error: ${t.status} - ${e}`);
97
+ const r = await t.text();
98
+ throw new Error(`Request error: ${t.status} - ${r}`);
99
99
  }
100
100
  return await t.json();
101
101
  } catch (t) {
@@ -108,14 +108,14 @@ const h = [
108
108
  d
109
109
  ];
110
110
  function f(s) {
111
- const r = new a(s), o = h.map((e) => new e(r)), t = { config: r };
112
- return o.forEach((e) => {
113
- Object.getOwnPropertyNames(e).forEach((n) => {
114
- typeof e[n] == "function" && (t[n] = e[n].bind(e));
111
+ const e = new a(s), n = h.map((r) => new r(e)), t = { config: e };
112
+ return n.forEach((r) => {
113
+ Object.getOwnPropertyNames(r).forEach((i) => {
114
+ typeof r[i] == "function" && (t[i] = r[i].bind(r));
115
115
  });
116
- const i = Object.getPrototypeOf(e);
117
- Object.getOwnPropertyNames(i).forEach((n) => {
118
- n !== "constructor" && typeof e[n] == "function" && (t[n] = e[n].bind(e));
116
+ const o = Object.getPrototypeOf(r);
117
+ Object.getOwnPropertyNames(o).forEach((i) => {
118
+ i !== "constructor" && typeof r[i] == "function" && (t[i] = r[i].bind(r));
119
119
  });
120
120
  }), t;
121
121
  }
@@ -1 +1 @@
1
- (function(s,i){typeof exports=="object"&&typeof module<"u"?i(exports):typeof define=="function"&&define.amd?define(["exports"],i):(s=typeof globalThis<"u"?globalThis:s||self,i(s["sizebay-core-sdk"]={}))})(this,function(s){"use strict";const i={tracker:{production:"https://data-event-service.internalsizebay.com/events",development:"https://data-event-service.internalsizebay.com/events"},aiImageService:{production:"https://ai-image-service.example.com/production",development:"https://ai-image-service.example.com/development"}};class p{constructor(r){const o=r.env||"development";this.serviceOverrides=r.services||{},this.endpoints={};for(const e in i)if(Object.prototype.hasOwnProperty.call(i,e)){const c=i[e][o];if(!c)continue;this.endpoints[e]=c}}getEndpoint(r){const o=this.endpoints[r];if(!o)throw new Error(`Endpoint for service '${r}' is not configured.`);return o}getServiceConfig(r){return this.serviceOverrides[r]||{}}}class d{constructor(r){this.endpoint=r.getEndpoint("tracker")}async track(r,o){const e={eventName:r,...o};try{const t=await fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok){const c=await t.text();throw new Error(`Request error: ${t.status} - ${c}`)}return await t.json()}catch(t){throw t}}}class f{constructor(r){this.endpoint=r.getEndpoint("aiImageService")}async getSimilarProducts(r){const o=new URL(`${this.endpoint}/recommendations/similar`);Object.entries(r).forEach(([e,t])=>{t!==void 0&&o.searchParams.append(e,String(t))});try{const e=await fetch(o.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok){const t=await e.text();throw new Error(`Request error: ${e.status} - ${t}`)}return await e.json()}catch(e){throw new Error(`Error fetching similar products: ${e.message}`)}}async getRecommendedProductSize(r){const o=new URL(`${this.endpoint}/recommendations/size-by-products`);try{const e=await fetch(o.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)});if(!e.ok){const t=await e.text();throw new Error(`Request error: ${e.status} - ${t}`)}return await e.json()}catch(e){throw new Error(`Error fetching recommended product size: ${e.message}`)}}}const h=[d,f];function u(a){const r=new p(a),o=h.map(t=>new t(r)),e={config:r};return o.forEach(t=>{Object.getOwnPropertyNames(t).forEach(n=>{typeof t[n]=="function"&&(e[n]=t[n].bind(t))});const c=Object.getPrototypeOf(t);Object.getOwnPropertyNames(c).forEach(n=>{n!=="constructor"&&typeof t[n]=="function"&&(e[n]=t[n].bind(t))})}),e}s.createClient=u,Object.defineProperty(s,Symbol.toStringTag,{value:"Module"})});
1
+ (function(c,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(c=typeof globalThis<"u"?globalThis:c||self,s(c["sizebay-core-sdk"]={}))})(this,function(c){"use strict";const s={tracker:{production:"https://data-event-service.internalsizebay.com",development:"https://data-event-service.internalsizebay.com"},aiImageService:{production:"https://ai-image-service.internalsizebay.com/",development:"https://ai-image-service-dev.internalsizebay.com/"}};class p{constructor(t){const n=t.env||"development";this.serviceOverrides=t.services||{},this.endpoints={};for(const e in s)if(Object.prototype.hasOwnProperty.call(s,e)){const o=s[e][n];if(!o)continue;this.endpoints[e]=o}}getEndpoint(t){const n=this.endpoints[t];if(!n)throw new Error(`Endpoint for service '${t}' is not configured.`);return n}getServiceConfig(t){return this.serviceOverrides[t]||{}}}class d{constructor(t){this.endpoint=t.getEndpoint("tracker")}async track(t,n){const e={eventName:t,...n},r=new URL(`${this.endpoint}/events`);try{const o=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!o.ok){const i=await o.text();throw new Error(`Request error: ${o.status} - ${i}`)}return await o.json()}catch(o){throw o}}}class f{constructor(t){this.endpoint=t.getEndpoint("aiImageService")}async getSimilarProducts(t){const n=new URL(`${this.endpoint}/recommendations/similar`);Object.entries(t).forEach(([e,r])=>{r!==void 0&&n.searchParams.append(e,String(r))});try{const e=await fetch(n.toString(),{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok){const r=await e.text();throw new Error(`Request error: ${e.status} - ${r}`)}return await e.json()}catch(e){throw new Error(`Error fetching similar products: ${e.message}`)}}async getRecommendedSizeByProducts(t){const n=new URL(`${this.endpoint}/recommendations/size-by-products`);try{const e=await fetch(n.toString(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});if(!e.ok){const r=await e.text();throw new Error(`Request error: ${e.status} - ${r}`)}return await e.json()}catch(e){throw new Error(`Error fetching recommended product size: ${e.message}`)}}}const h=[d,f];function u(a){const t=new p(a),n=h.map(r=>new r(t)),e={config:t};return n.forEach(r=>{Object.getOwnPropertyNames(r).forEach(i=>{typeof r[i]=="function"&&(e[i]=r[i].bind(r))});const o=Object.getPrototypeOf(r);Object.getOwnPropertyNames(o).forEach(i=>{i!=="constructor"&&typeof r[i]=="function"&&(e[i]=r[i].bind(r))})}),e}c.createClient=u,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
@@ -1,8 +1,8 @@
1
1
  import { Config } from '../config';
2
- import { GetRecommendedProductSizeParams, GetRecommendedProductSizeResponse, GetSimilarProductsParams, GetSimilarProductsResponse } from '../types/ai-image-service.types';
2
+ import { GetRecommendedSizeByProductsParams, GetRecommendedSizeByProductsResponse, GetSimilarProductsParams, GetSimilarProductsResponse } from '../types/ai-image-service.types';
3
3
  export declare class AIImageService {
4
4
  private endpoint;
5
5
  constructor(config: Config);
6
6
  getSimilarProducts(params: GetSimilarProductsParams): Promise<GetSimilarProductsResponse>;
7
- getRecommendedProductSize(payload: GetRecommendedProductSizeParams): Promise<GetRecommendedProductSizeResponse>;
7
+ getRecommendedSizeByProducts(payload: GetRecommendedSizeByProductsParams): Promise<GetRecommendedSizeByProductsResponse[]>;
8
8
  }
@@ -1,7 +1,7 @@
1
- import { TrackData } from '../types';
1
+ import { TrackData, TrackResponse } from '../types';
2
2
  import { Config } from '../config';
3
3
  export declare class Tracker {
4
4
  private endpoint;
5
5
  constructor(config: Config);
6
- track(eventName: string, payload: TrackData): Promise<any>;
6
+ track(eventName: string, payload: TrackData): Promise<TrackResponse>;
7
7
  }
@@ -1,7 +1,7 @@
1
1
  export interface GetSimilarProductsParams {
2
2
  tenantId: number;
3
- collectionName?: string;
4
- sessionId?: number;
3
+ collectionName: string;
4
+ sessionId: number;
5
5
  permalink: string;
6
6
  page?: number;
7
7
  perPage?: number;
@@ -29,20 +29,14 @@ export interface GetSimilarProductsResponse {
29
29
  perPage: number;
30
30
  total: number;
31
31
  }
32
- export interface ProductRecommendedSize {
33
- permalink: string;
34
- analysisResponse: any | null;
35
- productInfo: any | null;
36
- recommendedSize: string;
37
- recommendedComposedMeasure: any | null;
38
- composedMeasureOrder: any | null;
39
- productGender: string;
40
- profileName: string;
32
+ export interface GetRecommendedSizeByProductsParams {
33
+ tenantId: number;
34
+ sid?: string;
41
35
  sizeSystem: string;
36
+ permalinks: string[];
42
37
  }
43
- export interface GetRecommendedProductSizeParams {
44
- products: ProductRecommendedSize[];
45
- }
46
- export interface GetRecommendedProductSizeResponse {
47
- [key: string]: string | number | boolean;
38
+ export interface GetRecommendedSizeByProductsResponse {
39
+ id: string;
40
+ permalink: string;
41
+ recommendedSize: string | null;
48
42
  }
@@ -11,3 +11,18 @@ export interface TrackData {
11
11
  export interface DataEventPayload extends TrackData {
12
12
  eventName: string;
13
13
  }
14
+ export interface TrackSuccessResponse {
15
+ statusCode: 201;
16
+ message: 'Event successfully created.';
17
+ }
18
+ export interface TrackBadRequestResponse {
19
+ statusCode: 400;
20
+ error: 'Bad Request';
21
+ message: string[];
22
+ }
23
+ export interface TrackServerErrorResponse {
24
+ statusCode: 500;
25
+ error: 'Internal server error';
26
+ message: string[];
27
+ }
28
+ export type TrackResponse = TrackSuccessResponse | TrackBadRequestResponse | TrackServerErrorResponse;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sizebay-core-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A SDK designed for integrating multiple services (such as event tracking, AI services, etc.) into your application.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -2,13 +2,13 @@ import { EndpointDefinition } from "@src/types";
2
2
 
3
3
  export const endpoints: Record<string, EndpointDefinition> = {
4
4
  tracker: {
5
- production: 'https://data-event-service.internalsizebay.com/events',
6
- development: 'https://data-event-service.internalsizebay.com/events',
5
+ production: 'https://data-event-service.internalsizebay.com',
6
+ development: 'https://data-event-service.internalsizebay.com',
7
7
  },
8
8
 
9
9
  aiImageService: {
10
- production: 'https://ai-image-service.example.com/production',
11
- development: 'https://ai-image-service.example.com/development',
10
+ production: 'https://ai-image-service.internalsizebay.com/',
11
+ development: 'https://ai-image-service-dev.internalsizebay.com/',
12
12
  },
13
13
  // Adicione outros serviços conforme necessário
14
14
  };
@@ -1,7 +1,7 @@
1
1
  import { Config } from '@src/config';
2
2
  import {
3
- GetRecommendedProductSizeParams,
4
- GetRecommendedProductSizeResponse,
3
+ GetRecommendedSizeByProductsParams,
4
+ GetRecommendedSizeByProductsResponse,
5
5
  GetSimilarProductsParams,
6
6
  GetSimilarProductsResponse,
7
7
  } from '@src/types/ai-image-service.types';
@@ -42,9 +42,9 @@ export class AIImageService {
42
42
  }
43
43
  }
44
44
 
45
- public async getRecommendedProductSize(
46
- payload: GetRecommendedProductSizeParams,
47
- ): Promise<GetRecommendedProductSizeResponse> {
45
+ public async getRecommendedSizeByProducts(
46
+ payload: GetRecommendedSizeByProductsParams,
47
+ ): Promise<GetRecommendedSizeByProductsResponse[]> {
48
48
  const url = new URL(`${this.endpoint}/recommendations/size-by-products`);
49
49
 
50
50
  try {
@@ -60,7 +60,7 @@ export class AIImageService {
60
60
  const errorText = await response.text();
61
61
  throw new Error(`Request error: ${response.status} - ${errorText}`);
62
62
  }
63
- return (await response.json()) as GetRecommendedProductSizeResponse;
63
+ return (await response.json()) as GetRecommendedSizeByProductsResponse[];
64
64
  } catch (error: any) {
65
65
  throw new Error(`Error fetching recommended product size: ${error.message}`);
66
66
  }
@@ -1,24 +1,23 @@
1
- import { DataEventPayload, TrackData } from "../types";
1
+ import { DataEventPayload, TrackData, TrackResponse } from "../types";
2
2
  import { Config } from "../config";
3
3
 
4
4
  export class Tracker {
5
5
 
6
6
  private endpoint: string;
7
7
 
8
- constructor(config: Config) {
9
- // Define "config" como não enumerável
10
-
8
+ constructor(config: Config) {
11
9
  this.endpoint = config.getEndpoint('tracker');
12
10
  }
13
11
 
14
- public async track(eventName: string, payload: TrackData): Promise<any> {
12
+ public async track(eventName: string, payload: TrackData): Promise<TrackResponse> {
15
13
  const data: DataEventPayload = {
16
14
  eventName,
17
15
  ...payload,
18
16
  };
17
+ const url = new URL(`${this.endpoint}/events`);
19
18
 
20
19
  try {
21
- const response = await fetch(this.endpoint, {
20
+ const response = await fetch(url, {
22
21
  method: "POST",
23
22
  headers: { "Content-Type": "application/json" },
24
23
  body: JSON.stringify(data),
@@ -1,11 +1,12 @@
1
1
  export interface GetSimilarProductsParams {
2
2
  tenantId: number;
3
- collectionName?: string;
4
- sessionId?: number;
3
+ collectionName: string;
4
+ sessionId: number;
5
5
  permalink: string;
6
6
  page?: number;
7
7
  perPage?: number;
8
8
  }
9
+
9
10
  export interface Product {
10
11
  id: string;
11
12
  title: string;
@@ -31,22 +32,16 @@ export interface GetSimilarProductsResponse {
31
32
  total: number;
32
33
  }
33
34
 
34
- export interface ProductRecommendedSize {
35
- permalink: string;
36
- analysisResponse: any | null;
37
- productInfo: any | null;
38
- recommendedSize: string;
39
- recommendedComposedMeasure: any | null;
40
- composedMeasureOrder: any | null;
41
- productGender: string;
42
- profileName: string;
35
+ export interface GetRecommendedSizeByProductsParams {
36
+ tenantId: number;
37
+ sid?: string;
43
38
  sizeSystem: string;
39
+ permalinks: string[];
44
40
  }
45
41
 
46
- export interface GetRecommendedProductSizeParams {
47
- products: ProductRecommendedSize[];
48
- }
49
42
 
50
- export interface GetRecommendedProductSizeResponse {
51
- [key: string]: string | number | boolean;
43
+ export interface GetRecommendedSizeByProductsResponse {
44
+ id: string;
45
+ permalink: string;
46
+ recommendedSize: string | null;
52
47
  }
@@ -1,6 +1,3 @@
1
- /**
2
- * Represents any valid JSON value.
3
- */
4
1
  export type JSONValue =
5
2
  | string
6
3
  | number
@@ -9,9 +6,6 @@ export type JSONValue =
9
6
  | JSONValue[]
10
7
  | { [key: string]: JSONValue };
11
8
 
12
- /**
13
- * Interface that defines the structure of a tracked event.
14
- */
15
9
  export interface TrackData {
16
10
  sid: string;
17
11
  tenantId: number;
@@ -20,9 +14,30 @@ export interface TrackData {
20
14
  properties: Record<string, JSONValue>;
21
15
  }
22
16
 
23
- /**
24
- * Payload for the track event.
25
- */
26
17
  export interface DataEventPayload extends TrackData {
27
18
  eventName: string;
28
- }
19
+ }
20
+
21
+ export interface TrackSuccessResponse {
22
+ statusCode: 201;
23
+ message: 'Event successfully created.';
24
+ }
25
+
26
+ export interface TrackBadRequestResponse {
27
+ statusCode: 400;
28
+ error: 'Bad Request';
29
+
30
+ message: string[];
31
+ }
32
+
33
+ export interface TrackServerErrorResponse {
34
+ statusCode: 500;
35
+ error: 'Internal server error';
36
+
37
+ message: string[];
38
+ }
39
+
40
+ export type TrackResponse =
41
+ | TrackSuccessResponse
42
+ | TrackBadRequestResponse
43
+ | TrackServerErrorResponse;
@@ -2,27 +2,27 @@ import { AIImageService } from '@src/modules/ai-image-service';
2
2
  import {
3
3
  GetSimilarProductsParams,
4
4
  GetSimilarProductsResponse,
5
- GetRecommendedProductSizeParams,
6
- GetRecommendedProductSizeResponse,
5
+ GetRecommendedSizeByProductsParams,
6
+ GetRecommendedSizeByProductsResponse,
7
7
  } from '@src/types/ai-image-service.types';
8
8
 
9
9
  describe('AIImageService', () => {
10
- // Use a valid base URL for constructing request URLs.
10
+
11
11
  const fakeEndpoint = 'https://example.com/ai-image-service';
12
12
  let fakeConfig: { getEndpoint: (serviceName: string) => string };
13
13
  let aiImageService: AIImageService;
14
14
 
15
15
  beforeEach(() => {
16
- // Reinitialize the fake configuration for each test.
16
+
17
17
  fakeConfig = {
18
18
  getEndpoint: (serviceName: string) => fakeEndpoint,
19
19
  };
20
- // Cast fakeConfig as any to bypass missing properties required by Config.
20
+
21
21
  aiImageService = new AIImageService(fakeConfig as any);
22
22
  });
23
23
 
24
24
  afterEach(() => {
25
- // Reset global.fetch if it was set.
25
+
26
26
  if (global.fetch && (global.fetch as jest.Mock).mockReset) {
27
27
  (global.fetch as jest.Mock).mockReset();
28
28
  }
@@ -73,7 +73,6 @@ describe('AIImageService', () => {
73
73
 
74
74
  const result = await aiImageService.getSimilarProducts(params);
75
75
 
76
- // Build expected URL with query parameters.
77
76
  const expectedUrl = new URL(`${fakeEndpoint}/recommendations/similar`);
78
77
  Object.entries(params).forEach(([key, value]) => {
79
78
  if (value !== undefined) {
@@ -131,12 +130,16 @@ describe('AIImageService', () => {
131
130
  });
132
131
  });
133
132
 
134
- describe('getRecommendedProductSize', () => {
133
+ describe('getRecommendedSizeByProducts', () => {
135
134
  it('should send the POST request with the correct payload and return the JSON response', async () => {
136
- const fakeResponseData: GetRecommendedProductSizeResponse = {
137
- recommendedSize: 'M',
138
- someOtherKey: 123,
139
- };
135
+
136
+ const fakeResponseData: GetRecommendedSizeByProductsResponse[] = [
137
+ {
138
+ id: '1',
139
+ permalink: 'https://example.com/product/1',
140
+ recommendedSize: 'M',
141
+ },
142
+ ];
140
143
 
141
144
  const fakeFetchResponse = {
142
145
  ok: true,
@@ -145,23 +148,15 @@ describe('AIImageService', () => {
145
148
 
146
149
  global.fetch = jest.fn().mockResolvedValue(fakeFetchResponse as any);
147
150
 
148
- const payload: GetRecommendedProductSizeParams = {
149
- products: [
150
- {
151
- permalink: 'https://example.com/product/1',
152
- analysisResponse: null,
153
- productInfo: null,
154
- recommendedSize: 'M',
155
- recommendedComposedMeasure: null,
156
- composedMeasureOrder: null,
157
- productGender: 'unisex',
158
- profileName: 'profile1',
159
- sizeSystem: 'US',
160
- },
161
- ],
151
+ const payload: GetRecommendedSizeByProductsParams = {
152
+ tenantId: 123,
153
+
154
+ sid: 'some-session-id',
155
+ sizeSystem: 'US',
156
+ permalinks: ['https://example.com/product/1'],
162
157
  };
163
158
 
164
- const result = await aiImageService.getRecommendedProductSize(payload);
159
+ const result = await aiImageService.getRecommendedSizeByProducts(payload);
165
160
 
166
161
  const expectedUrl = `${fakeEndpoint}/recommendations/size-by-products`;
167
162
 
@@ -183,24 +178,14 @@ describe('AIImageService', () => {
183
178
 
184
179
  global.fetch = jest.fn().mockResolvedValue(fakeFetchResponse as any);
185
180
 
186
- const payload: GetRecommendedProductSizeParams = {
187
- products: [
188
- {
189
- permalink: 'https://example.com/product/1',
190
- analysisResponse: null,
191
- productInfo: null,
192
- recommendedSize: 'M',
193
- recommendedComposedMeasure: null,
194
- composedMeasureOrder: null,
195
- productGender: 'unisex',
196
- profileName: 'profile1',
197
- sizeSystem: 'US',
198
- },
199
- ],
181
+ const payload: GetRecommendedSizeByProductsParams = {
182
+ tenantId: 123,
183
+ sizeSystem: 'US',
184
+ permalinks: ['https://example.com/product/1'],
200
185
  };
201
186
 
202
187
  await expect(
203
- aiImageService.getRecommendedProductSize(payload),
188
+ aiImageService.getRecommendedSizeByProducts(payload),
204
189
  ).rejects.toThrow(`Request error: 500 - ${errorText}`);
205
190
  });
206
191
 
@@ -208,27 +193,17 @@ describe('AIImageService', () => {
208
193
  const errorMessage = 'Network error';
209
194
  global.fetch = jest.fn().mockRejectedValue(new Error(errorMessage));
210
195
 
211
- const payload: GetRecommendedProductSizeParams = {
212
- products: [
213
- {
214
- permalink: 'https://example.com/product/1',
215
- analysisResponse: null,
216
- productInfo: null,
217
- recommendedSize: 'M',
218
- recommendedComposedMeasure: null,
219
- composedMeasureOrder: null,
220
- productGender: 'unisex',
221
- profileName: 'profile1',
222
- sizeSystem: 'US',
223
- },
224
- ],
196
+ const payload: GetRecommendedSizeByProductsParams = {
197
+ tenantId: 123,
198
+ sizeSystem: 'US',
199
+ permalinks: ['https://example.com/product/1'],
225
200
  };
226
201
 
227
202
  await expect(
228
- aiImageService.getRecommendedProductSize(payload),
203
+ aiImageService.getRecommendedSizeByProducts(payload),
229
204
  ).rejects.toThrow(
230
205
  `Error fetching recommended product size: ${errorMessage}`,
231
206
  );
232
207
  });
233
208
  });
234
- });
209
+ });
@@ -14,7 +14,9 @@ describe('Tracker', () => {
14
14
  });
15
15
 
16
16
  afterEach(() => {
17
- jest.resetAllMocks();
17
+ if (global.fetch && (global.fetch as jest.Mock).mockClear) {
18
+ (global.fetch as jest.Mock).mockClear();
19
+ }
18
20
  });
19
21
 
20
22
  it('should send the event and return the JSON response', async () => {
@@ -36,7 +38,8 @@ describe('Tracker', () => {
36
38
 
37
39
  const result = await tracker.track(eventName, payload);
38
40
 
39
- expect(global.fetch).toHaveBeenCalledWith(fakeEndpoint, {
41
+ const expectedUrl = new URL(`${fakeEndpoint}/events`);
42
+ expect(global.fetch).toHaveBeenCalledWith(expectedUrl, {
40
43
  method: 'POST',
41
44
  headers: { 'Content-Type': 'application/json' },
42
45
  body: JSON.stringify({ eventName, ...payload }),
@@ -46,7 +49,6 @@ describe('Tracker', () => {
46
49
 
47
50
  it('should throw an error if the response is not ok', async () => {
48
51
  const errorText = 'Internal Server Error';
49
-
50
52
  const fakeFetchResponse = {
51
53
  ok: false,
52
54
  status: 500,