core-services-sdk 1.3.19 → 1.3.21
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/.eslintrc.json +14 -0
- package/.vscode/settings.json +6 -1
- package/eslint.config.js +21 -0
- package/package.json +12 -5
- package/scripts/bump-version.js +68 -0
- package/src/core/normalize-phone-number.js +7 -4
- package/src/core/regex-utils.js +6 -2
- package/src/http/http.js +41 -86
- package/src/mongodb/validate-mongo-uri.js +1 -1
- package/src/rabbit-mq/rabbit-mq.js +3 -1
- package/tests/http/http-method.unit.test.js +1 -1
- package/tests/http/http.unit.test.js +7 -21
- package/tests/ids/prefixes.unit.test.js +1 -1
- package/tests/templates/template-loader.unit.test.js +0 -4
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"es2021": true,
|
|
4
|
+
"node": true
|
|
5
|
+
},
|
|
6
|
+
"extends": ["eslint:recommended", "plugin:prettier/recommended"],
|
|
7
|
+
"plugins": ["prettier"],
|
|
8
|
+
"rules": {
|
|
9
|
+
"prettier/prettier": "error",
|
|
10
|
+
"no-unused-vars": "warn",
|
|
11
|
+
"no-console": "off"
|
|
12
|
+
},
|
|
13
|
+
"ignores": ["node_modules", "dist", ".next"]
|
|
14
|
+
}
|
package/.vscode/settings.json
CHANGED
|
@@ -12,5 +12,10 @@
|
|
|
12
12
|
},
|
|
13
13
|
"javascript.preferences.importModuleSpecifierEnding": "js",
|
|
14
14
|
"js/ts.implicitProjectConfig.checkJs": true,
|
|
15
|
-
"javascript.validate.enable": true
|
|
15
|
+
"javascript.validate.enable": true,
|
|
16
|
+
"eslint.validate": ["javascript"],
|
|
17
|
+
|
|
18
|
+
"editor.codeActionsOnSave": {
|
|
19
|
+
"source.fixAll.eslint": true
|
|
20
|
+
}
|
|
16
21
|
}
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import eslintPluginPrettier from 'eslint-plugin-prettier'
|
|
2
|
+
|
|
3
|
+
/** @type {import("eslint").Linter.FlatConfig} */
|
|
4
|
+
export default [
|
|
5
|
+
{
|
|
6
|
+
files: ['**/*.js'],
|
|
7
|
+
languageOptions: {
|
|
8
|
+
sourceType: 'module',
|
|
9
|
+
ecmaVersion: 'latest',
|
|
10
|
+
},
|
|
11
|
+
plugins: {
|
|
12
|
+
prettier: eslintPluginPrettier,
|
|
13
|
+
},
|
|
14
|
+
rules: {
|
|
15
|
+
'no-console': 'off',
|
|
16
|
+
'no-unused-vars': 'warn',
|
|
17
|
+
'curly': ['error', 'all'],
|
|
18
|
+
'prettier/prettier': 'error',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
]
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "core-services-sdk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.21",
|
|
4
4
|
"main": "src/index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"lint": "eslint .",
|
|
8
|
+
"lint:fix": "eslint . --fix",
|
|
9
|
+
"test": "vitest run --coverage",
|
|
10
|
+
"format": "prettier --write .",
|
|
11
|
+
"bump": "node ./scripts/bump-version.js"
|
|
8
12
|
},
|
|
9
13
|
"repository": {
|
|
10
14
|
"type": "git",
|
|
@@ -28,7 +32,6 @@
|
|
|
28
32
|
"google-libphonenumber": "^3.2.42",
|
|
29
33
|
"http-status": "^2.1.0",
|
|
30
34
|
"mongodb": "^6.18.0",
|
|
31
|
-
"node-fetch": "^3.3.2",
|
|
32
35
|
"nodemailer": "^7.0.5",
|
|
33
36
|
"pino": "^9.7.0",
|
|
34
37
|
"uuid": "^11.1.0",
|
|
@@ -38,6 +41,10 @@
|
|
|
38
41
|
"@vitest/coverage-v8": "^3.2.4",
|
|
39
42
|
"path": "^0.12.7",
|
|
40
43
|
"url": "^0.11.4",
|
|
41
|
-
"vitest": "^3.2.4"
|
|
44
|
+
"vitest": "^3.2.4",
|
|
45
|
+
"eslint": "^9.30.0",
|
|
46
|
+
"eslint-config-prettier": "^10.1.5",
|
|
47
|
+
"eslint-plugin-prettier": "^5.5.1",
|
|
48
|
+
"prettier": "^3.6.2"
|
|
42
49
|
}
|
|
43
|
-
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { execSync } from 'child_process'
|
|
4
|
+
|
|
5
|
+
const type = process.argv[2] // "major" | "minor" | "patch" | "-major" | "-minor" | "-patch"
|
|
6
|
+
|
|
7
|
+
if (!['major', 'minor', 'patch', '-major', '-minor', '-patch'].includes(type)) {
|
|
8
|
+
console.error(`Usage: npm run bump <major|minor|patch|-major|-minor|-patch>`)
|
|
9
|
+
process.exit(1)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const pkgPath = path.resolve(process.cwd(), 'package.json')
|
|
13
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
|
|
14
|
+
|
|
15
|
+
let [major, minor, patch] = pkg.version.split('.').map(Number)
|
|
16
|
+
|
|
17
|
+
const bump = () => {
|
|
18
|
+
switch (type) {
|
|
19
|
+
case 'major':
|
|
20
|
+
return [major + 1, 0, 0]
|
|
21
|
+
case 'minor':
|
|
22
|
+
return [major, minor + 1, 0]
|
|
23
|
+
case 'patch':
|
|
24
|
+
return [major, minor, patch + 1]
|
|
25
|
+
case '-major':
|
|
26
|
+
if (major === 0) {
|
|
27
|
+
throw new Error('Cannot decrement major below 0')
|
|
28
|
+
}
|
|
29
|
+
return [major - 1, 0, 0]
|
|
30
|
+
case '-minor':
|
|
31
|
+
if (minor === 0) {
|
|
32
|
+
if (major === 0) {
|
|
33
|
+
throw new Error('Cannot decrement minor below 0.0')
|
|
34
|
+
}
|
|
35
|
+
return [major - 1, 0, 0]
|
|
36
|
+
}
|
|
37
|
+
return [major, minor - 1, 0]
|
|
38
|
+
case '-patch':
|
|
39
|
+
if (patch === 0) {
|
|
40
|
+
if (minor === 0) {
|
|
41
|
+
if (major === 0) {
|
|
42
|
+
throw new Error('Cannot decrement below 0.0.0')
|
|
43
|
+
}
|
|
44
|
+
return [major - 1, 0, 0]
|
|
45
|
+
}
|
|
46
|
+
return [major, minor - 1, 0]
|
|
47
|
+
}
|
|
48
|
+
return [major, minor, patch - 1]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const [newMajor, newMinor, newPatch] = bump()
|
|
53
|
+
const newVersion = `${newMajor}.${newMinor}.${newPatch}`
|
|
54
|
+
|
|
55
|
+
pkg.version = newVersion
|
|
56
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
|
|
57
|
+
|
|
58
|
+
console.log(`✔ Updated version to ${newVersion}`)
|
|
59
|
+
|
|
60
|
+
// update package-lock.json if exists
|
|
61
|
+
if (fs.existsSync('./package-lock.json')) {
|
|
62
|
+
try {
|
|
63
|
+
execSync('npm install --package-lock-only', { stdio: 'inherit' })
|
|
64
|
+
console.log('✔ package-lock.json updated')
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error('Failed to update package-lock.json', err)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -7,10 +7,9 @@ import * as raw from 'google-libphonenumber'
|
|
|
7
7
|
export function getLib() {
|
|
8
8
|
// Prefer direct (CJS-style or ESM w/ named), else default
|
|
9
9
|
// e.g. raw.PhoneNumberUtil OR raw.default.PhoneNumberUtil
|
|
10
|
-
// eslint-disable-next-line no-unused-vars
|
|
11
10
|
/** @type {any} */
|
|
12
11
|
const anyRaw = raw
|
|
13
|
-
const lib = anyRaw.PhoneNumberUtil ? anyRaw : anyRaw.default ?? anyRaw
|
|
12
|
+
const lib = anyRaw.PhoneNumberUtil ? anyRaw : (anyRaw.default ?? anyRaw)
|
|
14
13
|
|
|
15
14
|
if (!lib || !lib.PhoneNumberUtil || !lib.PhoneNumberFormat) {
|
|
16
15
|
throw new Error('google-libphonenumber failed to load (exports not found)')
|
|
@@ -71,7 +70,9 @@ export function normalizePhoneOrThrowIntl(input) {
|
|
|
71
70
|
try {
|
|
72
71
|
const util = phoneUtil()
|
|
73
72
|
const parsed = util.parseAndKeepRawInput(clean(input))
|
|
74
|
-
if (!util.isValidNumber(parsed))
|
|
73
|
+
if (!util.isValidNumber(parsed)) {
|
|
74
|
+
throw new Error('Phone number failed validation')
|
|
75
|
+
}
|
|
75
76
|
return toResult(parsed)
|
|
76
77
|
} catch (e) {
|
|
77
78
|
const err = new Error('Invalid phone number')
|
|
@@ -91,7 +92,9 @@ export function normalizePhoneOrThrowWithRegion(input, defaultRegion) {
|
|
|
91
92
|
try {
|
|
92
93
|
const util = phoneUtil()
|
|
93
94
|
const parsed = util.parseAndKeepRawInput(clean(input), defaultRegion)
|
|
94
|
-
if (!util.isValidNumber(parsed))
|
|
95
|
+
if (!util.isValidNumber(parsed)) {
|
|
96
|
+
throw new Error('Phone number failed validation')
|
|
97
|
+
}
|
|
95
98
|
return toResult(parsed)
|
|
96
99
|
} catch (e) {
|
|
97
100
|
const err = new Error('Invalid phone number')
|
package/src/core/regex-utils.js
CHANGED
|
@@ -16,8 +16,12 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
export const isValidRegex = (pattern) => {
|
|
19
|
-
if (pattern instanceof RegExp)
|
|
20
|
-
|
|
19
|
+
if (pattern instanceof RegExp) {
|
|
20
|
+
return true
|
|
21
|
+
}
|
|
22
|
+
if (typeof pattern !== 'string') {
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
21
25
|
try {
|
|
22
26
|
new RegExp(pattern)
|
|
23
27
|
return true
|
package/src/http/http.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A lightweight HTTP client wrapper around
|
|
3
|
-
*
|
|
2
|
+
* A lightweight HTTP client wrapper around Node.js native fetch
|
|
3
|
+
* supporting JSON, XML, and plain text responses.
|
|
4
|
+
* Provides simplified helper methods for GET, POST, PUT, PATCH, and DELETE
|
|
5
|
+
* with automatic error handling.
|
|
4
6
|
*
|
|
5
7
|
* @module http
|
|
6
8
|
*/
|
|
7
9
|
|
|
8
|
-
import fetch from 'node-fetch'
|
|
9
10
|
import httpStatus from 'http-status'
|
|
10
11
|
import { parseStringPromise } from 'xml2js'
|
|
11
12
|
|
|
@@ -20,26 +21,27 @@ const JSON_HEADER = {
|
|
|
20
21
|
/**
|
|
21
22
|
* Checks if the HTTP status is considered successful (2xx).
|
|
22
23
|
*
|
|
23
|
-
* @param {
|
|
24
|
+
* @param {Response} response
|
|
24
25
|
* @returns {boolean}
|
|
25
26
|
*/
|
|
26
27
|
const isOkStatus = ({ status }) =>
|
|
27
28
|
status >= httpStatus.OK && status < httpStatus.MULTIPLE_CHOICES
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
31
|
+
* Ensures the response has a successful status, otherwise throws HttpError.
|
|
32
|
+
*
|
|
33
|
+
* @param {Response} response
|
|
34
|
+
* @returns {Promise<Response>}
|
|
32
35
|
*/
|
|
33
36
|
const checkStatus = async (response) => {
|
|
34
37
|
if (!isOkStatus(response)) {
|
|
35
38
|
const text = await response.text()
|
|
36
|
-
const info = tryConvertJsonResponse(text)
|
|
37
39
|
const { status, statusText } = response
|
|
38
|
-
|
|
39
40
|
throw new HttpError({
|
|
40
41
|
code: status,
|
|
41
42
|
httpStatusCode: status,
|
|
42
43
|
httpStatusText: statusText,
|
|
44
|
+
extendInfo: { text },
|
|
43
45
|
})
|
|
44
46
|
}
|
|
45
47
|
return response
|
|
@@ -48,19 +50,17 @@ const checkStatus = async (response) => {
|
|
|
48
50
|
/**
|
|
49
51
|
* Reads the raw text from a fetch response.
|
|
50
52
|
*
|
|
51
|
-
* @param {
|
|
52
|
-
* @returns {Promise<string>}
|
|
53
|
+
* @param {Response} response
|
|
54
|
+
* @returns {Promise<string>}
|
|
53
55
|
*/
|
|
54
|
-
const getTextResponse = async (response) =>
|
|
55
|
-
return await response.text()
|
|
56
|
-
}
|
|
56
|
+
const getTextResponse = async (response) => response.text()
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Attempts to parse a JSON string.
|
|
60
60
|
*
|
|
61
|
-
* @param {string} responseText
|
|
62
|
-
* @returns {Object}
|
|
63
|
-
* @throws {SyntaxError} If
|
|
61
|
+
* @param {string} responseText
|
|
62
|
+
* @returns {Object}
|
|
63
|
+
* @throws {SyntaxError} If not valid JSON.
|
|
64
64
|
*/
|
|
65
65
|
const tryConvertJsonResponse = (responseText) => {
|
|
66
66
|
try {
|
|
@@ -72,10 +72,10 @@ const tryConvertJsonResponse = (responseText) => {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
*
|
|
75
|
+
* Extracts JSON from a response, or returns raw text on failure.
|
|
76
76
|
*
|
|
77
|
-
* @param {
|
|
78
|
-
* @returns {Promise<Object|string>}
|
|
77
|
+
* @param {Response} response
|
|
78
|
+
* @returns {Promise<Object|string>}
|
|
79
79
|
*/
|
|
80
80
|
const tryGetJsonResponse = async (response) => {
|
|
81
81
|
let jsonText
|
|
@@ -83,16 +83,18 @@ const tryGetJsonResponse = async (response) => {
|
|
|
83
83
|
jsonText = await getTextResponse(response)
|
|
84
84
|
return tryConvertJsonResponse(jsonText)
|
|
85
85
|
} catch (error) {
|
|
86
|
-
if (!jsonText)
|
|
86
|
+
if (!jsonText) {
|
|
87
|
+
throw error
|
|
88
|
+
}
|
|
87
89
|
return jsonText
|
|
88
90
|
}
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
/**
|
|
92
|
-
*
|
|
94
|
+
* Extracts XML from a response, or returns raw text on failure.
|
|
93
95
|
*
|
|
94
|
-
* @param {
|
|
95
|
-
* @returns {Promise<Object|string>}
|
|
96
|
+
* @param {Response} response
|
|
97
|
+
* @returns {Promise<Object|string>}
|
|
96
98
|
*/
|
|
97
99
|
const tryGetXmlResponse = async (response) => {
|
|
98
100
|
let xmlText
|
|
@@ -100,17 +102,19 @@ const tryGetXmlResponse = async (response) => {
|
|
|
100
102
|
xmlText = await getTextResponse(response)
|
|
101
103
|
return await parseStringPromise(xmlText)
|
|
102
104
|
} catch (error) {
|
|
103
|
-
if (!xmlText)
|
|
105
|
+
if (!xmlText) {
|
|
106
|
+
throw error
|
|
107
|
+
}
|
|
104
108
|
return xmlText
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
/**
|
|
109
|
-
*
|
|
113
|
+
* Parses the fetch response based on expected type.
|
|
110
114
|
*
|
|
111
|
-
* @param {
|
|
112
|
-
* @param {string} responseType
|
|
113
|
-
* @returns {Promise<any>}
|
|
115
|
+
* @param {Response} response
|
|
116
|
+
* @param {string} responseType
|
|
117
|
+
* @returns {Promise<any>}
|
|
114
118
|
*/
|
|
115
119
|
const getResponsePayload = async (response, responseType) => {
|
|
116
120
|
switch (responseType) {
|
|
@@ -119,149 +123,100 @@ const getResponsePayload = async (response, responseType) => {
|
|
|
119
123
|
case ResponseType.xml:
|
|
120
124
|
return tryGetXmlResponse(response)
|
|
121
125
|
default:
|
|
122
|
-
case ResponseType.text:
|
|
123
126
|
return getTextResponse(response)
|
|
124
127
|
}
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
/**
|
|
128
131
|
* Sends an HTTP GET request.
|
|
129
|
-
*
|
|
130
|
-
* @param {Object} params
|
|
131
|
-
* @param {string} params.url - Target URL.
|
|
132
|
-
* @param {Object} [params.headers] - Optional request headers.
|
|
133
|
-
* @param {string} [params.credentials='include'] - Credential policy.
|
|
134
|
-
* @param {string} [params.expectedType='json'] - Expected response format.
|
|
135
|
-
* @returns {Promise<any>} Parsed response data.
|
|
136
132
|
*/
|
|
137
133
|
export const get = async ({
|
|
138
134
|
url,
|
|
139
135
|
headers = {},
|
|
140
|
-
credentials = 'include',
|
|
141
136
|
expectedType = ResponseType.json,
|
|
142
137
|
}) => {
|
|
143
|
-
/** @type {import('node-fetch').Response} */
|
|
144
138
|
const response = await fetch(url, {
|
|
145
139
|
method: HTTP_METHODS.GET,
|
|
146
140
|
headers: { ...JSON_HEADER, ...headers },
|
|
147
|
-
...(credentials ? { credentials } : {}),
|
|
148
141
|
})
|
|
149
|
-
|
|
150
142
|
await checkStatus(response)
|
|
151
|
-
return
|
|
143
|
+
return getResponsePayload(response, expectedType)
|
|
152
144
|
}
|
|
153
145
|
|
|
154
146
|
/**
|
|
155
147
|
* Sends an HTTP POST request.
|
|
156
|
-
*
|
|
157
|
-
* @param {Object} params
|
|
158
|
-
* @param {string} params.url - Target URL.
|
|
159
|
-
* @param {Object} params.body - Request body (will be JSON.stringify-ed).
|
|
160
|
-
* @param {Object} [params.headers] - Optional request headers.
|
|
161
|
-
* @param {string} [params.credentials='include'] - Credential policy.
|
|
162
|
-
* @param {string} [params.expectedType='json'] - Expected response format.
|
|
163
|
-
* @returns {Promise<any>} Parsed response data.
|
|
164
148
|
*/
|
|
165
149
|
export const post = async ({
|
|
166
150
|
url,
|
|
167
151
|
body,
|
|
168
|
-
headers,
|
|
169
|
-
credentials = 'include',
|
|
152
|
+
headers = {},
|
|
170
153
|
expectedType = ResponseType.json,
|
|
171
154
|
}) => {
|
|
172
155
|
const response = await fetch(url, {
|
|
173
156
|
method: HTTP_METHODS.POST,
|
|
174
157
|
headers: { ...JSON_HEADER, ...headers },
|
|
175
158
|
body: JSON.stringify(body),
|
|
176
|
-
...(credentials ? { credentials } : {}),
|
|
177
159
|
})
|
|
178
160
|
await checkStatus(response)
|
|
179
|
-
return
|
|
161
|
+
return getResponsePayload(response, expectedType)
|
|
180
162
|
}
|
|
181
163
|
|
|
182
164
|
/**
|
|
183
165
|
* Sends an HTTP PUT request.
|
|
184
|
-
*
|
|
185
|
-
* @param {Object} params
|
|
186
|
-
* @param {string} params.url
|
|
187
|
-
* @param {Object} params.body
|
|
188
|
-
* @param {Object} [params.headers]
|
|
189
|
-
* @param {string} [params.credentials='include']
|
|
190
|
-
* @param {string} [params.expectedType='json']
|
|
191
|
-
* @returns {Promise<any>} Parsed response data.
|
|
192
166
|
*/
|
|
193
167
|
export const put = async ({
|
|
194
168
|
url,
|
|
195
169
|
body,
|
|
196
170
|
headers = {},
|
|
197
|
-
credentials = 'include',
|
|
198
171
|
expectedType = ResponseType.json,
|
|
199
172
|
}) => {
|
|
200
173
|
const response = await fetch(url, {
|
|
201
174
|
method: HTTP_METHODS.PUT,
|
|
202
175
|
headers: { ...JSON_HEADER, ...headers },
|
|
203
176
|
body: JSON.stringify(body),
|
|
204
|
-
...(credentials ? { credentials } : {}),
|
|
205
177
|
})
|
|
206
178
|
await checkStatus(response)
|
|
207
|
-
return
|
|
179
|
+
return getResponsePayload(response, expectedType)
|
|
208
180
|
}
|
|
209
181
|
|
|
210
182
|
/**
|
|
211
183
|
* Sends an HTTP PATCH request.
|
|
212
|
-
*
|
|
213
|
-
* @param {Object} params - Same as `post`.
|
|
214
|
-
* @returns {Promise<any>} Parsed response data.
|
|
215
184
|
*/
|
|
216
185
|
export const patch = async ({
|
|
217
186
|
url,
|
|
218
187
|
body,
|
|
219
|
-
headers,
|
|
220
|
-
credentials = 'include',
|
|
188
|
+
headers = {},
|
|
221
189
|
expectedType = ResponseType.json,
|
|
222
190
|
}) => {
|
|
223
191
|
const response = await fetch(url, {
|
|
224
192
|
method: HTTP_METHODS.PATCH,
|
|
225
193
|
headers: { ...JSON_HEADER, ...headers },
|
|
226
194
|
body: JSON.stringify(body),
|
|
227
|
-
...(credentials ? { credentials } : {}),
|
|
228
195
|
})
|
|
229
196
|
await checkStatus(response)
|
|
230
|
-
return
|
|
197
|
+
return getResponsePayload(response, expectedType)
|
|
231
198
|
}
|
|
232
199
|
|
|
233
200
|
/**
|
|
234
201
|
* Sends an HTTP DELETE request.
|
|
235
|
-
*
|
|
236
|
-
* @param {Object} params - Same as `post`, but body is optional.
|
|
237
|
-
* @returns {Promise<any>} Parsed response data.
|
|
238
202
|
*/
|
|
239
203
|
export const deleteApi = async ({
|
|
240
204
|
url,
|
|
241
205
|
body,
|
|
242
|
-
headers,
|
|
243
|
-
credentials = 'include',
|
|
206
|
+
headers = {},
|
|
244
207
|
expectedType = ResponseType.json,
|
|
245
208
|
}) => {
|
|
246
209
|
const response = await fetch(url, {
|
|
247
210
|
method: HTTP_METHODS.DELETE,
|
|
248
211
|
headers: { ...JSON_HEADER, ...headers },
|
|
249
212
|
...(body ? { body: JSON.stringify(body) } : {}),
|
|
250
|
-
...(credentials ? { credentials } : {}),
|
|
251
213
|
})
|
|
252
214
|
await checkStatus(response)
|
|
253
|
-
return
|
|
215
|
+
return getResponsePayload(response, expectedType)
|
|
254
216
|
}
|
|
255
217
|
|
|
256
218
|
/**
|
|
257
|
-
* Consolidated HTTP client
|
|
258
|
-
*
|
|
259
|
-
* @namespace http
|
|
260
|
-
* @property {Function} get - HTTP GET method.
|
|
261
|
-
* @property {Function} post - HTTP POST method.
|
|
262
|
-
* @property {Function} put - HTTP PUT method.
|
|
263
|
-
* @property {Function} patch - HTTP PATCH method.
|
|
264
|
-
* @property {Function} deleteApi - HTTP DELETE method.
|
|
219
|
+
* Consolidated HTTP client.
|
|
265
220
|
*/
|
|
266
221
|
export const http = {
|
|
267
222
|
get,
|
|
@@ -75,7 +75,9 @@ export const subscribeToQueue = async ({
|
|
|
75
75
|
!!prefetch && (await channel.prefetch(prefetch))
|
|
76
76
|
|
|
77
77
|
channel.consume(queue, async (msgInfo) => {
|
|
78
|
-
if (!msgInfo)
|
|
78
|
+
if (!msgInfo) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
79
81
|
|
|
80
82
|
try {
|
|
81
83
|
const { msgId, data } = parseMessage(msgInfo)
|
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import { vi, it, expect, describe, afterEach } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import fetch from 'node-fetch'
|
|
4
3
|
import { http } from '../../src/http/http.js'
|
|
5
4
|
import { HttpError } from '../../src/http/HttpError.js'
|
|
6
5
|
import { HTTP_METHODS } from '../../src/http/http-method.js'
|
|
7
6
|
import { ResponseType } from '../../src/http/responseType.js'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
...actual,
|
|
13
|
-
default: vi.fn(),
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
const mockFetch = /** @type {typeof fetch} */ (fetch)
|
|
8
|
+
// Mock the global fetch
|
|
9
|
+
const mockFetch = vi.fn()
|
|
10
|
+
global.fetch = mockFetch
|
|
18
11
|
|
|
19
12
|
const createMockResponse = ({
|
|
20
13
|
body = '',
|
|
@@ -23,22 +16,22 @@ const createMockResponse = ({
|
|
|
23
16
|
headers = {},
|
|
24
17
|
} = {}) => {
|
|
25
18
|
return {
|
|
26
|
-
ok: status >= 200 && status < 300,
|
|
27
19
|
status,
|
|
28
20
|
statusText,
|
|
29
21
|
text: vi.fn().mockResolvedValue(body),
|
|
30
|
-
headers: {
|
|
22
|
+
headers: {
|
|
23
|
+
get: vi.fn().mockImplementation((k) => headers[k]),
|
|
24
|
+
},
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
27
|
|
|
34
|
-
describe('http client', () => {
|
|
28
|
+
describe('http client (native fetch)', () => {
|
|
35
29
|
afterEach(() => {
|
|
36
30
|
vi.clearAllMocks()
|
|
37
31
|
})
|
|
38
32
|
|
|
39
33
|
describe('GET', () => {
|
|
40
34
|
it('should return parsed JSON response', async () => {
|
|
41
|
-
// @ts-ignore
|
|
42
35
|
mockFetch.mockResolvedValueOnce(
|
|
43
36
|
createMockResponse({ body: JSON.stringify({ hello: 'world' }) }),
|
|
44
37
|
)
|
|
@@ -52,7 +45,6 @@ describe('http client', () => {
|
|
|
52
45
|
})
|
|
53
46
|
|
|
54
47
|
it('should throw HttpError on non-2xx status', async () => {
|
|
55
|
-
// @ts-ignore
|
|
56
48
|
mockFetch.mockResolvedValueOnce(
|
|
57
49
|
createMockResponse({
|
|
58
50
|
status: 404,
|
|
@@ -69,7 +61,6 @@ describe('http client', () => {
|
|
|
69
61
|
|
|
70
62
|
describe('POST', () => {
|
|
71
63
|
it('should send a JSON body and return parsed JSON', async () => {
|
|
72
|
-
// @ts-ignore
|
|
73
64
|
mockFetch.mockResolvedValueOnce(
|
|
74
65
|
createMockResponse({ body: JSON.stringify({ ok: true }) }),
|
|
75
66
|
)
|
|
@@ -92,7 +83,6 @@ describe('http client', () => {
|
|
|
92
83
|
|
|
93
84
|
describe('PUT', () => {
|
|
94
85
|
it('should send a PUT request and return JSON', async () => {
|
|
95
|
-
// @ts-ignore
|
|
96
86
|
mockFetch.mockResolvedValueOnce(
|
|
97
87
|
createMockResponse({ body: JSON.stringify({ updated: true }) }),
|
|
98
88
|
)
|
|
@@ -108,7 +98,6 @@ describe('http client', () => {
|
|
|
108
98
|
|
|
109
99
|
describe('PATCH', () => {
|
|
110
100
|
it('should send a PATCH request and return JSON', async () => {
|
|
111
|
-
// @ts-ignore
|
|
112
101
|
mockFetch.mockResolvedValueOnce(
|
|
113
102
|
createMockResponse({ body: JSON.stringify({ patched: true }) }),
|
|
114
103
|
)
|
|
@@ -124,7 +113,6 @@ describe('http client', () => {
|
|
|
124
113
|
|
|
125
114
|
describe('DELETE', () => {
|
|
126
115
|
it('should send a DELETE request with body and return JSON', async () => {
|
|
127
|
-
// @ts-ignore
|
|
128
116
|
mockFetch.mockResolvedValueOnce(
|
|
129
117
|
createMockResponse({ body: JSON.stringify({ deleted: true }) }),
|
|
130
118
|
)
|
|
@@ -140,7 +128,6 @@ describe('http client', () => {
|
|
|
140
128
|
|
|
141
129
|
describe('ResponseType', () => {
|
|
142
130
|
it('should return text if expectedType is text', async () => {
|
|
143
|
-
// @ts-ignore
|
|
144
131
|
mockFetch.mockResolvedValueOnce(createMockResponse({ body: 'hello' }))
|
|
145
132
|
|
|
146
133
|
const result = await http.get({
|
|
@@ -153,7 +140,6 @@ describe('http client', () => {
|
|
|
153
140
|
|
|
154
141
|
it('should return XML as parsed object if expectedType is xml', async () => {
|
|
155
142
|
const xml = `<note><to>User</to><from>ChatGPT</from></note>`
|
|
156
|
-
// @ts-ignore
|
|
157
143
|
mockFetch.mockResolvedValueOnce(createMockResponse({ body: xml }))
|
|
158
144
|
|
|
159
145
|
const result = await http.get({
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import dot from 'dot'
|
|
2
1
|
import * as fs from 'fs/promises'
|
|
3
2
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
4
3
|
|
|
@@ -7,9 +6,6 @@ import { loadTemplates } from '../../src/templates/template-loader.js'
|
|
|
7
6
|
vi.mock('fs/promises')
|
|
8
7
|
|
|
9
8
|
describe('loadTemplates', () => {
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
const mockCompile = vi.spyOn(dot, 'compile')
|
|
12
|
-
|
|
13
9
|
beforeEach(() => {
|
|
14
10
|
vi.resetAllMocks()
|
|
15
11
|
})
|