@happyvertical/utils 0.80.0 → 0.80.2

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.
@@ -1,934 +0,0 @@
1
- import { createId as createId$1 } from "@paralleldrive/cuid2";
2
- import { add, isValid, format, parse, parseISO } from "date-fns";
3
- import pluralize from "pluralize";
4
- function toCamelCase(str) {
5
- return str.toLowerCase().replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
6
- }
7
- function toScreamingSnakeCase(str) {
8
- return str.replace(/([A-Z])/g, "_$1").toUpperCase().replace(/^_/, "");
9
- }
10
- function convertType(value, type) {
11
- switch (type) {
12
- case "number": {
13
- const num = Number(value);
14
- if (Number.isNaN(num)) {
15
- throw new Error(`Cannot convert "${value}" to number: result is NaN`);
16
- }
17
- return num;
18
- }
19
- case "boolean":
20
- return value.toLowerCase() === "true" || value === "1" || value.toLowerCase() === "yes";
21
- case "json":
22
- try {
23
- return JSON.parse(value);
24
- } catch (error) {
25
- throw new Error(
26
- `Cannot parse "${value}" as JSON: ${error instanceof Error ? error.message : "Unknown error"}`
27
- );
28
- }
29
- default:
30
- return value;
31
- }
32
- }
33
- function loadEnvConfig(userOptions = {}, options = {}) {
34
- const {
35
- prefix = "HAVE",
36
- packageName,
37
- schema = {},
38
- transform = {},
39
- allowUnknown = true
40
- } = options;
41
- const envPrefix = packageName && prefix ? `${prefix}_${packageName.toUpperCase()}_` : prefix ? `${prefix}_` : "";
42
- const config = { ...userOptions };
43
- const fieldsToScan = allowUnknown ? (
44
- // Scan all env vars if allowUnknown is true
45
- /* @__PURE__ */ new Set([
46
- ...Object.keys(schema),
47
- // Also scan environment for any matching vars
48
- ...Object.keys(process.env).filter((key) => envPrefix && key.startsWith(envPrefix)).map((key) => {
49
- const fieldName = key.slice(envPrefix.length);
50
- return toCamelCase(fieldName);
51
- })
52
- ])
53
- ) : (
54
- // Only scan schema fields if allowUnknown is false
55
- new Set(Object.keys(schema))
56
- );
57
- for (const fieldName of fieldsToScan) {
58
- if (fieldName in userOptions) {
59
- continue;
60
- }
61
- const envVarName = envPrefix ? envPrefix + toScreamingSnakeCase(fieldName) : fieldName;
62
- const envValue = process.env[envVarName];
63
- if (envValue === void 0) {
64
- continue;
65
- }
66
- const transformFn = transform[fieldName];
67
- if (transformFn) {
68
- try {
69
- config[fieldName] = transformFn(envValue);
70
- } catch (error) {
71
- console.warn(
72
- `Failed to transform ${envVarName}="${envValue}":`,
73
- error instanceof Error ? error.message : error
74
- );
75
- }
76
- continue;
77
- }
78
- const fieldType = schema[fieldName];
79
- if (fieldType) {
80
- try {
81
- config[fieldName] = convertType(envValue, fieldType);
82
- } catch (error) {
83
- console.warn(
84
- `Failed to convert ${envVarName}="${envValue}" to ${fieldType}:`,
85
- error instanceof Error ? error.message : error
86
- );
87
- }
88
- continue;
89
- }
90
- config[fieldName] = envValue;
91
- }
92
- return config;
93
- }
94
- function extractCodeBlock(text, language) {
95
- if (!text) {
96
- return "";
97
- }
98
- const langPattern = language ? `${language}\\s*` : "(?:\\w+\\s*)?";
99
- const codeBlockRegex = new RegExp(
100
- `\`\`\`${langPattern}\\r?\\n([\\s\\S]*?)\\r?\\n\`\`\``,
101
- "i"
102
- );
103
- const match = text.match(codeBlockRegex);
104
- if (match?.[1]) {
105
- return match[1].trim();
106
- }
107
- const inlineRegex = /`([^`]+)`/;
108
- const inlineMatch = text.match(inlineRegex);
109
- if (inlineMatch?.[1]) {
110
- return inlineMatch[1].trim();
111
- }
112
- return "";
113
- }
114
- function extractJSON(text) {
115
- if (!text) {
116
- throw new SyntaxError("Cannot extract JSON from empty text");
117
- }
118
- let jsonText = extractCodeBlock(text, "json");
119
- if (!jsonText) {
120
- jsonText = extractCodeBlock(text);
121
- }
122
- if (!jsonText) {
123
- const jsonObjectMatch = text.match(/\{[\s\S]*\}/);
124
- const jsonArrayMatch = text.match(/\[[\s\S]*\]/);
125
- if (jsonObjectMatch) {
126
- jsonText = jsonObjectMatch[0];
127
- } else if (jsonArrayMatch) {
128
- jsonText = jsonArrayMatch[0];
129
- } else {
130
- jsonText = text.trim();
131
- }
132
- }
133
- try {
134
- return JSON.parse(jsonText);
135
- } catch (error) {
136
- throw new SyntaxError(
137
- `Failed to parse JSON: ${error instanceof Error ? error.message : "Unknown error"}`
138
- );
139
- }
140
- }
141
- function extractAllCodeBlocks(text, language) {
142
- if (!text) {
143
- return [];
144
- }
145
- const langPattern = language ? `${language}\\s*` : "(?:\\w+\\s*)?";
146
- const codeBlockRegex = new RegExp(
147
- `\`\`\`${langPattern}\\r?\\n([\\s\\S]*?)\\r?\\n\`\`\``,
148
- "gi"
149
- );
150
- const blocks = [];
151
- const matches = text.matchAll(codeBlockRegex);
152
- for (const match of matches) {
153
- if (match[1]) {
154
- blocks.push(match[1].trim());
155
- }
156
- }
157
- return blocks;
158
- }
159
- function extractFunctionDefinition(code, functionName) {
160
- if (!code || !functionName) {
161
- return "";
162
- }
163
- const patterns = [
164
- // function foo() { ... }
165
- {
166
- regex: new RegExp(
167
- `function\\s+${functionName}\\s*\\([^)]*\\)\\s*\\{`,
168
- "i"
169
- ),
170
- hasBraces: true
171
- },
172
- // const foo = function() { ... }
173
- {
174
- regex: new RegExp(
175
- `(?:const|let|var)\\s+${functionName}\\s*=\\s*function\\s*\\([^)]*\\)\\s*\\{`,
176
- "i"
177
- ),
178
- hasBraces: true
179
- },
180
- // const foo = () => { ... }
181
- {
182
- regex: new RegExp(
183
- `(?:const|let|var)\\s+${functionName}\\s*=\\s*\\([^)]*\\)\\s*=>\\s*\\{`,
184
- "i"
185
- ),
186
- hasBraces: true
187
- },
188
- // const foo = () => ... (no braces)
189
- {
190
- regex: new RegExp(
191
- `(?:const|let|var)\\s+${functionName}\\s*=\\s*\\([^)]*\\)\\s*=>\\s*[^;]+;?`,
192
- "i"
193
- ),
194
- hasBraces: false
195
- }
196
- ];
197
- for (const { regex, hasBraces } of patterns) {
198
- const match = code.match(regex);
199
- if (match && match.index !== void 0) {
200
- const startIdx = match.index;
201
- if (!hasBraces) {
202
- return match[0].trim();
203
- }
204
- const braceIdx = code.indexOf("{", startIdx);
205
- if (braceIdx === -1) continue;
206
- let idx = braceIdx;
207
- let depth = 0;
208
- let endIdx = -1;
209
- while (idx < code.length) {
210
- const char = code[idx];
211
- if (char === "{") {
212
- depth++;
213
- } else if (char === "}") {
214
- depth--;
215
- if (depth === 0) {
216
- endIdx = idx;
217
- break;
218
- }
219
- }
220
- idx++;
221
- }
222
- if (endIdx !== -1) {
223
- return code.slice(startIdx, endIdx + 1).trim();
224
- }
225
- }
226
- }
227
- return "";
228
- }
229
- const DANGEROUS_PATTERNS = [
230
- /require\s*\(/i,
231
- // No require()
232
- /import\s+/i,
233
- // No import statements
234
- /eval\s*\(/i,
235
- // No eval()
236
- /Function\s*\(/i,
237
- // No Function constructor
238
- /process\./i,
239
- // No process access
240
- /fs\./i,
241
- // No filesystem module
242
- /child_process/i,
243
- // No child process
244
- /__dirname/i,
245
- // No directory access
246
- /__filename/i,
247
- // No file access
248
- /global\./i
249
- // No global object manipulation
250
- ];
251
- function validateCode(code, options = {}) {
252
- const {
253
- allowedGlobals,
254
- disallowedPatterns = DANGEROUS_PATTERNS,
255
- maxLength = 5e4,
256
- allowRequire = false,
257
- allowImport = false,
258
- allowEval = false,
259
- checkSyntax = true
260
- } = options;
261
- const errors = [];
262
- const warnings = [];
263
- if (!code || code.trim().length === 0) {
264
- errors.push("Code is empty");
265
- return { valid: false, errors, warnings };
266
- }
267
- if (code.length > maxLength) {
268
- errors.push(
269
- `Code exceeds maximum length (${code.length} > ${maxLength} characters)`
270
- );
271
- }
272
- const patternFlags = /* @__PURE__ */ new Map([
273
- [DANGEROUS_PATTERNS[0], "require"],
274
- // /require\s*\(/i
275
- [DANGEROUS_PATTERNS[1], "import"],
276
- // /import\s+/i
277
- [DANGEROUS_PATTERNS[2], "eval"],
278
- // /eval\s*\(/i
279
- [DANGEROUS_PATTERNS[3], "eval"]
280
- // /Function\s*\(/i - also controlled by allowEval
281
- // Patterns 4-9 are always dangerous (process, fs, child_process, etc.)
282
- ]);
283
- const effectivePatterns = disallowedPatterns.filter((_pattern, index) => {
284
- const patternType = patternFlags.get(DANGEROUS_PATTERNS[index]);
285
- if (patternType === "require" && allowRequire) {
286
- return false;
287
- }
288
- if (patternType === "import" && allowImport) {
289
- return false;
290
- }
291
- if (patternType === "eval" && allowEval) {
292
- return false;
293
- }
294
- return true;
295
- });
296
- for (const pattern of effectivePatterns) {
297
- if (pattern.test(code)) {
298
- errors.push(
299
- `Code contains disallowed pattern: ${pattern.source.replace(/\\/g, "")}`
300
- );
301
- }
302
- }
303
- if (allowedGlobals) {
304
- const undeclaredVars = findUndeclaredVariables(code, allowedGlobals);
305
- if (undeclaredVars.length > 0) {
306
- warnings.push(
307
- `Potentially undeclared variables: ${undeclaredVars.join(", ")}`
308
- );
309
- }
310
- }
311
- if (checkSyntax) {
312
- const syntaxErrors = checkCodeSyntax(code);
313
- errors.push(...syntaxErrors);
314
- }
315
- const stats = {
316
- length: code.length,
317
- lines: code.split("\n").length,
318
- hasAsync: /\basync\b\s*(function|\([\w\s,={}[\]]*\)\s*=>|\w+\s*\()/m.test(
319
- code
320
- ),
321
- hasArrowFunctions: /=>/.test(code),
322
- hasClasses: /\bclass\s+\w+/.test(code)
323
- };
324
- if (stats.lines > 100) {
325
- warnings.push(
326
- `Code is long (${stats.lines} lines) - consider breaking into smaller functions`
327
- );
328
- }
329
- return {
330
- valid: errors.length === 0,
331
- errors,
332
- warnings,
333
- stats
334
- };
335
- }
336
- function checkCodeSyntax(code) {
337
- const errors = [];
338
- try {
339
- new Function(code);
340
- } catch (error) {
341
- if (error instanceof SyntaxError) {
342
- const message = error.message;
343
- if (message.includes("await is only valid") && /\bawait\b/.test(code)) {
344
- try {
345
- new Function(`(async function() { ${code} })()`);
346
- return errors;
347
- } catch (asyncError) {
348
- if (asyncError instanceof SyntaxError) {
349
- errors.push(`Syntax error: ${asyncError.message}`);
350
- }
351
- }
352
- } else {
353
- errors.push(`Syntax error: ${message}`);
354
- }
355
- }
356
- }
357
- return errors;
358
- }
359
- function findUndeclaredVariables(code, allowedGlobals) {
360
- const undeclaredVars = /* @__PURE__ */ new Set();
361
- const identifierRegex = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g;
362
- const matches = code.matchAll(identifierRegex);
363
- const declaredVars = /* @__PURE__ */ new Set();
364
- const declarationRegex = /\b(?:var|let|const|function)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)/g;
365
- const declarations = code.matchAll(declarationRegex);
366
- for (const match of declarations) {
367
- if (match[1]) {
368
- declaredVars.add(match[1]);
369
- }
370
- }
371
- for (const match of matches) {
372
- const identifier = match[1];
373
- if (isJavaScriptKeyword(identifier)) {
374
- continue;
375
- }
376
- if (declaredVars.has(identifier)) {
377
- continue;
378
- }
379
- if (allowedGlobals.includes(identifier)) {
380
- continue;
381
- }
382
- if (isCommonBuiltin(identifier)) {
383
- continue;
384
- }
385
- undeclaredVars.add(identifier);
386
- }
387
- return Array.from(undeclaredVars);
388
- }
389
- function isJavaScriptKeyword(word) {
390
- const keywords = [
391
- "break",
392
- "case",
393
- "catch",
394
- "class",
395
- "const",
396
- "continue",
397
- "debugger",
398
- "default",
399
- "delete",
400
- "do",
401
- "else",
402
- "export",
403
- "extends",
404
- "finally",
405
- "for",
406
- "function",
407
- "if",
408
- "import",
409
- "in",
410
- "instanceof",
411
- "let",
412
- "new",
413
- "return",
414
- "super",
415
- "switch",
416
- "this",
417
- "throw",
418
- "try",
419
- "typeof",
420
- "var",
421
- "void",
422
- "while",
423
- "with",
424
- "yield",
425
- "async",
426
- "await"
427
- ];
428
- return keywords.includes(word);
429
- }
430
- function isCommonBuiltin(word) {
431
- const builtins = [
432
- "Array",
433
- "Object",
434
- "String",
435
- "Number",
436
- "Boolean",
437
- "Date",
438
- "Math",
439
- "JSON",
440
- "RegExp",
441
- "Error",
442
- "Map",
443
- "Set",
444
- "Promise",
445
- "Symbol",
446
- "undefined",
447
- "null",
448
- "true",
449
- "false",
450
- "console",
451
- "parseInt",
452
- "parseFloat",
453
- "isNaN",
454
- "isFinite",
455
- "decodeURI",
456
- "decodeURIComponent",
457
- "encodeURI",
458
- "encodeURIComponent"
459
- ];
460
- return builtins.includes(word);
461
- }
462
- function isSafeCode(code) {
463
- const result = validateCode(code, {
464
- maxLength: 5e4,
465
- checkSyntax: true
466
- });
467
- return result.valid;
468
- }
469
- class ConsoleLogger {
470
- debug(message, context) {
471
- if (context) {
472
- console.debug(message, context);
473
- } else {
474
- console.debug(message);
475
- }
476
- }
477
- info(message, context) {
478
- if (context) {
479
- console.info(message, context);
480
- } else {
481
- console.info(message);
482
- }
483
- }
484
- warn(message, context) {
485
- if (context) {
486
- console.warn(message, context);
487
- } else {
488
- console.warn(message);
489
- }
490
- }
491
- error(message, context) {
492
- if (context) {
493
- console.error(message, context);
494
- } else {
495
- console.error(message);
496
- }
497
- }
498
- }
499
- class NoOpLogger {
500
- debug() {
501
- }
502
- info() {
503
- }
504
- warn() {
505
- }
506
- error() {
507
- }
508
- }
509
- let globalLogger = new ConsoleLogger();
510
- const setLogger = (logger) => {
511
- globalLogger = logger;
512
- };
513
- const getLogger = () => {
514
- return globalLogger;
515
- };
516
- const disableLogging = () => {
517
- globalLogger = new NoOpLogger();
518
- };
519
- const enableLogging = () => {
520
- globalLogger = new ConsoleLogger();
521
- };
522
- var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
523
- ErrorCode2["VALIDATION_ERROR"] = "VALIDATION_ERROR";
524
- ErrorCode2["API_ERROR"] = "API_ERROR";
525
- ErrorCode2["FILE_ERROR"] = "FILE_ERROR";
526
- ErrorCode2["NETWORK_ERROR"] = "NETWORK_ERROR";
527
- ErrorCode2["DATABASE_ERROR"] = "DATABASE_ERROR";
528
- ErrorCode2["PARSING_ERROR"] = "PARSING_ERROR";
529
- ErrorCode2["TIMEOUT_ERROR"] = "TIMEOUT_ERROR";
530
- ErrorCode2["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
531
- return ErrorCode2;
532
- })(ErrorCode || {});
533
- class BaseError extends Error {
534
- /** Error classification code */
535
- code;
536
- /** Additional context data for debugging */
537
- context;
538
- /** When the error occurred */
539
- timestamp;
540
- constructor(message, code = "UNKNOWN_ERROR", context) {
541
- super(message);
542
- this.name = this.constructor.name;
543
- this.code = code;
544
- this.context = context;
545
- this.timestamp = /* @__PURE__ */ new Date();
546
- Error.captureStackTrace?.(this, this.constructor);
547
- }
548
- /**
549
- * Serializes the error to a JSON-compatible object
550
- * @returns Object containing all error properties
551
- */
552
- toJSON() {
553
- return {
554
- name: this.name,
555
- message: this.message,
556
- code: this.code,
557
- context: this.context,
558
- timestamp: this.timestamp.toISOString(),
559
- stack: this.stack
560
- };
561
- }
562
- }
563
- class ValidationError extends BaseError {
564
- constructor(message, context) {
565
- super(message, "VALIDATION_ERROR", context);
566
- }
567
- }
568
- class ApiError extends BaseError {
569
- constructor(message, context) {
570
- super(message, "API_ERROR", context);
571
- }
572
- }
573
- class FileError extends BaseError {
574
- constructor(message, context) {
575
- super(message, "FILE_ERROR", context);
576
- }
577
- }
578
- class NetworkError extends BaseError {
579
- constructor(message, context) {
580
- super(message, "NETWORK_ERROR", context);
581
- }
582
- }
583
- class DatabaseError extends BaseError {
584
- constructor(message, context) {
585
- super(message, "DATABASE_ERROR", context);
586
- }
587
- }
588
- class ParsingError extends BaseError {
589
- constructor(message, context) {
590
- super(message, "PARSING_ERROR", context);
591
- }
592
- }
593
- class TimeoutError extends BaseError {
594
- constructor(message, context) {
595
- super(message, "TIMEOUT_ERROR", context);
596
- }
597
- }
598
- const makeId = (type = "cuid2") => {
599
- if (type === "cuid2") {
600
- return createId$1();
601
- }
602
- if (crypto?.randomUUID) {
603
- return crypto.randomUUID();
604
- }
605
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
606
- const r = Math.random() * 16 | 0;
607
- const v = c === "x" ? r : r & 3 | 8;
608
- return v.toString(16);
609
- });
610
- };
611
- const createId = createId$1;
612
- const makeSlug = (str) => {
613
- const from = "àáâäæãåāăąçćčđďèéêëēėęěğǵḧîïíīįìıİłḿñńǹňôöòóœøōõőṕŕřßśšşșťțûüùúūǘůűųẃẍÿýžźż+·/_,:;";
614
- const to = "aaaaaaaaaacccddeeeeeeeegghiiiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz--------------";
615
- const textToCompare = new RegExp(
616
- from.split("").join("|").replace(/\+/g, "\\+"),
617
- "g"
618
- );
619
- return str.toString().toLowerCase().replace("&", "-38-").replace(/\s+/g, "-").replace(textToCompare, (c) => to.charAt(from.indexOf(c))).replace(/[&.]/g, "-").replace(/[^\w-º+]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
620
- };
621
- const urlFilename = (url) => {
622
- const parsedUrl = new URL(url);
623
- const pathSegments = parsedUrl.pathname.split("/");
624
- const filename = pathSegments[pathSegments.length - 1];
625
- return filename || "index.html";
626
- };
627
- const urlPath = (url) => {
628
- const parsedUrl = new URL(url);
629
- const pathSegments = [
630
- parsedUrl.hostname,
631
- ...parsedUrl.pathname.split("/").filter(Boolean)
632
- ];
633
- return pathSegments.join("/");
634
- };
635
- const sleep = (duration) => {
636
- return new Promise((resolve) => {
637
- setTimeout(resolve, duration);
638
- });
639
- };
640
- function waitFor(it, { timeout = 0, delay = 1e3 } = {}) {
641
- return new Promise((resolve, reject) => {
642
- const beginTime = Date.now();
643
- (async function waitATick() {
644
- try {
645
- const result = await it();
646
- if (typeof result !== "undefined") {
647
- return resolve(result);
648
- }
649
- if (timeout > 0) {
650
- if (Date.now() > beginTime + timeout) {
651
- return reject(
652
- new TimeoutError("Function call timed out", {
653
- timeout,
654
- delay,
655
- elapsedTime: Date.now() - beginTime
656
- })
657
- );
658
- }
659
- }
660
- setTimeout(waitATick, delay);
661
- } catch (error) {
662
- reject(error);
663
- }
664
- })();
665
- });
666
- }
667
- const isArray = (obj) => {
668
- return Array.isArray(obj);
669
- };
670
- const isPlainObject = (obj) => {
671
- return typeof obj === "object" && obj !== null && !Array.isArray(obj);
672
- };
673
- const isUrl = (url) => {
674
- try {
675
- new URL(url);
676
- return true;
677
- } catch {
678
- return false;
679
- }
680
- };
681
- const camelCase = (str) => {
682
- return str.toLowerCase().replace(/[-_]+/g, " ").replace(/[^\w\s]/g, "").replace(/\s(.)/g, (_, char) => char.toUpperCase()).replace(/\s/g, "").replace(/^(.)/, (_, char) => char.toLowerCase());
683
- };
684
- const snakeCase = (str) => {
685
- return str.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "").replace(/[-\s]+/g, "_");
686
- };
687
- const keysToCamel = (obj) => {
688
- if (isPlainObject(obj)) {
689
- const n = {};
690
- Object.keys(obj).forEach((k) => {
691
- n[camelCase(k)] = keysToCamel(obj[k]);
692
- });
693
- return n;
694
- }
695
- if (isArray(obj)) {
696
- return obj.map((i) => keysToCamel(i));
697
- }
698
- return obj;
699
- };
700
- const keysToSnake = (obj) => {
701
- if (isPlainObject(obj)) {
702
- const n = {};
703
- Object.keys(obj).forEach((k) => {
704
- n[snakeCase(k)] = keysToSnake(obj[k]);
705
- });
706
- return n;
707
- }
708
- if (isArray(obj)) {
709
- return obj.map((i) => keysToSnake(i));
710
- }
711
- return obj;
712
- };
713
- const domainToCamel = (domain) => camelCase(domain);
714
- const logTicker = (tick, options = {}) => {
715
- const { chars = [".", "..", "..."] } = options;
716
- if (tick) {
717
- const index = chars.indexOf(tick);
718
- return index + 1 >= chars.length ? chars[0] : chars[index + 1];
719
- }
720
- return chars[0];
721
- };
722
- const parseAmazonDateString = (dateStr) => {
723
- const regex = /^([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2})([0-9]{2})([0-9]{2})([A-Z0-9]+)/;
724
- const match = dateStr.match(regex);
725
- if (!match) {
726
- throw new ParsingError("Could not parse Amazon date string", {
727
- dateString: dateStr,
728
- expectedFormat: "YYYYMMDDTHHMMSSZ"
729
- });
730
- }
731
- const [matched, year, month, day, hour, minutes, seconds, timezone] = match;
732
- if (matched !== dateStr) {
733
- throw new ParsingError("Invalid Amazon date string format", {
734
- dateString: dateStr,
735
- matched,
736
- expectedFormat: "YYYYMMDDTHHMMSSZ"
737
- });
738
- }
739
- const date = /* @__PURE__ */ new Date(
740
- `${year}-${month}-${day}T${hour}:${minutes}:${seconds}${timezone}`
741
- );
742
- return date;
743
- };
744
- const dateInString = (str) => {
745
- const cleanStr = str.toLowerCase();
746
- const underscoreMatch = str.match(/(\d{4})_(\d{1,2})_(\d{1,2})/);
747
- if (underscoreMatch) {
748
- const [, year2, month, day2] = underscoreMatch;
749
- const date2 = new Date(
750
- Number.parseInt(year2, 10),
751
- Number.parseInt(month, 10) - 1,
752
- Number.parseInt(day2, 10)
753
- );
754
- if (!Number.isNaN(date2.getTime())) return date2;
755
- }
756
- const dotMatch = str.match(/(\d{1,2})\.(\d{1,2})\.(\d{4})/);
757
- if (dotMatch) {
758
- const [, month, day2, year2] = dotMatch;
759
- const date2 = new Date(
760
- Number.parseInt(year2, 10),
761
- Number.parseInt(month, 10) - 1,
762
- Number.parseInt(day2, 10)
763
- );
764
- if (!Number.isNaN(date2.getTime())) return date2;
765
- }
766
- const isoMatch = cleanStr.match(/(\d{4})[-/](\d{1,2})[-/](\d{1,2})/);
767
- if (isoMatch) {
768
- const [, year2, month, day2] = isoMatch;
769
- const date2 = new Date(
770
- Number.parseInt(year2, 10),
771
- Number.parseInt(month, 10) - 1,
772
- Number.parseInt(day2, 10)
773
- );
774
- if (!Number.isNaN(date2.getTime())) return date2;
775
- }
776
- const usMatch = cleanStr.match(/(\d{1,2})[-/](\d{1,2})[-/](\d{4})/);
777
- if (usMatch) {
778
- const [, month, day2, year2] = usMatch;
779
- const date2 = new Date(
780
- Number.parseInt(year2, 10),
781
- Number.parseInt(month, 10) - 1,
782
- Number.parseInt(day2, 10)
783
- );
784
- if (!Number.isNaN(date2.getTime())) return date2;
785
- }
786
- const yearMatch = cleanStr.match(/20\d{2}/);
787
- if (!yearMatch) return null;
788
- const year = Number.parseInt(yearMatch[0], 10);
789
- const monthPatterns = {
790
- january: 1,
791
- jan: 1,
792
- february: 2,
793
- feb: 2,
794
- march: 3,
795
- mar: 3,
796
- april: 4,
797
- apr: 4,
798
- may: 5,
799
- june: 6,
800
- jun: 6,
801
- july: 7,
802
- jul: 7,
803
- august: 8,
804
- aug: 8,
805
- september: 9,
806
- sep: 9,
807
- sept: 9,
808
- october: 10,
809
- oct: 10,
810
- november: 11,
811
- nov: 11,
812
- december: 12,
813
- dec: 12
814
- };
815
- let foundMonth = null;
816
- let monthStart = -1;
817
- let monthName = "";
818
- for (const [name, monthNum] of Object.entries(monthPatterns)) {
819
- const monthIndex = cleanStr.indexOf(name);
820
- if (monthIndex !== -1) {
821
- foundMonth = monthNum;
822
- monthStart = monthIndex;
823
- monthName = name;
824
- break;
825
- }
826
- }
827
- if (!foundMonth) return null;
828
- const yearIndex = cleanStr.indexOf(yearMatch[0]);
829
- const beforeMonth = cleanStr.substring(
830
- Math.max(0, monthStart - 15),
831
- monthStart
832
- );
833
- const afterMonth = cleanStr.substring(
834
- monthStart + monthName.length,
835
- Math.min(cleanStr.length, monthStart + monthName.length + 15)
836
- );
837
- const beforeYear = cleanStr.substring(Math.max(0, yearIndex - 15), yearIndex);
838
- const afterYear = cleanStr.substring(
839
- yearIndex + 4,
840
- Math.min(cleanStr.length, yearIndex + 19)
841
- );
842
- const dayMatch = beforeMonth.match(/(?<!\d)(\d{1,2})\s*$/) || // Day before month (not preceded by another digit)
843
- afterMonth.match(/^\s*(\d{1,2})(?!\d)/) || // Day right after month (not followed by another digit)
844
- beforeYear.match(/(?<!\d)(\d{1,2})\s*$/) || // Day before year (not preceded by another digit)
845
- afterYear.match(/^\s*(\d{1,2})(?!\d)/) || // Day right after year (not followed by another digit)
846
- afterMonth.match(/[^\d](\d{1,2})(?!\d)/);
847
- const day = dayMatch ? Number.parseInt(dayMatch[1], 10) : 1;
848
- if (day < 1 || day > 31) return null;
849
- const date = new Date(year, foundMonth - 1, day);
850
- return !Number.isNaN(date.getTime()) ? date : null;
851
- };
852
- const prettyDate = (dateString) => {
853
- const date = new Date(dateString);
854
- return new Intl.DateTimeFormat(void 0, {
855
- year: "numeric",
856
- month: "long",
857
- day: "numeric"
858
- }).format(date);
859
- };
860
- const pluralizeWord = pluralize;
861
- const singularize = pluralize.singular;
862
- const isPlural = pluralize.isPlural;
863
- const isSingular = pluralize.isSingular;
864
- const formatDate = (date, formatStr = "yyyy-MM-dd") => {
865
- const dateObj = typeof date === "string" ? new Date(date) : date;
866
- return format(dateObj, formatStr);
867
- };
868
- const parseDate = (dateStr, formatStr) => {
869
- if (formatStr) {
870
- return parse(dateStr, formatStr, /* @__PURE__ */ new Date());
871
- }
872
- return parseISO(dateStr);
873
- };
874
- const isValidDate = isValid;
875
- const addInterval = add;
876
- const getTempDirectory = (subfolder) => {
877
- const tmpBase = process?.env ? process.env.TMPDIR || process.env.TMP || process.env.TEMP || "/tmp" : "/tmp";
878
- const basePath = `${tmpBase}/.have-sdk`;
879
- return subfolder ? `${basePath}/${subfolder}` : basePath;
880
- };
881
- export {
882
- ApiError as A,
883
- BaseError as B,
884
- makeId as C,
885
- DatabaseError as D,
886
- ErrorCode as E,
887
- FileError as F,
888
- makeSlug as G,
889
- parseAmazonDateString as H,
890
- parseDate as I,
891
- pluralizeWord as J,
892
- prettyDate as K,
893
- setLogger as L,
894
- singularize as M,
895
- NetworkError as N,
896
- sleep as O,
897
- ParsingError as P,
898
- snakeCase as Q,
899
- toCamelCase as R,
900
- toScreamingSnakeCase as S,
901
- TimeoutError as T,
902
- urlFilename as U,
903
- ValidationError as V,
904
- urlPath as W,
905
- validateCode as X,
906
- waitFor as Y,
907
- addInterval as a,
908
- convertType as b,
909
- camelCase as c,
910
- createId as d,
911
- dateInString as e,
912
- disableLogging as f,
913
- domainToCamel as g,
914
- enableLogging as h,
915
- extractAllCodeBlocks as i,
916
- extractCodeBlock as j,
917
- extractFunctionDefinition as k,
918
- extractJSON as l,
919
- formatDate as m,
920
- getLogger as n,
921
- getTempDirectory as o,
922
- isArray as p,
923
- isPlainObject as q,
924
- isPlural as r,
925
- isSafeCode as s,
926
- isSingular as t,
927
- isUrl as u,
928
- isValidDate as v,
929
- keysToCamel as w,
930
- keysToSnake as x,
931
- loadEnvConfig as y,
932
- logTicker as z
933
- };
934
- //# sourceMappingURL=universal-BeseWxvS.js.map