nuxt-ai-ready 2.5.3 → 3.0.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 +13 -12
- package/dist/chunks/agent-skills.mjs +35 -12
- package/dist/chunks/prerender.mjs +35 -24
- package/dist/cli.mjs +5 -2
- package/dist/module.d.mts +4 -0
- package/dist/module.json +2 -2
- package/dist/module.mjs +8 -4
- package/dist/runtime/app/index.d.ts +3 -0
- package/dist/runtime/app/index.js +2 -0
- package/dist/runtime/cache-control.d.ts +2 -0
- package/dist/runtime/cache-control.js +11 -0
- package/dist/runtime/llms-txt-utils.js +1 -1
- package/dist/runtime/server/db/context.d.ts +13 -0
- package/dist/runtime/server/db/drizzle/client.d.ts +6 -7
- package/dist/runtime/server/db/drizzle/client.js +13 -2
- package/dist/runtime/server/db/drizzle/providers/bun.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/bun.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/d1.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/d1.js +3 -2
- package/dist/runtime/server/db/drizzle/providers/libsql.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/libsql.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/neon.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/neon.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/node-sqlite.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/node-sqlite.js +2 -2
- package/dist/runtime/server/db/drizzle/providers/postgres.d.ts +2 -2
- package/dist/runtime/server/db/drizzle/providers/postgres.js +2 -2
- package/dist/runtime/server/db/drizzle/queries.d.ts +27 -27
- package/dist/runtime/server/db/drizzle/queries.js +6 -5
- package/dist/runtime/server/db/drizzle/raw.d.ts +2 -6
- package/dist/runtime/server/db/index.d.ts +1 -1
- package/dist/runtime/server/db/index.js +1 -1
- package/dist/runtime/server/db/queries.d.ts +36 -36
- package/dist/runtime/server/db/queries.js +8 -9
- package/dist/runtime/server/db/seed.d.ts +2 -2
- package/dist/runtime/server/db/seed.js +4 -3
- package/dist/runtime/server/db/shared.d.ts +8 -0
- package/dist/runtime/server/db/shared.js +8 -2
- package/dist/runtime/server/index.d.ts +2 -0
- package/dist/runtime/server/index.js +17 -0
- package/dist/runtime/server/mcp/tools/get-page-markdown.js +1 -1
- package/dist/runtime/server/mcp/tools/list-pages.js +1 -1
- package/dist/runtime/server/mcp/tools/search-pages.js +1 -1
- package/dist/runtime/server/middleware/markdown.prerender.js +1 -1
- package/dist/runtime/server/plugins/db-lifecycle-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/db-lifecycle-nitro3.js +16 -0
- package/dist/runtime/server/plugins/html-capture.prerender.js +6 -4
- package/dist/runtime/server/plugins/link-header-nitro3.d.ts +2 -0
- package/dist/runtime/server/plugins/link-header-nitro3.js +20 -0
- package/dist/runtime/server/plugins/link-header.d.ts +6 -0
- package/dist/runtime/server/plugins/link-header.js +7 -11
- package/dist/runtime/server/plugins/markdown-negotiation.js +8 -1
- package/dist/runtime/server/plugins/sitemap-seeder.js +3 -3
- package/dist/runtime/server/routes/agent-skills-artifact.d.ts +1 -1
- package/dist/runtime/server/routes/agent-skills-artifact.js +10 -10
- package/dist/runtime/server/routes/agent-skills-index.d.ts +1 -1
- package/dist/runtime/server/routes/agent-skills-index.js +7 -6
- package/dist/runtime/server/routes/ai-catalog.d.ts +2 -1
- package/dist/runtime/server/routes/ai-catalog.js +7 -8
- package/dist/runtime/server/routes/api-catalog.d.ts +3 -1
- package/dist/runtime/server/routes/api-catalog.js +12 -12
- package/dist/runtime/server/routes/llms-full.txt.get.js +1 -1
- package/dist/runtime/server/routes/mcp-server-card.d.ts +1 -1
- package/dist/runtime/server/routes/mcp-server-card.js +7 -8
- package/dist/runtime/server/utils/checkStale.d.ts +2 -2
- package/dist/runtime/server/utils/cloudflare-prerendered.d.ts +3 -0
- package/dist/runtime/server/utils/cloudflare-prerendered.js +23 -0
- package/dist/runtime/server/utils/cloudflare.d.ts +5 -5
- package/dist/runtime/server/utils/cloudflare.js +31 -7
- package/dist/runtime/server/utils/content-negotiation.d.ts +5 -3
- package/dist/runtime/server/utils/content-negotiation.js +8 -7
- package/dist/runtime/server/utils/context.d.ts +3 -3
- package/dist/runtime/server/utils/context.js +1 -1
- package/dist/runtime/server/utils/discovery-response.d.ts +2 -0
- package/dist/runtime/server/utils/link-header.d.ts +5 -3
- package/dist/runtime/server/utils/link-header.js +26 -2
- package/dist/runtime/server/utils/markdown-request.d.ts +4 -3
- package/dist/runtime/server/utils/markdown-request.js +15 -13
- package/dist/runtime/server/utils/negotiation-decision.d.ts +4 -0
- package/dist/runtime/server/utils/negotiation-decision.js +6 -5
- package/dist/runtime/server/utils/negotiation-response.js +47 -22
- package/dist/runtime/server/utils/prerender-html.d.ts +2 -1
- package/dist/runtime/server/utils/prerender-html.js +3 -1
- package/dist/runtime/types.d.ts +15 -7
- package/dist/shared/nuxt-ai-ready.B3hAuOLQ.mjs +29 -0
- package/dist/shared/{nuxt-ai-ready.CLSWou20.mjs → nuxt-ai-ready.C34F0LJo.mjs} +560 -219
- package/package.json +85 -20
- package/skills/nuxt-ai-ready/SKILL.md +26 -12
- package/skills/nuxt-ai-ready/references/runtime-indexing.md +7 -6
- package/dist/runtime/server/db/drizzle/providers/sqlite.d.ts +0 -8
- package/dist/runtime/server/db/drizzle/providers/sqlite.js +0 -15
- package/node_modules/@mdream/js/LICENSE.md +0 -9
- package/node_modules/@mdream/js/README.md +0 -792
- package/node_modules/@mdream/js/bin/mdream.mjs +0 -2
- package/node_modules/@mdream/js/dist/_chunks/const.mjs +0 -134
- package/node_modules/@mdream/js/dist/_chunks/index.d.mts +0 -9
- package/node_modules/@mdream/js/dist/_chunks/markdown-processor.mjs +0 -1968
- package/node_modules/@mdream/js/dist/_chunks/minimal.d.mts +0 -6
- package/node_modules/@mdream/js/dist/_chunks/parse.mjs +0 -2756
- package/node_modules/@mdream/js/dist/_chunks/plugins.mjs +0 -725
- package/node_modules/@mdream/js/dist/_chunks/resolve-plugins.mjs +0 -44
- package/node_modules/@mdream/js/dist/_chunks/stream.mjs +0 -37
- package/node_modules/@mdream/js/dist/_chunks/types.d.mts +0 -473
- package/node_modules/@mdream/js/dist/cli.d.mts +0 -1
- package/node_modules/@mdream/js/dist/cli.mjs +0 -32
- package/node_modules/@mdream/js/dist/core.d.mts +0 -15
- package/node_modules/@mdream/js/dist/core.mjs +0 -28
- package/node_modules/@mdream/js/dist/index.d.mts +0 -4
- package/node_modules/@mdream/js/dist/index.mjs +0 -58
- package/node_modules/@mdream/js/dist/llms-txt.d.mts +0 -86
- package/node_modules/@mdream/js/dist/llms-txt.mjs +0 -308
- package/node_modules/@mdream/js/dist/negotiate.d.mts +0 -35
- package/node_modules/@mdream/js/dist/negotiate.mjs +0 -121
- package/node_modules/@mdream/js/dist/parse.d.mts +0 -90
- package/node_modules/@mdream/js/dist/parse.mjs +0 -2
- package/node_modules/@mdream/js/dist/plugins.d.mts +0 -85
- package/node_modules/@mdream/js/dist/plugins.mjs +0 -2
- package/node_modules/@mdream/js/dist/preset/minimal.d.mts +0 -2
- package/node_modules/@mdream/js/dist/preset/minimal.mjs +0 -33
- package/node_modules/@mdream/js/dist/splitter.d.mts +0 -18
- package/node_modules/@mdream/js/dist/splitter.mjs +0 -194
- package/node_modules/@mdream/js/package.json +0 -103
- package/node_modules/cac/LICENSE +0 -21
- package/node_modules/cac/README.md +0 -492
- package/node_modules/cac/dist/index.d.ts +0 -196
- package/node_modules/cac/dist/index.js +0 -638
- package/node_modules/cac/package.json +0 -72
- package/node_modules/mdream/LICENSE.md +0 -9
- package/node_modules/mdream/README.md +0 -1091
- package/node_modules/mdream/bin/mdream.mjs +0 -46
- package/node_modules/mdream/dist/browser.d.mts +0 -105
- package/node_modules/mdream/dist/browser.mjs +0 -262
- package/node_modules/mdream/dist/edge.d.mts +0 -100
- package/node_modules/mdream/dist/edge.mjs +0 -250
- package/node_modules/mdream/dist/iife.js +0 -605
- package/node_modules/mdream/dist/index.d.mts +0 -89
- package/node_modules/mdream/dist/index.mjs +0 -184
- package/node_modules/mdream/dist/wasm.d.mts +0 -100
- package/node_modules/mdream/dist/wasm.mjs +0 -140
- package/node_modules/mdream/dist/worker.d.mts +0 -101
- package/node_modules/mdream/dist/worker.mjs +0 -217
- package/node_modules/mdream/napi/index.d.mts +0 -127
- package/node_modules/mdream/napi/index.d.ts +0 -127
- package/node_modules/mdream/napi/index.mjs +0 -725
- package/node_modules/mdream/napi/rust.android-arm-eabi.node +0 -0
- package/node_modules/mdream/napi/rust.android-arm64.node +0 -0
- package/node_modules/mdream/napi/rust.darwin-arm64.node +0 -0
- package/node_modules/mdream/napi/rust.darwin-x64.node +0 -0
- package/node_modules/mdream/napi/rust.freebsd-x64.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm-gnueabihf.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm64-gnu.node +0 -0
- package/node_modules/mdream/napi/rust.linux-arm64-musl.node +0 -0
- package/node_modules/mdream/napi/rust.linux-x64-gnu.node +0 -0
- package/node_modules/mdream/napi/rust.linux-x64-musl.node +0 -0
- package/node_modules/mdream/napi/rust.wasi.cjs +0 -2144
- package/node_modules/mdream/napi/rust.wasm32-wasi.wasm +0 -0
- package/node_modules/mdream/napi/rust.win32-arm64-msvc.node +0 -0
- package/node_modules/mdream/napi/rust.win32-x64-msvc.node +0 -0
- package/node_modules/mdream/node_modules/@emnapi/core/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/core/README.md +0 -1
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.d.ts +0 -392
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.d.ts +0 -392
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.full.js +0 -8351
- package/node_modules/mdream/node_modules/@emnapi/core/dist/emnapi-core.js +0 -7268
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/async-work.js +0 -843
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.d.ts +0 -4
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/index.js +0 -3
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/threadsafe-function.js +0 -1010
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.d.ts +0 -5
- package/node_modules/mdream/node_modules/@emnapi/core/dist/plugins/v8.js +0 -1446
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/README.md +0 -203
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/dist/wasi-threads.d.ts +0 -236
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/dist/wasi-threads.js +0 -1086
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/package.json +0 -35
- package/node_modules/mdream/node_modules/@emnapi/core/node_modules/@emnapi/wasi-threads/rollup.config.js +0 -6
- package/node_modules/mdream/node_modules/@emnapi/core/package.json +0 -39
- package/node_modules/mdream/node_modules/@emnapi/core/rollup.config.js +0 -60
- package/node_modules/mdream/node_modules/@emnapi/runtime/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/runtime/README.md +0 -1
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.d.ts +0 -833
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js +0 -2306
- package/node_modules/mdream/node_modules/@emnapi/runtime/dist/emnapi.js.map +0 -1
- package/node_modules/mdream/node_modules/@emnapi/runtime/index.cjs +0 -63
- package/node_modules/mdream/node_modules/@emnapi/runtime/package.json +0 -39
- package/node_modules/mdream/node_modules/@emnapi/runtime/rollup.config.js +0 -25
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/README.md +0 -203
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.d.ts +0 -240
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/dist/wasi-threads.js +0 -1118
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/package.json +0 -35
- package/node_modules/mdream/node_modules/@emnapi/wasi-threads/rollup.config.js +0 -6
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.cjs +0 -1472
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/emnapi-plugins.js +0 -1470
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs-proxy.cjs +0 -237
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/dist/fs.js +0 -17578
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/fs-proxy.js +0 -317
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/package.json +0 -67
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.cjs +0 -39
- package/node_modules/mdream/node_modules/@napi-rs/wasm-runtime/runtime.js +0 -36
- package/node_modules/mdream/node_modules/@tybys/wasm-util/LICENSE +0 -21
- package/node_modules/mdream/node_modules/@tybys/wasm-util/README.md +0 -193
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/tsdoc-metadata.json +0 -11
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.d.ts +0 -423
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm-bundler.js +0 -2932
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.js +0 -2932
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.esm.min.js +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.js +0 -2954
- package/node_modules/mdream/node_modules/@tybys/wasm-util/dist/wasm-util.min.js +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/asyncify.js +0 -158
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/index.js +0 -13
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/jspi.js +0 -46
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/load.js +0 -97
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/memory.js +0 -35
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/error.js +0 -103
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fd.js +0 -268
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/fs.js +0 -3
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/index.js +0 -192
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/path.js +0 -316
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/preview1.js +0 -1599
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/rights.js +0 -141
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/types.js +0 -220
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/wasi/util.js +0 -128
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/cjs/webassembly.js +0 -13
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/asyncify.mjs +0 -153
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/index.mjs +0 -9
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/jspi.mjs +0 -39
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/load.mjs +0 -89
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/memory.mjs +0 -28
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/error.mjs +0 -97
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fd.mjs +0 -256
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/fs.mjs +0 -1
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/index.mjs +0 -186
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/path.mjs +0 -310
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/preview1.mjs +0 -1593
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/rights.mjs +0 -135
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/types.mjs +0 -216
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/wasi/util.mjs +0 -113
- package/node_modules/mdream/node_modules/@tybys/wasm-util/lib/mjs/webassembly.mjs +0 -9
- package/node_modules/mdream/node_modules/@tybys/wasm-util/package.json +0 -58
- package/node_modules/mdream/node_modules/tslib/CopyrightNotice.txt +0 -15
- package/node_modules/mdream/node_modules/tslib/LICENSE.txt +0 -12
- package/node_modules/mdream/node_modules/tslib/README.md +0 -164
- package/node_modules/mdream/node_modules/tslib/SECURITY.md +0 -41
- package/node_modules/mdream/node_modules/tslib/modules/index.d.ts +0 -38
- package/node_modules/mdream/node_modules/tslib/modules/index.js +0 -70
- package/node_modules/mdream/node_modules/tslib/modules/package.json +0 -3
- package/node_modules/mdream/node_modules/tslib/package.json +0 -47
- package/node_modules/mdream/node_modules/tslib/tslib.d.ts +0 -460
- package/node_modules/mdream/node_modules/tslib/tslib.es6.html +0 -1
- package/node_modules/mdream/node_modules/tslib/tslib.es6.js +0 -402
- package/node_modules/mdream/node_modules/tslib/tslib.es6.mjs +0 -401
- package/node_modules/mdream/node_modules/tslib/tslib.html +0 -1
- package/node_modules/mdream/node_modules/tslib/tslib.js +0 -484
- package/node_modules/mdream/package.json +0 -110
- package/node_modules/mdream/skills/mdream/SKILL.md +0 -124
- package/node_modules/mdream/skills/mdream/references/runtimes.md +0 -49
- package/node_modules/mdream/wasm/mdream_edge.d.ts +0 -90
- package/node_modules/mdream/wasm/mdream_edge.js +0 -517
- package/node_modules/mdream/wasm/mdream_edge_bg.wasm +0 -0
- package/node_modules/mdream/wasm/mdream_edge_bg.wasm.d.ts +0 -20
- package/node_modules/mdream/wasm/package.json +0 -17
- package/node_modules/mdream/wasm-bundler/mdream_edge.d.ts +0 -45
- package/node_modules/mdream/wasm-bundler/mdream_edge.js +0 -13
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.js +0 -413
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm +0 -0
- package/node_modules/mdream/wasm-bundler/mdream_edge_bg.wasm.d.ts +0 -20
- package/node_modules/mdream/wasm-bundler/package.json +0 -19
- package/node_modules/pathe/LICENSE +0 -70
- package/node_modules/pathe/README.md +0 -73
- package/node_modules/pathe/dist/index.cjs +0 -39
- package/node_modules/pathe/dist/index.d.cts +0 -47
- package/node_modules/pathe/dist/index.d.mts +0 -47
- package/node_modules/pathe/dist/index.d.ts +0 -47
- package/node_modules/pathe/dist/index.mjs +0 -19
- package/node_modules/pathe/dist/shared/pathe.BSlhyZSM.cjs +0 -266
- package/node_modules/pathe/dist/shared/pathe.M-eThtNZ.mjs +0 -249
- package/node_modules/pathe/dist/utils.cjs +0 -82
- package/node_modules/pathe/dist/utils.d.cts +0 -32
- package/node_modules/pathe/dist/utils.d.mts +0 -32
- package/node_modules/pathe/dist/utils.d.ts +0 -32
- package/node_modules/pathe/dist/utils.mjs +0 -77
- package/node_modules/pathe/package.json +0 -61
- package/node_modules/pathe/utils.d.ts +0 -1
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { readFile, mkdir, writeFile, access } from 'node:fs/promises';
|
|
3
3
|
import { createRequire } from 'node:module';
|
|
4
|
-
import { dirname, basename, join } from 'node:path';
|
|
5
|
-
import { hasNuxtModule, useNuxt, useLogger, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, addServerImports, addServerHandler, extendRouteRules, addServerPlugin, addPlugin, addImports } from '@nuxt/kit';
|
|
6
|
-
import defu$1, { defu } from 'defu';
|
|
7
|
-
import { installNuxtSiteConfig, useSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
|
|
8
|
-
import { resolveNuxtContentVersion, renderNitroTypeAugmentations, setupNitroRuntimeCompatibility } from 'nuxtseo-shared/kit';
|
|
9
|
-
import { readPackageJSON, resolvePackageJSON } from 'pkg-types';
|
|
4
|
+
import { dirname, basename, join, resolve, relative } from 'node:path';
|
|
10
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
|
+
import { hasNuxtModule, useNuxt, useLogger, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, getLayerDirectories, tryResolveModule, directoryToURL, addServerImports, addServerHandler, extendRouteRules, getNitroVersion, addNitroPlugin, addPlugin, addImports } from '@nuxt/kit';
|
|
7
|
+
import defu$1, { defu } from 'defu';
|
|
8
|
+
import { useSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
|
|
9
|
+
import { resolveNuxtContentVersion, renderNitroTypeAugmentations, setupRuntimeAliases, setupNitroRuntimeCompatibility } from 'nuxtseo-shared/kit';
|
|
10
|
+
import { r as readPackageMetadata, a as resolvePackageMetadataPath } from './nuxt-ai-ready.B3hAuOLQ.mjs';
|
|
11
11
|
import { hasMarkdownTwin, normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
|
|
12
|
+
import { toDeployedRoute } from '../../dist/runtime/route-path.js';
|
|
12
13
|
import { SITEMAP_MD_ROUTE } from '../../dist/runtime/server/utils/sitemap-md.js';
|
|
13
|
-
import { publicCacheControl } from '../../dist/runtime/cache-control.js';
|
|
14
|
+
import { publicCacheControl, mergeVaryHeader } from '../../dist/runtime/cache-control.js';
|
|
14
15
|
import { MCP_SERVER_CARD_MEDIA_TYPE, AI_CATALOG_MEDIA_TYPE } from '../../dist/runtime/server/utils/discovery-response.js';
|
|
16
|
+
import { parseTOML, parseJSONC } from 'confbox';
|
|
17
|
+
import { createNitroRouteRuleMatcher } from 'nuxtseo-shared/server';
|
|
18
|
+
import { getContentNegotiationVary, resolveContentNegotiation } from '../../dist/runtime/server/utils/content-negotiation.js';
|
|
15
19
|
import { isAbsolute, join as join$1 } from 'pathe';
|
|
16
20
|
import { resolveI18nConfig, toRuntimeI18nConfig as toRuntimeI18nConfig$1 } from 'nuxtseo-shared/i18n';
|
|
17
|
-
import { toDeployedRoute } from '../../dist/runtime/route-path.js';
|
|
18
21
|
|
|
19
22
|
const SELECT_PAGE_DATA = "SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages";
|
|
20
23
|
function createBuildPageDataVirtual(options) {
|
|
@@ -24,12 +27,9 @@ export async function readPageDataFromFilesystem() { return { pages: [], errorRo
|
|
|
24
27
|
export async function readMarkdownLinkAvailabilityFromFilesystem() { return { runtimeMarkdownAvailable: false, paths: [] } }
|
|
25
28
|
`;
|
|
26
29
|
}
|
|
27
|
-
const readRows =
|
|
30
|
+
const readRows = `const { DatabaseSync } = await import('node' + ':sqlite')
|
|
28
31
|
const db = new DatabaseSync(dbPath, { open: true })
|
|
29
32
|
const rows = db.prepare(${JSON.stringify(SELECT_PAGE_DATA)}).all()
|
|
30
|
-
db.close()` : `const Database = (await import('better-sqlite3')).default
|
|
31
|
-
const db = new Database(dbPath, { readonly: true })
|
|
32
|
-
const rows = db.prepare(${JSON.stringify(SELECT_PAGE_DATA)}).all()
|
|
33
33
|
db.close()`;
|
|
34
34
|
return `
|
|
35
35
|
export async function readMarkdownLinkAvailabilityFromFilesystem() {
|
|
@@ -85,7 +85,7 @@ const COMARK_MODULE = "@harlan-zw/comark-content";
|
|
|
85
85
|
const COMARK_MINIMUM = [0, 1, 2];
|
|
86
86
|
async function comarkSatisfiesMinimum() {
|
|
87
87
|
const url = useNuxt().options.rootDir;
|
|
88
|
-
const pkg = await
|
|
88
|
+
const pkg = await readPackageMetadata(COMARK_MODULE, url).catch(() => {
|
|
89
89
|
return null;
|
|
90
90
|
});
|
|
91
91
|
const parts = pkg?.version?.split(".").map((part) => Number.parseInt(part, 10));
|
|
@@ -249,15 +249,19 @@ declare module '#ai-ready-virtual/i18n-runtime.mjs' {
|
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
declare module '#ai-ready-virtual/db-provider.mjs' {
|
|
252
|
-
import type {
|
|
252
|
+
import type { AiReadyDatabaseEvent } from '#ai-ready/server/db/context'
|
|
253
253
|
import type { DrizzleDatabase } from '#ai-ready/server/db/drizzle/client'
|
|
254
|
-
export function createClient(event?:
|
|
254
|
+
export function createClient(event?: AiReadyDatabaseEvent): Promise<DrizzleDatabase>
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
declare module '#ai-ready-virtual/db-schema.mjs' {
|
|
258
258
|
export * from '#ai-ready/server/db/schema/sqlite'
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
+
declare module '#ai-ready-virtual/database-runtime.mjs' {
|
|
262
|
+
export * from '#ai-ready/server/db/drizzle'
|
|
263
|
+
}
|
|
264
|
+
|
|
261
265
|
declare module '#ai-ready-virtual/content-lookup.mjs' {
|
|
262
266
|
import type { H3Event } from '#nuxtseo/h3'
|
|
263
267
|
export function lookupContentPage(event: H3Event, path: string): Promise<{
|
|
@@ -296,6 +300,7 @@ function resolveExternalSkillUrl(href, indexUrl) {
|
|
|
296
300
|
}
|
|
297
301
|
|
|
298
302
|
const AI_CATALOG_PATH = "/.well-known/ai-catalog.json";
|
|
303
|
+
const ARD_PATH = "/.well-known/ard.json";
|
|
299
304
|
function resolveAiCatalog(input) {
|
|
300
305
|
const hostname = new URL(input.siteUrl).hostname;
|
|
301
306
|
const serverName = input.serverCardName.split("/").at(-1);
|
|
@@ -303,6 +308,8 @@ function resolveAiCatalog(input) {
|
|
|
303
308
|
specVersion: "1.0",
|
|
304
309
|
entries: [{
|
|
305
310
|
identifier: `urn:air:${hostname}:mcp:${serverName}`,
|
|
311
|
+
displayName: input.serverCardTitle || input.serverCardName,
|
|
312
|
+
...input.serverCardDescription ? { description: input.serverCardDescription } : {},
|
|
306
313
|
type: MCP_SERVER_CARD_MEDIA_TYPE,
|
|
307
314
|
url: input.serverCardUrl
|
|
308
315
|
}]
|
|
@@ -512,16 +519,256 @@ function formatApiCatalogConfigError(error) {
|
|
|
512
519
|
}
|
|
513
520
|
}
|
|
514
521
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
+
const PARSERS = {
|
|
523
|
+
"wrangler.json": JSON.parse,
|
|
524
|
+
"wrangler.jsonc": parseJSONC,
|
|
525
|
+
"wrangler.toml": parseTOML
|
|
526
|
+
};
|
|
527
|
+
function parseRouting(routing) {
|
|
528
|
+
if (routing === void 0 || typeof routing === "boolean")
|
|
529
|
+
return routing;
|
|
530
|
+
if (Array.isArray(routing) && routing.every((pattern) => typeof pattern === "string"))
|
|
531
|
+
return routing;
|
|
532
|
+
throw new Error("Cloudflare assets.run_worker_first must be a boolean or an array of path patterns.");
|
|
533
|
+
}
|
|
534
|
+
async function readCloudflareAssetRouting(rootDir) {
|
|
535
|
+
let directory = rootDir;
|
|
536
|
+
while (true) {
|
|
537
|
+
for (const [name, parse] of Object.entries(PARSERS)) {
|
|
538
|
+
const source = await readFile(join(directory, name), "utf8").catch((error) => {
|
|
539
|
+
if (error.code === "ENOENT")
|
|
540
|
+
return void 0;
|
|
541
|
+
throw error;
|
|
542
|
+
});
|
|
543
|
+
if (source === void 0)
|
|
544
|
+
continue;
|
|
545
|
+
const config = parse(source);
|
|
546
|
+
return {
|
|
547
|
+
root: parseRouting(config.assets?.run_worker_first),
|
|
548
|
+
environments: Object.values(config.env || {}).flatMap((env) => {
|
|
549
|
+
const routing = parseRouting(env.assets?.run_worker_first);
|
|
550
|
+
return routing === void 0 ? [] : [routing];
|
|
551
|
+
})
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
const parent = dirname(directory);
|
|
555
|
+
if (parent === directory)
|
|
556
|
+
return { environments: [] };
|
|
557
|
+
directory = parent;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const RE_MD_EXT = /\.md$/;
|
|
562
|
+
function isStaticMarkdownSourceRoute(route) {
|
|
563
|
+
if (route.includes("*") || route.includes(":"))
|
|
564
|
+
return false;
|
|
565
|
+
return hasMarkdownTwin(route.split("?")[0] || route);
|
|
566
|
+
}
|
|
567
|
+
function staticDescribedbyEntry(baseURL) {
|
|
568
|
+
return `<${encodeURI(toDeployedRoute("/llms.txt", baseURL))}>; rel="describedby"`;
|
|
569
|
+
}
|
|
570
|
+
function buildStaticMarkdownLinkHeader(route, baseURL, describedby) {
|
|
571
|
+
const htmlRoute = encodeURI(toDeployedRoute(normalizePagePath(route), baseURL));
|
|
572
|
+
const parts = [
|
|
573
|
+
`<${htmlRoute}>; rel="alternate"; type="text/html"`,
|
|
574
|
+
`<${htmlRoute}>; rel="canonical"`
|
|
575
|
+
];
|
|
576
|
+
if (describedby)
|
|
577
|
+
parts.push(staticDescribedbyEntry(baseURL));
|
|
578
|
+
return parts.join(", ");
|
|
579
|
+
}
|
|
580
|
+
function pageRouteFromMarkdownTwin(fileName) {
|
|
581
|
+
if (!fileName?.endsWith(".md") || fileName === SITEMAP_MD_ROUTE)
|
|
582
|
+
return null;
|
|
583
|
+
const pageRoute = normalizePagePath(fileName.replace(RE_MD_EXT, ""));
|
|
584
|
+
if (pageRoute === "/index")
|
|
585
|
+
return "/";
|
|
586
|
+
return isStaticMarkdownSourceRoute(pageRoute) ? pageRoute : null;
|
|
587
|
+
}
|
|
588
|
+
function prerenderedMarkdownHeaderRules(prerenderedRoutes, baseURL, describedby, artifactRoutes) {
|
|
589
|
+
const artifacts = new Set(artifactRoutes);
|
|
590
|
+
const rules = /* @__PURE__ */ new Map();
|
|
591
|
+
for (const entry of prerenderedRoutes) {
|
|
592
|
+
if (entry.route !== void 0 && artifacts.has(entry.route) || entry.fileName !== void 0 && artifacts.has(entry.fileName)) {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
const pageRoute = pageRouteFromMarkdownTwin(entry.fileName);
|
|
596
|
+
if (pageRoute === null)
|
|
597
|
+
continue;
|
|
598
|
+
const mdRoute = toMarkdownPath(pageRoute);
|
|
599
|
+
if (!rules.has(mdRoute)) {
|
|
600
|
+
rules.set(mdRoute, {
|
|
601
|
+
route: mdRoute,
|
|
602
|
+
headers: {
|
|
603
|
+
"Content-Type": "text/markdown; charset=utf-8",
|
|
604
|
+
"Vary": "Accept",
|
|
605
|
+
"Link": buildStaticMarkdownLinkHeader(pageRoute, baseURL, describedby)
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return [...rules.values()];
|
|
611
|
+
}
|
|
612
|
+
const RE_EXACT_MARKDOWN_ROUTE$1 = /^\/[^*:\s]*\.md$/;
|
|
613
|
+
function isStaticHeaderRouteRule([, rule]) {
|
|
614
|
+
return Boolean(rule && "headers" in rule && rule.headers);
|
|
615
|
+
}
|
|
616
|
+
function planStaticMarkdownHeaderRules(routeRules, rules, limit) {
|
|
617
|
+
if (limit === null)
|
|
618
|
+
return { _tag: "apply", rules };
|
|
619
|
+
const entries = Object.entries(routeRules).filter(isStaticHeaderRouteRule);
|
|
620
|
+
const registeredMarkdown = entries.map(([route]) => route).filter((route) => RE_EXACT_MARKDOWN_ROUTE$1.test(route));
|
|
621
|
+
const other = entries.length - registeredMarkdown.length;
|
|
622
|
+
const markdown = /* @__PURE__ */ new Set([...registeredMarkdown, ...rules.map((rule) => rule.route)]);
|
|
623
|
+
const total = other + markdown.size;
|
|
624
|
+
if (total <= limit)
|
|
625
|
+
return { _tag: "apply", rules };
|
|
626
|
+
return { _tag: "skip", drop: registeredMarkdown, total, dropped: markdown.size };
|
|
627
|
+
}
|
|
628
|
+
function applyStaticMarkdownHeaderPlan(routeRules, plan) {
|
|
629
|
+
if (plan._tag === "skip") {
|
|
630
|
+
for (const route of plan.drop) {
|
|
631
|
+
const rule = routeRules[route];
|
|
632
|
+
if (rule)
|
|
633
|
+
rule.headers = void 0;
|
|
634
|
+
}
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
for (const { route, headers } of plan.rules) {
|
|
638
|
+
const existing = routeRules[route];
|
|
639
|
+
const merged = defu({ headers: { ...headers } }, existing);
|
|
640
|
+
const vary = Object.entries(existing?.headers || {}).filter(([name]) => name.toLowerCase() === "vary").map(([, value]) => value).join(", ");
|
|
641
|
+
if (headers.Vary) {
|
|
642
|
+
for (const name of Object.keys(merged.headers)) {
|
|
643
|
+
if (name.toLowerCase() === "vary")
|
|
644
|
+
delete merged.headers[name];
|
|
645
|
+
}
|
|
646
|
+
merged.headers.Vary = mergeVaryHeader(vary, headers.Vary);
|
|
647
|
+
}
|
|
648
|
+
routeRules[route] = merged;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
const MAX_WORKER_FIRST_PATTERNS = 100;
|
|
653
|
+
const RE_PATTERN_CHARACTERS = /[.+?^${}()|[\]\\]/g;
|
|
654
|
+
function cloudflarePrerenderedPages(routes, baseURL) {
|
|
655
|
+
return [...new Set(routes.filter((entry) => !entry.error && entry.fileName?.endsWith(".html") && isStaticMarkdownSourceRoute(entry.route)).map((entry) => normalizePagePath(toDeployedRoute(normalizePagePath(entry.route), baseURL))))];
|
|
656
|
+
}
|
|
657
|
+
function matchesPattern(path, pattern) {
|
|
658
|
+
return new RegExp(`^${pattern.replace(RE_PATTERN_CHARACTERS, "\\$&").replaceAll("*", ".*")}$`).test(path);
|
|
659
|
+
}
|
|
660
|
+
function pagePaths(pages) {
|
|
661
|
+
return pages.flatMap((page) => page === "/" ? ["/"] : [page, `${page}/`]);
|
|
662
|
+
}
|
|
663
|
+
function cloudflareStaticFallbackPaths(existing, pages, environments = []) {
|
|
664
|
+
if (existing === true || existing === false || environments.includes(true))
|
|
665
|
+
return [];
|
|
666
|
+
const patterns = [...existing || [], ...environments.flatMap((routing) => Array.isArray(routing) ? routing : [])];
|
|
667
|
+
return pagePaths(pages).filter((path) => !patterns.some((pattern) => matchesPattern(path, pattern.startsWith("!") ? pattern.slice(1) : pattern)));
|
|
668
|
+
}
|
|
669
|
+
function cloudflareNegotiationPatterns(existing, pages) {
|
|
670
|
+
if (existing === true || existing === false || pages.length === 0)
|
|
671
|
+
return existing;
|
|
672
|
+
const patterns = [...existing || []];
|
|
673
|
+
for (const path of cloudflareStaticFallbackPaths(existing, pages)) {
|
|
674
|
+
if (!patterns.includes(path))
|
|
675
|
+
patterns.push(path);
|
|
676
|
+
}
|
|
677
|
+
if (patterns.length > MAX_WORKER_FIRST_PATTERNS) {
|
|
678
|
+
throw new Error("Cloudflare Markdown negotiation exceeds 100 worker-first patterns. Configure broader assets.run_worker_first patterns, or disable aiReady.contentNegotiation.");
|
|
679
|
+
}
|
|
680
|
+
return patterns;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const CACHE_GUIDE = "https://nuxtseo.com/docs/ai-ready/guides/markdown#cache-safety";
|
|
684
|
+
function cacheFix(botNegotiation = false) {
|
|
685
|
+
const headers = getContentNegotiationVary(botNegotiation).split(",").map((header) => `'${header.trim().toLowerCase()}'`).join(", ");
|
|
686
|
+
return [
|
|
687
|
+
...botNegotiation ? [
|
|
688
|
+
"For lower cache cost, set aiReady: { botNegotiation: false } and keep Accept-only negotiation.",
|
|
689
|
+
"To retain bot negotiation, include all three inputs in this route's cache key.",
|
|
690
|
+
"Raw User-Agent variation can create many cache entries."
|
|
691
|
+
] : [],
|
|
692
|
+
`Add to this route rule: cache: { varies: [${headers}] }`,
|
|
693
|
+
"Keep existing cache options and varies entries.",
|
|
694
|
+
"HTTP Vary alone does not change Nitro's cache key.",
|
|
695
|
+
"If a CDN ignores Vary, set aiReady: { contentNegotiation: false } and use explicit .md URLs."
|
|
696
|
+
].join("\n ");
|
|
697
|
+
}
|
|
698
|
+
function resolveConfigurationWarnings(input) {
|
|
699
|
+
const warnings = [];
|
|
700
|
+
const hostname = input.siteUrl && URL.canParse(input.siteUrl) ? new URL(input.siteUrl).hostname : "";
|
|
701
|
+
if (!hostname || hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]") {
|
|
702
|
+
warnings.push('Set site.url to the public production URL. Discovery catalogs and canonical Markdown links need a public origin.\n In nuxt.config.ts, set site: { url: "https://your-domain.com" }. Replace the example with your production origin.');
|
|
703
|
+
}
|
|
704
|
+
if (input.policy === "disabled") {
|
|
705
|
+
warnings.push(`contentNegotiation: false disables Accept and bot negotiation.
|
|
706
|
+
Remove aiReady.contentNegotiation from nuxt.config.ts to restore automatic negotiation.
|
|
707
|
+
If disabled intentionally, link explicit .md URLs and verify they resolve after deployment.
|
|
708
|
+
Guide: ${CACHE_GUIDE}`);
|
|
709
|
+
} else if (input.static) {
|
|
710
|
+
warnings.push(`Static output cannot run Markdown negotiation middleware.
|
|
711
|
+
Link the generated .md URLs, or use a server deployment for automatic negotiation.
|
|
712
|
+
For edge negotiation, preserve these inputs: ${getContentNegotiationVary(input.botNegotiation)}.
|
|
713
|
+
Guide: ${CACHE_GUIDE}`);
|
|
714
|
+
}
|
|
715
|
+
const match = createNitroRouteRuleMatcher({ nitro: { routeRules: input.routeRules } });
|
|
716
|
+
for (const route of Object.keys(input.routeRules).sort()) {
|
|
717
|
+
if (!hasMarkdownTwin(route) || route.startsWith("/.well-known/"))
|
|
718
|
+
continue;
|
|
719
|
+
const rule = match(route);
|
|
720
|
+
if (rule.redirect || rule.proxy)
|
|
721
|
+
continue;
|
|
722
|
+
if (input.static || input.policy === "disabled")
|
|
723
|
+
continue;
|
|
724
|
+
const automatic = resolveContentNegotiation({ policy: "auto", routeRule: rule, botNegotiation: input.botNegotiation });
|
|
725
|
+
const fixCache = cacheFix(input.botNegotiation);
|
|
726
|
+
if (automatic._tag === "enabled")
|
|
727
|
+
continue;
|
|
728
|
+
if (input.policy === "enabled") {
|
|
729
|
+
const fix = automatic.source === "isr" ? `ISR cannot use automatic negotiation. Set isr: false on this route, or use explicit .md URLs.${rule.cache ? `
|
|
730
|
+
${fixCache}` : ""}` : fixCache;
|
|
731
|
+
warnings.push(`"${route}": contentNegotiation: true overrides cache protection.
|
|
732
|
+
Remove aiReady.contentNegotiation from nuxt.config.ts to restore automatic cache protection.
|
|
733
|
+
${fix}
|
|
734
|
+
Guide: ${CACHE_GUIDE}`);
|
|
735
|
+
} else if (automatic.source === "isr") {
|
|
736
|
+
warnings.push(`"${route}": ISR disables automatic Markdown negotiation.
|
|
737
|
+
To keep ISR, use explicit .md URLs.
|
|
738
|
+
To use negotiation, set isr: false on this route in nuxt.config.ts.${rule.cache ? `
|
|
739
|
+
${fixCache}` : ""}
|
|
740
|
+
Guide: ${CACHE_GUIDE}`);
|
|
741
|
+
} else {
|
|
742
|
+
warnings.push(`"${route}": response caching disables automatic Markdown negotiation.
|
|
743
|
+
In nuxt.config.ts:
|
|
744
|
+
${fixCache}
|
|
745
|
+
Guide: ${CACHE_GUIDE}`);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
return warnings;
|
|
522
749
|
}
|
|
750
|
+
|
|
523
751
|
const DATABASE_TYPE_NONE = "none";
|
|
524
752
|
const DATABASE_DEPENDENT_OPTIONS = ["runtimeSync", "cron"];
|
|
753
|
+
const DATABASE_CONSUMER_LABELS = {
|
|
754
|
+
runtimeSync: "runtime indexing (`aiReady.runtimeSync`)",
|
|
755
|
+
cron: "the indexing cron (`aiReady.cron`)",
|
|
756
|
+
mcp: "MCP site tools (`@nuxtjs/mcp-toolkit`)",
|
|
757
|
+
webmcp: "WebMCP site tools (`aiReady.webmcp`)"
|
|
758
|
+
};
|
|
759
|
+
function formatMissingDrizzleMessage(input) {
|
|
760
|
+
const consumers = Object.keys(DATABASE_CONSUMER_LABELS).filter((consumer) => input.requested[consumer]);
|
|
761
|
+
const subject = consumers.length === 0 ? "The `aiReady.database` option turns on the database." : `These features need the database: ${consumers.map((consumer) => DATABASE_CONSUMER_LABELS[consumer]).join(", ")}.`;
|
|
762
|
+
const version = input.peerRange?.replace(/^\^/, "");
|
|
763
|
+
const lines = [
|
|
764
|
+
subject,
|
|
765
|
+
"The database needs `drizzle-orm`. This app does not install it.",
|
|
766
|
+
`Install it: npx nypm add drizzle-orm${version ? `@${version}` : ""}`
|
|
767
|
+
];
|
|
768
|
+
if (consumers.length > 0 && consumers.every((consumer) => consumer === "mcp" || consumer === "webmcp"))
|
|
769
|
+
lines.push("If you do not need the site tools, set `aiReady.database: false`.");
|
|
770
|
+
return lines.join("\n");
|
|
771
|
+
}
|
|
525
772
|
const DEFAULT_SQLITE_FILENAME = ".data/ai-ready/pages.db";
|
|
526
773
|
function formatConflictMessage(conflicts) {
|
|
527
774
|
const names = conflicts.map((option) => `\`aiReady.${option}\``).join(", ");
|
|
@@ -797,7 +1044,10 @@ function parseSupportedMcpProtocolVersions(source) {
|
|
|
797
1044
|
async function resolveInstalledMcpProtocolVersions(input) {
|
|
798
1045
|
const resolutionBases = [.../* @__PURE__ */ new Set([...input.modulesDir, input.rootDir])];
|
|
799
1046
|
const sdkResolutionAttempts = resolutionBases.map(
|
|
800
|
-
(base) =>
|
|
1047
|
+
(base) => Promise.resolve().then(() => {
|
|
1048
|
+
const toolkitPackagePath = resolvePackageMetadataPath("@nuxtjs/mcp-toolkit", base, input.modulesDir.includes(base) ? { searchDirectory: base } : void 0);
|
|
1049
|
+
return createRequire(toolkitPackagePath).resolve("@modelcontextprotocol/sdk/types.js");
|
|
1050
|
+
})
|
|
801
1051
|
);
|
|
802
1052
|
return Promise.allSettled(sdkResolutionAttempts).then((results) => {
|
|
803
1053
|
const resolved = results.find((result) => result.status === "fulfilled");
|
|
@@ -852,7 +1102,7 @@ function createMcpServerCardEtag(card) {
|
|
|
852
1102
|
function escapeRegExp(value) {
|
|
853
1103
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
854
1104
|
}
|
|
855
|
-
function ensureStaticHeader(contents, route, name, value) {
|
|
1105
|
+
function ensureStaticHeader(contents, route, name, value, mode = "default") {
|
|
856
1106
|
const eol = contents.includes("\r\n") ? "\r\n" : "\n";
|
|
857
1107
|
const routePattern = new RegExp(`^${escapeRegExp(route)}[\\t ]*\\r?$`, "gm");
|
|
858
1108
|
const routeMatches = [...contents.matchAll(routePattern)];
|
|
@@ -874,13 +1124,60 @@ function ensureStaticHeader(contents, route, name, value) {
|
|
|
874
1124
|
"im"
|
|
875
1125
|
);
|
|
876
1126
|
if (existingHeaderPattern.test(block)) {
|
|
1127
|
+
if (mode === "append") {
|
|
1128
|
+
const removalPattern = new RegExp(`^[\\t ]+![\\t ]*${escapedName}[\\t ]*\\r?$`, "im");
|
|
1129
|
+
if (removalPattern.test(block))
|
|
1130
|
+
return contents;
|
|
1131
|
+
const valuePattern = new RegExp(`^([\\t ]+${escapedName}[\\t ]*:[\\t ]*)([^\\r\\n]*)(\\r?$)`, "im");
|
|
1132
|
+
const match = block.match(valuePattern);
|
|
1133
|
+
if (match) {
|
|
1134
|
+
const merged = block.replace(valuePattern, (_line, prefix2, current, suffix) => {
|
|
1135
|
+
const appended = name.toLowerCase() === "link" ? current.includes(value) ? current : [current, value].filter(Boolean).join(", ") : mergeVaryHeader(current, value);
|
|
1136
|
+
return `${prefix2}${appended}${suffix}`;
|
|
1137
|
+
});
|
|
1138
|
+
return `${contents.slice(0, blockStart)}${merged}${contents.slice(blockEnd)}`;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
877
1141
|
return contents;
|
|
878
1142
|
}
|
|
879
1143
|
const prefix = blockStart === routeLineEnd ? eol : "";
|
|
880
1144
|
return `${contents.slice(0, blockStart)}${prefix} ${name}: ${value}${eol}${contents.slice(blockStart)}`;
|
|
881
1145
|
}
|
|
1146
|
+
function mergeStaticDiscoveryHeaders(contents, baseURL, entries) {
|
|
1147
|
+
if (entries.length === 0)
|
|
1148
|
+
return contents;
|
|
1149
|
+
const route = toDeployedRoute("/*", baseURL);
|
|
1150
|
+
const blocks = splitHeaderBlocks(contents);
|
|
1151
|
+
const matching = blocks.filter((block) => block.route === route);
|
|
1152
|
+
let merged = matching[0]?.text || "";
|
|
1153
|
+
for (const block of matching.slice(1)) {
|
|
1154
|
+
for (const line of block.text.split(/(?<=\n)/).slice(1)) {
|
|
1155
|
+
const header = line.match(/^[\t ]+([^:\s]+):[\t ]*([^\r\n]*)/);
|
|
1156
|
+
if (header?.[1]?.toLowerCase() === "link") {
|
|
1157
|
+
merged = ensureStaticHeader(merged, route, header[1], header[2], "append");
|
|
1158
|
+
} else if (header) {
|
|
1159
|
+
const existing = new RegExp(`^[\\t ]+${escapeRegExp(header[1])}[\\t ]*:[^\\r\\n]*(?:\\r?\\n|$)`, "gim");
|
|
1160
|
+
merged = ensureStaticHeader(merged.replace(existing, ""), route, header[1], header[2]);
|
|
1161
|
+
} else {
|
|
1162
|
+
merged += line;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (matching.length > 1) {
|
|
1167
|
+
let inserted = false;
|
|
1168
|
+
contents = blocks.map((block) => {
|
|
1169
|
+
if (block.route !== route)
|
|
1170
|
+
return block.text;
|
|
1171
|
+
if (inserted)
|
|
1172
|
+
return "";
|
|
1173
|
+
inserted = true;
|
|
1174
|
+
return merged;
|
|
1175
|
+
}).join("");
|
|
1176
|
+
}
|
|
1177
|
+
return entries.reduce((headers, entry) => ensureStaticHeader(headers, route, "Link", entry, "append"), contents);
|
|
1178
|
+
}
|
|
882
1179
|
const CLOUDFLARE_STATIC_HEADER_RULE_LIMIT = 100;
|
|
883
|
-
const RE_EXACT_MARKDOWN_ROUTE
|
|
1180
|
+
const RE_EXACT_MARKDOWN_ROUTE = /^\/[^*\s]*\.md[\t ]*\r?$/;
|
|
884
1181
|
function splitHeaderBlocks(contents) {
|
|
885
1182
|
const blocks = [];
|
|
886
1183
|
let current = { route: null, text: "" };
|
|
@@ -900,7 +1197,7 @@ function enforceStaticHeaderBudget(contents, limit) {
|
|
|
900
1197
|
const ruleCount = blocks.filter((block) => block.route !== null).length;
|
|
901
1198
|
if (ruleCount <= limit)
|
|
902
1199
|
return { contents, total: ruleCount, dropped: 0 };
|
|
903
|
-
const kept = blocks.filter((block) => block.route === null || !RE_EXACT_MARKDOWN_ROUTE
|
|
1200
|
+
const kept = blocks.filter((block) => block.route === null || !RE_EXACT_MARKDOWN_ROUTE.test(block.route));
|
|
904
1201
|
return {
|
|
905
1202
|
contents: kept.map((block) => block.text).join(""),
|
|
906
1203
|
total: kept.filter((block) => block.route !== null).length,
|
|
@@ -908,85 +1205,6 @@ function enforceStaticHeaderBudget(contents, limit) {
|
|
|
908
1205
|
};
|
|
909
1206
|
}
|
|
910
1207
|
|
|
911
|
-
const RE_MD_EXT = /\.md$/;
|
|
912
|
-
function isStaticMarkdownSourceRoute(route) {
|
|
913
|
-
if (route.includes("*") || route.includes(":"))
|
|
914
|
-
return false;
|
|
915
|
-
return hasMarkdownTwin(route.split("?")[0] || route);
|
|
916
|
-
}
|
|
917
|
-
function staticDescribedbyEntry(baseURL) {
|
|
918
|
-
return `<${encodeURI(toDeployedRoute("/llms.txt", baseURL))}>; rel="describedby"`;
|
|
919
|
-
}
|
|
920
|
-
function buildStaticMarkdownLinkHeader(route, baseURL, describedby) {
|
|
921
|
-
const htmlRoute = encodeURI(toDeployedRoute(normalizePagePath(route), baseURL));
|
|
922
|
-
const parts = [
|
|
923
|
-
`<${htmlRoute}>; rel="alternate"; type="text/html"`,
|
|
924
|
-
`<${htmlRoute}>; rel="canonical"`
|
|
925
|
-
];
|
|
926
|
-
if (describedby)
|
|
927
|
-
parts.push(staticDescribedbyEntry(baseURL));
|
|
928
|
-
return parts.join(", ");
|
|
929
|
-
}
|
|
930
|
-
function pageRouteFromMarkdownTwin(fileName) {
|
|
931
|
-
if (!fileName?.endsWith(".md") || fileName === SITEMAP_MD_ROUTE)
|
|
932
|
-
return null;
|
|
933
|
-
const pageRoute = normalizePagePath(fileName.replace(RE_MD_EXT, ""));
|
|
934
|
-
if (pageRoute === "/index")
|
|
935
|
-
return "/";
|
|
936
|
-
return isStaticMarkdownSourceRoute(pageRoute) ? pageRoute : null;
|
|
937
|
-
}
|
|
938
|
-
function prerenderedMarkdownHeaderRules(prerenderedRoutes, baseURL, describedby, artifactRoutes) {
|
|
939
|
-
const artifacts = new Set(artifactRoutes);
|
|
940
|
-
const rules = /* @__PURE__ */ new Map();
|
|
941
|
-
for (const entry of prerenderedRoutes) {
|
|
942
|
-
if (entry.route !== void 0 && artifacts.has(entry.route) || entry.fileName !== void 0 && artifacts.has(entry.fileName)) {
|
|
943
|
-
continue;
|
|
944
|
-
}
|
|
945
|
-
const pageRoute = pageRouteFromMarkdownTwin(entry.fileName);
|
|
946
|
-
if (pageRoute === null)
|
|
947
|
-
continue;
|
|
948
|
-
const mdRoute = toMarkdownPath(pageRoute);
|
|
949
|
-
if (!rules.has(mdRoute)) {
|
|
950
|
-
rules.set(mdRoute, {
|
|
951
|
-
route: mdRoute,
|
|
952
|
-
headers: {
|
|
953
|
-
"Content-Type": "text/markdown; charset=utf-8",
|
|
954
|
-
"Link": buildStaticMarkdownLinkHeader(pageRoute, baseURL, describedby)
|
|
955
|
-
}
|
|
956
|
-
});
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
return [...rules.values()];
|
|
960
|
-
}
|
|
961
|
-
const RE_EXACT_MARKDOWN_ROUTE = /^\/[^*:\s]*\.md$/;
|
|
962
|
-
function isStaticHeaderRouteRule([, rule]) {
|
|
963
|
-
return Boolean(rule && "headers" in rule && rule.headers);
|
|
964
|
-
}
|
|
965
|
-
function planStaticMarkdownHeaderRules(routeRules, rules, limit) {
|
|
966
|
-
if (limit === null)
|
|
967
|
-
return { _tag: "apply", rules };
|
|
968
|
-
const entries = Object.entries(routeRules).filter(isStaticHeaderRouteRule);
|
|
969
|
-
const registeredMarkdown = entries.map(([route]) => route).filter((route) => RE_EXACT_MARKDOWN_ROUTE.test(route));
|
|
970
|
-
const other = entries.length - registeredMarkdown.length;
|
|
971
|
-
const markdown = /* @__PURE__ */ new Set([...registeredMarkdown, ...rules.map((rule) => rule.route)]);
|
|
972
|
-
const total = other + markdown.size;
|
|
973
|
-
if (total <= limit)
|
|
974
|
-
return { _tag: "apply", rules };
|
|
975
|
-
return { _tag: "skip", drop: registeredMarkdown, total, dropped: markdown.size };
|
|
976
|
-
}
|
|
977
|
-
function applyStaticMarkdownHeaderPlan(routeRules, plan) {
|
|
978
|
-
if (plan._tag === "skip") {
|
|
979
|
-
for (const route of plan.drop) {
|
|
980
|
-
const rule = routeRules[route];
|
|
981
|
-
if (rule)
|
|
982
|
-
rule.headers = void 0;
|
|
983
|
-
}
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
for (const { route, headers } of plan.rules)
|
|
987
|
-
routeRules[route] = defu({ headers }, routeRules[route]);
|
|
988
|
-
}
|
|
989
|
-
|
|
990
1208
|
const DEFAULT_MAX_OUTPUT_CHARS = 1500;
|
|
991
1209
|
const DEFAULT_LIST_LIMIT = 20;
|
|
992
1210
|
const DEFAULT_SEARCH_LIMIT = 10;
|
|
@@ -1104,22 +1322,24 @@ const module$1 = defineNuxtModule({
|
|
|
1104
1322
|
meta: {
|
|
1105
1323
|
name: "nuxt-ai-ready",
|
|
1106
1324
|
compatibility: {
|
|
1107
|
-
nuxt: "
|
|
1325
|
+
nuxt: "^4.6.0 || ^5.0.0-0"
|
|
1108
1326
|
},
|
|
1109
1327
|
configKey: "aiReady"
|
|
1110
1328
|
},
|
|
1111
1329
|
moduleDependencies: {
|
|
1112
|
-
"@nuxtjs/robots": {
|
|
1113
|
-
version: ">=
|
|
1330
|
+
[fileURLToPath(import.meta.resolve("@nuxtjs/robots"))]: {
|
|
1331
|
+
version: ">=7.0.0"
|
|
1114
1332
|
},
|
|
1115
|
-
"@nuxtjs/sitemap": {
|
|
1116
|
-
version: ">=
|
|
1333
|
+
[fileURLToPath(import.meta.resolve("@nuxtjs/sitemap"))]: {
|
|
1334
|
+
version: ">=9.0.0"
|
|
1117
1335
|
},
|
|
1118
|
-
|
|
1119
|
-
|
|
1336
|
+
// Keep package-relative resolution until the minimum Nuxt version includes this fix:
|
|
1337
|
+
// https://github.com/nuxt/nuxt/pull/36542
|
|
1338
|
+
[fileURLToPath(import.meta.resolve("nuxt-site-config"))]: {
|
|
1339
|
+
version: ">=5.0.0"
|
|
1120
1340
|
},
|
|
1121
|
-
"nuxtseo-shared": {
|
|
1122
|
-
version: ">=
|
|
1341
|
+
[fileURLToPath(import.meta.resolve("nuxtseo-shared"))]: {
|
|
1342
|
+
version: ">=6.0.0"
|
|
1123
1343
|
},
|
|
1124
1344
|
"@nuxtjs/mcp-toolkit": {
|
|
1125
1345
|
version: ">=0.18.0",
|
|
@@ -1148,13 +1368,14 @@ const module$1 = defineNuxtModule({
|
|
|
1148
1368
|
const resolveFromModule = createRequire(moduleEntryUrl);
|
|
1149
1369
|
const nuxtSeoSharedI18nRuntimePath = resolveFromModule.resolve("nuxtseo-shared/i18n-runtime");
|
|
1150
1370
|
const nuxtSeoSharedUtilsPath = resolveFromModule.resolve("nuxtseo-shared/utils");
|
|
1151
|
-
const { resolve } = createResolver(moduleEntryUrl);
|
|
1152
|
-
const { version } = await
|
|
1371
|
+
const { resolve: resolve$1 } = createResolver(moduleEntryUrl);
|
|
1372
|
+
const { version, peerDependencies } = await readPackageMetadata(resolve$1("../package.json"));
|
|
1153
1373
|
logger.level = config.debug || nuxt.options.debug ? 4 : 3;
|
|
1154
1374
|
if (config.enabled === false) {
|
|
1155
1375
|
logger.debug("Module is disabled, skipping setup.");
|
|
1156
1376
|
return;
|
|
1157
1377
|
}
|
|
1378
|
+
setupRuntimeAliases({ namespace: "#ai-ready", app: resolve$1("./runtime/app"), server: resolve$1("./runtime/server") }, nuxt);
|
|
1158
1379
|
const agentSkillsConfig = config.agentSkills === false ? false : config.agentSkills ?? {};
|
|
1159
1380
|
const agentSkillsError = (issues) => {
|
|
1160
1381
|
const details = issues.map((issue) => `${issue.index === void 0 ? "agentSkills" : `agentSkills.skills[${issue.index}]`}.${issue.field}: ${issue.message}`).join("\n");
|
|
@@ -1166,7 +1387,8 @@ ${details}`);
|
|
|
1166
1387
|
const { applyRootAlias, prepareAgentSkills, resolveAgentSkillsConfig } = await import('../chunks/agent-skills.mjs');
|
|
1167
1388
|
const prepared = await prepareAgentSkills(agentSkillsConfig, {
|
|
1168
1389
|
rootDir: nuxt.options.rootDir,
|
|
1169
|
-
scanDirs: nuxt.
|
|
1390
|
+
scanDirs: getLayerDirectories(nuxt).map((layer) => layer.root),
|
|
1391
|
+
publicDirs: getLayerDirectories(nuxt).map((layer) => layer.public)
|
|
1170
1392
|
});
|
|
1171
1393
|
if (prepared._tag === "Invalid")
|
|
1172
1394
|
throw agentSkillsError(prepared.issues);
|
|
@@ -1178,7 +1400,7 @@ ${details}`);
|
|
|
1178
1400
|
agentSkillsResult = await resolveAgentSkillsConfig(
|
|
1179
1401
|
{ ...agentSkillsConfig, skills: rooted.skills },
|
|
1180
1402
|
nuxt.options.rootDir,
|
|
1181
|
-
{ sitemapMd: config.sitemapMd !== false }
|
|
1403
|
+
{ sitemapMd: config.sitemapMd !== false, publicDirs: getLayerDirectories(nuxt).map((layer) => layer.public) }
|
|
1182
1404
|
);
|
|
1183
1405
|
if (agentSkillsResult._tag === "Invalid")
|
|
1184
1406
|
throw agentSkillsError(agentSkillsResult.issues);
|
|
@@ -1205,18 +1427,19 @@ ${details}`);
|
|
|
1205
1427
|
});
|
|
1206
1428
|
const mcpNeedsDatabase = mcpToolkitState._tag === "Enabled" && (config.mcp?.resources !== false || config.mcp?.tools !== false && Object.values(requestedSiteTools.config).some((tool) => tool.mcp.enabled));
|
|
1207
1429
|
const webmcpNeedsDatabase = !!config.webmcp && (config.webmcp === true || config.webmcp.tools !== false) && Object.values(requestedSiteTools.config).some((tool) => tool.webmcp.enabled);
|
|
1430
|
+
const databaseRequested = {
|
|
1431
|
+
runtimeSync: !!config.runtimeSync,
|
|
1432
|
+
cron: !!config.cron,
|
|
1433
|
+
mcp: mcpNeedsDatabase,
|
|
1434
|
+
webmcp: webmcpNeedsDatabase
|
|
1435
|
+
};
|
|
1208
1436
|
const databaseResolution = resolveDatabaseConfig({
|
|
1209
1437
|
database: config.database,
|
|
1210
1438
|
rootDir: nuxt.options.rootDir,
|
|
1211
1439
|
preset: String(nuxt.options.nitro.preset || ""),
|
|
1212
1440
|
// Vercel Postgres sets POSTGRES_URL.
|
|
1213
1441
|
hasPostgresUrl: !!(process.env.POSTGRES_URL || process.env.DATABASE_URL || (config.database || void 0)?.url),
|
|
1214
|
-
requested:
|
|
1215
|
-
runtimeSync: !!config.runtimeSync,
|
|
1216
|
-
cron: !!config.cron,
|
|
1217
|
-
mcp: mcpNeedsDatabase,
|
|
1218
|
-
webmcp: webmcpNeedsDatabase
|
|
1219
|
-
}
|
|
1442
|
+
requested: databaseRequested
|
|
1220
1443
|
});
|
|
1221
1444
|
if (databaseResolution._tag === "Invalid")
|
|
1222
1445
|
throw new Error(`[nuxt-ai-ready] ${databaseResolution.message}`);
|
|
@@ -1224,6 +1447,11 @@ ${details}`);
|
|
|
1224
1447
|
logger[log.level](log.message);
|
|
1225
1448
|
const database = databaseResolution.database;
|
|
1226
1449
|
const databaseEnabled = database._tag === "Enabled";
|
|
1450
|
+
if (databaseEnabled) {
|
|
1451
|
+
const drizzle = await tryResolveModule("drizzle-orm", directoryToURL(nuxt.options.rootDir));
|
|
1452
|
+
if (!drizzle)
|
|
1453
|
+
throw new Error(`[nuxt-ai-ready] ${formatMissingDrizzleMessage({ requested: databaseRequested, peerRange: peerDependencies["drizzle-orm"] })}`);
|
|
1454
|
+
}
|
|
1227
1455
|
if (!databaseEnabled)
|
|
1228
1456
|
logger.debug("Database disabled. Page storage, runtime indexing and site tools are off.");
|
|
1229
1457
|
const siteToolsResult = databaseEnabled ? requestedSiteTools : resolveSiteToolsConfig(config.tools, { database });
|
|
@@ -1231,7 +1459,6 @@ ${details}`);
|
|
|
1231
1459
|
logger.warn(warning);
|
|
1232
1460
|
const siteToolsConfig = siteToolsResult.config;
|
|
1233
1461
|
const hasMcpSiteTools = Object.values(siteToolsConfig).some((tool) => tool.mcp.enabled);
|
|
1234
|
-
await installNuxtSiteConfig();
|
|
1235
1462
|
const nitroCompatibility = setupNitroRuntimeCompatibility(nuxt);
|
|
1236
1463
|
const siteConfig = useSiteConfig();
|
|
1237
1464
|
const apiCatalogResult = resolveApiCatalogConfig(config.apiCatalog, {
|
|
@@ -1260,6 +1487,10 @@ ${details}`);
|
|
|
1260
1487
|
nuxt.options.mcp = configuredMcpOptions;
|
|
1261
1488
|
nuxt.options.mcp.name = mcpServerCardName;
|
|
1262
1489
|
}
|
|
1490
|
+
if (nuxt.options.mcp !== false && config.mcp?.tools !== false && hasMcpSiteTools) {
|
|
1491
|
+
nuxt.options.mcp = configuredMcpOptions;
|
|
1492
|
+
nuxt.options.mcp.instructions ??= "Use this server when you need information from this site's indexed pages. Read the available tool descriptions before choosing a tool.";
|
|
1493
|
+
}
|
|
1263
1494
|
const i18nConfig = await detectI18n({ autoI18n: config.autoI18n });
|
|
1264
1495
|
if (i18nConfig) {
|
|
1265
1496
|
logger.info(`i18n detected: ${i18nConfig.locales.length} locales (default: ${i18nConfig.defaultLocale}, strategy: ${i18nConfig.strategy})`);
|
|
@@ -1289,7 +1520,7 @@ ${details}`);
|
|
|
1289
1520
|
});
|
|
1290
1521
|
}
|
|
1291
1522
|
const ftsTokenizer = i18nConfig && hasCjkLocale(i18nConfig) ? "trigram" : "unicode61 remove_diacritics 2";
|
|
1292
|
-
nuxt.options.alias["#ai-ready"] = resolve("./runtime");
|
|
1523
|
+
nuxt.options.alias["#ai-ready"] = resolve$1("./runtime");
|
|
1293
1524
|
addServerImports([
|
|
1294
1525
|
"countPages",
|
|
1295
1526
|
"indexPage",
|
|
@@ -1299,26 +1530,11 @@ ${details}`);
|
|
|
1299
1530
|
"streamPages"
|
|
1300
1531
|
].map((name) => ({
|
|
1301
1532
|
name,
|
|
1302
|
-
from: resolve("./runtime")
|
|
1533
|
+
from: resolve$1("./runtime")
|
|
1303
1534
|
})));
|
|
1304
|
-
let betterSqlite3Availability;
|
|
1305
|
-
const hasBetterSqlite3 = () => {
|
|
1306
|
-
betterSqlite3Availability ||= resolvePackageJSON("better-sqlite3", { from: nuxt.options.rootDir }).then(
|
|
1307
|
-
() => true,
|
|
1308
|
-
// Missing is expected when no requested feature uses SQLite.
|
|
1309
|
-
() => false
|
|
1310
|
-
);
|
|
1311
|
-
return betterSqlite3Availability;
|
|
1312
|
-
};
|
|
1313
|
-
const nativeNodeSqlite = supportsNativeNodeSqlite(process.versions.node || "");
|
|
1314
|
-
if (database._tag === "Enabled" && database.type === "sqlite" && !nativeNodeSqlite && !await hasBetterSqlite3()) {
|
|
1315
|
-
throw new Error(
|
|
1316
|
-
`[nuxt-ai-ready] SQLite needs "better-sqlite3" on Node ${process.versions.node}, but it isn't installed. Add it to your app: \`npm i better-sqlite3\` (or \`pnpm add\` / \`yarn add\`). Node 22.13 and later use built-in \`node:sqlite\`. For edge deployments, configure D1, Neon, LibSQL, or Bun instead.`
|
|
1317
|
-
);
|
|
1318
|
-
}
|
|
1319
1535
|
let mcpAvailable = mcpToolkitState._tag === "Enabled";
|
|
1320
1536
|
nuxt.hook("mcp:definitions:paths", (paths) => {
|
|
1321
|
-
const mcpRuntimeDir = resolve("./runtime/server/mcp");
|
|
1537
|
+
const mcpRuntimeDir = resolve$1("./runtime/server/mcp");
|
|
1322
1538
|
const mcpConfig = config.mcp || {};
|
|
1323
1539
|
if (mcpConfig.tools !== false && hasMcpSiteTools)
|
|
1324
1540
|
(paths.tools ||= []).push(`${mcpRuntimeDir}/tools`);
|
|
@@ -1396,18 +1612,13 @@ ${details}`);
|
|
|
1396
1612
|
const hasPrerenderedRoutes = !!(nuxt.options.nitro.prerender?.routes?.length || nuxt.options.nitro.prerender?.crawlLinks);
|
|
1397
1613
|
const preparing = nuxt.options._prepare === true;
|
|
1398
1614
|
const prerenderEnabled = !preparing && !!(isStatic || hasPrerenderedRoutes);
|
|
1399
|
-
if (prerenderEnabled && !nativeNodeSqlite && !await hasBetterSqlite3()) {
|
|
1400
|
-
throw new Error(
|
|
1401
|
-
`[nuxt-ai-ready] Build time page indexing needs "better-sqlite3" on Node ${process.versions.node}. Add it to your app: \`npm i better-sqlite3\` (or \`pnpm add\` / \`yarn add\`). Node 22.13 and later need no extra package.`
|
|
1402
|
-
);
|
|
1403
|
-
}
|
|
1404
1615
|
const isSPA = nuxt.options.ssr === false;
|
|
1405
1616
|
let apiCatalogRegistered = false;
|
|
1406
1617
|
const registerApiCatalog = (catalog) => {
|
|
1407
1618
|
if (apiCatalogRegistered)
|
|
1408
1619
|
return;
|
|
1409
1620
|
apiCatalogRegistered = true;
|
|
1410
|
-
addServerHandler({ route: API_CATALOG_PATH, handler: resolve("./runtime/server/routes/api-catalog"), lazy: true });
|
|
1621
|
+
addServerHandler({ route: API_CATALOG_PATH, handler: resolve$1("./runtime/server/routes/api-catalog"), lazy: true });
|
|
1411
1622
|
const apiCatalogLink = `<${catalog.href}>; rel="api-catalog"`;
|
|
1412
1623
|
extendRouteRules("/**", {
|
|
1413
1624
|
headers: { Link: apiCatalogLink }
|
|
@@ -1466,7 +1677,7 @@ ${details}`);
|
|
|
1466
1677
|
const mcpLink = {
|
|
1467
1678
|
title: "MCP",
|
|
1468
1679
|
href: withSiteUrl(finalMcpToolkitState.route, { withBase: true }),
|
|
1469
|
-
description: "Model Context Protocol server endpoint for AI agent integration."
|
|
1680
|
+
description: config.mcp?.tools !== false && hasMcpSiteTools ? "Use this MCP endpoint when you need information from this site's indexed pages." : "Model Context Protocol server endpoint for AI agent integration."
|
|
1470
1681
|
};
|
|
1471
1682
|
const firstSection = mergedLlmsTxt.sections?.[0];
|
|
1472
1683
|
if (firstSection) {
|
|
@@ -1550,7 +1761,7 @@ ${details}`);
|
|
|
1550
1761
|
cacheMaxAge: mcpServerCardResult.config.cacheMaxAge,
|
|
1551
1762
|
etag
|
|
1552
1763
|
};
|
|
1553
|
-
const handler = resolve("./runtime/server/routes/mcp-server-card");
|
|
1764
|
+
const handler = resolve$1("./runtime/server/routes/mcp-server-card");
|
|
1554
1765
|
addServerHandler({ route: mcpServerCardRoute, method: "get", handler, lazy: true });
|
|
1555
1766
|
addServerHandler({ route: mcpServerCardRoute, method: "head", handler, lazy: true });
|
|
1556
1767
|
addServerHandler({ route: mcpServerCardRoute, method: "options", handler, lazy: true });
|
|
@@ -1570,6 +1781,8 @@ ${details}`);
|
|
|
1570
1781
|
const document = resolveAiCatalog({
|
|
1571
1782
|
siteUrl: siteConfig.url,
|
|
1572
1783
|
serverCardName: card.name,
|
|
1784
|
+
serverCardTitle: card.title,
|
|
1785
|
+
serverCardDescription: card.description,
|
|
1573
1786
|
serverCardUrl: withSiteUrl(mcpServerCardRoute, { withBase: true })
|
|
1574
1787
|
});
|
|
1575
1788
|
const aiCatalogEtag = createAiCatalogEtag(document);
|
|
@@ -1579,22 +1792,24 @@ ${details}`);
|
|
|
1579
1792
|
document,
|
|
1580
1793
|
etag: aiCatalogEtag
|
|
1581
1794
|
};
|
|
1582
|
-
const aiCatalogHandler = resolve("./runtime/server/routes/ai-catalog");
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1795
|
+
const aiCatalogHandler = resolve$1("./runtime/server/routes/ai-catalog");
|
|
1796
|
+
for (const route of [ARD_PATH, AI_CATALOG_PATH]) {
|
|
1797
|
+
addServerHandler({ route, method: "get", handler: aiCatalogHandler, lazy: true });
|
|
1798
|
+
addServerHandler({ route, method: "head", handler: aiCatalogHandler, lazy: true });
|
|
1799
|
+
addServerHandler({ route, method: "options", handler: aiCatalogHandler, lazy: true });
|
|
1800
|
+
extendRouteRules(route, {
|
|
1801
|
+
sitemap: false,
|
|
1802
|
+
headers: {
|
|
1803
|
+
"Access-Control-Allow-Headers": "Content-Type, If-None-Match",
|
|
1804
|
+
"Access-Control-Allow-Methods": "GET, HEAD",
|
|
1805
|
+
"Access-Control-Allow-Origin": "*",
|
|
1806
|
+
"Access-Control-Expose-Headers": "ETag",
|
|
1807
|
+
"Cache-Control": `public, max-age=${aiCatalogCacheMaxAge}`,
|
|
1808
|
+
"Content-Type": AI_CATALOG_MEDIA_TYPE,
|
|
1809
|
+
"ETag": aiCatalogEtag
|
|
1810
|
+
}
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1598
1813
|
}
|
|
1599
1814
|
});
|
|
1600
1815
|
const sitemapConfig = nuxt.options.sitemap;
|
|
@@ -1614,6 +1829,15 @@ ${details}`);
|
|
|
1614
1829
|
await writeFile(join(cacheDir, "secret"), runtimeSyncSecret);
|
|
1615
1830
|
}
|
|
1616
1831
|
nuxt.hooks.hook("nitro:config", (nitroConfig) => {
|
|
1832
|
+
if (getNitroVersion(nuxt) === 3) {
|
|
1833
|
+
const nativeConfig = nitroConfig;
|
|
1834
|
+
if (nativeConfig.noExternals !== true)
|
|
1835
|
+
nativeConfig.noExternals = [...nativeConfig.noExternals || [], "nuxt-ai-ready"];
|
|
1836
|
+
} else {
|
|
1837
|
+
const externals = nitroConfig.externals ||= {};
|
|
1838
|
+
externals.inline ||= [];
|
|
1839
|
+
externals.inline.push(resolve$1("./runtime"));
|
|
1840
|
+
}
|
|
1617
1841
|
nitroConfig.experimental = nitroConfig.experimental || {};
|
|
1618
1842
|
nitroConfig.experimental.asyncContext = true;
|
|
1619
1843
|
const preset = String(nitroConfig.preset || "");
|
|
@@ -1622,20 +1846,11 @@ ${details}`);
|
|
|
1622
1846
|
nitroConfig.experimental.wasm = true;
|
|
1623
1847
|
if (nitroCompatibility._tag === "nitro-v3") {
|
|
1624
1848
|
const nitro3Config = nitroConfig;
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
nitro3Config.noExternals = noExternals;
|
|
1849
|
+
if (nitro3Config.noExternals !== true)
|
|
1850
|
+
nitro3Config.noExternals = [...nitro3Config.noExternals || [], "sitemapd"];
|
|
1628
1851
|
if (!isEdgePreset) {
|
|
1629
1852
|
nitro3Config.traceDeps ||= [];
|
|
1630
1853
|
nitro3Config.traceDeps.push("mdream*");
|
|
1631
|
-
nitro3Config.rolldownConfig ||= {};
|
|
1632
|
-
const external = nitro3Config.rolldownConfig.external;
|
|
1633
|
-
if (Array.isArray(external))
|
|
1634
|
-
external.push("mdream");
|
|
1635
|
-
else if (typeof external === "string" || external instanceof RegExp)
|
|
1636
|
-
nitro3Config.rolldownConfig.external = [external, "mdream"];
|
|
1637
|
-
else if (!external)
|
|
1638
|
-
nitro3Config.rolldownConfig.external = ["mdream"];
|
|
1639
1854
|
}
|
|
1640
1855
|
} else {
|
|
1641
1856
|
const externals = nitroConfig.externals ||= {};
|
|
@@ -1666,7 +1881,7 @@ ${details}`);
|
|
|
1666
1881
|
nitroConfig.experimental.tasks = true;
|
|
1667
1882
|
nitroConfig.tasks = nitroConfig.tasks || {};
|
|
1668
1883
|
nitroConfig.tasks["ai-ready:cron"] = {
|
|
1669
|
-
handler: resolve("./runtime/server/tasks/ai-ready-cron")
|
|
1884
|
+
handler: resolve$1("./runtime/server/tasks/ai-ready-cron")
|
|
1670
1885
|
};
|
|
1671
1886
|
nitroConfig.scheduledTasks = nitroConfig.scheduledTasks || {};
|
|
1672
1887
|
nitroConfig.scheduledTasks[cronSchedule] = nitroConfig.scheduledTasks[cronSchedule] || [];
|
|
@@ -1701,7 +1916,6 @@ export const localAgentSkillArtifacts = ${JSON.stringify(agentSkillsResult.local
|
|
|
1701
1916
|
nitroConfig.virtual["#ai-ready-virtual/read-page-data.mjs"] = createBuildPageDataVirtual({
|
|
1702
1917
|
buildDbPath,
|
|
1703
1918
|
markdownLinkAvailabilityPath,
|
|
1704
|
-
nativeNodeSqlite,
|
|
1705
1919
|
dev: nuxt.options.dev
|
|
1706
1920
|
});
|
|
1707
1921
|
nitroConfig.virtual["#ai-ready-virtual/page-data.mjs"] = `export const pages = []
|
|
@@ -1711,7 +1925,7 @@ import { createModuleLogger } from ${JSON.stringify(nuxtSeoSharedUtilsPath)}
|
|
|
1711
1925
|
export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
1712
1926
|
`;
|
|
1713
1927
|
const providerMap = {
|
|
1714
|
-
sqlite:
|
|
1928
|
+
sqlite: "#ai-ready/server/db/drizzle/providers/node-sqlite",
|
|
1715
1929
|
bun: "#ai-ready/server/db/drizzle/providers/bun",
|
|
1716
1930
|
d1: "#ai-ready/server/db/drizzle/providers/d1",
|
|
1717
1931
|
libsql: "#ai-ready/server/db/drizzle/providers/libsql",
|
|
@@ -1721,8 +1935,52 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1721
1935
|
nitroConfig.virtual["#ai-ready-virtual/db-provider.mjs"] = database._tag === "Enabled" ? `export { createClient } from '${providerMap[database.type] || providerMap.sqlite}'` : `export function createClient() {
|
|
1722
1936
|
throw new Error('[nuxt-ai-ready] The database is disabled. Set \`aiReady.database\` to store pages at runtime.')
|
|
1723
1937
|
}`;
|
|
1938
|
+
const databaseRuntime = "#ai-ready-virtual/database-runtime.mjs";
|
|
1939
|
+
if (database._tag === "Disabled") {
|
|
1940
|
+
const databaseExports = [
|
|
1941
|
+
"useDrizzle",
|
|
1942
|
+
"useRawDb",
|
|
1943
|
+
"completeCronRun",
|
|
1944
|
+
"countPages",
|
|
1945
|
+
"deleteInfoValue",
|
|
1946
|
+
"getAllPages",
|
|
1947
|
+
"getContentHashes",
|
|
1948
|
+
"getInfoValue",
|
|
1949
|
+
"getNextSitemapToCrawl",
|
|
1950
|
+
"getPageByRoute",
|
|
1951
|
+
"getPageLastmods",
|
|
1952
|
+
"getPendingPages",
|
|
1953
|
+
"getRecentCronRuns",
|
|
1954
|
+
"getSitemapStatus",
|
|
1955
|
+
"initSchema",
|
|
1956
|
+
"markPageIndexed",
|
|
1957
|
+
"markRoutesPending",
|
|
1958
|
+
"markSitemapCrawled",
|
|
1959
|
+
"markSitemapCrawlPartial",
|
|
1960
|
+
"markSitemapError",
|
|
1961
|
+
"markSitemapSeeded",
|
|
1962
|
+
"resetSitemapErrors",
|
|
1963
|
+
"searchPages",
|
|
1964
|
+
"seedRoutes",
|
|
1965
|
+
"setInfoValue",
|
|
1966
|
+
"startCronRun",
|
|
1967
|
+
"syncSitemaps",
|
|
1968
|
+
"upsertPage"
|
|
1969
|
+
];
|
|
1970
|
+
nitroConfig.virtual[databaseRuntime] = `
|
|
1971
|
+
async function unavailable() {
|
|
1972
|
+
throw new Error('[nuxt-ai-ready] The database is disabled. Set \`aiReady.database\` to store pages at runtime.')
|
|
1973
|
+
}
|
|
1974
|
+
export { ${databaseExports.map((name) => `unavailable as ${name}`).join(", ")} }
|
|
1975
|
+
export async function closeDrizzle() {}
|
|
1976
|
+
export async function finishDrizzleResponse() {}
|
|
1977
|
+
export function trackDrizzleWork(event, work) { return work }
|
|
1978
|
+
`;
|
|
1979
|
+
} else {
|
|
1980
|
+
nitroConfig.virtual[databaseRuntime] = `export * from '#ai-ready/server/db/drizzle'`;
|
|
1981
|
+
}
|
|
1724
1982
|
const schemaPath = database._tag === "Enabled" && (database.type === "neon" || database.type === "postgres") ? "#ai-ready/server/db/schema/postgres" : "#ai-ready/server/db/schema/sqlite";
|
|
1725
|
-
nitroConfig.virtual["#ai-ready-virtual/db-schema.mjs"] = `export * from '${schemaPath}'
|
|
1983
|
+
nitroConfig.virtual["#ai-ready-virtual/db-schema.mjs"] = database._tag === "Enabled" ? `export * from '${schemaPath}'` : "export {}";
|
|
1726
1984
|
nitroConfig.virtual["#ai-ready-virtual/devtools-meta.mjs"] = `export const devtoolsMeta = ${JSON.stringify({
|
|
1727
1985
|
contentSignal: config.contentSignal || false,
|
|
1728
1986
|
mcp: { enabled: mcpAvailable, tools: mcpAvailable && config.mcp?.tools !== false && hasMcpSiteTools, resources: mcpAvailable && config.mcp?.resources !== false },
|
|
@@ -1735,6 +1993,7 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1735
1993
|
debug: config.debug || false,
|
|
1736
1994
|
debugCron: config.debugCron || false,
|
|
1737
1995
|
contentNegotiation: config.contentNegotiation === void 0 ? "auto" : config.contentNegotiation ? "enabled" : "disabled",
|
|
1996
|
+
botNegotiation: config.botNegotiation === true,
|
|
1738
1997
|
mdreamOptions: config.mdreamOptions || {},
|
|
1739
1998
|
sitemapMd: config.sitemapMd !== false,
|
|
1740
1999
|
describedby: config.describedby !== false,
|
|
@@ -1759,35 +2018,38 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1759
2018
|
apiCatalog: apiCatalogConfig
|
|
1760
2019
|
};
|
|
1761
2020
|
if (prerenderEnabled) {
|
|
1762
|
-
|
|
2021
|
+
addNitroPlugin(resolve$1("./runtime/server/plugins/html-capture.prerender"));
|
|
1763
2022
|
addServerHandler({
|
|
1764
2023
|
middleware: true,
|
|
1765
|
-
handler: resolve("./runtime/server/middleware/markdown.prerender")
|
|
2024
|
+
handler: resolve$1("./runtime/server/middleware/markdown.prerender")
|
|
1766
2025
|
});
|
|
1767
2026
|
addPlugin({
|
|
1768
2027
|
mode: "server",
|
|
1769
|
-
src: resolve("./runtime/app/plugins/md-hints.prerender")
|
|
2028
|
+
src: resolve$1("./runtime/app/plugins/md-hints.prerender")
|
|
1770
2029
|
});
|
|
1771
2030
|
}
|
|
1772
2031
|
addServerHandler({
|
|
1773
2032
|
middleware: true,
|
|
1774
|
-
handler: resolve("./runtime/server/middleware/markdown")
|
|
2033
|
+
handler: resolve$1("./runtime/server/middleware/markdown")
|
|
1775
2034
|
});
|
|
1776
|
-
|
|
1777
|
-
|
|
2035
|
+
if (getNitroVersion(nuxt) === 3) {
|
|
2036
|
+
extendRouteRules("/**.md", { cache: false });
|
|
2037
|
+
}
|
|
2038
|
+
addNitroPlugin(resolve$1(getNitroVersion(nuxt) === 3 ? "./runtime/server/plugins/link-header-nitro3" : "./runtime/server/plugins/link-header"));
|
|
2039
|
+
addNitroPlugin(resolve$1("./runtime/server/plugins/markdown-negotiation"));
|
|
1778
2040
|
addPlugin({
|
|
1779
2041
|
mode: "server",
|
|
1780
|
-
src: resolve("./runtime/app/plugins/md-alternate.server")
|
|
2042
|
+
src: resolve$1("./runtime/app/plugins/md-alternate.server")
|
|
1781
2043
|
});
|
|
1782
|
-
addServerHandler({ route: "/llms.txt", handler: resolve("./runtime/server/routes/llms.txt.get"), lazy: true });
|
|
1783
|
-
addServerHandler({ route: "/llms-full.txt", handler: resolve("./runtime/server/routes/llms-full.txt.get"), lazy: true });
|
|
2044
|
+
addServerHandler({ route: "/llms.txt", handler: resolve$1("./runtime/server/routes/llms.txt.get"), lazy: true });
|
|
2045
|
+
addServerHandler({ route: "/llms-full.txt", handler: resolve$1("./runtime/server/routes/llms-full.txt.get"), lazy: true });
|
|
1784
2046
|
if (config.sitemapMd !== false) {
|
|
1785
|
-
addServerHandler({ route: SITEMAP_MD_ROUTE, handler: resolve("./runtime/server/routes/sitemap.md.get"), lazy: true });
|
|
2047
|
+
addServerHandler({ route: SITEMAP_MD_ROUTE, handler: resolve$1("./runtime/server/routes/sitemap.md.get"), lazy: true });
|
|
1786
2048
|
}
|
|
1787
2049
|
if (agentSkillsResult._tag === "Enabled") {
|
|
1788
|
-
addServerHandler({ route: AGENT_SKILLS_INDEX_ROUTE, handler: resolve("./runtime/server/routes/agent-skills-index"), lazy: true });
|
|
2050
|
+
addServerHandler({ route: AGENT_SKILLS_INDEX_ROUTE, handler: resolve$1("./runtime/server/routes/agent-skills-index"), lazy: true });
|
|
1789
2051
|
for (const route of Object.keys(agentSkillsResult.localArtifacts)) {
|
|
1790
|
-
addServerHandler({ route, handler: resolve("./runtime/server/routes/agent-skills-artifact"), lazy: true });
|
|
2052
|
+
addServerHandler({ route, handler: resolve$1("./runtime/server/routes/agent-skills-artifact"), lazy: true });
|
|
1791
2053
|
extendRouteRules(route, {
|
|
1792
2054
|
headers: {
|
|
1793
2055
|
"Content-Type": "text/markdown; charset=utf-8",
|
|
@@ -1820,39 +2082,38 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1820
2082
|
if (webmcpConfig) {
|
|
1821
2083
|
addImports(["useWebMcpSupported", "useWebMcpTool"].map((name) => ({
|
|
1822
2084
|
name,
|
|
1823
|
-
from: resolve("./runtime/app/composables/webmcp")
|
|
2085
|
+
from: resolve$1("./runtime/app/composables/webmcp")
|
|
1824
2086
|
})));
|
|
1825
2087
|
nuxt.options.runtimeConfig.public["nuxt-ai-ready"] = {
|
|
1826
2088
|
webmcp: webmcpConfig
|
|
1827
2089
|
};
|
|
1828
|
-
addPlugin({ mode: "client", src: resolve("./runtime/app/plugins/webmcp.client") });
|
|
2090
|
+
addPlugin({ mode: "client", src: resolve$1("./runtime/app/plugins/webmcp.client") });
|
|
1829
2091
|
if (Object.keys(webmcpConfig.tools).length) {
|
|
1830
|
-
addServerHandler({ route: "/__ai-ready/pages", handler: resolve("./runtime/server/routes/__ai-ready/pages.get"), lazy: true });
|
|
2092
|
+
addServerHandler({ route: "/__ai-ready/pages", handler: resolve$1("./runtime/server/routes/__ai-ready/pages.get"), lazy: true });
|
|
1831
2093
|
}
|
|
1832
2094
|
}
|
|
1833
2095
|
if (nuxt.options.dev || config.debug) {
|
|
1834
|
-
addServerHandler({ route: "/__ai-ready__/debug.json", handler: resolve("./runtime/server/routes/__ai-ready/devtools.get"), lazy: true });
|
|
2096
|
+
addServerHandler({ route: "/__ai-ready__/debug.json", handler: resolve$1("./runtime/server/routes/__ai-ready/devtools.get"), lazy: true });
|
|
1835
2097
|
}
|
|
1836
2098
|
if (config.debug) {
|
|
1837
|
-
addServerHandler({ route: "/__ai-ready-debug", handler: resolve("./runtime/server/routes/__ai-ready-debug.get"), lazy: true });
|
|
2099
|
+
addServerHandler({ route: "/__ai-ready-debug", handler: resolve$1("./runtime/server/routes/__ai-ready-debug.get"), lazy: true });
|
|
1838
2100
|
}
|
|
1839
2101
|
if (runtimeSyncEnabled) {
|
|
1840
|
-
addServerHandler({ route: "/__ai-ready/status", handler: resolve("./runtime/server/routes/__ai-ready/status.get"), lazy: true });
|
|
1841
|
-
addServerHandler({ route: "/__ai-ready/poll", method: "post", handler: resolve("./runtime/server/routes/__ai-ready/poll.post"), lazy: true });
|
|
1842
|
-
addServerHandler({ route: "/__ai-ready/prune", method: "post", handler: resolve("./runtime/server/routes/__ai-ready/prune.post"), lazy: true });
|
|
1843
|
-
addServerHandler({ route: "/__ai-ready/restore", method: "post", handler: resolve("./runtime/server/routes/__ai-ready/restore.post"), lazy: true });
|
|
1844
|
-
addServerHandler({ route: "/__ai-ready/reindex", method: "post", handler: resolve("./runtime/server/routes/__ai-ready/reindex.post"), lazy: true });
|
|
1845
|
-
|
|
2102
|
+
addServerHandler({ route: "/__ai-ready/status", handler: resolve$1("./runtime/server/routes/__ai-ready/status.get"), lazy: true });
|
|
2103
|
+
addServerHandler({ route: "/__ai-ready/poll", method: "post", handler: resolve$1("./runtime/server/routes/__ai-ready/poll.post"), lazy: true });
|
|
2104
|
+
addServerHandler({ route: "/__ai-ready/prune", method: "post", handler: resolve$1("./runtime/server/routes/__ai-ready/prune.post"), lazy: true });
|
|
2105
|
+
addServerHandler({ route: "/__ai-ready/restore", method: "post", handler: resolve$1("./runtime/server/routes/__ai-ready/restore.post"), lazy: true });
|
|
2106
|
+
addServerHandler({ route: "/__ai-ready/reindex", method: "post", handler: resolve$1("./runtime/server/routes/__ai-ready/reindex.post"), lazy: true });
|
|
2107
|
+
addNitroPlugin(resolve$1("./runtime/server/plugins/sitemap-seeder"));
|
|
1846
2108
|
}
|
|
1847
2109
|
if (config.cron && !nuxt.options.dev) {
|
|
1848
|
-
addServerHandler({ route: "/__ai-ready/cron", handler: resolve("./runtime/server/routes/__ai-ready/cron.get"), lazy: true });
|
|
2110
|
+
addServerHandler({ route: "/__ai-ready/cron", handler: resolve$1("./runtime/server/routes/__ai-ready/cron.get"), lazy: true });
|
|
1849
2111
|
}
|
|
1850
2112
|
if (apiCatalogConfig)
|
|
1851
2113
|
registerApiCatalog(apiCatalogConfig);
|
|
1852
2114
|
if (!nuxt.options.dev && !nuxt.options._prepare) {
|
|
1853
2115
|
if (isSPA && !hasPrerenderedRoutes) {
|
|
1854
2116
|
logger.warn("SPA mode detected without prerendering. llms-full.txt will not be generated.");
|
|
1855
|
-
logger.warn("For full functionality, enable SSR or prerender routes.");
|
|
1856
2117
|
} else if (!isStatic && !hasPrerenderedRoutes) {
|
|
1857
2118
|
logger.info("SSR-only mode: llms-full.txt requires prerendering. Runtime markdown conversion available.");
|
|
1858
2119
|
}
|
|
@@ -1869,8 +2130,9 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1869
2130
|
artifactRoutes: agentSkillsResult._tag === "Enabled" ? Object.keys(agentSkillsResult.localArtifacts) : []
|
|
1870
2131
|
});
|
|
1871
2132
|
}
|
|
1872
|
-
if (databaseEnabled)
|
|
1873
|
-
|
|
2133
|
+
if (databaseEnabled) {
|
|
2134
|
+
addNitroPlugin(resolve$1(getNitroVersion(nuxt) === 3 ? "./runtime/server/plugins/db-lifecycle-nitro3" : "./runtime/server/plugins/db-lifecycle"));
|
|
2135
|
+
}
|
|
1874
2136
|
if (nuxt.options.dev) {
|
|
1875
2137
|
const { setupDevToolsUI } = await import('nuxtseo-shared/devtools');
|
|
1876
2138
|
setupDevToolsUI({
|
|
@@ -1878,7 +2140,7 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1878
2140
|
name: "nuxt-ai-ready",
|
|
1879
2141
|
title: "AI Ready",
|
|
1880
2142
|
icon: "carbon:ai-label"
|
|
1881
|
-
}, resolve, nuxt);
|
|
2143
|
+
}, resolve$1, nuxt);
|
|
1882
2144
|
}
|
|
1883
2145
|
for (const route of ["/llms.txt", "/llms-full.txt"]) {
|
|
1884
2146
|
extendRouteRules(route, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
@@ -1887,19 +2149,59 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1887
2149
|
extendRouteRules(SITEMAP_MD_ROUTE, { headers: { "Content-Type": "text/markdown; charset=utf-8" } });
|
|
1888
2150
|
}
|
|
1889
2151
|
const staticBaseURL = nuxt.options.app.baseURL || "/";
|
|
2152
|
+
const emittedWarnings = /* @__PURE__ */ new Set();
|
|
2153
|
+
const warnConfiguration = (nitro) => {
|
|
2154
|
+
if (preparing)
|
|
2155
|
+
return;
|
|
2156
|
+
const warnings = resolveConfigurationWarnings({
|
|
2157
|
+
policy: nuxt.options.runtimeConfig["nuxt-ai-ready"].contentNegotiation,
|
|
2158
|
+
botNegotiation: config.botNegotiation === true,
|
|
2159
|
+
static: nitro.options.static === true || isStatic,
|
|
2160
|
+
siteUrl: siteConfig.url || void 0,
|
|
2161
|
+
routeRules: nitro.options.routeRules
|
|
2162
|
+
});
|
|
2163
|
+
for (const warning of warnings) {
|
|
2164
|
+
if (!emittedWarnings.has(warning)) {
|
|
2165
|
+
emittedWarnings.add(warning);
|
|
2166
|
+
logger.warn(warning);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
};
|
|
2170
|
+
nuxt.hook("nitro:init", (nitro) => {
|
|
2171
|
+
warnConfiguration(nitro);
|
|
2172
|
+
nitro.hooks.hook("rollup:reload", () => warnConfiguration(nitro));
|
|
2173
|
+
});
|
|
2174
|
+
nuxt.hook("nitro:build:before", warnConfiguration);
|
|
1890
2175
|
for (const route of nuxt.options.nitro.prerender?.routes || []) {
|
|
1891
2176
|
if (!isStaticMarkdownSourceRoute(route))
|
|
1892
2177
|
continue;
|
|
1893
2178
|
extendRouteRules(toMarkdownPath(route), {
|
|
1894
2179
|
headers: {
|
|
1895
2180
|
"Content-Type": "text/markdown; charset=utf-8",
|
|
1896
|
-
"Link": buildStaticMarkdownLinkHeader(route, staticBaseURL, config.describedby !== false)
|
|
2181
|
+
"Link": buildStaticMarkdownLinkHeader(route, staticBaseURL, config.describedby !== false),
|
|
2182
|
+
"Vary": "Accept"
|
|
1897
2183
|
}
|
|
1898
2184
|
});
|
|
1899
2185
|
}
|
|
1900
2186
|
nuxt.hooks.hook("nitro:build:before", (nitro) => {
|
|
1901
2187
|
const isCloudflarePreset = String(nitro.options.preset || "").startsWith("cloudflare");
|
|
1902
|
-
nitro.hooks.hook("prerender:done", () => {
|
|
2188
|
+
nitro.hooks.hook("prerender:done", async () => {
|
|
2189
|
+
if (["cloudflare", "cloudflare-module", "cloudflare-durable"].includes(String(nitro.options.preset)) && !nitro.options.static && config.contentNegotiation === true) {
|
|
2190
|
+
const pages = cloudflarePrerenderedPages(nitro._prerenderedRoutes || [], staticBaseURL);
|
|
2191
|
+
const cloudflare = nitro.options.cloudflare ||= {};
|
|
2192
|
+
const wrangler = cloudflare.wrangler ||= {};
|
|
2193
|
+
const assets = wrangler.assets ||= {};
|
|
2194
|
+
const fileRouting = await readCloudflareAssetRouting(nitro.options.rootDir);
|
|
2195
|
+
const routing = defu$1({ value: assets.run_worker_first }, { value: fileRouting.root }).value;
|
|
2196
|
+
cloudflareNegotiationPatterns(routing, pages);
|
|
2197
|
+
const environmentConfig = wrangler;
|
|
2198
|
+
const configuredEnvironments = Object.values(environmentConfig.env || {}).flatMap((env) => env.assets?.run_worker_first === void 0 ? [] : [env.assets.run_worker_first]);
|
|
2199
|
+
const fallbackPaths = cloudflareStaticFallbackPaths(routing, pages, [...fileRouting.environments, ...configuredEnvironments]);
|
|
2200
|
+
const addedPaths = cloudflareStaticFallbackPaths(routing, pages);
|
|
2201
|
+
if (addedPaths.length > 0)
|
|
2202
|
+
assets.run_worker_first = [...Array.isArray(assets.run_worker_first) ? assets.run_worker_first : [], ...addedPaths];
|
|
2203
|
+
nitro.options.runtimeConfig["nuxt-ai-ready"].cloudflarePrerenderedPages = fallbackPaths;
|
|
2204
|
+
}
|
|
1903
2205
|
const plan = planStaticMarkdownHeaderRules(
|
|
1904
2206
|
nitro.options.routeRules,
|
|
1905
2207
|
prerenderedMarkdownHeaderRules(
|
|
@@ -1918,26 +2220,65 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1918
2220
|
applyStaticMarkdownHeaderPlan(nitro.options.routeRules, plan);
|
|
1919
2221
|
});
|
|
1920
2222
|
nitro.hooks.hook("compiled", async () => {
|
|
1921
|
-
const
|
|
2223
|
+
const generatedHeadersPath = join(nitro.options.output.publicDir, "_headers");
|
|
2224
|
+
let headersPath = generatedHeadersPath;
|
|
2225
|
+
let staticDiscoverySupported = isCloudflarePreset;
|
|
2226
|
+
if (isCloudflarePreset) {
|
|
2227
|
+
const wranglerPath = join(nitro.options.output.serverDir, "wrangler.json");
|
|
2228
|
+
const wrangler = await readFile(wranglerPath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
|
|
2229
|
+
if (error.code === "ENOENT")
|
|
2230
|
+
return void 0;
|
|
2231
|
+
throw error;
|
|
2232
|
+
});
|
|
2233
|
+
const assetsDirectory = wrangler?.assets?.directory || wrangler?.pages_build_output_dir;
|
|
2234
|
+
const assetsRoot = assetsDirectory ? resolve(dirname(wranglerPath), assetsDirectory) : String(nitro.options.preset).startsWith("cloudflare-pages") ? nitro.options.output.dir : resolve(nitro.options.output.publicDir, ...staticBaseURL.split("/").filter(Boolean).map(() => ".."));
|
|
2235
|
+
const assetPath = relative(nitro.options.output.dir, assetsRoot);
|
|
2236
|
+
if (assetPath === ".." || assetPath.startsWith("../")) {
|
|
2237
|
+
staticDiscoverySupported = false;
|
|
2238
|
+
logger.warn("Skipped shared discovery headers because Cloudflare assets are outside the Nitro output directory.");
|
|
2239
|
+
} else {
|
|
2240
|
+
headersPath = join(assetsRoot, "_headers");
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
1922
2243
|
logger.debug(`Checking for _headers file: ${headersPath}`);
|
|
1923
2244
|
const exists = await access(headersPath).then(() => true).catch(() => false);
|
|
1924
|
-
if (exists) {
|
|
1925
|
-
const
|
|
2245
|
+
if (exists || isCloudflarePreset) {
|
|
2246
|
+
const readHeaders = (path) => readFile(path, "utf8").catch((error) => {
|
|
2247
|
+
if (error.code === "ENOENT")
|
|
2248
|
+
return "";
|
|
2249
|
+
throw error;
|
|
2250
|
+
});
|
|
2251
|
+
const rootHeaders = exists ? await readHeaders(headersPath) : "";
|
|
2252
|
+
const generatedHeaders = generatedHeadersPath === headersPath ? "" : await readHeaders(generatedHeadersPath);
|
|
2253
|
+
const headers = [rootHeaders, generatedHeaders].filter(Boolean).join("\n");
|
|
2254
|
+
const markdownPattern = isCloudflarePreset ? toDeployedRoute("/*.md", staticBaseURL) : "/*.md";
|
|
1926
2255
|
let mergedHeaders = ensureStaticHeader(
|
|
1927
2256
|
headers,
|
|
1928
|
-
|
|
2257
|
+
markdownPattern,
|
|
1929
2258
|
"Content-Type",
|
|
1930
2259
|
"text/markdown; charset=utf-8"
|
|
1931
2260
|
);
|
|
2261
|
+
mergedHeaders = ensureStaticHeader(mergedHeaders, markdownPattern, "Vary", "Accept", "append");
|
|
1932
2262
|
if (config.describedby !== false) {
|
|
1933
2263
|
mergedHeaders = ensureStaticHeader(
|
|
1934
2264
|
mergedHeaders,
|
|
1935
|
-
|
|
2265
|
+
markdownPattern,
|
|
1936
2266
|
"Link",
|
|
1937
2267
|
staticDescribedbyEntry(nitro.options.baseURL || "/")
|
|
1938
2268
|
);
|
|
1939
2269
|
}
|
|
1940
2270
|
if (isCloudflarePreset) {
|
|
2271
|
+
const hasArtifact = (route) => access(join(nitro.options.output.publicDir, route)).then(() => true).catch((error) => {
|
|
2272
|
+
if (error.code === "ENOENT")
|
|
2273
|
+
return false;
|
|
2274
|
+
throw error;
|
|
2275
|
+
});
|
|
2276
|
+
const discovery = [];
|
|
2277
|
+
if (staticDiscoverySupported && config.describedby !== false && await hasArtifact("/llms.txt"))
|
|
2278
|
+
discovery.push(staticDescribedbyEntry(staticBaseURL));
|
|
2279
|
+
if (staticDiscoverySupported && apiCatalogConfig && await hasArtifact(API_CATALOG_PATH))
|
|
2280
|
+
discovery.push(`<${encodeURI(apiCatalogConfig.href)}>; rel="api-catalog"`);
|
|
2281
|
+
mergedHeaders = mergeStaticDiscoveryHeaders(mergedHeaders, staticBaseURL, discovery);
|
|
1941
2282
|
const budget = enforceStaticHeaderBudget(mergedHeaders, CLOUDFLARE_STATIC_HEADER_RULE_LIMIT);
|
|
1942
2283
|
if (budget.dropped > 0) {
|
|
1943
2284
|
mergedHeaders = budget.contents;
|
|
@@ -1946,7 +2287,7 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1946
2287
|
if (budget.total > CLOUDFLARE_STATIC_HEADER_RULE_LIMIT)
|
|
1947
2288
|
logger.warn(`_headers still has ${budget.total} rules after dropping the .md rules. Cloudflare will reject the deploy until the other rules fit under ${CLOUDFLARE_STATIC_HEADER_RULE_LIMIT}.`);
|
|
1948
2289
|
}
|
|
1949
|
-
if (mergedHeaders !==
|
|
2290
|
+
if (mergedHeaders !== rootHeaders || !exists) {
|
|
1950
2291
|
await writeFile(headersPath, mergedHeaders);
|
|
1951
2292
|
logger.debug("Merged .md charset header into _headers");
|
|
1952
2293
|
}
|
|
@@ -1956,4 +2297,4 @@ export const logger = createModuleLogger('nuxt-ai-ready', ${!!config.debug})
|
|
|
1956
2297
|
}
|
|
1957
2298
|
});
|
|
1958
2299
|
|
|
1959
|
-
export { AGENT_SKILLS_SCHEMA as A, MARKDOWN_LINK_AVAILABILITY_FILE as M, logger as l, module$1 as m
|
|
2300
|
+
export { AGENT_SKILLS_SCHEMA as A, MARKDOWN_LINK_AVAILABILITY_FILE as M, logger as l, module$1 as m };
|