wiki-formant 0.1.4 → 0.2.0

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.
@@ -0,0 +1,43 @@
1
+ import type { HeaderReader } from './rate-limit.js';
2
+ export interface PlausibleConfig {
3
+ /** The hostname the Plausible property is registered under. */
4
+ domain: string;
5
+ /** Override for self-hosted Plausible. */
6
+ endpoint?: string;
7
+ }
8
+ export interface PlausibleExtra {
9
+ /** Revenue goal payload; accepted and ignored on plans without revenue goals. */
10
+ revenue?: {
11
+ currency: string;
12
+ amount: number;
13
+ };
14
+ /**
15
+ * Send the visitor's own user agent so the event joins their session rather
16
+ * than landing as the fixed bot-tracker pseudo-visitor. Right for an event
17
+ * a person triggered; wrong for one a crawler did.
18
+ */
19
+ userAgent?: string;
20
+ }
21
+ /**
22
+ * The exact request shape Plausible's events API expects.
23
+ *
24
+ * Never rejects: analytics must not be able to fail a response the reader is
25
+ * waiting on.
26
+ */
27
+ export declare function plausibleEvent(config: PlausibleConfig, name: string, url: string, props: Record<string, string>, headers: HeaderReader, extra?: PlausibleExtra): Promise<unknown>;
28
+ /**
29
+ * Props for an "MCP Call" event, read out of the JSON-RPC envelope.
30
+ *
31
+ * The body is untrusted and may be a batch, a notification, or malformed
32
+ * entirely, so every extraction is defensive and the result is always a
33
+ * complete props object. A batch is attributed to its first member — the
34
+ * alternative is one event per member, which would make a fan-out look like
35
+ * traffic it is not.
36
+ */
37
+ export declare function mcpCallProps(request: {
38
+ headers: HeaderReader;
39
+ url: string;
40
+ }, body: unknown, server?: string): Record<string, string>;
41
+ /** The hostname of a site URL, for the `domain` a Plausible property is filed under. */
42
+ export declare function plausibleDomain(siteUrl: string | undefined, fallback: string): string;
43
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,YAAY,EACrB,KAAK,GAAE,cAAmB,GACzB,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAC/C,IAAI,EAAE,OAAO,EACb,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMrF"}
@@ -0,0 +1,61 @@
1
+ // analytics.ts — server-side Plausible events for agent surfaces.
2
+ //
3
+ // The proxy counts an "AI Bot Visit" by matching user agents, which cannot see
4
+ // inside a JSON-RPC envelope. So an MCP call is only countable by tool name at
5
+ // the route, and that extraction — from a body that is untrusted and may be a
6
+ // batch — is the part worth sharing. Every wiki in the workspace had its own
7
+ // copy of it, differing only in the default hostname.
8
+ //
9
+ // Deferral stays with the caller: `after()` in a route handler,
10
+ // `event.waitUntil` in a proxy. Both are framework calls, and importing one
11
+ // here would cost this package its zero-dependency guarantee.
12
+ const DEFAULT_ENDPOINT = 'https://plausible.io/api/event';
13
+ /**
14
+ * The exact request shape Plausible's events API expects.
15
+ *
16
+ * Never rejects: analytics must not be able to fail a response the reader is
17
+ * waiting on.
18
+ */
19
+ export function plausibleEvent(config, name, url, props, headers, extra = {}) {
20
+ return fetch(config.endpoint ?? DEFAULT_ENDPOINT, {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ 'User-Agent': extra.userAgent || 'Mozilla/5.0 (compatible; BotTracker/1.0)',
25
+ 'X-Forwarded-For': headers.get('x-forwarded-for') || headers.get('x-real-ip') || '127.0.0.1',
26
+ },
27
+ body: JSON.stringify({
28
+ name,
29
+ url,
30
+ domain: config.domain,
31
+ props: JSON.stringify(props),
32
+ ...(extra.revenue ? { revenue: extra.revenue } : {}),
33
+ }),
34
+ }).catch(() => undefined);
35
+ }
36
+ /**
37
+ * Props for an "MCP Call" event, read out of the JSON-RPC envelope.
38
+ *
39
+ * The body is untrusted and may be a batch, a notification, or malformed
40
+ * entirely, so every extraction is defensive and the result is always a
41
+ * complete props object. A batch is attributed to its first member — the
42
+ * alternative is one event per member, which would make a fan-out look like
43
+ * traffic it is not.
44
+ */
45
+ export function mcpCallProps(request, body, server) {
46
+ const first = (Array.isArray(body) ? body[0] : body);
47
+ const method = typeof first?.method === 'string' ? first.method : 'unknown';
48
+ const tool = typeof first?.params?.name === 'string' ? first.params.name : undefined;
49
+ const ua = (request.headers.get('user-agent') || 'unknown').slice(0, 80);
50
+ return { ...(server ? { server } : {}), method, ...(tool ? { tool } : {}), ua };
51
+ }
52
+ /** The hostname of a site URL, for the `domain` a Plausible property is filed under. */
53
+ export function plausibleDomain(siteUrl, fallback) {
54
+ try {
55
+ return new URL(siteUrl || fallback).hostname;
56
+ }
57
+ catch {
58
+ return fallback.replace(/^https?:\/\//, '').replace(/\/.*$/, '');
59
+ }
60
+ }
61
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analytics.js","sourceRoot":"","sources":["../src/analytics.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,sDAAsD;AACtD,EAAE;AACF,gEAAgE;AAChE,4EAA4E;AAC5E,8DAA8D;AAsB9D,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AAE1D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAuB,EACvB,IAAY,EACZ,GAAW,EACX,KAA6B,EAC7B,OAAqB,EACrB,QAAwB,EAAE;IAE1B,OAAO,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,gBAAgB,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,YAAY,EAAE,KAAK,CAAC,SAAS,IAAI,0CAA0C;YAC3E,iBAAiB,EACf,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,WAAW;SAC5E;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,IAAI;YACJ,GAAG;YACH,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAC5B,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACrD,CAAC;KACH,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,OAA+C,EAC/C,IAAa,EACb,MAAe;IAEf,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAEtC,CAAC;IACd,MAAM,MAAM,GAAG,OAAO,KAAK,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,MAAM,IAAI,GAAG,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;AAClF,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,OAA2B,EAAE,QAAgB;IAC3E,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAC,QAAQ,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;AACH,CAAC"}
@@ -0,0 +1,57 @@
1
+ export interface CodeTab {
2
+ label: string;
3
+ language?: string;
4
+ code: string;
5
+ }
6
+ export interface ReferenceItem {
7
+ text: string;
8
+ url?: string | null;
9
+ }
10
+ export interface StatItem {
11
+ value: string | number;
12
+ label: string;
13
+ suffix?: string | null;
14
+ }
15
+ export interface LinkGridLink {
16
+ label: string;
17
+ href: string;
18
+ }
19
+ export interface LinkGridGroup {
20
+ heading: string;
21
+ description?: string | null;
22
+ links: readonly LinkGridLink[];
23
+ }
24
+ export interface BlockTreeOptions<B> {
25
+ /** Render one leaf block. Return `''` to drop it from the document. */
26
+ atomic: (block: B) => string;
27
+ /**
28
+ * The nested block groups a container holds, in document order, or `null`
29
+ * for a leaf. An infobox is one group; a columns block is one per column.
30
+ */
31
+ containers?: (block: B) => B[][] | null;
32
+ }
33
+ /**
34
+ * The whole tree as markdown. Containers flatten in document order, because a
35
+ * reader following prose does not have columns — and an agent quoting the page
36
+ * needs the sentences adjacent, not interleaved.
37
+ */
38
+ export declare function renderBlockTree<B>(blocks: readonly B[], opts: BlockTreeOptions<B>): string;
39
+ /**
40
+ * Fenced blocks, one per tab, each under its label.
41
+ *
42
+ * The editor stores highlighted code, so the tags come out before the fence
43
+ * goes on — a fenced block full of `<span class="hljs-keyword">` is worse than
44
+ * no code at all.
45
+ */
46
+ export declare function codeTabsToMarkdown(tabs: readonly CodeTab[]): string;
47
+ /** A maintenance notice as a blockquote. `label` is the caller's display string. */
48
+ export declare function bannerToMarkdown(label: string, text?: string | null): string;
49
+ /** A numbered citation list, or `''` when there is nothing to cite. */
50
+ export declare function referencesToMarkdown(items: readonly ReferenceItem[], title?: string): string;
51
+ /** Metric cards as a bullet list, or `''` when empty. */
52
+ export declare function statsToMarkdown(items: readonly StatItem[]): string;
53
+ /** Grouped links under their headings, with an optional lead paragraph. */
54
+ export declare function linkGridToMarkdown(groups: readonly LinkGridGroup[], intro?: string | null): string;
55
+ /** A flat bullet list of links — resolved page lists, feed items, link rails. */
56
+ export declare function linkList(items: readonly LinkGridLink[]): string;
57
+ //# sourceMappingURL=blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;CAChC;AAID,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,uEAAuE;IACvE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAe1F;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,MAAM,CAOnE;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE5E;AAED,uEAAuE;AACvE,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,KAAK,SAAe,GACnB,MAAM,CAMR;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,MAAM,CAGlE;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,aAAa,EAAE,EAChC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAWR;AAED,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAE/D"}
package/dist/blocks.js ADDED
@@ -0,0 +1,82 @@
1
+ // blocks.ts — the parts of a block tree that are the same wiki to wiki.
2
+ //
3
+ // A wiki's block TYPE SET is its own and always will be: one has an on-chain
4
+ // timeline, another an asset-price widget. What is not its own is the shape of
5
+ // the markdown those blocks flatten to. Two wikis in this workspace had the
6
+ // same seven case bodies, character for character, and the same container walk
7
+ // underneath them — including the same `\n{3,}` collapse at the end.
8
+ //
9
+ // So the dispatch stays with the caller (a `switch` over its own union, where a
10
+ // new block type is a compile error until it is handled) and the bodies come
11
+ // from here. Each renderer takes the block's DATA rather than the block, which
12
+ // keeps this file free of any one repo's type union.
13
+ import { decodeEntities } from './entities.js';
14
+ import { htmlToMarkdown, inlineToMarkdown } from './markdown.js';
15
+ /**
16
+ * The whole tree as markdown. Containers flatten in document order, because a
17
+ * reader following prose does not have columns — and an agent quoting the page
18
+ * needs the sentences adjacent, not interleaved.
19
+ */
20
+ export function renderBlockTree(blocks, opts) {
21
+ const { atomic, containers } = opts;
22
+ return blocks
23
+ .map(block => {
24
+ const groups = containers?.(block);
25
+ if (!groups)
26
+ return atomic(block);
27
+ return groups
28
+ .map(group => group.map(atomic).filter(Boolean).join('\n\n'))
29
+ .filter(Boolean)
30
+ .join('\n\n');
31
+ })
32
+ .filter(Boolean)
33
+ .join('\n\n')
34
+ .replace(/\n{3,}/g, '\n\n')
35
+ .trim();
36
+ }
37
+ // ---- the shared leaf renderers ----------------------------------------------
38
+ /**
39
+ * Fenced blocks, one per tab, each under its label.
40
+ *
41
+ * The editor stores highlighted code, so the tags come out before the fence
42
+ * goes on — a fenced block full of `<span class="hljs-keyword">` is worse than
43
+ * no code at all.
44
+ */
45
+ export function codeTabsToMarkdown(tabs) {
46
+ return tabs
47
+ .map(t => `**${t.label}**\n\n\`\`\`${t.language || ''}\n${decodeEntities(t.code.replace(/<[^>]+>/g, '')).trim()}\n\`\`\``)
48
+ .join('\n\n');
49
+ }
50
+ /** A maintenance notice as a blockquote. `label` is the caller's display string. */
51
+ export function bannerToMarkdown(label, text) {
52
+ return `> **[${label}]**${text ? ` ${inlineToMarkdown(text)}` : ''}`;
53
+ }
54
+ /** A numbered citation list, or `''` when there is nothing to cite. */
55
+ export function referencesToMarkdown(items, title = 'References') {
56
+ if (!items.length)
57
+ return '';
58
+ const lines = items.map((r, i) => `${i + 1}. ${inlineToMarkdown(r.text)}${r.url ? ` — ${r.url}` : ''}`);
59
+ return `### ${title}\n\n${lines.join('\n')}`;
60
+ }
61
+ /** Metric cards as a bullet list, or `''` when empty. */
62
+ export function statsToMarkdown(items) {
63
+ if (!items.length)
64
+ return '';
65
+ return items.map(s => `- **${s.value}${s.suffix ?? ''}** — ${s.label}`).join('\n');
66
+ }
67
+ /** Grouped links under their headings, with an optional lead paragraph. */
68
+ export function linkGridToMarkdown(groups, intro) {
69
+ const lead = intro ? `${inlineToMarkdown(intro)}\n\n` : '';
70
+ const rendered = groups.map(g => [
71
+ `### ${g.heading}`,
72
+ ...(g.description ? ['', htmlToMarkdown(g.description)] : []),
73
+ '',
74
+ ...g.links.map(l => `- [${l.label}](${l.href})`),
75
+ ].join('\n'));
76
+ return `${lead}${rendered.join('\n\n')}`;
77
+ }
78
+ /** A flat bullet list of links — resolved page lists, feed items, link rails. */
79
+ export function linkList(items) {
80
+ return items.map(l => `- [${l.label}](${l.href})`).join('\n');
81
+ }
82
+ //# sourceMappingURL=blocks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocks.js","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts CHANGED
@@ -11,8 +11,16 @@ export declare function textHeaders(etag: string, lastModified: string, maxAge?:
11
11
  * Headers for a markdown twin. Separate from `textHeaders` because the twin is
12
12
  * addressed per page and carries its own `Last-Modified`, and because a client
13
13
  * that asked for `.md` should not be handed `text/plain`.
14
+ *
15
+ * `lastModified` is optional because not every corpus has a row timestamp to
16
+ * offer, and a twin that stamps the epoch is worse than one that stamps
17
+ * nothing. `extra` carries whatever the mount needs on top — an `X-Robots-Tag`
18
+ * where the twin is a second public URL with no canonical of its own.
14
19
  */
15
- export declare function markdownHeaders(lastModified: string, maxAge?: number): Record<string, string>;
20
+ export declare function markdownHeaders(lastModified?: string | null, opts?: {
21
+ maxAge?: number;
22
+ extra?: Record<string, string>;
23
+ }): Record<string, string>;
16
24
  /** Strip URLs and collapse whitespace so an excerpt stays one readable line. */
17
25
  export declare function cleanSnippet(text: string, max?: number): string;
18
26
  /** One markdown bullet: linked title, excerpt, and the date an agent diffs on. */
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAOA,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAY1F;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAMjG;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,MAAM,SAAO,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM3F;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAQ5D;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,MAAM,CAMT"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAOA,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAY1F;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAMjG;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,MAAM,SAAO,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,EAC5B,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAC7D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAQ5D;AAED,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,MAAM,CAMT"}
package/dist/http.js CHANGED
@@ -43,12 +43,19 @@ export function textHeaders(etag, lastModified, maxAge = 3600) {
43
43
  * Headers for a markdown twin. Separate from `textHeaders` because the twin is
44
44
  * addressed per page and carries its own `Last-Modified`, and because a client
45
45
  * that asked for `.md` should not be handed `text/plain`.
46
+ *
47
+ * `lastModified` is optional because not every corpus has a row timestamp to
48
+ * offer, and a twin that stamps the epoch is worse than one that stamps
49
+ * nothing. `extra` carries whatever the mount needs on top — an `X-Robots-Tag`
50
+ * where the twin is a second public URL with no canonical of its own.
46
51
  */
47
- export function markdownHeaders(lastModified, maxAge = 3600) {
52
+ export function markdownHeaders(lastModified, opts = {}) {
53
+ const maxAge = opts.maxAge ?? 3600;
48
54
  return {
49
55
  'Content-Type': 'text/markdown; charset=utf-8',
50
56
  'Cache-Control': `public, s-maxage=${maxAge}, stale-while-revalidate=${maxAge * 24}`,
51
- 'Last-Modified': lastModified,
57
+ ...(lastModified ? { 'Last-Modified': lastModified } : {}),
58
+ ...opts.extra,
52
59
  };
53
60
  }
54
61
  /** Strip URLs and collapse whitespace so an excerpt stays one readable line. */
package/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,4 +5,7 @@ export * from './entities.js';
5
5
  export * from './http.js';
6
6
  export * from './pagination.js';
7
7
  export * from './versioning.js';
8
+ export * from './rate-limit.js';
9
+ export * from './analytics.js';
10
+ export * from './blocks.js';
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -10,4 +10,7 @@ export * from './entities.js';
10
10
  export * from './http.js';
11
11
  export * from './pagination.js';
12
12
  export * from './versioning.js';
13
+ export * from './rate-limit.js';
14
+ export * from './analytics.js';
15
+ export * from './blocks.js';
13
16
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,mBAAmB;AAEnB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,mBAAmB;AAEnB,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,41 @@
1
+ export interface RateLimitOptions {
2
+ /** Bucket capacity: the peak burst a caller may spend at once. */
3
+ capacity: number;
4
+ /** Tokens added per second: the sustained rate. */
5
+ refillPerSec: number;
6
+ }
7
+ export type RateLimitResult = {
8
+ ok: true;
9
+ remaining: number;
10
+ } | {
11
+ ok: false;
12
+ retryAfterSec: number;
13
+ };
14
+ /**
15
+ * Spend one token against `key`.
16
+ *
17
+ * Keys are namespaced by the caller (`"mcp:1.2.3.4"`, `"write:page:17"`), so
18
+ * one map backs every limiter in a process without them colliding.
19
+ */
20
+ export declare function rateLimit(key: string, opts: RateLimitOptions): RateLimitResult;
21
+ /** Anything with a header getter: a `Request`'s headers, or Next's `headers()`. */
22
+ export interface HeaderReader {
23
+ get(name: string): string | null | undefined;
24
+ }
25
+ /**
26
+ * The caller's address, from the proxy header the edge sets.
27
+ *
28
+ * Falls back to a single shared bucket rather than to per-caller buckets, so an
29
+ * unidentifiable caller is still limited — collectively, but limited. Keying on
30
+ * anything the caller controls (a user agent, say) hands every caller a fresh
31
+ * bucket per value, which turns the limiter off for exactly the traffic it is
32
+ * meant to catch.
33
+ */
34
+ export declare function clientIp(headers: HeaderReader): string;
35
+ /** `prefix:ip` — the key `rateLimit` expects for a per-IP gate. */
36
+ export declare function clientKey(prefix: string, headers: HeaderReader): string;
37
+ /** The message a 429 body carries, so every surface refuses in the same words. */
38
+ export declare function retryMessage(retryAfterSec: number): string;
39
+ /** Test seam: the bucket map is module state and outlives a single test. */
40
+ export declare function resetRateLimits(): void;
41
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AASzC;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,GAAG,eAAe,CAsB9E;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAGtD;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAEvE;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -0,0 +1,68 @@
1
+ // rate-limit.ts — the token bucket every agent surface in the workspace was
2
+ // carrying its own copy of.
3
+ //
4
+ // In-memory, so it survives across requests within one serverless instance and
5
+ // resets on a cold start. That is the right bar for the anonymous read surfaces
6
+ // this guards: it bounds a script without needing a Redis round-trip on the hot
7
+ // path. Swap for a shared store only when multi-instance sharing actually
8
+ // matters.
9
+ //
10
+ // Framework binding stays with the caller. Turning a verdict into a 429, and
11
+ // getting at the request headers in the first place, is four lines of whatever
12
+ // framework you are in — and importing one here would cost this package its
13
+ // zero-dependency guarantee.
14
+ const buckets = new Map();
15
+ /** Bounds memory under high-cardinality keying — one bucket per attacker IP. */
16
+ const MAX_KEYS = 10_000;
17
+ /**
18
+ * Spend one token against `key`.
19
+ *
20
+ * Keys are namespaced by the caller (`"mcp:1.2.3.4"`, `"write:page:17"`), so
21
+ * one map backs every limiter in a process without them colliding.
22
+ */
23
+ export function rateLimit(key, opts) {
24
+ const now = Date.now();
25
+ const existing = buckets.get(key);
26
+ if (!existing && buckets.size >= MAX_KEYS) {
27
+ // Map iteration is insertion-ordered, so this evicts the oldest key.
28
+ const oldest = buckets.keys().next().value;
29
+ if (oldest !== undefined)
30
+ buckets.delete(oldest);
31
+ }
32
+ const bucket = existing ?? { tokens: opts.capacity, updatedAt: now };
33
+ const elapsedSec = (now - bucket.updatedAt) / 1000;
34
+ bucket.tokens = Math.min(opts.capacity, bucket.tokens + elapsedSec * opts.refillPerSec);
35
+ bucket.updatedAt = now;
36
+ buckets.set(key, bucket);
37
+ if (bucket.tokens < 1) {
38
+ return { ok: false, retryAfterSec: Math.ceil((1 - bucket.tokens) / opts.refillPerSec) };
39
+ }
40
+ bucket.tokens -= 1;
41
+ return { ok: true, remaining: Math.floor(bucket.tokens) };
42
+ }
43
+ /**
44
+ * The caller's address, from the proxy header the edge sets.
45
+ *
46
+ * Falls back to a single shared bucket rather than to per-caller buckets, so an
47
+ * unidentifiable caller is still limited — collectively, but limited. Keying on
48
+ * anything the caller controls (a user agent, say) hands every caller a fresh
49
+ * bucket per value, which turns the limiter off for exactly the traffic it is
50
+ * meant to catch.
51
+ */
52
+ export function clientIp(headers) {
53
+ const forwarded = headers.get('x-forwarded-for');
54
+ return forwarded?.split(',')[0]?.trim() || headers.get('x-real-ip')?.trim() || 'anon';
55
+ }
56
+ /** `prefix:ip` — the key `rateLimit` expects for a per-IP gate. */
57
+ export function clientKey(prefix, headers) {
58
+ return `${prefix}:${clientIp(headers)}`;
59
+ }
60
+ /** The message a 429 body carries, so every surface refuses in the same words. */
61
+ export function retryMessage(retryAfterSec) {
62
+ return `Too many requests. Try again in ${retryAfterSec}s.`;
63
+ }
64
+ /** Test seam: the bucket map is module state and outlives a single test. */
65
+ export function resetRateLimits() {
66
+ buckets.clear();
67
+ }
68
+ //# sourceMappingURL=rate-limit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4BAA4B;AAC5B,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,0EAA0E;AAC1E,WAAW;AACX,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,4EAA4E;AAC5E,6BAA6B;AAe7B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE1C,gFAAgF;AAChF,MAAM,QAAQ,GAAG,MAAM,CAAC;AAExB;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,IAAsB;IAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAElC,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC1C,qEAAqE;QACrE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC3C,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,MAAM,GAAW,QAAQ,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC;IAC7E,MAAM,UAAU,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IACnD,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC;IACxF,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAEzB,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;IAC1F,CAAC;IAED,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACnB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;AAC5D,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAqB;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACjD,OAAO,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,IAAI,MAAM,CAAC;AACxF,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,OAAqB;IAC7D,OAAO,GAAG,MAAM,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,YAAY,CAAC,aAAqB;IAChD,OAAO,mCAAmC,aAAa,IAAI,CAAC;AAC9D,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC"}
@@ -60,8 +60,15 @@ export interface TaxonomyConfig {
60
60
  /** Below this a category fits on a screen or two; above it, readers need an index. */
61
61
  alphaIndexMinPages?: number;
62
62
  }
63
- /** Default: `/{tagPath}?sort=…&{facet}=…&letter=…`. Override for a prefixed mount. */
64
- export declare function defaultHref(tagPath: string, state: CategoryState): string;
63
+ /**
64
+ * `{prefix}/{tagPath}?sort=…&{facet}=…&letter=…` the URL contract every chip,
65
+ * letter and infobox row builds through, so a filtered view has exactly one
66
+ * address. `prefix` is the mount point: `''` for categories at the root,
67
+ * `'/wiki'` for a wiki hanging off a larger site.
68
+ */
69
+ export declare function hrefBuilder(prefix?: string): (tagPath: string, state: CategoryState) => string;
70
+ /** Categories mounted at the root. */
71
+ export declare const defaultHref: (tagPath: string, state: CategoryState) => string;
65
72
  export declare const DEFAULT_ALPHA_INDEX_MIN_PAGES = 40;
66
73
  /** Bucket for titles that don't start with a letter (numerals, `$CAPER`). */
67
74
  export declare function firstLetter(title: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"taxonomy.d.ts","sourceRoot":"","sources":["../src/taxonomy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"taxonomy.d.ts","sourceRoot":"","sources":["../src/taxonomy.ts"],"names":[],"mappings":"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"}
package/dist/taxonomy.js CHANGED
@@ -12,18 +12,30 @@
12
12
  // Two consumers proved the mechanism travels — one walks a nested tag tree, the
13
13
  // other a flat category list — so the tree itself is NOT in this module. Supply
14
14
  // `getMetadataKeys(tagPath)` and a `href` builder and the rest follows.
15
- /** Default: `/{tagPath}?sort=…&{facet}=…&letter=…`. Override for a prefixed mount. */
16
- export function defaultHref(tagPath, state) {
17
- const params = new URLSearchParams();
18
- if (state.sort)
19
- params.set('sort', state.sort);
20
- for (const [key, value] of Object.entries(state.filters ?? {}))
21
- params.set(key, value);
22
- if (state.letter)
23
- params.set('letter', state.letter);
24
- const query = params.toString();
25
- return `/${tagPath}${query ? `?${query}` : ''}`;
15
+ /**
16
+ * `{prefix}/{tagPath}?sort=…&{facet}=…&letter=…` the URL contract every chip,
17
+ * letter and infobox row builds through, so a filtered view has exactly one
18
+ * address. `prefix` is the mount point: `''` for categories at the root,
19
+ * `'/wiki'` for a wiki hanging off a larger site.
20
+ */
21
+ export function hrefBuilder(prefix = '') {
22
+ return (tagPath, state) => {
23
+ const params = new URLSearchParams();
24
+ if (state.sort)
25
+ params.set('sort', state.sort);
26
+ for (const [key, value] of Object.entries(state.filters ?? {}))
27
+ params.set(key, value);
28
+ if (state.letter)
29
+ params.set('letter', state.letter);
30
+ const query = params.toString();
31
+ // Trailing slash trimmed so a prefixed mount's root is `/wiki`, not
32
+ // `/wiki/`; the root mount's own root stays `/`.
33
+ const path = `${prefix}/${tagPath}`.replace(/\/$/, '') || '/';
34
+ return `${path}${query ? `?${query}` : ''}`;
35
+ };
26
36
  }
37
+ /** Categories mounted at the root. */
38
+ export const defaultHref = hrefBuilder();
27
39
  export const DEFAULT_ALPHA_INDEX_MIN_PAGES = 40;
28
40
  const metaValue = (page, key) => (page.metadata?.[key] ?? '').trim();
29
41
  /** Bucket for titles that don't start with a letter (numerals, `$CAPER`). */
@@ -1 +1 @@
1
- {"version":3,"file":"taxonomy.js","sourceRoot":"","sources":["../src/taxonomy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"taxonomy.js","sourceRoot":"","sources":["../src/taxonomy.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "wiki-formant",
3
- "version": "0.1.4",
4
- "description": "The portable half of a wiki: derived taxonomy, a spec-correct MCP transport, markdown twins, and the conditional-GET plumbing agent surfaces need. Zero runtime dependencies.",
3
+ "version": "0.2.0",
4
+ "description": "The portable half of a wiki: derived taxonomy, a spec-correct MCP transport, markdown twins, block rendering, rate limiting, and the conditional-GET plumbing agent surfaces need. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -16,7 +16,9 @@
16
16
  "model-context-protocol",
17
17
  "llms-txt",
18
18
  "markdown",
19
- "agent"
19
+ "agent",
20
+ "rate-limit",
21
+ "plausible"
20
22
  ],
21
23
  "sideEffects": false,
22
24
  "exports": {
@@ -47,6 +49,18 @@
47
49
  "./versioning": {
48
50
  "types": "./dist/versioning.d.ts",
49
51
  "import": "./dist/versioning.js"
52
+ },
53
+ "./rate-limit": {
54
+ "types": "./dist/rate-limit.d.ts",
55
+ "import": "./dist/rate-limit.js"
56
+ },
57
+ "./analytics": {
58
+ "types": "./dist/analytics.d.ts",
59
+ "import": "./dist/analytics.js"
60
+ },
61
+ "./blocks": {
62
+ "types": "./dist/blocks.d.ts",
63
+ "import": "./dist/blocks.js"
50
64
  }
51
65
  },
52
66
  "files": [