core-services-sdk 1.3.80 → 1.3.81

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "core-services-sdk",
3
- "version": "1.3.80",
3
+ "version": "1.3.81",
4
4
  "main": "src/index.js",
5
5
  "type": "module",
6
6
  "types": "types/index.d.ts",
@@ -49,14 +49,14 @@
49
49
  "zod": "^4.3.6"
50
50
  },
51
51
  "devDependencies": {
52
- "@vitest/coverage-v8": "^3.2.4",
53
- "eslint": "^9.30.0",
52
+ "@vitest/coverage-v8": "^4.0.18",
53
+ "eslint": "^10.0.1",
54
54
  "eslint-config-prettier": "^10.1.5",
55
55
  "eslint-plugin-prettier": "^5.5.1",
56
56
  "path": "^0.12.7",
57
57
  "prettier": "^3.6.2",
58
58
  "typescript": "^5.9.2",
59
59
  "url": "^0.11.4",
60
- "vitest": "^3.2.4"
60
+ "vitest": "^4.0.18"
61
61
  }
62
62
  }
package/src/http/http.js CHANGED
@@ -7,6 +7,50 @@
7
7
  * @module http
8
8
  */
9
9
 
10
+ /**
11
+ * @typedef {'json' | 'xml' | 'text' | 'raw' | 'file'} ResponseTypeValue
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} HttpGetOptions
16
+ * @property {string} url - The URL to send the request to.
17
+ * @property {Record<string, string>} [headers] - Optional HTTP headers.
18
+ * @property {RequestInit} [extraParams] - Additional fetch options.
19
+ * @property {ResponseTypeValue} [expectedType] - Expected response type.
20
+ */
21
+
22
+ /**
23
+ * @typedef {Object} HttpPostOptions
24
+ * @property {string} url - The URL to send the request to.
25
+ * @property {any} body - The request body to send.
26
+ * @property {Record<string, string>} [headers] - Optional HTTP headers.
27
+ * @property {ResponseTypeValue} [expectedType] - Expected response type.
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} HttpPutOptions
32
+ * @property {string} url - The URL to send the request to.
33
+ * @property {any} body - The request body to send.
34
+ * @property {Record<string, string>} [headers] - Optional HTTP headers.
35
+ * @property {ResponseTypeValue} [expectedType] - Expected response type.
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} HttpPatchOptions
40
+ * @property {string} url - The URL to send the request to.
41
+ * @property {any} body - The request body to send.
42
+ * @property {Record<string, string>} [headers] - Optional HTTP headers.
43
+ * @property {ResponseTypeValue} [expectedType] - Expected response type.
44
+ */
45
+
46
+ /**
47
+ * @typedef {Object} HttpDeleteOptions
48
+ * @property {string} url - The URL to send the request to.
49
+ * @property {any} [body] - Optional request body to send.
50
+ * @property {Record<string, string>} [headers] - Optional HTTP headers.
51
+ * @property {ResponseTypeValue} [expectedType] - Expected response type.
52
+ */
53
+
10
54
  import httpStatus from 'http-status'
11
55
  import { parseStringPromise } from 'xml2js'
12
56
 
