core-services-sdk 1.3.82 → 1.3.83
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 +1 -1
- package/src/http/http.js +12 -0
- package/tests/http/http.unit.test.js +70 -0
- package/types/http/http.d.ts +132 -35
- package/types/postgresql/index.d.ts +2 -0
- package/types/postgresql/pagination/paginate.d.ts +1 -0
- package/types/postgresql/repositories/BaseRepository.d.ts +50 -0
- package/types/postgresql/repositories/TenantScopedRepository.d.ts +11 -0
package/package.json
CHANGED
package/src/http/http.js
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* @property {string} url - The URL to send the request to.
|
|
25
25
|
* @property {any} body - The request body to send.
|
|
26
26
|
* @property {Record<string, string>} [headers] - Optional HTTP headers.
|
|
27
|
+
* @property {RequestInit} [extraParams] - Additional fetch options.
|
|
27
28
|
* @property {ResponseTypeValue} [expectedType] - Expected response type.
|
|
28
29
|
*/
|
|
29
30
|
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
* @property {string} url - The URL to send the request to.
|
|
33
34
|
* @property {any} body - The request body to send.
|
|
34
35
|
* @property {Record<string, string>} [headers] - Optional HTTP headers.
|
|
36
|
+
* @property {RequestInit} [extraParams] - Additional fetch options.
|
|
35
37
|
* @property {ResponseTypeValue} [expectedType] - Expected response type.
|
|
36
38
|
*/
|
|
37
39
|
|
|
@@ -40,6 +42,7 @@
|
|
|
40
42
|
* @property {string} url - The URL to send the request to.
|
|
41
43
|
* @property {any} body - The request body to send.
|
|
42
44
|
* @property {Record<string, string>} [headers] - Optional HTTP headers.
|
|
45
|
+
* @property {RequestInit} [extraParams] - Additional fetch options.
|
|
43
46
|
* @property {ResponseTypeValue} [expectedType] - Expected response type.
|
|
44
47
|
*/
|
|
45
48
|
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
* @property {string} url - The URL to send the request to.
|
|
49
52
|
* @property {any} [body] - Optional request body to send.
|
|
50
53
|
* @property {Record<string, string>} [headers] - Optional HTTP headers.
|
|
54
|
+
* @property {RequestInit} [extraParams] - Additional fetch options.
|
|
51
55
|
* @property {ResponseTypeValue} [expectedType] - Expected response type.
|
|
52
56
|
*/
|
|
53
57
|
|
|
@@ -205,9 +209,11 @@ export const post = async ({
|
|
|
205
209
|
url,
|
|
206
210
|
body,
|
|
207
211
|
headers = {},
|
|
212
|
+
extraParams = {},
|
|
208
213
|
expectedType = ResponseType.json,
|
|
209
214
|
}) => {
|
|
210
215
|
const response = await fetch(url, {
|
|
216
|
+
...extraParams,
|
|
211
217
|
method: HTTP_METHODS.POST,
|
|
212
218
|
headers: { ...JSON_HEADER, ...headers },
|
|
213
219
|
body: JSON.stringify(body),
|
|
@@ -227,9 +233,11 @@ export const put = async ({
|
|
|
227
233
|
url,
|
|
228
234
|
body,
|
|
229
235
|
headers = {},
|
|
236
|
+
extraParams = {},
|
|
230
237
|
expectedType = ResponseType.json,
|
|
231
238
|
}) => {
|
|
232
239
|
const response = await fetch(url, {
|
|
240
|
+
...extraParams,
|
|
233
241
|
method: HTTP_METHODS.PUT,
|
|
234
242
|
headers: { ...JSON_HEADER, ...headers },
|
|
235
243
|
body: expectedType === ResponseType.json ? JSON.stringify(body) : body,
|
|
@@ -249,9 +257,11 @@ export const patch = async ({
|
|
|
249
257
|
url,
|
|
250
258
|
body,
|
|
251
259
|
headers = {},
|
|
260
|
+
extraParams = {},
|
|
252
261
|
expectedType = ResponseType.json,
|
|
253
262
|
}) => {
|
|
254
263
|
const response = await fetch(url, {
|
|
264
|
+
...extraParams,
|
|
255
265
|
method: HTTP_METHODS.PATCH,
|
|
256
266
|
headers: { ...JSON_HEADER, ...headers },
|
|
257
267
|
body: JSON.stringify(body),
|
|
@@ -271,9 +281,11 @@ export const deleteApi = async ({
|
|
|
271
281
|
url,
|
|
272
282
|
body,
|
|
273
283
|
headers = {},
|
|
284
|
+
extraParams = {},
|
|
274
285
|
expectedType = ResponseType.json,
|
|
275
286
|
}) => {
|
|
276
287
|
const response = await fetch(url, {
|
|
288
|
+
...extraParams,
|
|
277
289
|
method: HTTP_METHODS.DELETE,
|
|
278
290
|
headers: { ...JSON_HEADER, ...headers },
|
|
279
291
|
...(body ? { body: JSON.stringify(body) } : {}),
|
|
@@ -185,3 +185,73 @@ describe('http client (native fetch)', () => {
|
|
|
185
185
|
})
|
|
186
186
|
})
|
|
187
187
|
})
|
|
188
|
+
|
|
189
|
+
describe('extraParams support', () => {
|
|
190
|
+
it('should pass extraParams to fetch in GET', async () => {
|
|
191
|
+
mockFetch.mockResolvedValueOnce(
|
|
192
|
+
createMockResponse({ body: JSON.stringify({ ok: true }) }),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
const controller = new AbortController()
|
|
196
|
+
|
|
197
|
+
await http.get({
|
|
198
|
+
url: 'http://test.com',
|
|
199
|
+
extraParams: {
|
|
200
|
+
signal: controller.signal,
|
|
201
|
+
redirect: 'follow',
|
|
202
|
+
},
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
expect(mockFetch).toHaveBeenCalledWith(
|
|
206
|
+
'http://test.com',
|
|
207
|
+
expect.objectContaining({
|
|
208
|
+
method: HTTP_METHODS.GET,
|
|
209
|
+
signal: controller.signal,
|
|
210
|
+
redirect: 'follow',
|
|
211
|
+
}),
|
|
212
|
+
)
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('should pass extraParams to fetch in POST', async () => {
|
|
216
|
+
mockFetch.mockResolvedValueOnce(
|
|
217
|
+
createMockResponse({ body: JSON.stringify({ ok: true }) }),
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
await http.post({
|
|
221
|
+
url: 'http://test.com',
|
|
222
|
+
body: { a: 1 },
|
|
223
|
+
extraParams: {
|
|
224
|
+
credentials: 'include',
|
|
225
|
+
},
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
expect(mockFetch).toHaveBeenCalledWith(
|
|
229
|
+
'http://test.com',
|
|
230
|
+
expect.objectContaining({
|
|
231
|
+
method: HTTP_METHODS.POST,
|
|
232
|
+
credentials: 'include',
|
|
233
|
+
}),
|
|
234
|
+
)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it('should pass extraParams to fetch in DELETE', async () => {
|
|
238
|
+
mockFetch.mockResolvedValueOnce(
|
|
239
|
+
createMockResponse({ body: JSON.stringify({ ok: true }) }),
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
await http.deleteApi({
|
|
243
|
+
url: 'http://test.com',
|
|
244
|
+
extraParams: {
|
|
245
|
+
keepalive: true,
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
expect(mockFetch).toHaveBeenCalledWith(
|
|
250
|
+
'http://test.com',
|
|
251
|
+
expect.objectContaining({
|
|
252
|
+
method: HTTP_METHODS.DELETE,
|
|
253
|
+
keepalive: true,
|
|
254
|
+
}),
|
|
255
|
+
)
|
|
256
|
+
})
|
|
257
|
+
})
|
package/types/http/http.d.ts
CHANGED
|
@@ -3,60 +3,157 @@ export function get({
|
|
|
3
3
|
headers,
|
|
4
4
|
extraParams,
|
|
5
5
|
expectedType,
|
|
6
|
-
}:
|
|
7
|
-
url: any
|
|
8
|
-
headers?: {}
|
|
9
|
-
extraParams?: {}
|
|
10
|
-
expectedType?: 'json'
|
|
11
|
-
}): Promise<any>
|
|
6
|
+
}: HttpGetOptions): Promise<any>
|
|
12
7
|
export function post({
|
|
13
8
|
url,
|
|
14
9
|
body,
|
|
15
10
|
headers,
|
|
11
|
+
extraParams,
|
|
16
12
|
expectedType,
|
|
17
|
-
}:
|
|
18
|
-
url: any
|
|
19
|
-
body: any
|
|
20
|
-
headers?: {}
|
|
21
|
-
expectedType?: 'json'
|
|
22
|
-
}): Promise<any>
|
|
13
|
+
}: HttpPostOptions): Promise<any>
|
|
23
14
|
export function put({
|
|
24
15
|
url,
|
|
25
16
|
body,
|
|
26
17
|
headers,
|
|
18
|
+
extraParams,
|
|
27
19
|
expectedType,
|
|
28
|
-
}:
|
|
29
|
-
url: any
|
|
30
|
-
body: any
|
|
31
|
-
headers?: {}
|
|
32
|
-
expectedType?: 'json'
|
|
33
|
-
}): Promise<any>
|
|
20
|
+
}: HttpPutOptions): Promise<any>
|
|
34
21
|
export function patch({
|
|
35
22
|
url,
|
|
36
23
|
body,
|
|
37
24
|
headers,
|
|
25
|
+
extraParams,
|
|
38
26
|
expectedType,
|
|
39
|
-
}:
|
|
40
|
-
url: any
|
|
41
|
-
body: any
|
|
42
|
-
headers?: {}
|
|
43
|
-
expectedType?: 'json'
|
|
44
|
-
}): Promise<any>
|
|
27
|
+
}: HttpPatchOptions): Promise<any>
|
|
45
28
|
export function deleteApi({
|
|
46
29
|
url,
|
|
47
30
|
body,
|
|
48
31
|
headers,
|
|
32
|
+
extraParams,
|
|
49
33
|
expectedType,
|
|
50
|
-
}:
|
|
51
|
-
|
|
34
|
+
}: HttpDeleteOptions): Promise<any>
|
|
35
|
+
/**
|
|
36
|
+
* Consolidated HTTP client with methods for common HTTP operations.
|
|
37
|
+
*
|
|
38
|
+
* @type {{
|
|
39
|
+
* get: (options: HttpGetOptions) => Promise<any>,
|
|
40
|
+
* put: (options: HttpPutOptions) => Promise<any>,
|
|
41
|
+
* post: (options: HttpPostOptions) => Promise<any>,
|
|
42
|
+
* patch: (options: HttpPatchOptions) => Promise<any>,
|
|
43
|
+
* deleteApi: (options: HttpDeleteOptions) => Promise<any>
|
|
44
|
+
* }}
|
|
45
|
+
*/
|
|
46
|
+
export const http: {
|
|
47
|
+
get: (options: HttpGetOptions) => Promise<any>
|
|
48
|
+
put: (options: HttpPutOptions) => Promise<any>
|
|
49
|
+
post: (options: HttpPostOptions) => Promise<any>
|
|
50
|
+
patch: (options: HttpPatchOptions) => Promise<any>
|
|
51
|
+
deleteApi: (options: HttpDeleteOptions) => Promise<any>
|
|
52
|
+
}
|
|
53
|
+
export type ResponseTypeValue = 'json' | 'xml' | 'text' | 'raw' | 'file'
|
|
54
|
+
export type HttpGetOptions = {
|
|
55
|
+
/**
|
|
56
|
+
* - The URL to send the request to.
|
|
57
|
+
*/
|
|
58
|
+
url: string
|
|
59
|
+
/**
|
|
60
|
+
* - Optional HTTP headers.
|
|
61
|
+
*/
|
|
62
|
+
headers?: Record<string, string>
|
|
63
|
+
/**
|
|
64
|
+
* - Additional fetch options.
|
|
65
|
+
*/
|
|
66
|
+
extraParams?: RequestInit
|
|
67
|
+
/**
|
|
68
|
+
* - Expected response type.
|
|
69
|
+
*/
|
|
70
|
+
expectedType?: ResponseTypeValue
|
|
71
|
+
}
|
|
72
|
+
export type HttpPostOptions = {
|
|
73
|
+
/**
|
|
74
|
+
* - The URL to send the request to.
|
|
75
|
+
*/
|
|
76
|
+
url: string
|
|
77
|
+
/**
|
|
78
|
+
* - The request body to send.
|
|
79
|
+
*/
|
|
80
|
+
body: any
|
|
81
|
+
/**
|
|
82
|
+
* - Optional HTTP headers.
|
|
83
|
+
*/
|
|
84
|
+
headers?: Record<string, string>
|
|
85
|
+
/**
|
|
86
|
+
* - Additional fetch options.
|
|
87
|
+
*/
|
|
88
|
+
extraParams?: RequestInit
|
|
89
|
+
/**
|
|
90
|
+
* - Expected response type.
|
|
91
|
+
*/
|
|
92
|
+
expectedType?: ResponseTypeValue
|
|
93
|
+
}
|
|
94
|
+
export type HttpPutOptions = {
|
|
95
|
+
/**
|
|
96
|
+
* - The URL to send the request to.
|
|
97
|
+
*/
|
|
98
|
+
url: string
|
|
99
|
+
/**
|
|
100
|
+
* - The request body to send.
|
|
101
|
+
*/
|
|
52
102
|
body: any
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
103
|
+
/**
|
|
104
|
+
* - Optional HTTP headers.
|
|
105
|
+
*/
|
|
106
|
+
headers?: Record<string, string>
|
|
107
|
+
/**
|
|
108
|
+
* - Additional fetch options.
|
|
109
|
+
*/
|
|
110
|
+
extraParams?: RequestInit
|
|
111
|
+
/**
|
|
112
|
+
* - Expected response type.
|
|
113
|
+
*/
|
|
114
|
+
expectedType?: ResponseTypeValue
|
|
115
|
+
}
|
|
116
|
+
export type HttpPatchOptions = {
|
|
117
|
+
/**
|
|
118
|
+
* - The URL to send the request to.
|
|
119
|
+
*/
|
|
120
|
+
url: string
|
|
121
|
+
/**
|
|
122
|
+
* - The request body to send.
|
|
123
|
+
*/
|
|
124
|
+
body: any
|
|
125
|
+
/**
|
|
126
|
+
* - Optional HTTP headers.
|
|
127
|
+
*/
|
|
128
|
+
headers?: Record<string, string>
|
|
129
|
+
/**
|
|
130
|
+
* - Additional fetch options.
|
|
131
|
+
*/
|
|
132
|
+
extraParams?: RequestInit
|
|
133
|
+
/**
|
|
134
|
+
* - Expected response type.
|
|
135
|
+
*/
|
|
136
|
+
expectedType?: ResponseTypeValue
|
|
137
|
+
}
|
|
138
|
+
export type HttpDeleteOptions = {
|
|
139
|
+
/**
|
|
140
|
+
* - The URL to send the request to.
|
|
141
|
+
*/
|
|
142
|
+
url: string
|
|
143
|
+
/**
|
|
144
|
+
* - Optional request body to send.
|
|
145
|
+
*/
|
|
146
|
+
body?: any
|
|
147
|
+
/**
|
|
148
|
+
* - Optional HTTP headers.
|
|
149
|
+
*/
|
|
150
|
+
headers?: Record<string, string>
|
|
151
|
+
/**
|
|
152
|
+
* - Additional fetch options.
|
|
153
|
+
*/
|
|
154
|
+
extraParams?: RequestInit
|
|
155
|
+
/**
|
|
156
|
+
* - Expected response type.
|
|
157
|
+
*/
|
|
158
|
+
expectedType?: ResponseTypeValue
|
|
62
159
|
}
|
|
@@ -5,4 +5,6 @@ export * from './filters/apply-filter.js'
|
|
|
5
5
|
export * from './modifiers/apply-order-by.js'
|
|
6
6
|
export * from './start-stop-postgres-docker.js'
|
|
7
7
|
export * from './modifiers/apply-pagination.js'
|
|
8
|
+
export * from './repositories/BaseRepository.js'
|
|
8
9
|
export * from './filters/apply-filter-snake-case.js'
|
|
10
|
+
export * from './repositories/TenantScopedRepository.js'
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseRepository
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - tableName getter (static + instance support)
|
|
6
|
+
* - baseQuery(options)
|
|
7
|
+
* - constructor-level query shaping (optional)
|
|
8
|
+
* - generic find() with pagination
|
|
9
|
+
*
|
|
10
|
+
* Does NOT enforce tenant isolation.
|
|
11
|
+
*/
|
|
12
|
+
export class BaseRepository {
|
|
13
|
+
constructor({ db, log, baseQueryBuilder }?: {})
|
|
14
|
+
db: any
|
|
15
|
+
log: any
|
|
16
|
+
_baseQueryBuilder: any
|
|
17
|
+
/**
|
|
18
|
+
* Each concrete repository must define:
|
|
19
|
+
* static tableName = 'table_name'
|
|
20
|
+
*/
|
|
21
|
+
get tableName(): any
|
|
22
|
+
/**
|
|
23
|
+
* Builds the base knex query.
|
|
24
|
+
* Applies constructor-level baseQueryBuilder if provided.
|
|
25
|
+
*/
|
|
26
|
+
baseQuery(options: {}, params: any): any
|
|
27
|
+
/**
|
|
28
|
+
* Generic paginated find
|
|
29
|
+
*/
|
|
30
|
+
find({
|
|
31
|
+
page,
|
|
32
|
+
limit,
|
|
33
|
+
filter,
|
|
34
|
+
orderBy,
|
|
35
|
+
options,
|
|
36
|
+
mapRow,
|
|
37
|
+
...restParams
|
|
38
|
+
}: {
|
|
39
|
+
[x: string]: any
|
|
40
|
+
page?: number
|
|
41
|
+
limit?: number
|
|
42
|
+
filter?: {}
|
|
43
|
+
orderBy?: {
|
|
44
|
+
column: string
|
|
45
|
+
direction: string
|
|
46
|
+
}
|
|
47
|
+
options?: {}
|
|
48
|
+
mapRow?: (row: any) => any
|
|
49
|
+
}): Promise<any>
|
|
50
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export class TenantScopedRepository extends BaseRepository {
|
|
2
|
+
/**
|
|
3
|
+
* Extracts and validates tenantId from filter
|
|
4
|
+
*/
|
|
5
|
+
getRequiredTenantId(filter?: {}): any
|
|
6
|
+
/**
|
|
7
|
+
* Overrides find to enforce tenant presence
|
|
8
|
+
*/
|
|
9
|
+
find(params?: {}): Promise<any>
|
|
10
|
+
}
|
|
11
|
+
import { BaseRepository } from './BaseRepository.js'
|