pagegraph 0.12.0 → 0.14.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 +325 -66
- package/dist/anthropic-messages-TqKpKmfW.js +1067 -0
- package/dist/anthropic-messages-TqKpKmfW.js.map +1 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +5 -5
- package/dist/audit.js.map +1 -1
- package/dist/azure-openai-responses-DJjBLwoI.js +231 -0
- package/dist/azure-openai-responses-DJjBLwoI.js.map +1 -0
- package/dist/build-only/audit.js +1 -1
- package/dist/build-only/claims.d.ts +1 -0
- package/dist/build-only/claims.js +6 -0
- package/dist/build-only/claims.js.map +1 -0
- package/dist/build-only/config.js +1 -1
- package/dist/build-only/oxlint.d.ts +1 -0
- package/dist/build-only/oxlint.js +6 -0
- package/dist/build-only/oxlint.js.map +1 -0
- package/dist/build-only/tanstack-start.js +1 -1
- package/dist/build-only/vite.js +1 -1
- package/dist/{checks-uZk5Em9A.js → checks-BS-aDXB_.js} +2 -2
- package/dist/checks-BS-aDXB_.js.map +1 -0
- package/dist/claims-Bch7Lxlo.d.ts +92 -0
- package/dist/claims-Bv7voeEV.js +431 -0
- package/dist/claims-Bv7voeEV.js.map +1 -0
- package/dist/claims.d.ts +94 -0
- package/dist/claims.js +2 -0
- package/dist/cli.js +17607 -43387
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js +41 -0
- package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js.map +1 -0
- package/dist/config.d.ts +9 -29
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/{content-kcEnQdfi.js → content-CHd0X4s6.js} +2 -2
- package/dist/{content-kcEnQdfi.js.map → content-CHd0X4s6.js.map} +1 -1
- package/dist/{content-B1cPtL8b.d.ts → content-DgNr7apS.d.ts} +4 -5
- package/dist/declare-D5o7hwmv.js.map +1 -1
- package/dist/diagnostics-Wt5faNDM.js +108 -0
- package/dist/diagnostics-Wt5faNDM.js.map +1 -0
- package/dist/dist-B6zg_Z3Z.js +4794 -0
- package/dist/dist-B6zg_Z3Z.js.map +1 -0
- package/dist/document-CztEu3Vd.d.ts +109 -0
- package/dist/document-Dvemcv7V.js +379 -0
- package/dist/document-Dvemcv7V.js.map +1 -0
- package/dist/env-api-keys-C-OA0yM-.js +124 -0
- package/dist/env-api-keys-C-OA0yM-.js.map +1 -0
- package/dist/error-body-CyiejW4b.js +103 -0
- package/dist/error-body-CyiejW4b.js.map +1 -0
- package/dist/facts-1OKclPOk.js +115 -0
- package/dist/facts-1OKclPOk.js.map +1 -0
- package/dist/github-copilot-headers-CEpMOpQF.js +24 -0
- package/dist/github-copilot-headers-CEpMOpQF.js.map +1 -0
- package/dist/google-generative-ai-BxABKIKO.js +330 -0
- package/dist/google-generative-ai-BxABKIKO.js.map +1 -0
- package/dist/google-shared-0gpM2jFi.js +19471 -0
- package/dist/google-shared-0gpM2jFi.js.map +1 -0
- package/dist/google-vertex-D8Eb5cbu.js +376 -0
- package/dist/google-vertex-D8Eb5cbu.js.map +1 -0
- package/dist/{declare-DVgdEdOL.d.ts → graph-D1PIndsC.d.ts} +117 -6
- package/dist/{graph-Bcsourlv.js → graph-DMNOLXLu.js} +23 -13
- package/dist/graph-DMNOLXLu.js.map +1 -0
- package/dist/hash-Dp7EzZUo.js +18 -0
- package/dist/hash-Dp7EzZUo.js.map +1 -0
- package/dist/headers-BRNMVpzu.js +19 -0
- package/dist/headers-BRNMVpzu.js.map +1 -0
- package/dist/index-C5w9ripz.d.ts +204 -0
- package/dist/index.d.ts +6 -160
- package/dist/index.js +37 -5
- package/dist/index.js.map +1 -1
- package/dist/inline-BbS93GAT.js +682 -0
- package/dist/inline-BbS93GAT.js.map +1 -0
- package/dist/json-parse-C10znB7l.js +383 -0
- package/dist/json-parse-C10znB7l.js.map +1 -0
- package/dist/llms-Dhr_5u2O.js +19 -0
- package/dist/llms-Dhr_5u2O.js.map +1 -0
- package/dist/markdown-C6dRE9zD.js +168 -0
- package/dist/markdown-C6dRE9zD.js.map +1 -0
- package/dist/markdown-path-lJB9BAVZ.js +6 -0
- package/dist/markdown-path-lJB9BAVZ.js.map +1 -0
- package/dist/{message-DT_CjUdt.js → message-CuBjgZ74.js} +2 -2
- package/dist/{message-DT_CjUdt.js.map → message-CuBjgZ74.js.map} +1 -1
- package/dist/mistral-conversations-CvaqBWjR.js +690 -0
- package/dist/mistral-conversations-CvaqBWjR.js.map +1 -0
- package/dist/models-DcT5qOEL.js +1203 -0
- package/dist/models-DcT5qOEL.js.map +1 -0
- package/dist/node-Ccvru9GE.js +26 -0
- package/dist/node-Ccvru9GE.js.map +1 -0
- package/dist/node-MEosBOF2.js +2403 -0
- package/dist/node-MEosBOF2.js.map +1 -0
- package/dist/openai-BCBEd2eO.js +17350 -0
- package/dist/openai-BCBEd2eO.js.map +1 -0
- package/dist/openai-codex-responses-vJqxeeRC.js +1268 -0
- package/dist/openai-codex-responses-vJqxeeRC.js.map +1 -0
- package/dist/openai-completions-Cb_fRAbI.js +989 -0
- package/dist/openai-completions-Cb_fRAbI.js.map +1 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js +10 -0
- package/dist/openai-prompt-cache-Bc6qNWt0.js.map +1 -0
- package/dist/openai-responses-sDuh82G5.js +268 -0
- package/dist/openai-responses-sDuh82G5.js.map +1 -0
- package/dist/openai-responses-shared-mhuo1Jov.js +599 -0
- package/dist/openai-responses-shared-mhuo1Jov.js.map +1 -0
- package/dist/openrouter-images-CRmBkzpX.js +127 -0
- package/dist/openrouter-images-CRmBkzpX.js.map +1 -0
- package/dist/oxlint.d.ts +58 -0
- package/dist/oxlint.js +202 -0
- package/dist/oxlint.js.map +1 -0
- package/dist/page-heads-BfjWQvau.d.ts +108 -0
- package/dist/{page-heads-6y-CARRQ.js → page-heads-BgbaIjj9.js} +3 -3
- package/dist/page-heads-BgbaIjj9.js.map +1 -0
- package/dist/pi-Bvw6J0gh.js +56795 -0
- package/dist/pi-Bvw6J0gh.js.map +1 -0
- package/dist/pi-messages-CejiVYvO.js +308 -0
- package/dist/pi-messages-CejiVYvO.js.map +1 -0
- package/dist/{projections-DeEFe7XT.d.ts → projections-Bk-qOOsR.d.ts} +2 -2
- package/dist/provider-env-t38GK5FF.js +39 -0
- package/dist/provider-env-t38GK5FF.js.map +1 -0
- package/dist/provider-retry-DzKoh1X7.js +80 -0
- package/dist/provider-retry-DzKoh1X7.js.map +1 -0
- package/dist/react.d.ts +3 -2
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -1
- package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
- package/dist/sanitize-unicode-Ds14l9Om.js +28 -0
- package/dist/sanitize-unicode-Ds14l9Om.js.map +1 -0
- package/dist/sdk-C9_wiO6w.js +12503 -0
- package/dist/sdk-C9_wiO6w.js.map +1 -0
- package/dist/state-BuJP_3Lr.js +28102 -0
- package/dist/state-BuJP_3Lr.js.map +1 -0
- package/dist/system-one-shared-Dl10ZF7Z.js +167 -0
- package/dist/system-one-shared-Dl10ZF7Z.js.map +1 -0
- package/dist/tanstack-start/index.d.ts +29 -13
- package/dist/tanstack-start/index.js +391 -42
- package/dist/tanstack-start/index.js.map +1 -1
- package/dist/tanstack-start/markdown.d.ts +12 -0
- package/dist/tanstack-start/markdown.js +149 -0
- package/dist/tanstack-start/markdown.js.map +1 -0
- package/dist/tanstack-start/prerender-worker.d.ts +2 -0
- package/dist/tanstack-start/prerender-worker.js +7 -0
- package/dist/tanstack-start/prerender-worker.js.map +1 -0
- package/dist/tanstack-start/react.d.ts +7 -0
- package/dist/tanstack-start/react.js +12 -0
- package/dist/tanstack-start/react.js.map +1 -0
- package/dist/tanstack-start/server.d.ts +9 -3
- package/dist/tanstack-start/server.js +26 -2
- package/dist/tanstack-start/server.js.map +1 -1
- package/dist/transform-messages-BLJ8EfK6.js +468 -0
- package/dist/transform-messages-BLJ8EfK6.js.map +1 -0
- package/dist/typesafe-system-one-CwEWMV8P.js +25 -0
- package/dist/typesafe-system-one-CwEWMV8P.js.map +1 -0
- package/dist/{vite-graph-loader-01p1WxEq.js → vite-graph-loader-CsGiYNWE.js} +6 -5
- package/dist/vite-graph-loader-CsGiYNWE.js.map +1 -0
- package/dist/vite-graph-loader-DZCwejuJ.d.ts +133 -0
- package/package.json +47 -10
- package/dist/checks-uZk5Em9A.js.map +0 -1
- package/dist/graph-Bcsourlv.js.map +0 -1
- package/dist/graph-BxCY90vq.d.ts +0 -104
- package/dist/graph-CBIY71w6.d.ts +0 -57
- package/dist/page-heads-6y-CARRQ.js.map +0 -1
- package/dist/page-heads-DNkjMUEN.d.ts +0 -21
- package/dist/vite-graph-loader-01p1WxEq.js.map +0 -1
- package/dist/vite-graph-loader-Btgjz5RH.d.ts +0 -56
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { t as buildSeoGraph } from "../graph-
|
|
1
|
+
import { t as buildSeoGraph } from "../graph-DMNOLXLu.js";
|
|
2
2
|
import { n as graphToJson } from "../wire-B4RQMc4e.js";
|
|
3
|
-
import { a as globToRegExp } from "../checks-
|
|
3
|
+
import { a as globToRegExp } from "../checks-BS-aDXB_.js";
|
|
4
|
+
import { o as hashDocument } from "../inline-BbS93GAT.js";
|
|
5
|
+
import { t as decodeFacts } from "../facts-1OKclPOk.js";
|
|
6
|
+
import { n as documentMarkdown } from "../markdown-C6dRE9zD.js";
|
|
4
7
|
import { i as seoRouteConfig, n as inMemoryWriteFs, r as resolveOptions, t as deriveRouteConfig } from "../route-config-35ZEzkNC.js";
|
|
5
|
-
import { n as withCleanStdout } from "../vite-graph-loader-
|
|
6
|
-
import {
|
|
8
|
+
import { n as withCleanStdout } from "../vite-graph-loader-CsGiYNWE.js";
|
|
9
|
+
import { r as replayClaims } from "../claims-Bv7voeEV.js";
|
|
10
|
+
import { t as MARKDOWN_CAPTURE_PATH } from "../markdown-path-lJB9BAVZ.js";
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
import { mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
|
13
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
7
14
|
import { Generator, getConfig } from "@tanstack/router-generator";
|
|
8
|
-
import { createRunnableDevEnvironment, resolveConfig } from "vite";
|
|
15
|
+
import { createRunnableDevEnvironment, parseAst, resolveConfig } from "vite";
|
|
16
|
+
import * as Effect from "effect/Effect";
|
|
17
|
+
import * as Schema from "effect/Schema";
|
|
9
18
|
import { pathToFileURL } from "node:url";
|
|
10
19
|
//#region src/tanstack-start/routes.ts
|
|
11
20
|
/**
|
|
@@ -60,7 +69,12 @@ const messageOf = (cause) => cause instanceof Error ? cause.message : String(cau
|
|
|
60
69
|
const routeStaticData = (module, file) => {
|
|
61
70
|
const route = module["Route"];
|
|
62
71
|
if (route?.options === void 0) throw new Error(`${file} has no \`Route\` export`);
|
|
63
|
-
|
|
72
|
+
const data = route.options.staticData;
|
|
73
|
+
return data === void 0 ? void 0 : {
|
|
74
|
+
seo: data.seo,
|
|
75
|
+
markdown: data.markdown,
|
|
76
|
+
llms: data.llms
|
|
77
|
+
};
|
|
64
78
|
};
|
|
65
79
|
const loadCollections = async (runner, root, fullPath) => {
|
|
66
80
|
const path = relative(root, fullPath);
|
|
@@ -82,7 +96,8 @@ async function planGraph(root, options) {
|
|
|
82
96
|
options,
|
|
83
97
|
scan,
|
|
84
98
|
routeFiles: [scan.root, ...scan.nodes].filter(participates).map((node) => node.fullPath),
|
|
85
|
-
collectionsFile: options.collections === void 0 ? void 0 : resolve(root, options.collections)
|
|
99
|
+
collectionsFile: options.collections === void 0 ? void 0 : resolve(root, options.collections),
|
|
100
|
+
factsFile: options.facts === void 0 ? void 0 : resolve(root, options.facts)
|
|
86
101
|
};
|
|
87
102
|
}
|
|
88
103
|
/**
|
|
@@ -121,18 +136,269 @@ async function evaluateGraph(runner, plan) {
|
|
|
121
136
|
...options.routeConfig,
|
|
122
137
|
routesDirectory: options.routesDirectory
|
|
123
138
|
})).robotsExclusions;
|
|
139
|
+
const site = {
|
|
140
|
+
origin: options.origin,
|
|
141
|
+
indexable: options.indexable ?? true,
|
|
142
|
+
robots: {
|
|
143
|
+
disallow: [.../* @__PURE__ */ new Set([...exclusions, ...options.robots?.disallow ?? []])].sort(),
|
|
144
|
+
contentSignal: options.robots?.contentSignal,
|
|
145
|
+
directives: options.robots?.directives
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
let facts;
|
|
149
|
+
if (plan.factsFile !== void 0) {
|
|
150
|
+
const path = relative(root, plan.factsFile);
|
|
151
|
+
try {
|
|
152
|
+
const module = await runner.import(plan.factsFile);
|
|
153
|
+
if (module["facts"] === void 0) throw new Error(`${path} has no \`facts\` export`);
|
|
154
|
+
facts = decodeFacts(module["facts"]);
|
|
155
|
+
} catch (cause) {
|
|
156
|
+
throw new Error(`pagegraph could not evaluate ${path}: ${messageOf(cause)}`, { cause });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
124
159
|
return {
|
|
125
160
|
graph,
|
|
126
|
-
site
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
161
|
+
site,
|
|
162
|
+
markdown: options.markdown === void 0 ? null : { origin: options.markdown.origin },
|
|
163
|
+
facts
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/markdown/schema.ts
|
|
168
|
+
const InlineNode = Schema.suspend(() => Schema.Union([
|
|
169
|
+
Schema.String,
|
|
170
|
+
Schema.Struct({
|
|
171
|
+
fact: Schema.String,
|
|
172
|
+
text: Schema.String
|
|
173
|
+
}),
|
|
174
|
+
Schema.Struct({
|
|
175
|
+
tag: Schema.Literals([
|
|
176
|
+
"em",
|
|
177
|
+
"strong",
|
|
178
|
+
"a",
|
|
179
|
+
"code",
|
|
180
|
+
"br"
|
|
181
|
+
]),
|
|
182
|
+
href: Schema.optionalKey(Schema.String),
|
|
183
|
+
children: Schema.Array(InlineNode)
|
|
184
|
+
})
|
|
185
|
+
]));
|
|
186
|
+
const Message = Schema.Struct({
|
|
187
|
+
hash: Schema.String,
|
|
188
|
+
tree: Schema.Array(InlineNode),
|
|
189
|
+
text: Schema.String,
|
|
190
|
+
source: Schema.String,
|
|
191
|
+
facts: Schema.Array(Schema.String),
|
|
192
|
+
audience: Schema.Literals([
|
|
193
|
+
"all",
|
|
194
|
+
"agents",
|
|
195
|
+
"humans"
|
|
196
|
+
])
|
|
197
|
+
});
|
|
198
|
+
const BodyEntry = Schema.Union([Schema.Struct({
|
|
199
|
+
type: Schema.Literal("message"),
|
|
200
|
+
message: Message
|
|
201
|
+
}), Schema.Struct({
|
|
202
|
+
type: Schema.Literal("visual"),
|
|
203
|
+
text: Schema.String,
|
|
204
|
+
source: Schema.String,
|
|
205
|
+
audience: Schema.Literals([
|
|
206
|
+
"all",
|
|
207
|
+
"agents",
|
|
208
|
+
"humans"
|
|
209
|
+
])
|
|
210
|
+
})]);
|
|
211
|
+
const PageDocument = Schema.Struct({
|
|
212
|
+
path: Schema.String,
|
|
213
|
+
hash: Schema.String,
|
|
214
|
+
title: Schema.String,
|
|
215
|
+
description: Schema.String,
|
|
216
|
+
sections: Schema.Array(Schema.Struct({
|
|
217
|
+
claimsMarkdown: Schema.optionalKey(Schema.String),
|
|
218
|
+
evidence: Schema.optionalKey(Schema.Boolean),
|
|
219
|
+
kind: Schema.String,
|
|
220
|
+
id: Schema.String,
|
|
221
|
+
title: Schema.optionalKey(Message),
|
|
222
|
+
language: Schema.optionalKey(Schema.String),
|
|
223
|
+
body: Schema.Array(BodyEntry),
|
|
224
|
+
items: Schema.Array(Schema.Struct({
|
|
225
|
+
title: Schema.optionalKey(Message),
|
|
226
|
+
href: Schema.optionalKey(Schema.String),
|
|
227
|
+
body: Schema.Array(BodyEntry),
|
|
228
|
+
cells: Schema.Array(Message),
|
|
229
|
+
source: Schema.String,
|
|
230
|
+
audience: Schema.Literals([
|
|
231
|
+
"all",
|
|
232
|
+
"agents",
|
|
233
|
+
"humans"
|
|
234
|
+
])
|
|
235
|
+
})),
|
|
236
|
+
source: Schema.String,
|
|
237
|
+
audience: Schema.Literals([
|
|
238
|
+
"all",
|
|
239
|
+
"agents",
|
|
240
|
+
"humans"
|
|
241
|
+
])
|
|
242
|
+
})),
|
|
243
|
+
messages: Schema.Array(Message),
|
|
244
|
+
facts: Schema.Array(Schema.String)
|
|
245
|
+
});
|
|
246
|
+
const CaptureBundle = Schema.Struct({
|
|
247
|
+
origin: Schema.String,
|
|
248
|
+
documents: Schema.Array(PageDocument),
|
|
249
|
+
heads: Schema.Array(Schema.Struct({
|
|
250
|
+
path: Schema.String,
|
|
251
|
+
title: Schema.String,
|
|
252
|
+
description: Schema.String
|
|
253
|
+
}))
|
|
254
|
+
});
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/tanstack-start/persist-markdown.ts
|
|
257
|
+
/** File names must remain inside the package's capture and the client's output trees. */
|
|
258
|
+
function documentName(path) {
|
|
259
|
+
if (!path.startsWith("/") || path.startsWith("//") || /[?#\\$\u0000-\u001f\u007f]/.test(path) || path !== "/" && path.endsWith("/") || path.slice(1).split("/").some((part) => part === "." || part === ".." || part === "*" || part === "" && path !== "/")) throw new Error(`Invalid captured document path "${path}"`);
|
|
260
|
+
return path === "/" ? "index" : path.slice(1);
|
|
261
|
+
}
|
|
262
|
+
function verifyDocument(document) {
|
|
263
|
+
const name = documentName(document.path);
|
|
264
|
+
const { hash, ...content } = document;
|
|
265
|
+
if (!/^[0-9a-f]{64}$/.test(hash) || hashDocument(content) !== hash) throw new Error(`Invalid captured document hash for "${document.path}"`);
|
|
266
|
+
return name;
|
|
267
|
+
}
|
|
268
|
+
/** Only valid captures at their derived paths belong to pagegraph; preserve unrelated files. */
|
|
269
|
+
async function pruneDocuments(directory, paths) {
|
|
270
|
+
const visit = async (folder) => {
|
|
271
|
+
const entries = await readdir(folder, { withFileTypes: true });
|
|
272
|
+
for (const entry of entries) {
|
|
273
|
+
const file = resolve(folder, entry.name);
|
|
274
|
+
if (entry.isDirectory()) {
|
|
275
|
+
await visit(file);
|
|
276
|
+
continue;
|
|
133
277
|
}
|
|
278
|
+
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
279
|
+
const contents = await readFile(file, "utf8");
|
|
280
|
+
let document;
|
|
281
|
+
let name;
|
|
282
|
+
try {
|
|
283
|
+
document = Schema.decodeUnknownSync(Schema.fromJsonString(PageDocument))(contents, { onExcessProperty: "error" });
|
|
284
|
+
name = verifyDocument(document);
|
|
285
|
+
} catch {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
if (file === resolve(directory, `${name}.json`) && !paths.has(document.path)) await unlink(file);
|
|
134
289
|
}
|
|
135
290
|
};
|
|
291
|
+
await visit(directory);
|
|
292
|
+
}
|
|
293
|
+
/** Documents, twins, and graph heads are persisted before prerender onSuccess returns. */
|
|
294
|
+
async function persistMarkdownCapture(html, root, clientOutDir, claims, facts = {}) {
|
|
295
|
+
const bundle = Schema.decodeUnknownSync(Schema.fromJsonString(CaptureBundle))(html, { onExcessProperty: "error" });
|
|
296
|
+
const origin = new URL(bundle.origin);
|
|
297
|
+
if (origin.protocol !== "https:" && origin.protocol !== "http:" || origin.origin !== bundle.origin) throw new Error(`Invalid captured markdown origin "${bundle.origin}"`);
|
|
298
|
+
const active = /* @__PURE__ */ new Set();
|
|
299
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
300
|
+
const names = bundle.documents.map((document) => {
|
|
301
|
+
if (active.has(document.path)) throw new Error(`Duplicate captured document path "${document.path}"`);
|
|
302
|
+
active.add(document.path);
|
|
303
|
+
const name = verifyDocument(document);
|
|
304
|
+
if (destinations.has(name)) throw new Error(`Captured document paths share the output name "${name}"`);
|
|
305
|
+
destinations.add(name);
|
|
306
|
+
return name;
|
|
307
|
+
});
|
|
308
|
+
await unlink(resolve(clientOutDir, MARKDOWN_CAPTURE_PATH.slice(1)));
|
|
309
|
+
const directory = resolve(root, ".pagegraph/documents");
|
|
310
|
+
await mkdir(directory, { recursive: true });
|
|
311
|
+
for (const [index, document] of bundle.documents.entries()) {
|
|
312
|
+
const name = names[index];
|
|
313
|
+
const destination = resolve(directory, `${name}.json`);
|
|
314
|
+
const twin = resolve(clientOutDir, `${name}.md`);
|
|
315
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
316
|
+
await writeFile(destination, JSON.stringify(document));
|
|
317
|
+
await mkdir(dirname(twin), { recursive: true });
|
|
318
|
+
await writeFile(twin, documentMarkdown(document, bundle.origin));
|
|
319
|
+
}
|
|
320
|
+
await pruneDocuments(directory, active);
|
|
321
|
+
await writeFile(resolve(root, ".pagegraph/heads.json"), `${JSON.stringify(bundle.heads)}\n`);
|
|
322
|
+
if (claims !== void 0) await Effect.runPromise(replayClaims(root, bundle.documents, bundle.heads, facts, claims));
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/tanstack-start/source.ts
|
|
326
|
+
var DocumentSourceError = class extends Schema.TaggedError()("DocumentSourceError", { message: Schema.String }) {};
|
|
327
|
+
const SOURCE_COMPONENTS = /* @__PURE__ */ new Set([
|
|
328
|
+
"T",
|
|
329
|
+
"Title",
|
|
330
|
+
"Section",
|
|
331
|
+
"Visual",
|
|
332
|
+
"ForAgents",
|
|
333
|
+
"ForHumans"
|
|
334
|
+
]);
|
|
335
|
+
const parse = Effect.fn("DocumentSource.parse")(function* (code, id) {
|
|
336
|
+
return yield* Effect.try({
|
|
337
|
+
try: () => parseAst(code, { lang: id.endsWith(".tsx") ? "tsx" : id.endsWith(".ts") ? "ts" : id.endsWith(".jsx") ? "jsx" : "js" }, id),
|
|
338
|
+
catch: (cause) => new DocumentSourceError({ message: `Cannot parse document source ${id}: ${cause instanceof Error ? cause.message : String(cause)}` })
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
function componentNames(program) {
|
|
342
|
+
const named = /* @__PURE__ */ new Set();
|
|
343
|
+
const sections = /* @__PURE__ */ new Set();
|
|
344
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
345
|
+
for (const node of program.body) {
|
|
346
|
+
if (node.type !== "ImportDeclaration" || node.source.value !== "pagegraph/react" || node.importKind === "type") continue;
|
|
347
|
+
for (const specifier of node.specifiers) if (specifier.type === "ImportSpecifier") {
|
|
348
|
+
if (specifier.importKind === "type") continue;
|
|
349
|
+
const imported = specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
|
|
350
|
+
if (SOURCE_COMPONENTS.has(imported)) named.add(specifier.local.name);
|
|
351
|
+
if (imported === "Section") sections.add(specifier.local.name);
|
|
352
|
+
} else if (specifier.type === "ImportNamespaceSpecifier") namespaces.add(specifier.local.name);
|
|
353
|
+
}
|
|
354
|
+
return {
|
|
355
|
+
named,
|
|
356
|
+
sections,
|
|
357
|
+
namespaces
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function memberParts(name) {
|
|
361
|
+
if (name.type === "JSXIdentifier") return [name.name];
|
|
362
|
+
if (name.type !== "JSXMemberExpression") return [];
|
|
363
|
+
return [...memberParts(name.object), name.property.name];
|
|
364
|
+
}
|
|
365
|
+
function isSourceComponent(name, names) {
|
|
366
|
+
const [base, ...members] = memberParts(name);
|
|
367
|
+
if (base === void 0) return false;
|
|
368
|
+
if (members.length === 0) return names.named.has(base);
|
|
369
|
+
if (names.namespaces.has(base)) return members.length === 1 && members[0] !== void 0 && SOURCE_COMPONENTS.has(members[0]) || members.length === 2 && members[0] === "Section" && members[1] === "Item";
|
|
370
|
+
return names.sections.has(base) && members.length === 1 && members[0] === "Item";
|
|
371
|
+
}
|
|
372
|
+
function walk(value, visit) {
|
|
373
|
+
if (Array.isArray(value)) for (const child of value) walk(child, visit);
|
|
374
|
+
else if (typeof value === "object" && value !== null) {
|
|
375
|
+
if (isOpeningElement(value)) visit(value);
|
|
376
|
+
for (const child of Object.values(value)) walk(child, visit);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function isOpeningElement(node) {
|
|
380
|
+
return "type" in node && node.type === "JSXOpeningElement";
|
|
381
|
+
}
|
|
382
|
+
function transformDocumentSource(code, id, root) {
|
|
383
|
+
const program = Effect.runSync(parse(code, id));
|
|
384
|
+
const names = componentNames(program);
|
|
385
|
+
const edits = [];
|
|
386
|
+
const file = relative(resolve(root), resolve(id)).split(sep).join("/");
|
|
387
|
+
walk(program, (node) => {
|
|
388
|
+
if (!isSourceComponent(node.name, names)) return;
|
|
389
|
+
if (node.attributes.some((attribute) => attribute.type === "JSXAttribute" && attribute.name.type === "JSXIdentifier" && attribute.name.name === "source")) return;
|
|
390
|
+
const line = code.slice(0, node.start).split("\n").length;
|
|
391
|
+
edits.push({
|
|
392
|
+
start: node.name.end,
|
|
393
|
+
end: node.name.end,
|
|
394
|
+
value: ` source=${JSON.stringify(`${file}:${line}`)}`
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
if (edits.length === 0) return void 0;
|
|
398
|
+
edits.sort((a, b) => b.start - a.start);
|
|
399
|
+
let transformed = code;
|
|
400
|
+
for (const edit of edits) transformed = transformed.slice(0, edit.start) + edit.value + transformed.slice(edit.end);
|
|
401
|
+
return { code: transformed };
|
|
136
402
|
}
|
|
137
403
|
//#endregion
|
|
138
404
|
//#region src/tanstack-start/plugin.ts
|
|
@@ -164,7 +430,11 @@ const RESOLVED_RUNTIME_ID = `\0virtual:pagegraph/runtime`;
|
|
|
164
430
|
const ENTRY_ID = "virtual:pagegraph/entry";
|
|
165
431
|
const RESOLVED_ENTRY_ID = `\0${ENTRY_ID}`;
|
|
166
432
|
/** The runtime entry imports the virtual module, so dep pre-bundling must leave it to this plugin. */
|
|
167
|
-
const
|
|
433
|
+
const RUNTIME_ENTRIES = [
|
|
434
|
+
"pagegraph/tanstack-start/server",
|
|
435
|
+
"pagegraph/tanstack-start/markdown",
|
|
436
|
+
"pagegraph/tanstack-start/react"
|
|
437
|
+
];
|
|
168
438
|
/** Where a build writes the graph environment's output, relative to the Vite root. */
|
|
169
439
|
const BUILD_DIRECTORY = "node_modules/.cache/pagegraph/build";
|
|
170
440
|
const runtimeModulesPlugin = {
|
|
@@ -179,10 +449,14 @@ const runtimeModulesPlugin = {
|
|
|
179
449
|
})
|
|
180
450
|
}
|
|
181
451
|
};
|
|
182
|
-
const runtimeModule = ({ graph, site }) => `export const graph = ${JSON.stringify(graphToJson(graph))};\nexport const site = ${JSON.stringify(site)};\n`;
|
|
452
|
+
const runtimeModule = ({ graph, site, markdown, facts }) => `export const graph = ${JSON.stringify(graphToJson(graph))};\nexport const site = ${JSON.stringify(site)};\nexport const markdown = ${JSON.stringify(markdown)};\nexport const facts = ${JSON.stringify(facts) ?? "undefined"};\n`;
|
|
183
453
|
/** The graph environment's build entry: a loader per module the plan evaluates. */
|
|
184
454
|
const entryModule = (plan) => {
|
|
185
|
-
return `export const modules = {\n${[
|
|
455
|
+
return `export const modules = {\n${[
|
|
456
|
+
...plan.routeFiles,
|
|
457
|
+
...plan.collectionsFile === void 0 ? [] : [plan.collectionsFile],
|
|
458
|
+
...plan.factsFile === void 0 ? [] : [plan.factsFile]
|
|
459
|
+
].map((file) => ` ${JSON.stringify(file)}: () => import(${JSON.stringify(file)}),`).join("\n")}\n};\n`;
|
|
186
460
|
};
|
|
187
461
|
/** Build the graph environment with the build's config, import its output, and evaluate. */
|
|
188
462
|
const buildGraph = async (builder, environment, plan) => {
|
|
@@ -196,8 +470,10 @@ const buildGraph = async (builder, environment, plan) => {
|
|
|
196
470
|
} }, plan);
|
|
197
471
|
};
|
|
198
472
|
function pagegraph(options) {
|
|
473
|
+
if (options.claims !== void 0 && options.markdown === void 0) throw new Error("Claims require pagegraph({ markdown: { origin }, claims: { rules, model } }) so the build captures documents.");
|
|
199
474
|
const api = { options };
|
|
200
|
-
let root =
|
|
475
|
+
let root = process.cwd();
|
|
476
|
+
let clientOutDir = resolve(root, "dist/client");
|
|
201
477
|
let server;
|
|
202
478
|
let devEnvironment;
|
|
203
479
|
/** The plan the graph environment's build entry is generated from. */
|
|
@@ -213,7 +489,7 @@ function pagegraph(options) {
|
|
|
213
489
|
if (started === generation) return result;
|
|
214
490
|
}
|
|
215
491
|
};
|
|
216
|
-
return [
|
|
492
|
+
return Object.assign([
|
|
217
493
|
{
|
|
218
494
|
name: PLUGIN_NAME,
|
|
219
495
|
api,
|
|
@@ -244,14 +520,18 @@ function pagegraph(options) {
|
|
|
244
520
|
return;
|
|
245
521
|
}
|
|
246
522
|
environmentConfig.optimizeDeps ??= {};
|
|
247
|
-
environmentConfig.optimizeDeps.exclude = [...environmentConfig.optimizeDeps.exclude ?? [],
|
|
523
|
+
environmentConfig.optimizeDeps.exclude = [...environmentConfig.optimizeDeps.exclude ?? [], ...RUNTIME_ENTRIES];
|
|
248
524
|
},
|
|
249
525
|
configResolved(resolved) {
|
|
250
526
|
root = resolved.root;
|
|
527
|
+
clientOutDir = resolve(root, resolved.environments.client?.build.outDir ?? "dist/client");
|
|
251
528
|
},
|
|
252
|
-
configureServer
|
|
253
|
-
|
|
254
|
-
|
|
529
|
+
configureServer: {
|
|
530
|
+
order: "pre",
|
|
531
|
+
handler(devServer) {
|
|
532
|
+
server = devServer;
|
|
533
|
+
devEnvironment = devServer.environments[GRAPH_ENVIRONMENT$1];
|
|
534
|
+
}
|
|
255
535
|
},
|
|
256
536
|
hotUpdate({ file, modules }) {
|
|
257
537
|
if (this.environment.name !== "pagegraph") return;
|
|
@@ -288,7 +568,7 @@ function pagegraph(options) {
|
|
|
288
568
|
if (buildPlan === void 0) throw new Error(`[${PLUGIN_NAME}] ${ENTRY_ID} is only built by the pagegraph buildApp hook`);
|
|
289
569
|
return entryModule(buildPlan);
|
|
290
570
|
}
|
|
291
|
-
if (this.environment.name === "pagegraph") return "export const graph = null;\nexport const site = null;\n";
|
|
571
|
+
if (this.environment.name === "pagegraph") return "export const graph = null;\nexport const site = null;\nexport const markdown = null;\nexport const facts = undefined;\n";
|
|
292
572
|
if (current === void 0) {
|
|
293
573
|
if (devEnvironment === void 0) throw new Error(`[${PLUGIN_NAME}] the graph was not built before ${this.environment.name} imported it; build with Vite's app builder (\`vite build\`).`);
|
|
294
574
|
current = evaluateInDev(devEnvironment);
|
|
@@ -297,68 +577,137 @@ function pagegraph(options) {
|
|
|
297
577
|
}
|
|
298
578
|
}
|
|
299
579
|
},
|
|
580
|
+
{
|
|
581
|
+
name: "pagegraph:markdown",
|
|
582
|
+
enforce: "pre",
|
|
583
|
+
applyToEnvironment: (environment) => environment.name !== GRAPH_ENVIRONMENT$1,
|
|
584
|
+
resolveId: {
|
|
585
|
+
filter: { id: /^virtual:pagegraph\/prerender-server$/ },
|
|
586
|
+
handler: (id) => `\0${id}`
|
|
587
|
+
},
|
|
588
|
+
load: {
|
|
589
|
+
filter: { id: /^\0virtual:pagegraph\/prerender-server$/ },
|
|
590
|
+
handler: () => `export { default } from ${JSON.stringify(resolve(root, options.markdown?.serverEntry ?? "dist/server/index.js"))};`
|
|
591
|
+
},
|
|
592
|
+
transform: {
|
|
593
|
+
filter: {
|
|
594
|
+
id: /\.[jt]sx?(\?|$)/,
|
|
595
|
+
code: /pagegraph\/react/
|
|
596
|
+
},
|
|
597
|
+
handler(code, id) {
|
|
598
|
+
const file = id.split("?")[0];
|
|
599
|
+
if (file === void 0 || file.includes("/node_modules/") || file.endsWith(".gen.ts") || !file.startsWith(`${root}/`)) return;
|
|
600
|
+
return transformDocumentSource(code, file, root);
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
configurePreviewServer(previewServer) {
|
|
604
|
+
previewServer.middlewares.use((_request, response, next) => {
|
|
605
|
+
response.on("finish", () => {
|
|
606
|
+
const error = response.getHeader("x-pagegraph-error");
|
|
607
|
+
if (typeof error === "string") previewServer.config.logger.error(decodeURIComponent(error));
|
|
608
|
+
});
|
|
609
|
+
next();
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
},
|
|
300
613
|
runtimeModulesPlugin,
|
|
301
614
|
...options.routeConfig === void 0 ? [] : [seoRouteConfig({
|
|
302
615
|
...options.routeConfig,
|
|
303
616
|
routesDirectory: options.routesDirectory
|
|
304
617
|
})]
|
|
305
|
-
]
|
|
618
|
+
], { prerenderPages: options.markdown === void 0 ? [] : [{
|
|
619
|
+
path: MARKDOWN_CAPTURE_PATH,
|
|
620
|
+
sitemap: { exclude: true },
|
|
621
|
+
prerender: { onSuccess: async ({ html }) => {
|
|
622
|
+
if (current === void 0) throw new Error("The pagegraph graph must be evaluated before Markdown persistence.");
|
|
623
|
+
const app = await current;
|
|
624
|
+
await persistMarkdownCapture(html, root, clientOutDir, options.claims, app.facts);
|
|
625
|
+
} }
|
|
626
|
+
}] });
|
|
306
627
|
}
|
|
307
628
|
//#endregion
|
|
308
629
|
//#region src/tanstack-start/load.ts
|
|
309
630
|
/**
|
|
310
631
|
* Evaluate an app's graph outside a running dev server — for a build, the
|
|
311
|
-
* CLI (`
|
|
632
|
+
* CLI (`pagegraph.config.ts`), and build-time head loading — through the same
|
|
312
633
|
* `pagegraph` environment the dev server uses.
|
|
313
634
|
*/
|
|
314
635
|
const GRAPH_ENVIRONMENT = "pagegraph";
|
|
636
|
+
const cliEnvironmentOverride = (command) => command === "build" ? { [GRAPH_ENVIRONMENT]: { isBundled: false } } : void 0;
|
|
637
|
+
/** Locate the config without overriding its authored root with an inline root. */
|
|
638
|
+
const appConfig = (options) => ({
|
|
639
|
+
configFile: options.configFile ?? [
|
|
640
|
+
"js",
|
|
641
|
+
"mjs",
|
|
642
|
+
"ts",
|
|
643
|
+
"cjs",
|
|
644
|
+
"mts",
|
|
645
|
+
"cts"
|
|
646
|
+
].map((extension) => resolve(options.root, `vite.config.${extension}`)).find(existsSync) ?? false,
|
|
647
|
+
logLevel: "error",
|
|
648
|
+
plugins: [{
|
|
649
|
+
name: "pagegraph:loader-root",
|
|
650
|
+
enforce: "pre",
|
|
651
|
+
config(config) {
|
|
652
|
+
config.root ??= options.root;
|
|
653
|
+
}
|
|
654
|
+
}]
|
|
655
|
+
});
|
|
315
656
|
const pluginApi = (plugins, configFile) => {
|
|
316
657
|
const plugin = plugins.find((candidate) => candidate.name === "pagegraph");
|
|
317
658
|
if (plugin?.api === void 0) throw new Error(`${configFile ?? "The Vite config"} does not register pagegraph() from "pagegraph/tanstack-start".`);
|
|
318
659
|
return plugin.api;
|
|
319
660
|
};
|
|
320
661
|
/**
|
|
321
|
-
* Resolve the app's Vite config
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
* `mode` for the deployment the graph should describe.
|
|
662
|
+
* Resolve the app's Vite config, evaluate the graph in its `pagegraph`
|
|
663
|
+
* environment, and release it. The command defaults to `serve`; callers can
|
|
664
|
+
* request `build` to match the deployed site configuration.
|
|
325
665
|
*/
|
|
326
666
|
async function evaluateAppGraph(options) {
|
|
667
|
+
const command = options.command ?? "serve";
|
|
327
668
|
const config = await resolveConfig({
|
|
328
|
-
|
|
329
|
-
configFile: options.configFile,
|
|
669
|
+
...appConfig(options),
|
|
330
670
|
mode: options.mode,
|
|
331
|
-
|
|
332
|
-
},
|
|
671
|
+
environments: cliEnvironmentOverride(command)
|
|
672
|
+
}, command);
|
|
333
673
|
const api = pluginApi(config.plugins, config.configFile);
|
|
334
674
|
const environment = createRunnableDevEnvironment(GRAPH_ENVIRONMENT, config, { hot: false });
|
|
335
675
|
await environment.init();
|
|
336
676
|
try {
|
|
337
677
|
await environment.pluginContainer.buildStart({});
|
|
338
|
-
|
|
678
|
+
const app = await evaluateGraph(environment.runner, await planGraph(config.root, api.options));
|
|
679
|
+
return {
|
|
680
|
+
...app,
|
|
681
|
+
pagegraph: {
|
|
682
|
+
root: config.root,
|
|
683
|
+
options: api.options,
|
|
684
|
+
facts: app.facts ?? {}
|
|
685
|
+
}
|
|
686
|
+
};
|
|
339
687
|
} finally {
|
|
340
688
|
await environment.close();
|
|
341
689
|
}
|
|
342
690
|
}
|
|
343
691
|
/**
|
|
344
|
-
* A `
|
|
345
|
-
*
|
|
692
|
+
* A `pagegraph.config.ts` graph loader for a TanStack Start app. It uses the
|
|
693
|
+
* built site's identity by default; pass `command: "serve"` for a dev host.
|
|
346
694
|
*
|
|
347
695
|
* ```ts
|
|
348
696
|
* export default defineSeoConfig({
|
|
349
|
-
* origin: "https://example.com",
|
|
350
697
|
* loadGraph: tanstackStartGraph({ root: import.meta.dirname }),
|
|
351
698
|
* });
|
|
352
699
|
* ```
|
|
353
700
|
*/
|
|
354
|
-
const tanstackStartGraph = (options) => async () => {
|
|
355
|
-
const { graph, site } = await withCleanStdout(() => evaluateAppGraph({
|
|
701
|
+
const tanstackStartGraph = (options) => async (_input, environment) => {
|
|
702
|
+
const { graph, site, pagegraph } = await withCleanStdout(() => evaluateAppGraph({
|
|
356
703
|
...options,
|
|
357
|
-
|
|
704
|
+
command: environment?.command ?? options.command ?? "build",
|
|
705
|
+
mode: environment?.mode ?? options.mode ?? "production"
|
|
358
706
|
}));
|
|
359
707
|
return {
|
|
360
708
|
graph,
|
|
361
|
-
|
|
709
|
+
site,
|
|
710
|
+
pagegraph,
|
|
362
711
|
dispose: async () => {}
|
|
363
712
|
};
|
|
364
713
|
};
|