@@ -25,7 +69,7 @@ const JSON_HEADER = {
25
69
  * @returns {boolean}
26
70
  */
27
71
  const isOkStatus = ({ status }) =>
28
- status >= httpStatus.OK && status < httpStatus.MULTIPLE_CHOICES
72
+ status >= httpStatus.OK && status < httpStatus.BAD_REQUEST
29
73
 
30
74
  /**
31
75
  * Ensures the response has a successful status, otherwise throws HttpError.
@@ -121,6 +165,8 @@ const getResponsePayload = async (response, responseType) => {
121
165
  return tryGetJsonResponse(response)
122
166
  case ResponseType.xml:
123
167
  return tryGetXmlResponse(response)
168
+ case ResponseType.raw:
169
+ return response
124
170
  default:
125
171
  return getTextResponse(response)
126
172
  }
@@ -128,13 +174,19 @@ const getResponsePayload = async (response, responseType) => {
128
174
 
129
175
  /**
130
176
  * Sends an HTTP GET request.
177
+ *
178
+ * @param {HttpGetOptions} options - The request options.
179
+ * @returns {Promise<any>} The parsed response based on expectedType.
180
+ * @throws {HttpError} If the response status is not successful.
131
181
  */
132
182
  export const get = async ({
133
183
  url,
134
184
  headers = {},
185
+ extraParams = {},
135
186
  expectedType = ResponseType.json,
136
187
  }) => {
137
188
  const response = await fetch(url, {
189
+ ...extraParams,
138
190
  method: HTTP_METHODS.GET,
139
191
  headers: { ...JSON_HEADER, ...headers },
140
192
  })
@@ -144,6 +196,10 @@ export const get = async ({
144
196
 
145
197
  /**
146
198
  * Sends an HTTP POST request.
199
+ *
200
+ * @param {HttpPostOptions} options - The request options.
201
+ * @returns {Promise<any>} The parsed response based on expectedType.
202
+ * @throws {HttpError} If the response status is not successful.
147
203
  */
148
204
  export const post = async ({
149
205
  url,
@@ -162,6 +218,10 @@ export const post = async ({
162
218
 
163
219
  /**
164
220
  * Sends an HTTP PUT request.
221
+ *
222
+ * @param {HttpPutOptions} options - The request options.
223
+ * @returns {Promise<any>} The parsed response based on expectedType.
224
+ * @throws {HttpError} If the response status is not successful.
165
225
  */
166
226
  export const put = async ({
167
227
  url,
@@ -172,7 +232,7 @@ export const put = async ({
172
232
  const response = await fetch(url, {
173
233
  method: HTTP_METHODS.PUT,
174
234
  headers: { ...JSON_HEADER, ...headers },
175
- body: JSON.stringify(body),
235
+ body: expectedType === ResponseType.json ? JSON.stringify(body) : body,
176
236
  })
177
237
  await checkStatus(response)
178
238
  return getResponsePayload(response, expectedType)
@@ -180,6 +240,10 @@ export const put = async ({
180
240
 
181
241
  /**
182
242
  * Sends an HTTP PATCH request.
243
+ *
244
+ * @param {HttpPatchOptions} options - The request options.
245
+ * @returns {Promise<any>} The parsed response based on expectedType.
246
+ * @throws {HttpError} If the response status is not successful.
183
247
  */
184
248
  export const patch = async ({
185
249
  url,
@@ -198,6 +262,10 @@ export const patch = async ({
198
262
 
199
263
  /**
200
264
  * Sends an HTTP DELETE request.
265
+ *
266
+ * @param {HttpDeleteOptions} options - The request options.
267
+ * @returns {Promise<any>} The parsed response based on expectedType.
268
+ * @throws {HttpError} If the response status is not successful.
201
269
  */
202
270
  export const deleteApi = async ({
203
271
  url,
@@ -215,7 +283,15 @@ export const deleteApi = async ({
215
283
  }
216
284
 
217
285
  /**
218
- * Consolidated HTTP client.
286
+ * Consolidated HTTP client with methods for common HTTP operations.
287
+ *
288
+ * @type {{
289
+ * get: (options: HttpGetOptions) => Promise<any>,
290
+ * put: (options: HttpPutOptions) => Promise<any>,
291
+ * post: (options: HttpPostOptions) => Promise<any>,
292
+ * patch: (options: HttpPatchOptions) => Promise<any>,
293
+ * deleteApi: (options: HttpDeleteOptions) => Promise<any>
294
+ * }}
219
295
  */
220
296
  export const http = {
221
297
  get,
@@ -10,6 +10,7 @@
10
10
  */
11
11
  export const ResponseType = Object.freeze({
12
12
  xml: 'xml',
13
+ raw: 'raw',
13
14
  json: 'json',
14
15
  text: 'text',
15
16
  file: 'file',
@@ -77,7 +77,6 @@ for (const scenario of scenarios) {
77
77
 
78
78
  const result = prepareEnvValidation(definition, scenario.values, { mask })
79
79
 
80
- // פה הבחירה שלך מה לעשות עם זה
81
80
  console.log(result.table)
82
81
 
83
82
  if (!result.success) {
@@ -149,5 +149,39 @@ describe('http client (native fetch)', () => {
149
149
 
150
150
  expect(result).toHaveProperty('note')
151
151
  })
152
+
153
+ it('should return raw response object if expectedType is raw', async () => {
154
+ const mockResponse = createMockResponse({ body: 'raw data', status: 200 })
155
+ mockFetch.mockResolvedValueOnce(mockResponse)
156
+
157
+ const result = await http.get({
158
+ url: 'http://test.com',
159
+ expectedType: ResponseType.raw,
160
+ })
161
+
162
+ expect(result).toBe(mockResponse)
163
+ expect(result.status).toBe(200)
164
+ })
165
+ })
166
+
167
+ describe('PUT with non-JSON body', () => {
168
+ it('should not stringify body when expectedType is not json', async () => {
169
+ const rawBody = 'plain text body'
170
+ mockFetch.mockResolvedValueOnce(createMockResponse({ body: 'OK' }))
171
+
172
+ await http.put({
173
+ url: 'http://test.com',
174
+ body: rawBody,
175
+ expectedType: ResponseType.text,
176
+ })
177
+
178
+ expect(mockFetch).toHaveBeenCalledWith(
179
+ 'http://test.com',
180
+ expect.objectContaining({
181
+ method: 'PUT',
182
+ body: rawBody,
183
+ }),
184
+ )
185
+ })
152
186
  })
153
187
  })
@@ -7,6 +7,7 @@ describe('ResponseType', () => {
7
7
  it('should contain correct response type mappings', () => {
8
8
  expect(ResponseType).toEqual({
9
9
  xml: 'xml',
10
+ raw: 'raw',
10
11
  json: 'json',
11
12
  text: 'text',
12
13
  file: 'file',
@@ -32,7 +33,7 @@ describe('ResponseType', () => {
32
33
 
33
34
  it('should include expected keys', () => {
34
35
  const keys = Object.keys(ResponseType)
35
- expect(keys).toEqual(['xml', 'json', 'text', 'file'])
36
+ expect(keys).toEqual(['xml', 'raw', 'json', 'text', 'file'])
36
37
  })
37
38
 
38
39
  it('should include expected values', () => {
@@ -41,5 +42,6 @@ describe('ResponseType', () => {
41
42
  expect(values).toContain('xml')
42
43
  expect(values).toContain('text')
43
44
  expect(values).toContain('file')
45
+ expect(values).toContain('raw')
44
46
  })
45
47
  })
@@ -17,9 +17,9 @@ vi.mock('../../src/mailer/transport.factory.js', async () => {
17
17
 
18
18
  // Mock Mailer class
19
19
  vi.mock('../../src/mailer/mailer.service.js', async () => {
20
- const Mailer = vi.fn().mockImplementation((transport) => ({
21
- send: vi.fn((opts) => transport.sendMail(opts)),
22
- }))
20
+ const Mailer = vi.fn(function (transport) {
21
+ this.send = vi.fn((opts) => transport.sendMail(opts))
22
+ })
23
23
  return { Mailer }
24
24
  })
25
25
 
@@ -30,8 +30,12 @@ vi.mock('@sendgrid/mail', () => {
30
30
  // ---------------- Mock AWS SESv2 ----------------
31
31
  vi.mock('@aws-sdk/client-sesv2', () => {
32
32
  const mockSesInstance = { mocked: true }
33
- const SESv2Client = vi.fn(() => mockSesInstance)
34
- const SendEmailCommand = vi.fn(() => 'mocked-command')
33
+ const SESv2Client = vi.fn(function () {
34
+ Object.assign(this, mockSesInstance)
35
+ })
36
+ const SendEmailCommand = vi.fn(function () {
37
+ return 'mocked-command'
38
+ })
35
39
 
36
40
  globalThis.__mockedSesv2Client__ = SESv2Client
37
41
  globalThis.__mockedSesv2Instance__ = mockSesInstance
@@ -137,12 +141,10 @@ describe('TransportFactory', () => {
137
141
  })
138
142
 
139
143
  const args = nodemailer.createTransport.mock.calls[0][0]
140
- expect(args).toEqual({
141
- SES: {
142
- sesClient: globalThis.__mockedSesv2Instance__,
143
- SendEmailCommand: globalThis.__mockedSendEmailCommand__,
144
- },
145
- })
144
+ expect(args.SES.sesClient).toBeInstanceOf(globalThis.__mockedSesv2Client__)
145
+ expect(args.SES.SendEmailCommand).toBe(
146
+ globalThis.__mockedSendEmailCommand__,
147
+ )
146
148
 
147
149
  expect(transport.type).toBe('mock-transport')
148
150
  })
@@ -162,12 +164,10 @@ describe('TransportFactory', () => {
162
164
  })
163
165
 
164
166
  const args = nodemailer.createTransport.mock.calls[0][0]
165
- expect(args).toEqual({
166
- SES: {
167
- sesClient: globalThis.__mockedSesv2Instance__,
168
- SendEmailCommand: globalThis.__mockedSendEmailCommand__,
169
- },
170
- })
167
+ expect(args.SES.sesClient).toBeInstanceOf(globalThis.__mockedSesv2Client__)
168
+ expect(args.SES.SendEmailCommand).toBe(
169
+ globalThis.__mockedSendEmailCommand__,
170
+ )
171
171
 
172
172
  expect(transport.type).toBe('mock-transport')
173
173
  })
@@ -1,10 +1,12 @@
1
1
  export function get({
2
2
  url,
3
3
  headers,
4
+ extraParams,
4
5
  expectedType,
5
6
  }: {
6
7
  url: any
7
8
  headers?: {}
9
+ extraParams?: {}
8
10
  expectedType?: 'json'
9
11
  }): Promise<any>
10
12
  export function post({
@@ -14,6 +14,7 @@ export type ResponseType = string
14
14
  */
15
15
  export const ResponseType: Readonly<{
16
16
  xml: 'xml'
17
+ raw: 'raw'
17
18
  json: 'json'
18
19
  text: 'text'
19
20
  file: 'file'
@@ -1,22 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npm test:*)",
5
- "Bash(docker rm:*)",
6
- "Bash(docker run:*)",
7
- "Bash(mongosh:*)",
8
- "Bash(for:*)",
9
- "Bash(do if mongosh --port 27099 --eval \"db.runCommand({ ping: 1 })\")",
10
- "Bash(then echo \"Connected after $i attempts\")",
11
- "Bash(break)",
12
- "Bash(fi)",
13
- "Bash(echo:*)",
14
- "Bash(done)",
15
- "Bash(docker logs:*)",
16
- "Bash(docker system:*)",
17
- "Bash(docker volume prune:*)",
18
- "Bash(docker image prune:*)",
19
- "Bash(docker builder prune:*)"
20
- ]
21
- }
22
- }