@turndown/library 0.1.24 → 0.1.29
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/dist/index.cjs +1719 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2820 -0
- package/dist/index.d.ts +2820 -2
- package/dist/index.mjs +1577 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +10 -6
- package/dist/helpers/date/index.d.ts +0 -113
- package/dist/helpers/date/index.js +0 -171
- package/dist/helpers/index.d.ts +0 -4
- package/dist/helpers/index.js +0 -3
- package/dist/helpers/object/index.d.ts +0 -298
- package/dist/helpers/object/index.js +0 -540
- package/dist/helpers/string/index.d.ts +0 -258
- package/dist/helpers/string/index.js +0 -496
- package/dist/index.js +0 -2
- package/dist/types/api/index.d.ts +0 -71
- package/dist/types/api/index.js +0 -54
- package/dist/types/auth/index.d.ts +0 -107
- package/dist/types/auth/index.js +0 -8
- package/dist/types/auth/routes.d.ts +0 -160
- package/dist/types/auth/routes.js +0 -1
- package/dist/types/base/index.d.ts +0 -200
- package/dist/types/base/index.js +0 -177
- package/dist/types/base/paging.types.d.ts +0 -47
- package/dist/types/base/paging.types.js +0 -1
- package/dist/types/checklist-template/index.d.ts +0 -48
- package/dist/types/checklist-template/index.js +0 -1
- package/dist/types/checklist-template/routes.d.ts +0 -85
- package/dist/types/checklist-template/routes.js +0 -1
- package/dist/types/company/index.d.ts +0 -22
- package/dist/types/company/index.js +0 -7
- package/dist/types/company/routes.d.ts +0 -100
- package/dist/types/company/routes.js +0 -1
- package/dist/types/damage-report/index.d.ts +0 -148
- package/dist/types/damage-report/index.js +0 -29
- package/dist/types/damage-report/routes.d.ts +0 -112
- package/dist/types/damage-report/routes.js +0 -1
- package/dist/types/errors/index.d.ts +0 -66
- package/dist/types/errors/index.js +0 -41
- package/dist/types/health/index.d.ts +0 -20
- package/dist/types/health/index.js +0 -1
- package/dist/types/health/routes.d.ts +0 -10
- package/dist/types/health/routes.js +0 -1
- package/dist/types/image/index.d.ts +0 -35
- package/dist/types/image/index.js +0 -12
- package/dist/types/image/routes.d.ts +0 -32
- package/dist/types/image/routes.js +0 -1
- package/dist/types/index.d.ts +0 -22
- package/dist/types/index.js +0 -22
- package/dist/types/inventory/index.d.ts +0 -124
- package/dist/types/inventory/index.js +0 -30
- package/dist/types/inventory/routes.d.ts +0 -109
- package/dist/types/inventory/routes.js +0 -1
- package/dist/types/job/index.d.ts +0 -7
- package/dist/types/job/index.js +0 -1
- package/dist/types/property/index.d.ts +0 -113
- package/dist/types/property/index.js +0 -25
- package/dist/types/property/routes.d.ts +0 -54
- package/dist/types/property/routes.js +0 -1
- package/dist/types/room/index.d.ts +0 -28
- package/dist/types/room/index.js +0 -17
- package/dist/types/room/routes.d.ts +0 -35
- package/dist/types/room/routes.js +0 -1
- package/dist/types/room-checklist/index.d.ts +0 -43
- package/dist/types/room-checklist/index.js +0 -1
- package/dist/types/room-checklist/routes.d.ts +0 -78
- package/dist/types/room-checklist/routes.js +0 -1
- package/dist/types/subscription/index.d.ts +0 -32
- package/dist/types/subscription/index.js +0 -16
- package/dist/types/user/index.d.ts +0 -59
- package/dist/types/user/index.js +0 -20
- package/dist/types/user/routes.d.ts +0 -46
- package/dist/types/user/routes.js +0 -1
- package/dist/types/work-session/index.d.ts +0 -97
- package/dist/types/work-session/index.js +0 -18
- package/dist/types/work-session/routes.d.ts +0 -89
- package/dist/types/work-session/routes.js +0 -1
|
@@ -1,496 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* String utilities for common text manipulation tasks.
|
|
3
|
-
*/
|
|
4
|
-
const wordBoundaryRegex = /([a-z0-9])([A-Z])/g;
|
|
5
|
-
const acronymBoundaryRegex = /([A-Z]+)([A-Z][a-z])/g;
|
|
6
|
-
const getWords = (value) => {
|
|
7
|
-
return value
|
|
8
|
-
.trim()
|
|
9
|
-
.replace(acronymBoundaryRegex, "$1 $2")
|
|
10
|
-
.replace(wordBoundaryRegex, "$1 $2")
|
|
11
|
-
.replace(/[^a-zA-Z0-9]+/g, " ")
|
|
12
|
-
.trim()
|
|
13
|
-
.split(/\s+/)
|
|
14
|
-
.filter(Boolean);
|
|
15
|
-
};
|
|
16
|
-
const capitalizeWord = (value) => {
|
|
17
|
-
if (!value) {
|
|
18
|
-
return "";
|
|
19
|
-
}
|
|
20
|
-
return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase();
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Adds commas to a number for thousands separators.
|
|
24
|
-
*
|
|
25
|
-
* @example formatNumber(1000) => '1,000'
|
|
26
|
-
* @example formatNumber('1234567') => '1,234,567'
|
|
27
|
-
* @example formatNumber(1234567.89) => '1,234,567.89'
|
|
28
|
-
*/
|
|
29
|
-
export const formatNumber = (value) => {
|
|
30
|
-
const str = String(value);
|
|
31
|
-
const [integer, decimal] = str.split(".");
|
|
32
|
-
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
33
|
-
return decimal !== undefined
|
|
34
|
-
? `${formattedInteger}.${decimal}`
|
|
35
|
-
: formattedInteger;
|
|
36
|
-
};
|
|
37
|
-
export const normalCase = (str) => {
|
|
38
|
-
if (!str) {
|
|
39
|
-
return "";
|
|
40
|
-
}
|
|
41
|
-
return getWords(str).map(capitalizeWord).join(" ");
|
|
42
|
-
};
|
|
43
|
-
export const sentenceCase = (str) => {
|
|
44
|
-
if (!str) {
|
|
45
|
-
return "";
|
|
46
|
-
}
|
|
47
|
-
const normalizedValue = str.trim().toLowerCase();
|
|
48
|
-
return normalizedValue.charAt(0).toUpperCase() + normalizedValue.slice(1);
|
|
49
|
-
};
|
|
50
|
-
export const upperCase = (str) => {
|
|
51
|
-
return str?.toUpperCase() ?? "";
|
|
52
|
-
};
|
|
53
|
-
export const lowerCase = (str) => {
|
|
54
|
-
return str?.toLowerCase() ?? "";
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* Converts a string to camelCase.
|
|
58
|
-
*
|
|
59
|
-
* @example toCamelCase('hello-world') => 'helloWorld'
|
|
60
|
-
* @example toCamelCase('hello_world') => 'helloWorld'
|
|
61
|
-
*/
|
|
62
|
-
export const toCamelCase = (str) => {
|
|
63
|
-
const words = getWords(str);
|
|
64
|
-
if (words.length === 0) {
|
|
65
|
-
return "";
|
|
66
|
-
}
|
|
67
|
-
const [firstWord, ...remainingWords] = words;
|
|
68
|
-
return [firstWord.toLowerCase(), ...remainingWords.map(capitalizeWord)].join("");
|
|
69
|
-
};
|
|
70
|
-
export const camelCase = toCamelCase;
|
|
71
|
-
/**
|
|
72
|
-
* Converts a string to kebab-case.
|
|
73
|
-
*
|
|
74
|
-
* @example toKebabCase('helloWorld') => 'hello-world'
|
|
75
|
-
* @example toKebabCase('Hello_World') => 'hello-world'
|
|
76
|
-
*/
|
|
77
|
-
export const toKebabCase = (str) => {
|
|
78
|
-
return getWords(str)
|
|
79
|
-
.map((word) => word.toLowerCase())
|
|
80
|
-
.join("-");
|
|
81
|
-
};
|
|
82
|
-
export const kebabCase = toKebabCase;
|
|
83
|
-
/**
|
|
84
|
-
* Converts a string to snake_case.
|
|
85
|
-
*
|
|
86
|
-
* @example toSnakeCase('helloWorld') => 'hello_world'
|
|
87
|
-
* @example toSnakeCase('hello-world') => 'hello_world'
|
|
88
|
-
*/
|
|
89
|
-
export const toSnakeCase = (str) => {
|
|
90
|
-
return getWords(str)
|
|
91
|
-
.map((word) => word.toLowerCase())
|
|
92
|
-
.join("_");
|
|
93
|
-
};
|
|
94
|
-
export const snakeCase = toSnakeCase;
|
|
95
|
-
/**
|
|
96
|
-
* Converts a string to PascalCase.
|
|
97
|
-
*
|
|
98
|
-
* @example toPascalCase('hello-world') => 'HelloWorld'
|
|
99
|
-
* @example toPascalCase('hello_world') => 'HelloWorld'
|
|
100
|
-
*/
|
|
101
|
-
export const toPascalCase = (str) => {
|
|
102
|
-
return getWords(str).map(capitalizeWord).join("");
|
|
103
|
-
};
|
|
104
|
-
export const pascalCase = toPascalCase;
|
|
105
|
-
export const snakeCaseToSpaces = (str) => {
|
|
106
|
-
return str.replace(/_+/g, " ").trim();
|
|
107
|
-
};
|
|
108
|
-
export const kebabToSpaces = (str) => {
|
|
109
|
-
return str.replace(/-+/g, " ").trim();
|
|
110
|
-
};
|
|
111
|
-
/**
|
|
112
|
-
* Capitalizes the first character of a string.
|
|
113
|
-
*
|
|
114
|
-
* @example capitalize('hello world') => 'Hello world'
|
|
115
|
-
*/
|
|
116
|
-
export const capitalize = (str) => {
|
|
117
|
-
if (!str) {
|
|
118
|
-
return "";
|
|
119
|
-
}
|
|
120
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
121
|
-
};
|
|
122
|
-
/**
|
|
123
|
-
* Capitalizes the first letter of each word.
|
|
124
|
-
*
|
|
125
|
-
* @example titleCase('hello world') => 'Hello World'
|
|
126
|
-
*/
|
|
127
|
-
export const titleCase = (str) => {
|
|
128
|
-
return str.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
129
|
-
};
|
|
130
|
-
/**
|
|
131
|
-
* Truncates a string to a specified length and adds ellipsis.
|
|
132
|
-
*
|
|
133
|
-
* @example truncate('hello world', 5) => 'he...'
|
|
134
|
-
*/
|
|
135
|
-
export const truncate = (str, length, suffix = "...") => {
|
|
136
|
-
if (length <= 0) {
|
|
137
|
-
return "";
|
|
138
|
-
}
|
|
139
|
-
if (str.length <= length) {
|
|
140
|
-
return str;
|
|
141
|
-
}
|
|
142
|
-
const maxLength = Math.max(0, length - suffix.length);
|
|
143
|
-
if (maxLength === 0) {
|
|
144
|
-
return suffix.length > length ? "" : suffix;
|
|
145
|
-
}
|
|
146
|
-
return str.slice(0, maxLength) + suffix;
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* Removes all whitespace from a string.
|
|
150
|
-
*
|
|
151
|
-
* @example removeWhitespace('hello world') => 'helloworld'
|
|
152
|
-
*/
|
|
153
|
-
export const removeWhitespace = (str) => {
|
|
154
|
-
return str.replace(/\s+/g, "");
|
|
155
|
-
};
|
|
156
|
-
/**
|
|
157
|
-
* Removes all non-alphanumeric characters.
|
|
158
|
-
*
|
|
159
|
-
* @example removeSpecialChars('hello@world#123') => 'helloworld123'
|
|
160
|
-
*/
|
|
161
|
-
export const removeSpecialChars = (str) => {
|
|
162
|
-
return str.replace(/[^a-zA-Z0-9]/g, "");
|
|
163
|
-
};
|
|
164
|
-
/**
|
|
165
|
-
* Generates a URL-friendly slug from a string.
|
|
166
|
-
*
|
|
167
|
-
* @example slug('Hello World 2024!') => 'hello-world-2024'
|
|
168
|
-
*/
|
|
169
|
-
export const slug = (str) => {
|
|
170
|
-
return str
|
|
171
|
-
.toLowerCase()
|
|
172
|
-
.trim()
|
|
173
|
-
.replace(/[^\w\s-]/g, "")
|
|
174
|
-
.replace(/[\s_]+/g, "-")
|
|
175
|
-
.replace(/-+/g, "-")
|
|
176
|
-
.replace(/^-+|-+$/g, "");
|
|
177
|
-
};
|
|
178
|
-
/**
|
|
179
|
-
* Validates if a string is a valid email.
|
|
180
|
-
*
|
|
181
|
-
* @example isEmail('user@example.com') => true
|
|
182
|
-
*/
|
|
183
|
-
export const isEmail = (str) => {
|
|
184
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
185
|
-
return emailRegex.test(str.trim());
|
|
186
|
-
};
|
|
187
|
-
/**
|
|
188
|
-
* Validates if a string is a valid URL.
|
|
189
|
-
*
|
|
190
|
-
* @example isUrl('https://example.com') => true
|
|
191
|
-
*/
|
|
192
|
-
export const isUrl = (str) => {
|
|
193
|
-
try {
|
|
194
|
-
const parsedUrl = new URL(str);
|
|
195
|
-
return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
|
|
196
|
-
}
|
|
197
|
-
catch {
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
/**
|
|
202
|
-
* Validates if a string contains only numbers.
|
|
203
|
-
*
|
|
204
|
-
* @example isNumeric('12345') => true
|
|
205
|
-
* @example isNumeric('123abc') => false
|
|
206
|
-
*/
|
|
207
|
-
export const isNumeric = (str) => {
|
|
208
|
-
return /^\d+$/.test(str);
|
|
209
|
-
};
|
|
210
|
-
/**
|
|
211
|
-
* Checks if a string is empty or contains only whitespace.
|
|
212
|
-
*
|
|
213
|
-
* @example isEmpty(' ') => true
|
|
214
|
-
* @example isEmpty('hello') => false
|
|
215
|
-
*/
|
|
216
|
-
export const isEmpty = (str) => {
|
|
217
|
-
return str.trim().length === 0;
|
|
218
|
-
};
|
|
219
|
-
/**
|
|
220
|
-
* Reverses a string.
|
|
221
|
-
*
|
|
222
|
-
* @example reverse('hello') => 'olleh'
|
|
223
|
-
*/
|
|
224
|
-
export const reverse = (str) => {
|
|
225
|
-
return Array.from(str).reverse().join("");
|
|
226
|
-
};
|
|
227
|
-
/**
|
|
228
|
-
* Repeats a string a specified number of times.
|
|
229
|
-
*
|
|
230
|
-
* @example repeat('ab', 3) => 'ababab'
|
|
231
|
-
*/
|
|
232
|
-
export const repeat = (str, times) => {
|
|
233
|
-
return str.repeat(Math.max(0, Math.floor(times)));
|
|
234
|
-
};
|
|
235
|
-
/**
|
|
236
|
-
* Pads a string to a specified length.
|
|
237
|
-
*
|
|
238
|
-
* @example padStart('5', 3, '0') => '005'
|
|
239
|
-
* @example padEnd('5', 3, '0') => '500'
|
|
240
|
-
*/
|
|
241
|
-
export const padStart = (str, length, padChar = " ") => {
|
|
242
|
-
return str.padStart(length, padChar);
|
|
243
|
-
};
|
|
244
|
-
export const padEnd = (str, length, padChar = " ") => {
|
|
245
|
-
return str.padEnd(length, padChar);
|
|
246
|
-
};
|
|
247
|
-
/**
|
|
248
|
-
* Encodes a string to Base64.
|
|
249
|
-
*
|
|
250
|
-
* @example toBase64('hello') => 'aGVsbG8='
|
|
251
|
-
*/
|
|
252
|
-
export const toBase64 = (str) => {
|
|
253
|
-
return Buffer.from(str, "utf-8").toString("base64");
|
|
254
|
-
};
|
|
255
|
-
/**
|
|
256
|
-
* Decodes a Base64 string.
|
|
257
|
-
*
|
|
258
|
-
* @example fromBase64('aGVsbG8=') => 'hello'
|
|
259
|
-
*/
|
|
260
|
-
export const fromBase64 = (str) => {
|
|
261
|
-
return Buffer.from(str, "base64").toString("utf-8");
|
|
262
|
-
};
|
|
263
|
-
/**
|
|
264
|
-
* Counts the number of words in a string.
|
|
265
|
-
*
|
|
266
|
-
* @example wordCount('hello world test') => 3
|
|
267
|
-
*/
|
|
268
|
-
export const wordCount = (str) => {
|
|
269
|
-
const trimmedValue = str.trim();
|
|
270
|
-
if (!trimmedValue) {
|
|
271
|
-
return 0;
|
|
272
|
-
}
|
|
273
|
-
return trimmedValue.split(/\s+/).length;
|
|
274
|
-
};
|
|
275
|
-
/**
|
|
276
|
-
* Counts the number of characters, excluding whitespace.
|
|
277
|
-
*
|
|
278
|
-
* @example charCount('hello world') => 10
|
|
279
|
-
*/
|
|
280
|
-
export const charCount = (str) => {
|
|
281
|
-
return str.replace(/\s/g, "").length;
|
|
282
|
-
};
|
|
283
|
-
/**
|
|
284
|
-
* Repeats a character a specified number of times.
|
|
285
|
-
*
|
|
286
|
-
* @example repeatChar('*', 5) => '*****'
|
|
287
|
-
*/
|
|
288
|
-
export const repeatChar = (char, times) => {
|
|
289
|
-
return char.repeat(Math.max(0, Math.floor(times)));
|
|
290
|
-
};
|
|
291
|
-
/**
|
|
292
|
-
* Extracts numbers from a string.
|
|
293
|
-
*
|
|
294
|
-
* @example extractNumbers('abc123def456') => '123456'
|
|
295
|
-
*/
|
|
296
|
-
export const extractNumbers = (str) => {
|
|
297
|
-
return str.replace(/\D/g, "");
|
|
298
|
-
};
|
|
299
|
-
/**
|
|
300
|
-
* Removes duplicate consecutive characters.
|
|
301
|
-
*
|
|
302
|
-
* @example removeDuplicates('aabbccdd') => 'abcd'
|
|
303
|
-
*/
|
|
304
|
-
export const removeDuplicates = (str) => {
|
|
305
|
-
return str.replace(/(.)\1+/g, "$1");
|
|
306
|
-
};
|
|
307
|
-
/**
|
|
308
|
-
* Checks if a string is a palindrome.
|
|
309
|
-
*
|
|
310
|
-
* @example isPalindrome('racecar') => true
|
|
311
|
-
* @example isPalindrome('hello') => false
|
|
312
|
-
*/
|
|
313
|
-
export const isPalindrome = (str) => {
|
|
314
|
-
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
315
|
-
return cleaned === cleaned.split("").reverse().join("");
|
|
316
|
-
};
|
|
317
|
-
/**
|
|
318
|
-
* Finds the longest word in a string.
|
|
319
|
-
*
|
|
320
|
-
* @example longestWord('the quick brown fox') => 'quick'
|
|
321
|
-
*/
|
|
322
|
-
export const longestWord = (str) => {
|
|
323
|
-
const words = str.trim().split(/\s+/).filter(Boolean);
|
|
324
|
-
return words.reduce((longest, word) => (word.length > longest.length ? word : longest), "");
|
|
325
|
-
};
|
|
326
|
-
/**
|
|
327
|
-
* Pluralizes common English words using a simple ruleset.
|
|
328
|
-
*
|
|
329
|
-
* @example pluralize('cat') => 'cats'
|
|
330
|
-
* @example pluralize('box') => 'boxes'
|
|
331
|
-
*/
|
|
332
|
-
export const pluralize = (word) => {
|
|
333
|
-
const exceptions = {
|
|
334
|
-
child: "children",
|
|
335
|
-
person: "people",
|
|
336
|
-
man: "men",
|
|
337
|
-
woman: "women",
|
|
338
|
-
tooth: "teeth",
|
|
339
|
-
foot: "feet",
|
|
340
|
-
mouse: "mice",
|
|
341
|
-
};
|
|
342
|
-
const lowercaseWord = word.toLowerCase();
|
|
343
|
-
const exception = exceptions[lowercaseWord];
|
|
344
|
-
if (exception) {
|
|
345
|
-
return word.charAt(0) === word.charAt(0).toUpperCase()
|
|
346
|
-
? capitalize(exception)
|
|
347
|
-
: exception;
|
|
348
|
-
}
|
|
349
|
-
if (/[^aeiou]y$/i.test(word)) {
|
|
350
|
-
return `${word.slice(0, -1)}ies`;
|
|
351
|
-
}
|
|
352
|
-
if (/(s|x|z|ch|sh)$/i.test(word)) {
|
|
353
|
-
return `${word}es`;
|
|
354
|
-
}
|
|
355
|
-
if (/fe$/i.test(word)) {
|
|
356
|
-
return `${word.slice(0, -2)}ves`;
|
|
357
|
-
}
|
|
358
|
-
if (/f$/i.test(word)) {
|
|
359
|
-
return `${word.slice(0, -1)}ves`;
|
|
360
|
-
}
|
|
361
|
-
return `${word}s`;
|
|
362
|
-
};
|
|
363
|
-
/**
|
|
364
|
-
* Highlights a substring within a string by wrapping it with markers.
|
|
365
|
-
*
|
|
366
|
-
* @example highlight('hello world', 'world', '**') => 'hello **world**'
|
|
367
|
-
*/
|
|
368
|
-
export const highlight = (str, substring, marker = "**") => {
|
|
369
|
-
if (!substring) {
|
|
370
|
-
return str;
|
|
371
|
-
}
|
|
372
|
-
return str.replace(new RegExp(`(${escapeRegex(substring)})`, "gi"), `${marker}$1${marker}`);
|
|
373
|
-
};
|
|
374
|
-
/**
|
|
375
|
-
* Converts a string to a regex-safe string.
|
|
376
|
-
*
|
|
377
|
-
* @example escapeRegex('a.b*c') => 'a\\.b\\*c'
|
|
378
|
-
*/
|
|
379
|
-
export const escapeRegex = (str) => {
|
|
380
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
381
|
-
};
|
|
382
|
-
/**
|
|
383
|
-
* Finds similarity between two strings using Levenshtein distance.
|
|
384
|
-
* Returns a value between 0 and 1, where 1 means identical.
|
|
385
|
-
*
|
|
386
|
-
* @example stringSimilarity('hello', 'hallo') => 0.8
|
|
387
|
-
*/
|
|
388
|
-
export const stringSimilarity = (str1, str2) => {
|
|
389
|
-
const s1 = str1.toLowerCase();
|
|
390
|
-
const s2 = str2.toLowerCase();
|
|
391
|
-
const longer = s1.length > s2.length ? s1 : s2;
|
|
392
|
-
const shorter = s1.length > s2.length ? s2 : s1;
|
|
393
|
-
if (longer.length === 0) {
|
|
394
|
-
return 1;
|
|
395
|
-
}
|
|
396
|
-
const editDistance = getEditDistance(longer, shorter);
|
|
397
|
-
return (longer.length - editDistance) / longer.length;
|
|
398
|
-
};
|
|
399
|
-
/**
|
|
400
|
-
* Helper function to calculate edit distance (Levenshtein distance).
|
|
401
|
-
*/
|
|
402
|
-
const getEditDistance = (s1, s2) => {
|
|
403
|
-
const costs = [];
|
|
404
|
-
for (let i = 0; i <= s1.length; i += 1) {
|
|
405
|
-
let lastValue = i;
|
|
406
|
-
for (let j = 0; j <= s2.length; j += 1) {
|
|
407
|
-
if (i === 0) {
|
|
408
|
-
costs[j] = j;
|
|
409
|
-
}
|
|
410
|
-
else if (j > 0) {
|
|
411
|
-
let newValue = costs[j - 1];
|
|
412
|
-
if (s1.charAt(i - 1) !== s2.charAt(j - 1)) {
|
|
413
|
-
newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
|
|
414
|
-
}
|
|
415
|
-
costs[j - 1] = lastValue;
|
|
416
|
-
lastValue = newValue;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
if (i > 0) {
|
|
420
|
-
costs[s2.length] = lastValue;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return costs[s2.length];
|
|
424
|
-
};
|
|
425
|
-
/**
|
|
426
|
-
* Strips HTML tags from a string.
|
|
427
|
-
*
|
|
428
|
-
* @example stripHtml('<p>Hello <b>world</b></p>') => 'Hello world'
|
|
429
|
-
*/
|
|
430
|
-
export const stripHtml = (str) => {
|
|
431
|
-
return str.replace(/<[^>]*>/g, "");
|
|
432
|
-
};
|
|
433
|
-
/**
|
|
434
|
-
* Replaces multiple spaces with a single space.
|
|
435
|
-
*
|
|
436
|
-
* @example normalizeSpaces('hello world') => 'hello world'
|
|
437
|
-
*/
|
|
438
|
-
export const normalizeSpaces = (str) => {
|
|
439
|
-
return str.replace(/\s+/g, " ").trim();
|
|
440
|
-
};
|
|
441
|
-
/**
|
|
442
|
-
* Converts a string to a number, returning null if not valid.
|
|
443
|
-
*
|
|
444
|
-
* @example toNumber('123') => 123
|
|
445
|
-
* @example toNumber('abc') => null
|
|
446
|
-
*/
|
|
447
|
-
export const toNumber = (str) => {
|
|
448
|
-
if (str.trim() === "") {
|
|
449
|
-
return null;
|
|
450
|
-
}
|
|
451
|
-
const num = Number(str);
|
|
452
|
-
return Number.isNaN(num) ? null : num;
|
|
453
|
-
};
|
|
454
|
-
/**
|
|
455
|
-
* Splits a string by multiple delimiters.
|
|
456
|
-
*
|
|
457
|
-
* @example splitMultiple('a,b;c:d', ',', ';', ':') => ['a', 'b', 'c', 'd']
|
|
458
|
-
*/
|
|
459
|
-
export const splitMultiple = (str, ...delimiters) => {
|
|
460
|
-
if (delimiters.length === 0) {
|
|
461
|
-
return [str].filter((part) => part.length > 0);
|
|
462
|
-
}
|
|
463
|
-
let result = [str];
|
|
464
|
-
delimiters.forEach((delimiter) => {
|
|
465
|
-
if (delimiter !== "") {
|
|
466
|
-
result = result.flatMap((part) => part.split(delimiter));
|
|
467
|
-
}
|
|
468
|
-
});
|
|
469
|
-
return result.filter((part) => part.length > 0);
|
|
470
|
-
};
|
|
471
|
-
/**
|
|
472
|
-
* Checks if a string contains any of the provided substrings.
|
|
473
|
-
*
|
|
474
|
-
* @example containsAny('hello world', 'foo', 'world') => true
|
|
475
|
-
*/
|
|
476
|
-
export const containsAny = (str, ...substrings) => {
|
|
477
|
-
return substrings.some((substring) => str.includes(substring));
|
|
478
|
-
};
|
|
479
|
-
/**
|
|
480
|
-
* Checks if a string contains all of the provided substrings.
|
|
481
|
-
*
|
|
482
|
-
* @example containsAll('hello world', 'hello', 'world') => true
|
|
483
|
-
*/
|
|
484
|
-
export const containsAll = (str, ...substrings) => {
|
|
485
|
-
return substrings.every((substring) => str.includes(substring));
|
|
486
|
-
};
|
|
487
|
-
export const formatAddress = (address) => {
|
|
488
|
-
const parts = [
|
|
489
|
-
address.addressLine1,
|
|
490
|
-
address.addressLine2,
|
|
491
|
-
address.city,
|
|
492
|
-
address.stateCode,
|
|
493
|
-
address.postalCode,
|
|
494
|
-
].filter(Boolean);
|
|
495
|
-
return parts.join(", ");
|
|
496
|
-
};
|
package/dist/index.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API Response Types
|
|
3
|
-
* Standard response structure for all API endpoints
|
|
4
|
-
*/
|
|
5
|
-
import { TurndownObject } from "../base";
|
|
6
|
-
export declare const HTTP_METHOD: {
|
|
7
|
-
readonly Get: "GET";
|
|
8
|
-
readonly Post: "POST";
|
|
9
|
-
readonly Put: "PUT";
|
|
10
|
-
readonly Patch: "PATCH";
|
|
11
|
-
readonly Delete: "DELETE";
|
|
12
|
-
};
|
|
13
|
-
export type THttpMethod = (typeof HTTP_METHOD)[keyof typeof HTTP_METHOD];
|
|
14
|
-
export interface IApiError<TDetails extends object = TurndownObject> {
|
|
15
|
-
message: string;
|
|
16
|
-
code?: string;
|
|
17
|
-
details?: TDetails;
|
|
18
|
-
}
|
|
19
|
-
export interface IApiMeta {
|
|
20
|
-
timestamp: string;
|
|
21
|
-
version: string;
|
|
22
|
-
environment: string;
|
|
23
|
-
requestId?: string;
|
|
24
|
-
}
|
|
25
|
-
export interface IApiResponse<TData = TurndownObject> {
|
|
26
|
-
success: boolean;
|
|
27
|
-
data?: TData | null;
|
|
28
|
-
error?: IApiError | null;
|
|
29
|
-
meta?: IApiMeta;
|
|
30
|
-
}
|
|
31
|
-
export type TApiResponse<T> = {
|
|
32
|
-
data: T;
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Error Codes
|
|
36
|
-
* Standardized error codes used across the platform
|
|
37
|
-
*/
|
|
38
|
-
export declare const ERROR_CODES: {
|
|
39
|
-
readonly BAD_REQUEST: "BAD_REQUEST";
|
|
40
|
-
readonly VALIDATION_ERROR: "VALIDATION_ERROR";
|
|
41
|
-
readonly MISSING_FIELDS: "MISSING_FIELDS";
|
|
42
|
-
readonly UNAUTHORIZED: "UNAUTHORIZED";
|
|
43
|
-
readonly INVALID_TOKEN: "INVALID_TOKEN";
|
|
44
|
-
readonly INVALID_CREDENTIALS: "INVALID_CREDENTIALS";
|
|
45
|
-
readonly FORBIDDEN: "FORBIDDEN";
|
|
46
|
-
readonly NOT_FOUND: "NOT_FOUND";
|
|
47
|
-
readonly CONFLICT: "CONFLICT";
|
|
48
|
-
readonly ALREADY_EXISTS: "ALREADY_EXISTS";
|
|
49
|
-
readonly RATE_LIMIT: "RATE_LIMIT";
|
|
50
|
-
readonly RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED";
|
|
51
|
-
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
52
|
-
readonly DATABASE_ERROR: "DATABASE_ERROR";
|
|
53
|
-
};
|
|
54
|
-
export type TErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];
|
|
55
|
-
/**
|
|
56
|
-
* HTTP Status Codes
|
|
57
|
-
* Common status codes used in responses
|
|
58
|
-
*/
|
|
59
|
-
export declare const HTTP_STATUS: {
|
|
60
|
-
readonly OK: 200;
|
|
61
|
-
readonly CREATED: 201;
|
|
62
|
-
readonly NO_CONTENT: 204;
|
|
63
|
-
readonly BAD_REQUEST: 400;
|
|
64
|
-
readonly UNAUTHORIZED: 401;
|
|
65
|
-
readonly FORBIDDEN: 403;
|
|
66
|
-
readonly NOT_FOUND: 404;
|
|
67
|
-
readonly CONFLICT: 409;
|
|
68
|
-
readonly RATE_LIMIT: 429;
|
|
69
|
-
readonly INTERNAL_ERROR: 500;
|
|
70
|
-
};
|
|
71
|
-
export type THttpStatusCode = (typeof HTTP_STATUS)[keyof typeof HTTP_STATUS];
|
package/dist/types/api/index.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* API Response Types
|
|
3
|
-
* Standard response structure for all API endpoints
|
|
4
|
-
*/
|
|
5
|
-
export const HTTP_METHOD = {
|
|
6
|
-
Get: "GET",
|
|
7
|
-
Post: "POST",
|
|
8
|
-
Put: "PUT",
|
|
9
|
-
Patch: "PATCH",
|
|
10
|
-
Delete: "DELETE",
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Error Codes
|
|
14
|
-
* Standardized error codes used across the platform
|
|
15
|
-
*/
|
|
16
|
-
export const ERROR_CODES = {
|
|
17
|
-
// 400 - Bad Request
|
|
18
|
-
BAD_REQUEST: "BAD_REQUEST",
|
|
19
|
-
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
20
|
-
MISSING_FIELDS: "MISSING_FIELDS",
|
|
21
|
-
// 401 - Unauthorized
|
|
22
|
-
UNAUTHORIZED: "UNAUTHORIZED",
|
|
23
|
-
INVALID_TOKEN: "INVALID_TOKEN",
|
|
24
|
-
INVALID_CREDENTIALS: "INVALID_CREDENTIALS",
|
|
25
|
-
// 403 - Forbidden
|
|
26
|
-
FORBIDDEN: "FORBIDDEN",
|
|
27
|
-
// 404 - Not Found
|
|
28
|
-
NOT_FOUND: "NOT_FOUND",
|
|
29
|
-
// 409 - Conflict
|
|
30
|
-
CONFLICT: "CONFLICT",
|
|
31
|
-
ALREADY_EXISTS: "ALREADY_EXISTS",
|
|
32
|
-
// 429 - Rate Limiting
|
|
33
|
-
RATE_LIMIT: "RATE_LIMIT",
|
|
34
|
-
RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED",
|
|
35
|
-
// 500 - Server Errors
|
|
36
|
-
INTERNAL_ERROR: "INTERNAL_ERROR",
|
|
37
|
-
DATABASE_ERROR: "DATABASE_ERROR",
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* HTTP Status Codes
|
|
41
|
-
* Common status codes used in responses
|
|
42
|
-
*/
|
|
43
|
-
export const HTTP_STATUS = {
|
|
44
|
-
OK: 200,
|
|
45
|
-
CREATED: 201,
|
|
46
|
-
NO_CONTENT: 204,
|
|
47
|
-
BAD_REQUEST: 400,
|
|
48
|
-
UNAUTHORIZED: 401,
|
|
49
|
-
FORBIDDEN: 403,
|
|
50
|
-
NOT_FOUND: 404,
|
|
51
|
-
CONFLICT: 409,
|
|
52
|
-
RATE_LIMIT: 429,
|
|
53
|
-
INTERNAL_ERROR: 500,
|
|
54
|
-
};
|