@j0hanz/superfetch 1.0.2 → 1.0.3
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/README.md +590 -327
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +6 -10
- package/dist/config/index.js.map +1 -1
- package/dist/config/types.d.ts +251 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/errors/app-error.d.ts +2 -20
- package/dist/errors/app-error.d.ts.map +1 -1
- package/dist/errors/app-error.js +0 -18
- package/dist/errors/app-error.js.map +1 -1
- package/dist/index.js +13 -47
- package/dist/index.js.map +1 -1
- package/dist/middleware/error-handler.d.ts +1 -5
- package/dist/middleware/error-handler.d.ts.map +1 -1
- package/dist/middleware/error-handler.js +1 -11
- package/dist/middleware/error-handler.js.map +1 -1
- package/dist/middleware/rate-limiter.d.ts +2 -20
- package/dist/middleware/rate-limiter.d.ts.map +1 -1
- package/dist/middleware/rate-limiter.js +11 -44
- package/dist/middleware/rate-limiter.js.map +1 -1
- package/dist/prompts/index.d.ts +0 -3
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +0 -3
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/index.d.ts +0 -3
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +1 -4
- package/dist/resources/index.js.map +1 -1
- package/dist/server.d.ts +0 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -6
- package/dist/server.js.map +1 -1
- package/dist/services/cache.d.ts +9 -6
- package/dist/services/cache.d.ts.map +1 -1
- package/dist/services/cache.js +71 -20
- package/dist/services/cache.js.map +1 -1
- package/dist/services/card-extractor.d.ts +10 -0
- package/dist/services/card-extractor.d.ts.map +1 -0
- package/dist/services/card-extractor.js +187 -0
- package/dist/services/card-extractor.js.map +1 -0
- package/dist/services/extractor.d.ts +6 -19
- package/dist/services/extractor.d.ts.map +1 -1
- package/dist/services/extractor.js +53 -46
- package/dist/services/extractor.js.map +1 -1
- package/dist/services/fetcher.d.ts +4 -11
- package/dist/services/fetcher.d.ts.map +1 -1
- package/dist/services/fetcher.js +30 -36
- package/dist/services/fetcher.js.map +1 -1
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +4 -6
- package/dist/services/logger.js.map +1 -1
- package/dist/services/parser.d.ts +1 -6
- package/dist/services/parser.d.ts.map +1 -1
- package/dist/services/parser.js +64 -47
- package/dist/services/parser.js.map +1 -1
- package/dist/tools/handlers/fetch-links.tool.d.ts +5 -12
- package/dist/tools/handlers/fetch-links.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-links.tool.js +104 -79
- package/dist/tools/handlers/fetch-links.tool.js.map +1 -1
- package/dist/tools/handlers/fetch-markdown.tool.d.ts +7 -4
- package/dist/tools/handlers/fetch-markdown.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-markdown.tool.js +84 -84
- package/dist/tools/handlers/fetch-markdown.tool.js.map +1 -1
- package/dist/tools/handlers/fetch-url.tool.d.ts +8 -6
- package/dist/tools/handlers/fetch-url.tool.d.ts.map +1 -1
- package/dist/tools/handlers/fetch-url.tool.js +51 -93
- package/dist/tools/handlers/fetch-url.tool.js.map +1 -1
- package/dist/tools/handlers/fetch-urls.tool.d.ts +5 -0
- package/dist/tools/handlers/fetch-urls.tool.d.ts.map +1 -0
- package/dist/tools/handlers/fetch-urls.tool.js +147 -0
- package/dist/tools/handlers/fetch-urls.tool.js.map +1 -0
- package/dist/tools/index.d.ts +0 -4
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +145 -15
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/utils/common.d.ts +8 -0
- package/dist/tools/utils/common.d.ts.map +1 -0
- package/dist/tools/utils/common.js +35 -0
- package/dist/tools/utils/common.js.map +1 -0
- package/dist/tools/utils/fetch-pipeline.d.ts +3 -0
- package/dist/tools/utils/fetch-pipeline.d.ts.map +1 -0
- package/dist/tools/utils/fetch-pipeline.js +37 -0
- package/dist/tools/utils/fetch-pipeline.js.map +1 -0
- package/dist/tools/utils/index.d.ts +4 -0
- package/dist/tools/utils/index.d.ts.map +1 -0
- package/dist/tools/utils/index.js +3 -0
- package/dist/tools/utils/index.js.map +1 -0
- package/dist/tools/utils/response-builder.d.ts +3 -0
- package/dist/tools/utils/response-builder.d.ts.map +1 -0
- package/dist/tools/utils/response-builder.js +24 -0
- package/dist/tools/utils/response-builder.js.map +1 -0
- package/dist/transformers/jsonl.transformer.d.ts +1 -1
- package/dist/transformers/jsonl.transformer.d.ts.map +1 -1
- package/dist/transformers/jsonl.transformer.js +2 -1
- package/dist/transformers/jsonl.transformer.js.map +1 -1
- package/dist/transformers/markdown.transformer.d.ts +1 -1
- package/dist/transformers/markdown.transformer.d.ts.map +1 -1
- package/dist/transformers/markdown.transformer.js +116 -2
- package/dist/transformers/markdown.transformer.js.map +1 -1
- package/dist/types/content.types.d.ts +11 -11
- package/dist/types/content.types.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/schemas.d.ts +39 -12
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/utils/concurrency.d.ts +2 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +25 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/content-cleaner.d.ts +32 -0
- package/dist/utils/content-cleaner.d.ts.map +1 -0
- package/dist/utils/content-cleaner.js +240 -0
- package/dist/utils/content-cleaner.js.map +1 -0
- package/dist/utils/language-detector.d.ts +5 -0
- package/dist/utils/language-detector.d.ts.map +1 -0
- package/dist/utils/language-detector.js +50 -0
- package/dist/utils/language-detector.js.map +1 -0
- package/dist/utils/sanitizer.d.ts +0 -10
- package/dist/utils/sanitizer.d.ts.map +1 -1
- package/dist/utils/sanitizer.js +3 -11
- package/dist/utils/sanitizer.js.map +1 -1
- package/dist/utils/tool-error-handler.d.ts +1 -15
- package/dist/utils/tool-error-handler.d.ts.map +1 -1
- package/dist/utils/tool-error-handler.js +1 -1
- package/dist/utils/tool-error-handler.js.map +1 -1
- package/dist/utils/url-validator.d.ts +0 -8
- package/dist/utils/url-validator.d.ts.map +1 -1
- package/dist/utils/url-validator.js +17 -31
- package/dist/utils/url-validator.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card link extraction utilities for preserving card-style navigation
|
|
3
|
+
* from documentation sites before Readability strips them.
|
|
4
|
+
*/
|
|
5
|
+
const NOISE_SELECTORS = 'style, svg, [class*="icon"], [aria-hidden="true"]';
|
|
6
|
+
/**
|
|
7
|
+
* Clean element by removing noise (styles, SVGs, icons)
|
|
8
|
+
*/
|
|
9
|
+
function cleanElement(element) {
|
|
10
|
+
const clone = element.cloneNode(true);
|
|
11
|
+
clone.querySelectorAll(NOISE_SELECTORS).forEach((el) => el.remove());
|
|
12
|
+
return clone;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Extract clean title from a card-like link element
|
|
16
|
+
*/
|
|
17
|
+
function extractCardTitle(link) {
|
|
18
|
+
const clone = cleanElement(link);
|
|
19
|
+
// Look for the first div child which typically contains the title in card layouts
|
|
20
|
+
for (const div of clone.querySelectorAll('div')) {
|
|
21
|
+
if (div.querySelector('div'))
|
|
22
|
+
continue; // Skip container divs
|
|
23
|
+
const text = div.textContent.trim();
|
|
24
|
+
if (text.length > 1 &&
|
|
25
|
+
text.length < 50 &&
|
|
26
|
+
!text.includes(' with ') &&
|
|
27
|
+
!text.includes('Use ')) {
|
|
28
|
+
return text;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// Look for structured title elements
|
|
32
|
+
const titleEl = clone.querySelector('[class*="title"], h2, h3, h4, h5, strong');
|
|
33
|
+
if (titleEl) {
|
|
34
|
+
const title = titleEl.textContent.trim();
|
|
35
|
+
if (title.length > 1 && title.length < 100)
|
|
36
|
+
return title;
|
|
37
|
+
}
|
|
38
|
+
// Fall back to first meaningful text content
|
|
39
|
+
const text = clone.textContent.trim().replace(/\s+/g, ' ');
|
|
40
|
+
if (!text || text.length <= 1 || text.length >= 100)
|
|
41
|
+
return null;
|
|
42
|
+
// Extract title part (first word/phrase before description)
|
|
43
|
+
const words = text.split(/(?=Use |Try |Learn |Get )/);
|
|
44
|
+
if (words.length > 1 && words[0])
|
|
45
|
+
return words[0].trim();
|
|
46
|
+
const firstLine = text
|
|
47
|
+
.split(/[.\n]/)
|
|
48
|
+
.find((s) => s.trim().length > 1)
|
|
49
|
+
?.trim();
|
|
50
|
+
return firstLine ?? text;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract description from a card-like link element
|
|
54
|
+
*/
|
|
55
|
+
function extractCardDescription(link) {
|
|
56
|
+
const clone = cleanElement(link);
|
|
57
|
+
const descEl = clone.querySelector('p, [class*="description"], [class*="muted"]');
|
|
58
|
+
if (descEl) {
|
|
59
|
+
const desc = descEl.textContent.trim();
|
|
60
|
+
if (desc.length > 5 && desc.length < 200)
|
|
61
|
+
return desc;
|
|
62
|
+
}
|
|
63
|
+
const text = clone.textContent.trim().replace(/\s+/g, ' ');
|
|
64
|
+
if (!text)
|
|
65
|
+
return null;
|
|
66
|
+
const descMatch = /(Use |Try |Learn |Get ).*$/.exec(text);
|
|
67
|
+
if (descMatch && descMatch[0].length > 10)
|
|
68
|
+
return descMatch[0];
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Create a list item with link and optional description
|
|
73
|
+
* Formats as markdown-style link to preserve href for AI parsing
|
|
74
|
+
*/
|
|
75
|
+
function createLinkListItem(document, href, title, description) {
|
|
76
|
+
const li = document.createElement('li');
|
|
77
|
+
const link = document.createElement('a');
|
|
78
|
+
link.setAttribute('href', href);
|
|
79
|
+
link.textContent = title;
|
|
80
|
+
li.appendChild(link);
|
|
81
|
+
if (description && description !== title && !title.includes(description)) {
|
|
82
|
+
li.appendChild(document.createTextNode(` - ${description}`));
|
|
83
|
+
}
|
|
84
|
+
return li;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Process custom <card> elements (used by MDX-based docs)
|
|
88
|
+
*/
|
|
89
|
+
function processCustomCards(document) {
|
|
90
|
+
const customCards = document.querySelectorAll('card[href], card[title]');
|
|
91
|
+
if (customCards.length === 0)
|
|
92
|
+
return;
|
|
93
|
+
const list = document.createElement('ul');
|
|
94
|
+
list.setAttribute('data-preserved-cards', 'true');
|
|
95
|
+
for (const card of customCards) {
|
|
96
|
+
const href = card.getAttribute('href');
|
|
97
|
+
const title = card.getAttribute('title') ?? card.textContent.trim();
|
|
98
|
+
if (href && title) {
|
|
99
|
+
const desc = card.querySelector('p')?.textContent.trim();
|
|
100
|
+
list.appendChild(createLinkListItem(document, href, title, desc));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (list.children.length > 0) {
|
|
104
|
+
const firstCard = customCards[0];
|
|
105
|
+
firstCard?.parentNode?.insertBefore(list, firstCard);
|
|
106
|
+
customCards.forEach((card) => card.remove());
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Process CSS grid card containers
|
|
111
|
+
*/
|
|
112
|
+
function processCardGrids(document) {
|
|
113
|
+
for (const div of document.querySelectorAll('div')) {
|
|
114
|
+
const childLinks = Array.from(div.children).filter((child) => child.tagName === 'A' && child.hasAttribute('href'));
|
|
115
|
+
if (childLinks.length < 2)
|
|
116
|
+
continue;
|
|
117
|
+
const looksLikeCards = childLinks.every((link) => {
|
|
118
|
+
const hasStructuredContent = link.querySelector('svg, div, p, span');
|
|
119
|
+
const hasReasonableText = link.textContent.trim().length > 3;
|
|
120
|
+
return hasStructuredContent && hasReasonableText;
|
|
121
|
+
});
|
|
122
|
+
if (!looksLikeCards)
|
|
123
|
+
continue;
|
|
124
|
+
const section = document.createElement('div');
|
|
125
|
+
section.setAttribute('data-preserved-cards', 'true');
|
|
126
|
+
const list = document.createElement('ul');
|
|
127
|
+
for (const link of childLinks) {
|
|
128
|
+
const href = link.getAttribute('href');
|
|
129
|
+
const title = extractCardTitle(link);
|
|
130
|
+
const desc = extractCardDescription(link);
|
|
131
|
+
if (href && title) {
|
|
132
|
+
list.appendChild(createLinkListItem(document, href, title, desc));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (list.children.length > 0) {
|
|
136
|
+
section.appendChild(list);
|
|
137
|
+
div.parentNode?.replaceChild(section, div);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Process semantic card containers
|
|
143
|
+
*/
|
|
144
|
+
function processSemanticCards(document) {
|
|
145
|
+
const cardSelectors = [
|
|
146
|
+
'[class*="card-group"]',
|
|
147
|
+
'[class*="card-grid"]',
|
|
148
|
+
'[class*="cards"]',
|
|
149
|
+
'[data-cards]',
|
|
150
|
+
'[class*="link-card"]',
|
|
151
|
+
'[class*="feature-card"]',
|
|
152
|
+
];
|
|
153
|
+
for (const selector of cardSelectors) {
|
|
154
|
+
try {
|
|
155
|
+
for (const container of document.querySelectorAll(selector)) {
|
|
156
|
+
const links = container.querySelectorAll('a[href]');
|
|
157
|
+
if (links.length === 0)
|
|
158
|
+
continue;
|
|
159
|
+
const list = document.createElement('ul');
|
|
160
|
+
list.setAttribute('data-preserved-cards', 'true');
|
|
161
|
+
for (const link of links) {
|
|
162
|
+
const href = link.getAttribute('href');
|
|
163
|
+
const title = extractCardTitle(link);
|
|
164
|
+
if (href && title) {
|
|
165
|
+
list.appendChild(createLinkListItem(document, href, title));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (list.children.length > 0) {
|
|
169
|
+
container.parentNode?.replaceChild(list, container);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Selector might be invalid, skip it
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Pre-process HTML to preserve card links that Readability might strip.
|
|
180
|
+
* Converts card-like elements into simple link lists.
|
|
181
|
+
*/
|
|
182
|
+
export function preserveCardLinks(document) {
|
|
183
|
+
processCustomCards(document);
|
|
184
|
+
processCardGrids(document);
|
|
185
|
+
processSemanticCards(document);
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=card-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card-extractor.js","sourceRoot":"","sources":["../../src/services/card-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/** Metadata extracted from HTML document (internal) */
|
|
3
|
-
interface ExtractedMetadata {
|
|
4
|
-
title?: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
author?: string;
|
|
7
|
-
}
|
|
8
|
-
/** Combined extraction result (internal) */
|
|
9
|
-
interface ExtractionResult {
|
|
10
|
-
article: ExtractedArticle | null;
|
|
11
|
-
metadata: ExtractedMetadata;
|
|
12
|
-
}
|
|
1
|
+
import type { ExtractionResult } from '../config/types.js';
|
|
13
2
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* @param html - HTML string to extract content from
|
|
17
|
-
* @param url - URL of the page (used for resolving relative links)
|
|
18
|
-
* @returns Extraction result with article and metadata
|
|
3
|
+
* Main extraction function - uses Cheerio for metadata (fast)
|
|
4
|
+
* and lazy-loads JSDOM only when article extraction is needed
|
|
19
5
|
*/
|
|
20
|
-
export declare function extractContent(html: string, url: string
|
|
21
|
-
|
|
6
|
+
export declare function extractContent(html: string, url: string, options?: {
|
|
7
|
+
extractArticle?: boolean;
|
|
8
|
+
}): ExtractionResult;
|
|
22
9
|
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/services/extractor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/services/extractor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,oBAAoB,CAAC;AA8E5B;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAA6B,GAC/D,gBAAgB,CAsClB"}
|
|
@@ -1,65 +1,72 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as cheerio from 'cheerio';
|
|
2
|
+
import { JSDOM, VirtualConsole } from 'jsdom';
|
|
2
3
|
import { Readability } from '@mozilla/readability';
|
|
4
|
+
import { preserveCardLinks } from './card-extractor.js';
|
|
3
5
|
import { logError, logWarn } from './logger.js';
|
|
4
|
-
// Maximum HTML size to process (10MB)
|
|
5
6
|
const MAX_HTML_SIZE = 10 * 1024 * 1024;
|
|
6
|
-
function getMetaContent(document, selectors) {
|
|
7
|
-
for (const selector of selectors) {
|
|
8
|
-
const content = document.querySelector(selector)?.getAttribute('content');
|
|
9
|
-
if (content)
|
|
10
|
-
return content;
|
|
11
|
-
}
|
|
12
|
-
return undefined;
|
|
13
|
-
}
|
|
14
7
|
/**
|
|
15
|
-
*
|
|
8
|
+
* Extract metadata using Cheerio (fast, no full DOM)
|
|
9
|
+
* This avoids JSDOM overhead for simple meta tag extraction
|
|
16
10
|
*/
|
|
17
|
-
function
|
|
18
|
-
const
|
|
11
|
+
function extractMetadataWithCheerio($) {
|
|
12
|
+
const getMetaContent = (selectors) => {
|
|
13
|
+
for (const selector of selectors) {
|
|
14
|
+
const content = $(selector).attr('content');
|
|
15
|
+
if (content)
|
|
16
|
+
return content;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
20
|
+
const title = getMetaContent([
|
|
19
21
|
'meta[property="og:title"]',
|
|
20
22
|
'meta[name="twitter:title"]',
|
|
21
23
|
]) ??
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const description = getMetaContent(document, [
|
|
24
|
+
($('title').text() || undefined);
|
|
25
|
+
const description = getMetaContent([
|
|
25
26
|
'meta[property="og:description"]',
|
|
26
27
|
'meta[name="twitter:description"]',
|
|
27
28
|
'meta[name="description"]',
|
|
28
29
|
]);
|
|
29
|
-
const author = getMetaContent(
|
|
30
|
+
const author = getMetaContent([
|
|
30
31
|
'meta[name="author"]',
|
|
31
32
|
'meta[property="article:author"]',
|
|
32
33
|
]);
|
|
33
34
|
return { title, description, author };
|
|
34
35
|
}
|
|
35
36
|
/**
|
|
36
|
-
*
|
|
37
|
+
* Extract article content using JSDOM + Readability
|
|
38
|
+
* Only called when extractMainContent is true (lazy loading)
|
|
37
39
|
*/
|
|
38
|
-
function
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
function extractArticleWithJsdom(html, url) {
|
|
41
|
+
try {
|
|
42
|
+
// virtualConsole suppresses CSS parsing warnings from modern CSS features
|
|
43
|
+
const virtualConsole = new VirtualConsole();
|
|
44
|
+
const dom = new JSDOM(html, { url, virtualConsole });
|
|
45
|
+
const document = dom.window.document;
|
|
46
|
+
preserveCardLinks(document);
|
|
47
|
+
const reader = new Readability(document);
|
|
48
|
+
const article = reader.parse();
|
|
49
|
+
if (!article)
|
|
50
|
+
return null;
|
|
51
|
+
return {
|
|
52
|
+
title: article.title ?? undefined,
|
|
53
|
+
byline: article.byline ?? undefined,
|
|
54
|
+
content: article.content ?? '',
|
|
55
|
+
textContent: article.textContent ?? '',
|
|
56
|
+
excerpt: article.excerpt ?? undefined,
|
|
57
|
+
siteName: article.siteName ?? undefined,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logError('Failed to extract article with JSDOM', error instanceof Error ? error : undefined);
|
|
44
62
|
return null;
|
|
45
|
-
|
|
46
|
-
title: article.title ?? undefined,
|
|
47
|
-
byline: article.byline ?? undefined,
|
|
48
|
-
content: article.content ?? '',
|
|
49
|
-
textContent: article.textContent ?? '',
|
|
50
|
-
excerpt: article.excerpt ?? undefined,
|
|
51
|
-
siteName: article.siteName ?? undefined,
|
|
52
|
-
};
|
|
63
|
+
}
|
|
53
64
|
}
|
|
54
65
|
/**
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* @param html - HTML string to extract content from
|
|
58
|
-
* @param url - URL of the page (used for resolving relative links)
|
|
59
|
-
* @returns Extraction result with article and metadata
|
|
66
|
+
* Main extraction function - uses Cheerio for metadata (fast)
|
|
67
|
+
* and lazy-loads JSDOM only when article extraction is needed
|
|
60
68
|
*/
|
|
61
|
-
export function extractContent(html, url) {
|
|
62
|
-
// Input validation
|
|
69
|
+
export function extractContent(html, url, options = { extractArticle: true }) {
|
|
63
70
|
if (!html || typeof html !== 'string') {
|
|
64
71
|
logWarn('extractContent called with invalid HTML input');
|
|
65
72
|
return { article: null, metadata: {} };
|
|
@@ -68,7 +75,6 @@ export function extractContent(html, url) {
|
|
|
68
75
|
logWarn('extractContent called with invalid URL');
|
|
69
76
|
return { article: null, metadata: {} };
|
|
70
77
|
}
|
|
71
|
-
// Size validation to prevent memory issues
|
|
72
78
|
let processedHtml = html;
|
|
73
79
|
if (html.length > MAX_HTML_SIZE) {
|
|
74
80
|
logWarn('HTML content exceeds maximum size for extraction, truncating', {
|
|
@@ -78,12 +84,13 @@ export function extractContent(html, url) {
|
|
|
78
84
|
processedHtml = html.substring(0, MAX_HTML_SIZE);
|
|
79
85
|
}
|
|
80
86
|
try {
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
// Fast path: Extract metadata with Cheerio (no full DOM parsing)
|
|
88
|
+
const $ = cheerio.load(processedHtml);
|
|
89
|
+
const metadata = extractMetadataWithCheerio($);
|
|
90
|
+
// Lazy path: Only use JSDOM when article extraction is requested
|
|
91
|
+
const article = options.extractArticle
|
|
92
|
+
? extractArticleWithJsdom(processedHtml, url)
|
|
93
|
+
: null;
|
|
87
94
|
return { article, metadata };
|
|
88
95
|
}
|
|
89
96
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/services/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"extractor.js","sourceRoot":"","sources":["../../src/services/extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Destroys HTTP agents and closes all sockets
|
|
3
|
-
* Should be called during graceful shutdown
|
|
4
|
-
*/
|
|
5
1
|
export declare function destroyAgents(): void;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* @param maxRetries - Maximum retry attempts (1-10, defaults to 3)
|
|
11
|
-
*/
|
|
12
|
-
export declare function fetchUrlWithRetry(url: string, customHeaders?: Record<string, string>, maxRetries?: number): Promise<string>;
|
|
2
|
+
export declare function fetchUrlWithRetry(url: string, customHeaders?: Record<string, string>, maxRetries?: number, skipCache?: boolean): Promise<{
|
|
3
|
+
html: string;
|
|
4
|
+
fromHtmlCache: boolean;
|
|
5
|
+
}>;
|
|
13
6
|
//# sourceMappingURL=fetcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/services/fetcher.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/services/fetcher.ts"],"names":[],"mappings":"AA4CA,wBAAgB,aAAa,IAAI,IAAI,CAGpC;AA+HD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtC,UAAU,SAAI,EACd,SAAS,UAAQ,GAChB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAC,CAyCnD"}
|
package/dist/services/fetcher.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
1
|
+
import axios, {} from 'axios';
|
|
2
2
|
import http from 'http';
|
|
3
3
|
import https from 'https';
|
|
4
4
|
import { config } from '../config/index.js';
|
|
5
5
|
import { FetchError, TimeoutError } from '../errors/app-error.js';
|
|
6
|
+
import { getHtml, setHtml } from './cache.js';
|
|
6
7
|
import { logDebug, logError } from './logger.js';
|
|
7
8
|
const BLOCKED_HEADERS = new Set([
|
|
8
9
|
'host',
|
|
@@ -28,13 +29,8 @@ function calculateBackoff(attempt, maxDelay = 10000) {
|
|
|
28
29
|
const jitter = baseDelay * 0.25 * (Math.random() * 2 - 1);
|
|
29
30
|
return Math.round(baseDelay + jitter);
|
|
30
31
|
}
|
|
31
|
-
// HTTP/HTTPS agents with connection pooling for better performance
|
|
32
32
|
const httpAgent = new http.Agent({ keepAlive: true, maxSockets: 25 });
|
|
33
33
|
const httpsAgent = new https.Agent({ keepAlive: true, maxSockets: 25 });
|
|
34
|
-
/**
|
|
35
|
-
* Destroys HTTP agents and closes all sockets
|
|
36
|
-
* Should be called during graceful shutdown
|
|
37
|
-
*/
|
|
38
34
|
export function destroyAgents() {
|
|
39
35
|
httpAgent.destroy();
|
|
40
36
|
httpsAgent.destroy();
|
|
@@ -54,18 +50,16 @@ const client = axios.create({
|
|
|
54
50
|
},
|
|
55
51
|
validateStatus: (status) => status >= 200 && status < 300,
|
|
56
52
|
});
|
|
57
|
-
// Request interceptor for logging and request enhancement
|
|
58
53
|
client.interceptors.request.use((requestConfig) => {
|
|
59
54
|
logDebug('HTTP Request', {
|
|
60
55
|
method: requestConfig.method?.toUpperCase(),
|
|
61
56
|
url: requestConfig.url,
|
|
62
57
|
});
|
|
63
58
|
return requestConfig;
|
|
64
|
-
}, (error) => {
|
|
59
|
+
}, async (error) => {
|
|
65
60
|
logError('HTTP Request Error', error);
|
|
66
61
|
return Promise.reject(error);
|
|
67
62
|
});
|
|
68
|
-
// Response interceptor for logging and consistent error transformation
|
|
69
63
|
client.interceptors.response.use((response) => {
|
|
70
64
|
logDebug('HTTP Response', {
|
|
71
65
|
status: response.status,
|
|
@@ -73,9 +67,8 @@ client.interceptors.response.use((response) => {
|
|
|
73
67
|
contentType: response.headers['content-type'],
|
|
74
68
|
});
|
|
75
69
|
return response;
|
|
76
|
-
}, (error) => {
|
|
70
|
+
}, async (error) => {
|
|
77
71
|
const url = error.config?.url ?? 'unknown';
|
|
78
|
-
// Transform Axios errors to application errors
|
|
79
72
|
if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
|
|
80
73
|
logError('HTTP Timeout', { url, timeout: config.fetcher.timeout });
|
|
81
74
|
return Promise.reject(new TimeoutError(config.fetcher.timeout, true));
|
|
@@ -93,11 +86,6 @@ client.interceptors.response.use((response) => {
|
|
|
93
86
|
logError('HTTP Unknown Error', { url, message: error.message });
|
|
94
87
|
return Promise.reject(new FetchError(error.message, url));
|
|
95
88
|
});
|
|
96
|
-
/**
|
|
97
|
-
* Fetches HTML content from a URL (internal - use fetchUrlWithRetry for retry logic)
|
|
98
|
-
* @throws {FetchError} if request fails or returns non-HTML content
|
|
99
|
-
* @throws {TimeoutError} if request times out
|
|
100
|
-
*/
|
|
101
89
|
async function fetchUrl(url, customHeaders) {
|
|
102
90
|
const requestConfig = {
|
|
103
91
|
method: 'GET',
|
|
@@ -110,50 +98,56 @@ async function fetchUrl(url, customHeaders) {
|
|
|
110
98
|
}
|
|
111
99
|
try {
|
|
112
100
|
const response = await client.request(requestConfig);
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
const contentTypeHeader = response.headers['content-type'];
|
|
102
|
+
let contentType;
|
|
103
|
+
if (Array.isArray(contentTypeHeader)) {
|
|
104
|
+
const first = contentTypeHeader[0];
|
|
105
|
+
if (typeof first === 'string')
|
|
106
|
+
contentType = first;
|
|
107
|
+
}
|
|
108
|
+
else if (typeof contentTypeHeader === 'string') {
|
|
109
|
+
contentType = contentTypeHeader;
|
|
110
|
+
}
|
|
115
111
|
if (contentType && !isHtmlContentType(contentType)) {
|
|
116
112
|
throw new FetchError(`Unexpected content type: ${contentType}. Expected HTML content.`, url);
|
|
117
113
|
}
|
|
118
114
|
return response.data;
|
|
119
115
|
}
|
|
120
116
|
catch (error) {
|
|
121
|
-
// Re-throw our custom errors (from interceptors or content-type check)
|
|
122
117
|
if (error instanceof FetchError || error instanceof TimeoutError) {
|
|
123
118
|
throw error;
|
|
124
119
|
}
|
|
125
|
-
// Handle any unexpected errors
|
|
126
120
|
throw new FetchError(`Unexpected error: ${error instanceof Error ? error.message : 'Unknown'}`, url);
|
|
127
121
|
}
|
|
128
122
|
}
|
|
129
|
-
/**
|
|
130
|
-
* Checks if content type indicates HTML content
|
|
131
|
-
*/
|
|
132
123
|
function isHtmlContentType(contentType) {
|
|
133
124
|
const normalized = contentType.toLowerCase();
|
|
134
125
|
return (normalized.includes('text/html') ||
|
|
135
126
|
normalized.includes('application/xhtml') ||
|
|
136
127
|
normalized.includes('text/plain'));
|
|
137
128
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
129
|
+
export async function fetchUrlWithRetry(url, customHeaders, maxRetries = 3, skipCache = false) {
|
|
130
|
+
if (!skipCache) {
|
|
131
|
+
const cachedHtml = getHtml(url);
|
|
132
|
+
if (cachedHtml) {
|
|
133
|
+
logDebug('HTML Cache Hit', { url });
|
|
134
|
+
return { html: cachedHtml, fromHtmlCache: true };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
146
137
|
const retries = Math.min(Math.max(1, maxRetries), 10);
|
|
147
|
-
let lastError;
|
|
138
|
+
let lastError = new Error(`Failed to fetch ${url}`);
|
|
148
139
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
149
140
|
try {
|
|
150
|
-
|
|
141
|
+
const html = await fetchUrl(url, customHeaders);
|
|
142
|
+
setHtml(url, html);
|
|
143
|
+
logDebug('HTML Cache Set', { url });
|
|
144
|
+
return { html, fromHtmlCache: false };
|
|
151
145
|
}
|
|
152
146
|
catch (error) {
|
|
153
|
-
lastError = error instanceof Error ? error : new Error(
|
|
154
|
-
// Don't retry on client errors (4xx) except 429 (rate limited)
|
|
147
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
155
148
|
if (error instanceof FetchError && error.httpStatus) {
|
|
156
149
|
const status = error.httpStatus;
|
|
150
|
+
// Don't retry client errors (except 429 Too Many Requests)
|
|
157
151
|
if (status >= 400 && status < 500 && status !== 429) {
|
|
158
152
|
throw error;
|
|
159
153
|
}
|
|
@@ -164,6 +158,6 @@ export async function fetchUrlWithRetry(url, customHeaders, maxRetries = 3) {
|
|
|
164
158
|
}
|
|
165
159
|
}
|
|
166
160
|
}
|
|
167
|
-
throw new FetchError(`Failed after ${retries} attempts: ${lastError
|
|
161
|
+
throw new FetchError(`Failed after ${retries} attempts: ${lastError.message}`, url);
|
|
168
162
|
}
|
|
169
163
|
//# sourceMappingURL=fetcher.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/services/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"fetcher.js","sourceRoot":"","sources":["../../src/services/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAA4C,MAAM,OAAO,CAAC;AACxE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,MAAM;IACN,eAAe;IACf,QAAQ;IACR,iBAAiB;IACjB,WAAW;IACX,qBAAqB;CACtB,CAAC,CAAC;AAEH,SAAS,eAAe,CACtB,OAAgC;IAEhC,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAEpE,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC5C,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AACnE,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe,EAAE,QAAQ,GAAG,KAAK;IACzD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AACtE,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;AAExE,MAAM,UAAU,aAAa;IAC3B,SAAS,CAAC,OAAO,EAAE,CAAC;IACpB,UAAU,CAAC,OAAO,EAAE,CAAC;AACvB,CAAC;AAED,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO;IAC/B,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;IACzC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,gBAAgB;IACjD,SAAS;IACT,UAAU;IACV,OAAO,EAAE;QACP,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS;QACtC,MAAM,EACJ,4EAA4E;QAC9E,iBAAiB,EAAE,gBAAgB;QACnC,iBAAiB,EAAE,mBAAmB;QACtC,UAAU,EAAE,YAAY;KACzB;IACD,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG;CAC1D,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAC7B,CAAC,aAAa,EAAE,EAAE;IAChB,QAAQ,CAAC,cAAc,EAAE;QACvB,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE;QAC3C,GAAG,EAAE,aAAa,CAAC,GAAG;KACvB,CAAC,CAAC;IACH,OAAO,aAAa,CAAC;AACvB,CAAC,EACD,KAAK,EAAE,KAAiB,EAAE,EAAE;IAC1B,QAAQ,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;IACtC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAC9B,CAAC,QAAQ,EAAE,EAAE;IACX,QAAQ,CAAC,eAAe,EAAE;QACxB,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG;QACxB,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC;KAC9C,CAAC,CAAC;IACH,OAAO,QAAQ,CAAC;AAClB,CAAC,EACD,KAAK,EAAE,KAAiB,EAAE,EAAE;IAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC;IAE3C,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChE,QAAQ,CAAC,cAAc,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACnE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC;QAC7C,QAAQ,CAAC,qBAAqB,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC7D,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,UAAU,CAAC,QAAQ,MAAM,KAAK,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,CAC7D,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,QAAQ,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,UAAU,CAAC,kCAAkC,GAAG,EAAE,EAAE,GAAG,CAAC,CAC7D,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;AAC5D,CAAC,CACF,CAAC;AAEF,KAAK,UAAU,QAAQ,CACrB,GAAW,EACX,aAAsC;IAEtC,MAAM,aAAa,GAAuB;QACxC,MAAM,EAAE,KAAK;QACb,GAAG;QACH,YAAY,EAAE,MAAM;KACrB,CAAC;IAEF,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,CAAC,CAAC;IACjD,IAAI,SAAS,EAAE,CAAC;QACd,aAAa,CAAC,OAAO,GAAG,EAAE,GAAG,aAAa,CAAC,OAAO,EAAE,GAAG,SAAS,EAAE,CAAC;IACrE,CAAC;IAED,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAS,aAAa,CAAC,CAAC;QAC7D,MAAM,iBAAiB,GAAY,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAEpE,IAAI,WAA+B,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACrC,MAAM,KAAK,GAAY,iBAAiB,CAAC,CAAC,CAAC,CAAC;YAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,WAAW,GAAG,KAAK,CAAC;QACrD,CAAC;aAAM,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;YACjD,WAAW,GAAG,iBAAiB,CAAC;QAClC,CAAC;QAED,IAAI,WAAW,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,UAAU,CAClB,4BAA4B,WAAW,0BAA0B,EACjE,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;YACjE,MAAM,KAAK,CAAC;QACd,CAAC;QAED,MAAM,IAAI,UAAU,CAClB,qBAAqB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,EACzE,GAAG,CACJ,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC7C,OAAO,CACL,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC;QAChC,UAAU,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACxC,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAW,EACX,aAAsC,EACtC,UAAU,GAAG,CAAC,EACd,SAAS,GAAG,KAAK;IAEjB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI,SAAS,GAAU,IAAI,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC;IAE3D,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACnB,QAAQ,CAAC,gBAAgB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAEpC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;QACxC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAEtE,IAAI,KAAK,YAAY,UAAU,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;gBACpD,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,CAAC;gBAChC,2DAA2D;gBAC3D,IAAI,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;oBACpD,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAED,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBACxC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,UAAU,CAClB,gBAAgB,OAAO,cAAc,SAAS,CAAC,OAAO,EAAE,EACxD,GAAG,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAkDA,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE7E;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,IAAI,CAEN;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAE7E;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,IAAI,CAQN"}
|
package/dist/services/logger.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import winston from 'winston';
|
|
2
1
|
import fs from 'fs';
|
|
3
|
-
import { config } from '../config/index.js';
|
|
4
2
|
import path from 'path';
|
|
3
|
+
import winston from 'winston';
|
|
4
|
+
import { config } from '../config/index.js';
|
|
5
5
|
const logsDir = path.join(process.cwd(), 'logs');
|
|
6
|
-
// Ensure logs directory exists
|
|
6
|
+
// Ensure logs directory exists (mkdirSync with recursive is idempotent)
|
|
7
7
|
try {
|
|
8
|
-
|
|
9
|
-
fs.mkdirSync(logsDir, { recursive: true });
|
|
10
|
-
}
|
|
8
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
11
9
|
}
|
|
12
10
|
catch {
|
|
13
11
|
// If we can't create logs dir, file transports will fail gracefully
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/services/logger.ts"],"names":[],"mappings":"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"}
|