diigo-cache: date windows and search, designed as skipped specs (goal 1d)
The public page's filters, toward the weekly PESOS roundup (#23): ?days=N (7/30/90/365 presets), gmail-style after/before (UTC days, half-open: after inclusive, before exclusive; yyyy/mm/dd accepted), and q (words, "phrases", #tags exact against diigo's comma-separated tags, - negation); q alone searches the last 365 days and says so; malformed filters are a 400. Filtering walks diigo's updated-desc pages from 1 and stops at the window, so ?days=7 costs one page. src/query.ts is the typed, JSDoc'd API (stubs that throw); 22 specs are describe.skip until it lands. The fake webapp gains a dated account. Generated-by: Claude Opus 5.5
This commit is contained in:
1 parent
860bbee2b5
commit
3e5e139dea
4 files changed
+507
-7
No files matched your search
@@ -10,6 +10,32 @@ import { RpcTarget, WorkerEntrypoint } from "cloudflare:workers";
|
||||
const KNOWN_WEBAPP = "fake-webapp-id";
|
||||
const TOTAL = 30;
|
||||
|
||||
/** a second account, for date filters (goal 1d): 60 bookmarks, item n
|
||||
* updated n-1 days + 1 hour before the call, in diigo's updated-desc
|
||||
* order; tagged ocap, plus weekly every 7th; every 10th private; every
|
||||
* 5th an old bookmark edited recently (created 100 days before updated) */
|
||||
const DATED_WEBAPP = "fake-dated-webapp";
|
||||
const DATED_TOTAL = 60;
|
||||
/** the same shape, 1200 deep (~3.3 years, 50 pages): for walk cost */
|
||||
const DEEP_WEBAPP = "fake-deep-webapp";
|
||||
const DEEP_TOTAL = 1200;
|
||||
const HOUR = 60 * 60 * 1000;
|
||||
|
||||
function datedItem(n, now, user = "dated_dan") {
|
||||
return {
|
||||
link_id: 5000 + n,
|
||||
url: `https://dated.example/${n}`,
|
||||
title: `dated ${n}`,
|
||||
description: n % 7 === 0 ? "a week of fragments" : "",
|
||||
private: n % 10 === 0,
|
||||
u_name: user,
|
||||
user_id: 777,
|
||||
tags: n % 7 === 0 ? "ocap,weekly" : "ocap",
|
||||
created_at: Math.floor((now - (n - 1) * 24 * HOUR - HOUR - (n % 5 === 0 ? 100 * 24 * HOUR : 0)) / 1000),
|
||||
updated_at: Math.floor((now - (n - 1) * 24 * HOUR - HOUR) / 1000),
|
||||
};
|
||||
}
|
||||
|
||||
/** item n (1-based, in diigo's order): diigo's field names, made-up
|
||||
* values. link_id and updated_at are scrambled (distinct; 7 and 11 are
|
||||
* coprime to 31), so neither column sorts back into diigo's order — a
|
||||
@@ -35,32 +61,40 @@ let calls = 0;
|
||||
class FakeGet extends RpcTarget {
|
||||
#path;
|
||||
#params;
|
||||
constructor(path, params) {
|
||||
/** null (the plain account), "dated", or "deep" */
|
||||
#dated;
|
||||
constructor(path, params, dated) {
|
||||
super();
|
||||
this.#path = path;
|
||||
this.#params = params;
|
||||
this.#dated = dated;
|
||||
}
|
||||
pathjoin(ref) {
|
||||
return new FakeGet(ref, this.#params);
|
||||
return new FakeGet(ref, this.#params, this.#dated);
|
||||
}
|
||||
query(params) {
|
||||
return new FakeGet(this.#path, { ...this.#params, ...params });
|
||||
return new FakeGet(this.#path, { ...this.#params, ...params }, this.#dated);
|
||||
}
|
||||
async get() {
|
||||
calls += 1;
|
||||
if (this.#path !== "load_user_items") throw new Error(`fake webapp: no route ${this.#path}`);
|
||||
const count = Number(this.#params.count);
|
||||
const page = Number(this.#params.page_num);
|
||||
const total = this.#dated === "deep" ? DEEP_TOTAL : this.#dated ? DATED_TOTAL : TOTAL;
|
||||
const now = Date.now();
|
||||
const items = [];
|
||||
for (let n = (page - 1) * count + 1; n <= Math.min(page * count, TOTAL); n += 1) items.push(item(n));
|
||||
return JSON.stringify({ total: TOTAL, items });
|
||||
for (let n = (page - 1) * count + 1; n <= Math.min(page * count, total); n += 1) {
|
||||
items.push(this.#dated ? datedItem(n, now, this.#dated === "deep" ? "deep_dee" : "dated_dan") : item(n));
|
||||
}
|
||||
return JSON.stringify({ total, items });
|
||||
}
|
||||
}
|
||||
|
||||
export class WebAppFactory extends WorkerEntrypoint {
|
||||
async at(id) {
|
||||
if (id !== KNOWN_WEBAPP) throw new Error("fake webapp: unknown id");
|
||||
return new FakeGet("", {});
|
||||
const kind = { [KNOWN_WEBAPP]: null, [DATED_WEBAPP]: "dated", [DEEP_WEBAPP]: "deep" }[id];
|
||||
if (kind === undefined) throw new Error("fake webapp: unknown id");
|
||||
return new FakeGet("", {}, kind);
|
||||
}
|
||||
/** how many diigo calls so far (test hook) */
|
||||
async calls() {
|
||||
|
||||
Reference in new issue
Block a user