Using Callbacks
Feedcanon provides callbacks to track progress and hook into the resolution flow:
| Callback | Fires when | Data |
|---|---|---|
onFetch | After each HTTP request | { url, response } |
onMatch | URL matches initial response | { url, response, feed } |
onExists | existsFn finds URL in database | { url, data } |
onFetch
Fires after every HTTP request, whether successful or not.
typescript
import { findCanonical } from 'feedcanon'
const url = await findCanonical('https://example.com/feed', {
onFetch: ({ url, response }) => {
console.log(`${response.status} ${url}`)
},
})The response object contains:
| Property | Type | Description |
|---|---|---|
status | number | HTTP status code |
url | string | Final URL after redirects |
body | string | Response body |
headers | Headers | Response headers |
Use Cases
- Logging HTTP requests for debugging
- Tracking redirect chains
- Monitoring request counts
onMatch
Fires when a URL candidate produces content matching the initial response. It also fires once for the input URL, right after the feed is parsed and before any candidate is tested. If rewrites are configured, the URL reported is the rewritten one.
typescript
import { findCanonical } from 'feedcanon'
const aliases = []
const url = await findCanonical('https://example.com/feed', {
onMatch: ({ url, feed }) => {
console.log(`Match: ${url}`)
aliases.push(url)
},
})
// aliases contains all URLs that serve the same feedThe callback receives:
| Property | Type | Description |
|---|---|---|
url | string | The matching URL |
response | FetchFnResponse | The HTTP response |
feed | TFeed | Parsed feed object |
Use Cases
- Collecting URL aliases for the same feed
- Logging which candidates work
- Building redirect maps
onExists
Use existsFn to check if URLs already exist in your database. When found, that URL is returned immediately without further testing.
typescript
import { findCanonical } from 'feedcanon'
const url = await findCanonical('https://example.com/feed', {
existsFn: async (url) => {
return await db.feeds.findByUrl(url)
},
onExists: ({ url, data }) => {
console.log('Found existing:', url, data.id)
},
})The existsFn function:
- Receives each URL candidate being tested
- Returns your data if URL exists,
undefinedotherwise - Triggers early termination when a match is found
The onExists callback fires when existsFn returns data, giving you access to both the URL and your database record.
Examples
Logging
typescript
const url = await findCanonical('https://example.com/feed', {
onFetch: ({ url, response }) => {
console.log(`[${response.status}] ${url}`)
},
onMatch: ({ url }) => {
console.log(`[MATCH] ${url}`)
},
})Collecting Aliases
typescript
const aliases = []
const url = await findCanonical('http://www.example.com/feed/', {
onMatch: ({ url }) => {
aliases.push(url)
},
})
// url: 'https://example.com/feed'
// aliases: [
// 'http://www.example.com/feed/',
// 'https://www.example.com/feed/',
// 'https://example.com/feed',
// ]Database Lookup
typescript
const url = await findCanonical('https://example.com/feed', {
existsFn: async (url) => {
const [feed] = await db
.select()
.from(feeds)
.where(eq(feeds.url, url))
.limit(1)
return feed
},
onExists: ({ url, data }) => {
console.log('Using existing feed:', data.id)
},
})Full Tracing
typescript
const url = await findCanonical('https://example.com/feed', {
existsFn: async (url) => db.feeds.findByUrl(url),
onFetch: ({ url, response }) => {
console.log(`Fetch: ${response.status} ${url}`)
},
onMatch: ({ url, feed }) => {
console.log(`Match: ${url}`)
},
onExists: ({ url, data }) => {
console.log(`Exists: ${url} (id: ${data.id})`)
},
})