@saypsst/next 0.0.0-stage → 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.
- package/README.md +190 -2
- package/dist/chunk-4FFLVIJG.js +60 -0
- package/dist/chunk-5X6OYLUN.js +95 -0
- package/dist/chunk-CKSLG42W.js +42 -0
- package/dist/chunk-WHB66OTA.js +522 -0
- package/dist/chunk-XCY5RUQM.js +18 -0
- package/dist/config-CoVgm6Ny.d.ts +52 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +2 -0
- package/dist/llms.d.ts +8 -0
- package/dist/llms.js +16 -0
- package/dist/page.d.ts +41 -0
- package/dist/page.js +190 -0
- package/dist/proxy.d.ts +15 -0
- package/dist/proxy.js +89 -0
- package/dist/sitemap.d.ts +11 -0
- package/dist/sitemap.js +19 -0
- package/dist/style.d.ts +8 -0
- package/dist/style.js +12 -0
- package/dist/verify.d.ts +12 -0
- package/dist/verify.js +17 -0
- package/package.json +73 -4
package/dist/page.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { isBuildPhase } from './chunk-CKSLG42W.js';
|
|
2
|
+
import { PsstConfigError } from './chunk-4FFLVIJG.js';
|
|
3
|
+
export { PSST_REVALIDATE } from './chunk-4FFLVIJG.js';
|
|
4
|
+
import { fetchManifest, PsstUnavailableError, fetchPage } from './chunk-5X6OYLUN.js';
|
|
5
|
+
import { ContentError, parsePageDocument, hashDocument, shortHash, serializeJsonForScript, buildJsonLd, sitePathSchema, factValue } from './chunk-WHB66OTA.js';
|
|
6
|
+
import { notFound } from 'next/navigation';
|
|
7
|
+
import { connection } from 'next/server';
|
|
8
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
function linkProps(href) {
|
|
11
|
+
return href.startsWith("/") ? { href } : { href, rel: "noopener" };
|
|
12
|
+
}
|
|
13
|
+
function InlineContent({ items }) {
|
|
14
|
+
return items.map((i, n) => {
|
|
15
|
+
switch (i.type) {
|
|
16
|
+
case "text":
|
|
17
|
+
return i.text;
|
|
18
|
+
case "strong":
|
|
19
|
+
return /* @__PURE__ */ jsx("strong", { children: i.text }, n);
|
|
20
|
+
case "em":
|
|
21
|
+
return /* @__PURE__ */ jsx("em", { children: i.text }, n);
|
|
22
|
+
case "link":
|
|
23
|
+
return /* @__PURE__ */ jsx("a", { ...linkProps(i.href), children: i.text }, n);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function Table({ b, className }) {
|
|
28
|
+
return /* @__PURE__ */ jsxs("table", { className, children: [
|
|
29
|
+
/* @__PURE__ */ jsx("caption", { children: b.caption }),
|
|
30
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: b.columns.map((c, n) => /* @__PURE__ */ jsx("th", { scope: "col", children: c }, n)) }) }),
|
|
31
|
+
/* @__PURE__ */ jsx("tbody", { children: b.rows.map((r, n) => {
|
|
32
|
+
const [first = "", ...rest] = r;
|
|
33
|
+
return /* @__PURE__ */ jsxs("tr", { children: [
|
|
34
|
+
/* @__PURE__ */ jsx("th", { scope: "row", children: first }),
|
|
35
|
+
rest.map((c, m) => /* @__PURE__ */ jsx("td", { children: c }, m))
|
|
36
|
+
] }, n);
|
|
37
|
+
}) })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
function BlockView({ b }) {
|
|
41
|
+
switch (b.type) {
|
|
42
|
+
case "heading":
|
|
43
|
+
return b.level === 2 ? /* @__PURE__ */ jsx("h2", { children: b.text }) : /* @__PURE__ */ jsx("h3", { children: b.text });
|
|
44
|
+
case "paragraph":
|
|
45
|
+
return /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsx(InlineContent, { items: b.inline }) });
|
|
46
|
+
case "list": {
|
|
47
|
+
const items = b.items.map((i, n) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(InlineContent, { items: i }) }, n));
|
|
48
|
+
return b.ordered ? /* @__PURE__ */ jsx("ol", { children: items }) : /* @__PURE__ */ jsx("ul", { children: items });
|
|
49
|
+
}
|
|
50
|
+
case "table":
|
|
51
|
+
return /* @__PURE__ */ jsx(Table, { b, className: "psst-table" });
|
|
52
|
+
case "faq":
|
|
53
|
+
return /* @__PURE__ */ jsx("section", { className: "psst-faq", "aria-label": "Frequently asked questions", children: /* @__PURE__ */ jsx("dl", { children: b.items.flatMap((i, n) => [
|
|
54
|
+
/* @__PURE__ */ jsx("dt", { children: i.q }, `q${n}`),
|
|
55
|
+
/* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx(InlineContent, { items: i.a }) }, `a${n}`)
|
|
56
|
+
]) }) });
|
|
57
|
+
case "comparison":
|
|
58
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx(Table, { b, className: "psst-table psst-comparison" }),
|
|
60
|
+
b.notes.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "psst-notes", children: b.notes.map((note, n) => /* @__PURE__ */ jsx("li", { children: note }, n)) }) : null
|
|
61
|
+
] });
|
|
62
|
+
case "facts":
|
|
63
|
+
return /* @__PURE__ */ jsx("dl", { className: "psst-facts", children: b.items.flatMap((i, n) => [/* @__PURE__ */ jsx("dt", { children: i.label }, `l${n}`), /* @__PURE__ */ jsx("dd", { children: factValue(i) }, `v${n}`)]) });
|
|
64
|
+
case "cta":
|
|
65
|
+
return /* @__PURE__ */ jsx("p", { className: "psst-cta", children: /* @__PURE__ */ jsx("a", { className: "psst-button", ...linkProps(b.href), children: b.label }) });
|
|
66
|
+
case "image":
|
|
67
|
+
return /* @__PURE__ */ jsx("figure", { children: /* @__PURE__ */ jsx("img", { src: b.src, alt: b.alt, width: b.width, height: b.height, loading: "lazy", decoding: "async" }) });
|
|
68
|
+
case "citation":
|
|
69
|
+
return /* @__PURE__ */ jsxs("p", { className: "psst-citation", children: [
|
|
70
|
+
/* @__PURE__ */ jsx("cite", { children: /* @__PURE__ */ jsx("a", { href: b.url, rel: "noopener", children: b.title }) }),
|
|
71
|
+
", accessed ",
|
|
72
|
+
/* @__PURE__ */ jsx("time", { dateTime: b.accessed, children: b.accessed })
|
|
73
|
+
] });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function PsstMain({ doc, ctx }) {
|
|
77
|
+
const jsonLd = serializeJsonForScript(buildJsonLd(doc, ctx));
|
|
78
|
+
return /* @__PURE__ */ jsxs("main", { children: [
|
|
79
|
+
/* @__PURE__ */ jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: jsonLd } }),
|
|
80
|
+
/* @__PURE__ */ jsxs("article", { className: "psst-article", children: [
|
|
81
|
+
/* @__PURE__ */ jsx("h1", { children: doc.h1 }),
|
|
82
|
+
/* @__PURE__ */ jsx("p", { className: "psst-lede", children: doc.lede }),
|
|
83
|
+
/* @__PURE__ */ jsxs("p", { className: "psst-updated", children: [
|
|
84
|
+
"Updated ",
|
|
85
|
+
/* @__PURE__ */ jsx("time", { dateTime: doc.updatedAt, children: doc.updatedAt.slice(0, 10) })
|
|
86
|
+
] }),
|
|
87
|
+
doc.blocks.map((b, n) => /* @__PURE__ */ jsx(BlockView, { b }, n)),
|
|
88
|
+
doc.sources.length > 0 ? /* @__PURE__ */ jsxs("section", { className: "psst-sources", children: [
|
|
89
|
+
/* @__PURE__ */ jsx("h2", { children: "Sources" }),
|
|
90
|
+
/* @__PURE__ */ jsx("ol", { children: doc.sources.map((s, n) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: s.url, rel: "noopener", children: s.title }) }, n)) })
|
|
91
|
+
] }) : null
|
|
92
|
+
] })
|
|
93
|
+
] });
|
|
94
|
+
}
|
|
95
|
+
function DefaultShell({ siteName, nav = [], footer, children }) {
|
|
96
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
97
|
+
/* @__PURE__ */ jsxs("header", { className: "psst-header", children: [
|
|
98
|
+
/* @__PURE__ */ jsx("a", { className: "psst-brand", href: "/", children: siteName }),
|
|
99
|
+
nav.length > 0 ? /* @__PURE__ */ jsx("nav", { "aria-label": "Primary", children: nav.map((l, n) => /* @__PURE__ */ jsx("a", { ...linkProps(l.href), children: l.label }, n)) }) : null
|
|
100
|
+
] }),
|
|
101
|
+
children,
|
|
102
|
+
footer ? /* @__PURE__ */ jsx("footer", { className: "psst-footer", children: /* @__PURE__ */ jsx("p", { children: footer }) }) : null
|
|
103
|
+
] });
|
|
104
|
+
}
|
|
105
|
+
var PsstIntegrityError = class extends Error {
|
|
106
|
+
constructor(message) {
|
|
107
|
+
super(`psst: ${message}`);
|
|
108
|
+
this.name = "PsstIntegrityError";
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
async function resolvePath(config, fixed, props) {
|
|
112
|
+
if (fixed) return fixed;
|
|
113
|
+
const { slug } = await props.params;
|
|
114
|
+
if (!slug || slug.length === 0) notFound();
|
|
115
|
+
const path = `${config.prefix}/${slug.join("/")}`;
|
|
116
|
+
if (!sitePathSchema.safeParse(path).success) notFound();
|
|
117
|
+
return path;
|
|
118
|
+
}
|
|
119
|
+
async function fetchAtRender(config, path) {
|
|
120
|
+
try {
|
|
121
|
+
return await fetchPage(config, path);
|
|
122
|
+
} catch (err) {
|
|
123
|
+
if (err instanceof PsstUnavailableError && isBuildPhase()) {
|
|
124
|
+
console.warn(`${err.message}; ${path} will render at request time for this build`);
|
|
125
|
+
await connection();
|
|
126
|
+
}
|
|
127
|
+
throw err;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
async function load(config, fixed, props) {
|
|
131
|
+
const path = await resolvePath(config, fixed, props);
|
|
132
|
+
const result = await fetchAtRender(config, path);
|
|
133
|
+
if (result.status !== "ok") notFound();
|
|
134
|
+
const parsed = parsePageDocument(result.page.document, { domain: config.domain });
|
|
135
|
+
if (!parsed.success) throw new PsstIntegrityError(`document for ${path} failed the content contract`);
|
|
136
|
+
const hash = hashDocument(parsed.data);
|
|
137
|
+
if (hash !== result.page.hash) throw new PsstIntegrityError(`document hash mismatch for ${path}`);
|
|
138
|
+
return { path, doc: parsed.data, version: shortHash(hash) };
|
|
139
|
+
}
|
|
140
|
+
function psstPage(config, options = {}) {
|
|
141
|
+
const fixed = options.path;
|
|
142
|
+
if (fixed && !config.rootPaths.includes(fixed)) {
|
|
143
|
+
throw new PsstConfigError(`${fixed} is not in rootPaths; psst only serves root paths the dashboard claimed`);
|
|
144
|
+
}
|
|
145
|
+
const Shell = options.Shell;
|
|
146
|
+
async function Page(props) {
|
|
147
|
+
const { path, doc } = await load(config, fixed, props);
|
|
148
|
+
const main = /* @__PURE__ */ jsx(PsstMain, { doc, ctx: { siteName: config.siteName, domain: config.domain, canonicalPath: path } });
|
|
149
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
150
|
+
/* @__PURE__ */ jsx("link", { rel: "stylesheet", href: `${config.prefix}/_psst/style.css`, precedence: "psst" }),
|
|
151
|
+
Shell ? /* @__PURE__ */ jsx(Shell, { children: main }) : /* @__PURE__ */ jsx(DefaultShell, { siteName: config.siteName, nav: config.shell?.nav, footer: config.shell?.footer, children: main })
|
|
152
|
+
] });
|
|
153
|
+
}
|
|
154
|
+
async function generateMetadata(props) {
|
|
155
|
+
const { path, doc, version } = await load(config, fixed, props);
|
|
156
|
+
const canonical = `https://${config.domain}${path}`;
|
|
157
|
+
return {
|
|
158
|
+
title: { absolute: doc.title },
|
|
159
|
+
description: doc.description,
|
|
160
|
+
alternates: { canonical },
|
|
161
|
+
robots: { index: true, follow: true },
|
|
162
|
+
openGraph: {
|
|
163
|
+
type: doc.kind === "about" ? "website" : "article",
|
|
164
|
+
title: doc.title,
|
|
165
|
+
description: doc.description,
|
|
166
|
+
url: canonical,
|
|
167
|
+
siteName: config.siteName
|
|
168
|
+
},
|
|
169
|
+
twitter: { card: "summary", title: doc.title, description: doc.description },
|
|
170
|
+
other: { "psst-version": version }
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
async function generateStaticParams() {
|
|
174
|
+
if (fixed) return [];
|
|
175
|
+
try {
|
|
176
|
+
const manifest = await fetchManifest(config);
|
|
177
|
+
const base = `${config.prefix}/`;
|
|
178
|
+
return manifest.pages.filter((p) => p.kind !== "llms_txt" && p.path.startsWith(base) && p.path.length > base.length).map((p) => ({ slug: p.path.slice(base.length).split("/") }));
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if (err instanceof PsstUnavailableError || err instanceof ContentError) {
|
|
181
|
+
console.warn(`${err.message}; prerendering no psst pages, they render on first request`);
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
throw err;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return { default: Page, generateMetadata, generateStaticParams };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { PsstIntegrityError, psstPage };
|
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NextRequest, NextFetchEvent } from 'next/server';
|
|
2
|
+
import { a as PsstConfig } from './config-CoVgm6Ny.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
type ProxyResult = Response | null | undefined | void;
|
|
6
|
+
/** The shape of a Next proxy (`proxy.ts`, Next 16) or middleware (`middleware.ts`, Next 15) function. */
|
|
7
|
+
type PsstProxy = (request: NextRequest, event: NextFetchEvent) => ProxyResult | Promise<ProxyResult>;
|
|
8
|
+
/**
|
|
9
|
+
* Wrap the site's proxy. On every request: classify AI crawlers (by User-Agent, a claim not a proof) and AI
|
|
10
|
+
* referrers, and post a hit without awaiting it (`event.waitUntil`); no IP, cookie, query or UA string is sent.
|
|
11
|
+
* Withdrawn psst paths answer 410. Everything else goes to `proxy` unchanged, and its result is returned as is.
|
|
12
|
+
*/
|
|
13
|
+
declare function withPsst(config: PsstConfig, proxy?: PsstProxy): PsstProxy;
|
|
14
|
+
|
|
15
|
+
export { type PsstProxy, withPsst };
|
package/dist/proxy.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { USER_AGENT, fetchManifest } from './chunk-5X6OYLUN.js';
|
|
2
|
+
import { sitePathSchema, classifyUserAgent, classifyReferrer, hitRequestSchema, CONTENT_SCHEMA_VERSION } from './chunk-WHB66OTA.js';
|
|
3
|
+
|
|
4
|
+
// src/hits.ts
|
|
5
|
+
var AI_REFERRERS = /* @__PURE__ */ new Set(["chatgpt", "perplexity", "gemini", "copilot", "claude"]);
|
|
6
|
+
var ASSET = /\.(?:js|mjs|css|map|png|jpe?g|gif|webp|avif|svg|ico|woff2?|ttf|otf|mp4|webm)$/i;
|
|
7
|
+
function hitFor(config, request) {
|
|
8
|
+
if (request.method !== "GET" && request.method !== "HEAD") return null;
|
|
9
|
+
const h = request.headers;
|
|
10
|
+
if (h.get("x-psst-doctor") === "1") return null;
|
|
11
|
+
if (h.has("rsc") || h.has("next-router-prefetch") || h.get("purpose") === "prefetch" || h.get("sec-purpose")?.includes("prefetch")) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const path = request.nextUrl.pathname;
|
|
15
|
+
if (path.startsWith("/_next/") || ASSET.test(path)) return null;
|
|
16
|
+
if (!sitePathSchema.safeParse(path).success) return null;
|
|
17
|
+
const bot = classifyUserAgent(h.get("user-agent"));
|
|
18
|
+
const referrerClass = classifyReferrer(h.get("referer"));
|
|
19
|
+
if (bot.agent === null && !AI_REFERRERS.has(referrerClass)) return null;
|
|
20
|
+
const hit = hitRequestSchema.safeParse({
|
|
21
|
+
v: CONTENT_SCHEMA_VERSION,
|
|
22
|
+
publicId: config.site,
|
|
23
|
+
path,
|
|
24
|
+
agent: bot.agent,
|
|
25
|
+
agentClass: bot.agentClass,
|
|
26
|
+
referrerClass,
|
|
27
|
+
source: "proxy"
|
|
28
|
+
});
|
|
29
|
+
return hit.success ? hit.data : null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/proxy.ts
|
|
33
|
+
var HIT_TIMEOUT_MS = 300;
|
|
34
|
+
var MANIFEST_TTL_MS = 3e5;
|
|
35
|
+
var MANIFEST_TIMEOUT_MS = 2e3;
|
|
36
|
+
async function postHit(config, hit) {
|
|
37
|
+
try {
|
|
38
|
+
await fetch(`${config.edge}/v1/hits`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "content-type": "application/json", "user-agent": USER_AGENT },
|
|
41
|
+
body: JSON.stringify(hit),
|
|
42
|
+
signal: AbortSignal.timeout(HIT_TIMEOUT_MS)
|
|
43
|
+
});
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function withdrawnTracker(config) {
|
|
48
|
+
const state = { paths: /* @__PURE__ */ new Set(), fetchedAt: 0, refreshing: null };
|
|
49
|
+
return {
|
|
50
|
+
get: () => state.paths,
|
|
51
|
+
refreshIfStale(now) {
|
|
52
|
+
if (state.refreshing || now - state.fetchedAt < MANIFEST_TTL_MS) return null;
|
|
53
|
+
state.refreshing = fetchManifest(config, MANIFEST_TIMEOUT_MS).then((m) => {
|
|
54
|
+
state.paths = new Set(m.withdrawn);
|
|
55
|
+
state.fetchedAt = Date.now();
|
|
56
|
+
}).catch(() => {
|
|
57
|
+
state.fetchedAt = Date.now();
|
|
58
|
+
}).finally(() => {
|
|
59
|
+
state.refreshing = null;
|
|
60
|
+
});
|
|
61
|
+
return state.refreshing;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function isPsstPath(config, path) {
|
|
66
|
+
return path.startsWith(`${config.prefix}/`) || config.rootPaths.includes(path);
|
|
67
|
+
}
|
|
68
|
+
function gone() {
|
|
69
|
+
return new Response("Gone\n", {
|
|
70
|
+
status: 410,
|
|
71
|
+
headers: { "content-type": "text/plain; charset=utf-8", "cache-control": "public, max-age=0, s-maxage=300" }
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function withPsst(config, proxy) {
|
|
75
|
+
const withdrawn = withdrawnTracker(config);
|
|
76
|
+
return (request, event) => {
|
|
77
|
+
const hit = hitFor(config, request);
|
|
78
|
+
if (hit) event.waitUntil(postHit(config, hit));
|
|
79
|
+
const path = request.nextUrl.pathname;
|
|
80
|
+
if (isPsstPath(config, path)) {
|
|
81
|
+
const refresh = withdrawn.refreshIfStale(Date.now());
|
|
82
|
+
if (refresh) event.waitUntil(refresh);
|
|
83
|
+
if (withdrawn.get().has(path)) return gone();
|
|
84
|
+
}
|
|
85
|
+
return proxy ? proxy(request, event) : void 0;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { withPsst };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { a as PsstConfig } from './config-CoVgm6Ny.js';
|
|
2
|
+
export { P as PSST_REVALIDATE } from './config-CoVgm6Ny.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `GET` for `app/(psst){prefix}/sitemap.xml/route.ts`: the published HTML pages psst owns (the manifest already
|
|
7
|
+
* leaves withdrawn paths out), rendered with `renderSitemap` from `@psst/content`.
|
|
8
|
+
*/
|
|
9
|
+
declare function psstSitemap(config: PsstConfig): () => Promise<Response>;
|
|
10
|
+
|
|
11
|
+
export { psstSitemap };
|
package/dist/sitemap.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { psstRoute, textResponse } from './chunk-CKSLG42W.js';
|
|
2
|
+
export { PSST_REVALIDATE } from './chunk-4FFLVIJG.js';
|
|
3
|
+
import { fetchManifest, PsstUnavailableError } from './chunk-5X6OYLUN.js';
|
|
4
|
+
import { renderSitemap } from './chunk-WHB66OTA.js';
|
|
5
|
+
|
|
6
|
+
// src/sitemap.ts
|
|
7
|
+
function psstSitemap(config) {
|
|
8
|
+
return psstRoute(async () => {
|
|
9
|
+
const manifest = await fetchManifest(config);
|
|
10
|
+
if (manifest.site.domain !== config.domain) {
|
|
11
|
+
throw new PsstUnavailableError(`manifest domain ${manifest.site.domain} does not match psst.config domain ${config.domain}`);
|
|
12
|
+
}
|
|
13
|
+
const pages = manifest.pages.filter((p) => p.kind !== "llms_txt").map((p) => ({ path: p.path, title: p.title, updatedAt: p.updatedAt }));
|
|
14
|
+
const xml = renderSitemap({ siteName: config.siteName, domain: config.domain }, pages);
|
|
15
|
+
return textResponse(xml, "application/xml; charset=utf-8");
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { psstSitemap };
|
package/dist/style.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { a as PsstConfig } from './config-CoVgm6Ny.js';
|
|
2
|
+
export { P as PSST_REVALIDATE } from './config-CoVgm6Ny.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/** `GET` for `app/(psst){prefix}/_psst/style.css/route.ts`: the psst stylesheet, served same-origin. */
|
|
6
|
+
declare function psstStyle(config: PsstConfig): () => Promise<Response>;
|
|
7
|
+
|
|
8
|
+
export { psstStyle };
|
package/dist/style.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { edgeFileRoute } from './chunk-XCY5RUQM.js';
|
|
2
|
+
import './chunk-CKSLG42W.js';
|
|
3
|
+
export { PSST_REVALIDATE } from './chunk-4FFLVIJG.js';
|
|
4
|
+
import './chunk-5X6OYLUN.js';
|
|
5
|
+
import './chunk-WHB66OTA.js';
|
|
6
|
+
|
|
7
|
+
// src/style.ts
|
|
8
|
+
function psstStyle(config) {
|
|
9
|
+
return edgeFileRoute(config, { path: `${config.prefix}/_psst/style.css`, type: "text/css", maxBytes: 256 * 1024 });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { psstStyle };
|
package/dist/verify.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { a as PsstConfig } from './config-CoVgm6Ny.js';
|
|
2
|
+
export { P as PSST_REVALIDATE } from './config-CoVgm6Ny.js';
|
|
3
|
+
import 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `GET` for `app/(psst){prefix}/_psst/verify/route.ts`: the domain-proof text
|
|
7
|
+
* (`psst-site-verification: {publicId}.{proofNonce}`), copied from the edge so psst can check the site's own domain
|
|
8
|
+
* serves it.
|
|
9
|
+
*/
|
|
10
|
+
declare function psstVerify(config: PsstConfig): () => Promise<Response>;
|
|
11
|
+
|
|
12
|
+
export { psstVerify };
|
package/dist/verify.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { edgeFileRoute } from './chunk-XCY5RUQM.js';
|
|
2
|
+
import './chunk-CKSLG42W.js';
|
|
3
|
+
export { PSST_REVALIDATE } from './chunk-4FFLVIJG.js';
|
|
4
|
+
import './chunk-5X6OYLUN.js';
|
|
5
|
+
import './chunk-WHB66OTA.js';
|
|
6
|
+
|
|
7
|
+
// src/verify.ts
|
|
8
|
+
function psstVerify(config) {
|
|
9
|
+
return edgeFileRoute(config, {
|
|
10
|
+
path: `${config.prefix}/_psst/verify`,
|
|
11
|
+
type: "text/plain",
|
|
12
|
+
maxBytes: 1024,
|
|
13
|
+
accept: (body) => body.includes(`${config.site}.`)
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { psstVerify };
|
package/package.json
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saypsst/next",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Drop-in Next.js App Router route modules that serve psst pages on your own domain.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"README.md"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./page": {
|
|
18
|
+
"types": "./dist/page.d.ts",
|
|
19
|
+
"default": "./dist/page.js"
|
|
20
|
+
},
|
|
21
|
+
"./llms": {
|
|
22
|
+
"types": "./dist/llms.d.ts",
|
|
23
|
+
"default": "./dist/llms.js"
|
|
24
|
+
},
|
|
25
|
+
"./sitemap": {
|
|
26
|
+
"types": "./dist/sitemap.d.ts",
|
|
27
|
+
"default": "./dist/sitemap.js"
|
|
28
|
+
},
|
|
29
|
+
"./verify": {
|
|
30
|
+
"types": "./dist/verify.d.ts",
|
|
31
|
+
"default": "./dist/verify.js"
|
|
32
|
+
},
|
|
33
|
+
"./style": {
|
|
34
|
+
"types": "./dist/style.d.ts",
|
|
35
|
+
"default": "./dist/style.js"
|
|
36
|
+
},
|
|
37
|
+
"./proxy": {
|
|
38
|
+
"types": "./dist/proxy.d.ts",
|
|
39
|
+
"default": "./dist/proxy.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"lint": "eslint src test",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"build": "tsup && node scripts/check-dist.mjs"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public",
|
|
51
|
+
"provenance": true
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=20"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"next": ">=15 <17",
|
|
58
|
+
"react": ">=19"
|
|
59
|
+
},
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"zod": "4.6.7"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@psst/content": "workspace:*",
|
|
65
|
+
"@types/node": "20.19.43",
|
|
66
|
+
"@types/react": "19.3.0",
|
|
67
|
+
"@types/react-dom": "19.3.0",
|
|
68
|
+
"eslint": "^9",
|
|
69
|
+
"next": "16.4.3",
|
|
70
|
+
"react": "19.3.0",
|
|
71
|
+
"react-dom": "19.3.0",
|
|
72
|
+
"tsup": "8.5.1",
|
|
73
|
+
"typescript-eslint": "^8"
|
|
74
|
+
}
|
|
75
|
+
}
|