Comparing version 0.1.1 to 0.1.3
@@ -79,5 +79,10 @@ // deno-fmt-ignore-file | ||
map = new Map(); | ||
onReturningCachedResponse; | ||
get(id, after) { | ||
const { response , fetched } = this.map.get(id) || {}; | ||
return Promise.resolve(response && fetched && fetched > after ? response.clone() : undefined); | ||
if (response && fetched && fetched > after) { | ||
if (this.onReturningCachedResponse) this.onReturningCachedResponse(id, after, fetched, response); | ||
return Promise.resolve(response); | ||
} | ||
return Promise.resolve(undefined); | ||
} | ||
@@ -144,7 +149,7 @@ put(id, fetched, response) { | ||
const response = await findOrFetchActivityPubResponse(url, after, fetcher, cache); | ||
const { status , headers } = response; | ||
if (status !== 200) throw new Error(`Expected 200 response for ${url}, found ${status} body=${await response.text()}`); | ||
const contentType = headers.get('content-type') || '<none>'; | ||
if (!contentType.toLowerCase().includes('json')) throw new Error(`Expected json response for ${url}, found ${contentType} body=${await response.text()}`); | ||
return await response.json(); | ||
const { status , headers , bodyText } = response; | ||
if (status !== 200) throw new Error(`Expected 200 response for ${url}, found ${status} body=${bodyText}`); | ||
const contentType = headers['content-type'] || '<none>'; | ||
if (!contentType.toLowerCase().includes('json')) throw new Error(`Expected json response for ${url}, found ${contentType} body=${bodyText}`); | ||
return JSON.parse(bodyText); | ||
} | ||
@@ -159,4 +164,11 @@ async function findOrFetchActivityPubResponse(url, after, fetcher, cache) { | ||
}); | ||
await cache.put(url, new Date().toISOString(), res.clone()); | ||
return res; | ||
const response = { | ||
status: res.status, | ||
headers: Object.fromEntries([ | ||
...res.headers | ||
]), | ||
bodyText: await res.text() | ||
}; | ||
await cache.put(url, new Date().toISOString(), response); | ||
return response; | ||
} | ||
@@ -163,0 +175,0 @@ async function processNode(id, processReplies, threadcap, updateTime, fetcher, cache, callbacks) { |
@@ -79,5 +79,10 @@ // deno-fmt-ignore-file | ||
map = new Map(); | ||
onReturningCachedResponse; | ||
get(id, after) { | ||
const { response , fetched } = this.map.get(id) || {}; | ||
return Promise.resolve(response && fetched && fetched > after ? response.clone() : undefined); | ||
if (response && fetched && fetched > after) { | ||
if (this.onReturningCachedResponse) this.onReturningCachedResponse(id, after, fetched, response); | ||
return Promise.resolve(response); | ||
} | ||
return Promise.resolve(undefined); | ||
} | ||
@@ -144,7 +149,7 @@ put(id, fetched, response) { | ||
const response = await findOrFetchActivityPubResponse(url, after, fetcher, cache); | ||
const { status , headers } = response; | ||
if (status !== 200) throw new Error(`Expected 200 response for ${url}, found ${status} body=${await response.text()}`); | ||
const contentType = headers.get('content-type') || '<none>'; | ||
if (!contentType.toLowerCase().includes('json')) throw new Error(`Expected json response for ${url}, found ${contentType} body=${await response.text()}`); | ||
return await response.json(); | ||
const { status , headers , bodyText } = response; | ||
if (status !== 200) throw new Error(`Expected 200 response for ${url}, found ${status} body=${bodyText}`); | ||
const contentType = headers['content-type'] || '<none>'; | ||
if (!contentType.toLowerCase().includes('json')) throw new Error(`Expected json response for ${url}, found ${contentType} body=${bodyText}`); | ||
return JSON.parse(bodyText); | ||
} | ||
@@ -159,4 +164,11 @@ async function findOrFetchActivityPubResponse(url, after, fetcher, cache) { | ||
}); | ||
await cache.put(url, new Date().toISOString(), res.clone()); | ||
return res; | ||
const response = { | ||
status: res.status, | ||
headers: Object.fromEntries([ | ||
...res.headers | ||
]), | ||
bodyText: await res.text() | ||
}; | ||
await cache.put(url, new Date().toISOString(), response); | ||
return response; | ||
} | ||
@@ -163,0 +175,0 @@ async function processNode(id, processReplies, threadcap, updateTime, fetcher, cache, callbacks) { |
@@ -145,16 +145,23 @@ /** | ||
/** | ||
* Find a cached {@link Response} for the given ActivityPub id that is still considered current after the specified time. | ||
* Find a cached {@link TextResponse} for the given ActivityPub id that is still considered current after the specified time. | ||
* | ||
* Can return `undefined` if none are found. This will usually trigger a refetch during the update process. | ||
* | ||
* Assume that any {@link Response} returned here will be read. Clone any responses you are keeping around only in memory, since response body streams can only be read once. | ||
*/ | ||
get(id: string, after: Instant): Promise<Response | undefined>; | ||
get(id: string, after: Instant): Promise<TextResponse | undefined>; | ||
/** | ||
* Save the given {@link Response} as the current value (as of `fetched`) for the given ActivityPub id. | ||
* Save the given {@link TextResponse} as the current value (as of `fetched`) for the given ActivityPub id. | ||
* | ||
* Its up to the cache implementation to decide where/whether to store it somewhere before returning. | ||
*/ | ||
put(id: string, fetched: Instant, response: Response): Promise<void>; | ||
put(id: string, fetched: Instant, response: TextResponse): Promise<void>; | ||
} | ||
/** HTTP response with a text body. */ | ||
export interface TextResponse { | ||
/** The HTTP response {@link Response#status}. */ | ||
readonly status: number; | ||
/** The HTTP response {@link Response#headers}. */ | ||
readonly headers: Record<string, string>; | ||
/** The HTTP response body {@link Response#text} as a string. */ | ||
readonly bodyText: string; | ||
} | ||
/** If customizing the rate-limiter wait function used in {@link makeRateLimitedFetcher}, these are the inputs you have to work with. */ | ||
@@ -245,4 +252,4 @@ export declare type RateLimiterInput = { | ||
* - `userAgent`: The user-agent to use when fetching. | ||
* - `fetcher`: The underlying {@link Fetcher} function, and the {@link Cache} implemention to use. | ||
* - `cache`: The {@link Cache} implemention to use. | ||
* - `fetcher`: The underlying {@link Fetcher} function to use. | ||
* - `cache`: The {@link Cache} implementation to use. | ||
* - `callbacks`: (optional) The {@link Callbacks} interface to listen to interesting events in real-time during the update. | ||
@@ -264,4 +271,5 @@ */ | ||
private readonly map; | ||
get(id: string, after: Instant): Promise<Response | undefined>; | ||
put(id: string, fetched: Instant, response: Response): Promise<void>; | ||
onReturningCachedResponse?: (id: string, after: Instant, fetched: Instant, response: TextResponse) => void; | ||
get(id: string, after: Instant): Promise<TextResponse | undefined>; | ||
put(id: string, fetched: Instant, response: TextResponse): Promise<void>; | ||
} | ||
@@ -268,0 +276,0 @@ /** If no custom function is passed to {@link makeRateLimitedFetcher}, this is the function that is used to determine how long to wait (sleep) before making a rate-limited fetch call. */ |
{ | ||
"name": "threadcap", | ||
"version": "0.1.1", | ||
"version": "0.1.3", | ||
"description": "Threadcap helps you take and update snapshots of a public ActivityPub comment thread, given a root post url.", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -109,3 +109,3 @@ Threadcap helps you take and update snapshots of a public ActivityPub comment thread, given a root post url. | ||
```ts | ||
import { makeThreadcap, InMemoryCache, updateThreadcap, makeRateLimitedFetcher, Callbacks } from 'https://raw.githubusercontent.com/skymethod/minipub/v0.1.1/src/threadcap/threadcap.ts'; | ||
import { makeThreadcap, InMemoryCache, updateThreadcap, makeRateLimitedFetcher, Callbacks } from 'https://raw.githubusercontent.com/skymethod/minipub/v0.1.3/src/threadcap/threadcap.ts'; | ||
@@ -112,0 +112,0 @@ const userAgent = 'my-podcast-app/1.0'; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
63909
1288