nuxt-ai-ready 0.10.12 → 0.12.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 +7 -1
- package/dist/cli.mjs +11 -8
- package/dist/module.d.mts +7 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +80 -74
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +2 -1
- package/dist/runtime/server/db/drizzle/client.d.ts +20 -0
- package/dist/runtime/server/db/drizzle/client.js +29 -0
- package/dist/runtime/server/db/drizzle/index.d.ts +10 -0
- package/dist/runtime/server/db/drizzle/index.js +33 -0
- package/dist/runtime/server/db/drizzle/providers/bun.d.ts +7 -0
- package/dist/runtime/server/db/drizzle/providers/bun.js +25 -0
- package/dist/runtime/server/db/drizzle/providers/d1.d.ts +7 -0
- package/dist/runtime/server/db/drizzle/providers/d1.js +19 -0
- package/dist/runtime/server/db/drizzle/providers/libsql.d.ts +7 -0
- package/dist/runtime/server/db/drizzle/providers/libsql.js +15 -0
- package/dist/runtime/server/db/drizzle/providers/neon.d.ts +7 -0
- package/dist/runtime/server/db/drizzle/providers/neon.js +18 -0
- package/dist/runtime/server/db/drizzle/providers/sqlite.d.ts +8 -0
- package/dist/runtime/server/db/drizzle/providers/sqlite.js +25 -0
- package/dist/runtime/server/db/drizzle/queries.d.ts +190 -0
- package/dist/runtime/server/db/drizzle/queries.js +573 -0
- package/dist/runtime/server/db/drizzle/raw.d.ts +28 -0
- package/dist/runtime/server/db/drizzle/raw.js +93 -0
- package/dist/runtime/server/db/index.d.ts +2 -12
- package/dist/runtime/server/db/index.js +1 -36
- package/dist/runtime/server/db/queries.d.ts +5 -0
- package/dist/runtime/server/db/queries.js +27 -3
- package/dist/runtime/server/db/schema/postgres.d.ts +1500 -0
- package/dist/runtime/server/db/schema/postgres.js +66 -0
- package/dist/runtime/server/db/schema/sqlite.d.ts +1580 -0
- package/dist/runtime/server/db/schema/sqlite.js +66 -0
- package/dist/runtime/server/db/schema-sql.d.ts +6 -2
- package/dist/runtime/server/db/schema-sql.js +73 -92
- package/dist/runtime/server/db/shared.d.ts +1 -6
- package/dist/runtime/server/db/shared.js +0 -19
- package/dist/runtime/server/plugins/db-lifecycle.js +3 -3
- package/dist/runtime/server/plugins/sitemap-seeder.js +19 -2
- package/dist/runtime/server/routes/__ai-ready/restore.post.js +2 -2
- package/dist/runtime/server/routes/__ai-ready-debug.get.js +4 -4
- package/dist/runtime/server/utils/checkStale.js +19 -31
- package/dist/runtime/server/utils/indexnow.js +12 -13
- package/dist/runtime/types.d.ts +10 -4
- package/package.json +41 -32
- package/dist/runtime/server/db/provider/d1.d.ts +0 -3
- package/dist/runtime/server/db/provider/d1.js +0 -7
- package/dist/runtime/server/db/provider/libsql.d.ts +0 -3
- package/dist/runtime/server/db/provider/libsql.js +0 -9
- package/dist/runtime/server/db/provider/sqlite-bun.d.ts +0 -3
- package/dist/runtime/server/db/provider/sqlite-bun.js +0 -13
- package/dist/runtime/server/db/provider/sqlite-node.d.ts +0 -3
- package/dist/runtime/server/db/provider/sqlite-node.js +0 -13
package/README.md
CHANGED
|
@@ -33,6 +33,12 @@ Install `nuxt-ai-ready` dependency to your project:
|
|
|
33
33
|
npx nuxi@latest module add nuxt-ai-ready
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
> [!TIP]
|
|
37
|
+
> Generate an Agent Skill for this package using [skilld](https://github.com/harlan-zw/skilld):
|
|
38
|
+
> ```bash
|
|
39
|
+
> npx skilld add nuxt-ai-ready
|
|
40
|
+
> ```
|
|
41
|
+
|
|
36
42
|
## Documentation
|
|
37
43
|
|
|
38
44
|
[📖 Read the full documentation](https://nuxtseo.com/ai-ready) for more information.
|
|
@@ -41,7 +47,7 @@ npx nuxi@latest module add nuxt-ai-ready
|
|
|
41
47
|
|
|
42
48
|
<p align="center">
|
|
43
49
|
<a href="https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg">
|
|
44
|
-
<img src='https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg'/>
|
|
50
|
+
<img src='https://raw.githubusercontent.com/harlan-zw/static/main/sponsors.svg' alt="Sponsors"/>
|
|
45
51
|
</a>
|
|
46
52
|
</p>
|
|
47
53
|
|
package/dist/cli.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { defineCommand, runMain } from 'citty';
|
|
|
5
5
|
import { consola } from 'consola';
|
|
6
6
|
import { colors } from 'consola/utils';
|
|
7
7
|
import { resolve, join } from 'pathe';
|
|
8
|
+
import { readPackageJSON } from 'pkg-types';
|
|
8
9
|
|
|
9
10
|
async function getSecret(cwd) {
|
|
10
11
|
const secretPath = join(cwd, "node_modules/.cache/nuxt/ai-ready/secret");
|
|
@@ -16,10 +17,11 @@ async function getSecret(cwd) {
|
|
|
16
17
|
const main = defineCommand({
|
|
17
18
|
meta: {
|
|
18
19
|
name: "nuxt-ai-ready",
|
|
19
|
-
description: "Nuxt AI Ready CLI"
|
|
20
|
+
description: "Nuxt AI Ready CLI",
|
|
21
|
+
version: await readPackageJSON(import.meta.url).then((p) => p.version || "0.0.0")
|
|
20
22
|
},
|
|
21
23
|
subCommands: {
|
|
22
|
-
status: defineCommand({
|
|
24
|
+
status: () => defineCommand({
|
|
23
25
|
meta: {
|
|
24
26
|
name: "status",
|
|
25
27
|
description: "Show indexing status and IndexNow sync progress"
|
|
@@ -71,7 +73,7 @@ const main = defineCommand({
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
}),
|
|
74
|
-
poll: defineCommand({
|
|
76
|
+
poll: () => defineCommand({
|
|
75
77
|
meta: {
|
|
76
78
|
name: "poll",
|
|
77
79
|
description: "Trigger page indexing"
|
|
@@ -131,7 +133,7 @@ const main = defineCommand({
|
|
|
131
133
|
}
|
|
132
134
|
}
|
|
133
135
|
}),
|
|
134
|
-
restore: defineCommand({
|
|
136
|
+
restore: () => defineCommand({
|
|
135
137
|
meta: {
|
|
136
138
|
name: "restore",
|
|
137
139
|
description: "Restore database from prerendered dump"
|
|
@@ -145,8 +147,9 @@ const main = defineCommand({
|
|
|
145
147
|
},
|
|
146
148
|
clear: {
|
|
147
149
|
type: "boolean",
|
|
148
|
-
description: "Clear existing pages first
|
|
149
|
-
default: true
|
|
150
|
+
description: "Clear existing pages first",
|
|
151
|
+
default: true,
|
|
152
|
+
negativeDescription: "Restore without clearing existing pages"
|
|
150
153
|
},
|
|
151
154
|
cwd: {
|
|
152
155
|
type: "string",
|
|
@@ -179,7 +182,7 @@ const main = defineCommand({
|
|
|
179
182
|
}
|
|
180
183
|
}
|
|
181
184
|
}),
|
|
182
|
-
prune: defineCommand({
|
|
185
|
+
prune: () => defineCommand({
|
|
183
186
|
meta: {
|
|
184
187
|
name: "prune",
|
|
185
188
|
description: "Remove stale routes from database"
|
|
@@ -243,7 +246,7 @@ const main = defineCommand({
|
|
|
243
246
|
}
|
|
244
247
|
}
|
|
245
248
|
}),
|
|
246
|
-
indexnow: defineCommand({
|
|
249
|
+
indexnow: () => defineCommand({
|
|
247
250
|
meta: {
|
|
248
251
|
name: "indexnow",
|
|
249
252
|
description: "Trigger IndexNow sync"
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import {
|
|
2
|
+
import { LlmsTxtConfig, ModuleOptions } from '../dist/runtime/types.js';
|
|
3
3
|
export { ModuleOptions } from '../dist/runtime/types.js';
|
|
4
4
|
|
|
5
5
|
interface ParsedMarkdownResult {
|
|
@@ -27,6 +27,12 @@ interface ModuleHooks {
|
|
|
27
27
|
notes: string[];
|
|
28
28
|
}) => void | Promise<void>;
|
|
29
29
|
}
|
|
30
|
+
declare module '@nuxt/schema' {
|
|
31
|
+
interface NuxtHooks {
|
|
32
|
+
'ai-ready:page:markdown': ModuleHooks['ai-ready:page:markdown'];
|
|
33
|
+
'ai-ready:llms-txt': ModuleHooks['ai-ready:llms-txt'];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
30
36
|
interface ModulePublicRuntimeConfig {
|
|
31
37
|
debug: boolean;
|
|
32
38
|
debugCron: boolean;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomBytes } from 'node:crypto';
|
|
2
2
|
import { mkdir, writeFile, appendFile, stat, access } from 'node:fs/promises';
|
|
3
3
|
import { join, dirname } from 'node:path';
|
|
4
|
-
import { useLogger, useNuxt,
|
|
4
|
+
import { useLogger, useNuxt, addTypeTemplate, addTemplate, defineNuxtModule, createResolver, hasNuxtModule, addServerHandler, addPlugin, addServerPlugin } from '@nuxt/kit';
|
|
5
5
|
import defu from 'defu';
|
|
6
6
|
import { useSiteConfig, installNuxtSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
|
|
7
7
|
import { readPackageJSON } from 'pkg-types';
|
|
@@ -11,7 +11,7 @@ import { isTest, isCI } from 'std-env';
|
|
|
11
11
|
import { parseSitemapXml } from '@nuxtjs/sitemap/utils';
|
|
12
12
|
import { colorize } from 'consola/utils';
|
|
13
13
|
import { withBase } from 'ufo';
|
|
14
|
-
import {
|
|
14
|
+
import { initSchema, computeContentHash, insertPage, queryAllPages, exportDbDump } from '../dist/runtime/server/db/shared.js';
|
|
15
15
|
import { comparePageHashes, submitToIndexNowShared } from '../dist/runtime/server/utils/indexnow-shared.js';
|
|
16
16
|
import { buildLlmsFullTxtHeader, formatPageForLlmsFullTxt } from '../dist/runtime/server/utils/llms-full.js';
|
|
17
17
|
import { join as join$1, isAbsolute } from 'pathe';
|
|
@@ -59,12 +59,12 @@ function hookNuxtSeoProLicense() {
|
|
|
59
59
|
}
|
|
60
60
|
}).catch((err) => {
|
|
61
61
|
if (err?.response?.status === 401) {
|
|
62
|
-
spinner.
|
|
62
|
+
spinner.error("Invalid API key");
|
|
63
63
|
p.note("Your API key is invalid.\n\nhttps://nuxtseo.com/pro/dashboard", "License Issue");
|
|
64
64
|
throw new Error("Invalid Nuxt SEO Pro API key.");
|
|
65
65
|
}
|
|
66
66
|
if (err?.response?.status === 403) {
|
|
67
|
-
spinner.
|
|
67
|
+
spinner.error("No active subscription");
|
|
68
68
|
p.note("Your subscription has expired or is inactive.\n\nhttps://nuxtseo.com/pro/dashboard", "License Issue");
|
|
69
69
|
throw new Error("No active Nuxt SEO Pro subscription.");
|
|
70
70
|
}
|
|
@@ -72,7 +72,7 @@ function hookNuxtSeoProLicense() {
|
|
|
72
72
|
return null;
|
|
73
73
|
});
|
|
74
74
|
if (!res) {
|
|
75
|
-
spinner.
|
|
75
|
+
spinner.cancel("License verification skipped (network issue)");
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
78
|
spinner.stop("License verified \u2713");
|
|
@@ -140,13 +140,21 @@ async function initCrawler(state) {
|
|
|
140
140
|
if (state.dbPath) {
|
|
141
141
|
logger.debug(`Creating directory for SQLite: ${dirname(state.dbPath)}`);
|
|
142
142
|
await mkdir(dirname(state.dbPath), { recursive: true });
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
const { default: Database } = await import('better-sqlite3');
|
|
144
|
+
const sqlite = new Database(state.dbPath);
|
|
145
|
+
const db = {
|
|
146
|
+
all: async (sql, params = []) => sqlite.prepare(sql).all(...params),
|
|
147
|
+
first: async (sql, params = []) => sqlite.prepare(sql).get(...params),
|
|
148
|
+
exec: async (sql, params = []) => {
|
|
149
|
+
sqlite.prepare(sql).run(...params);
|
|
150
|
+
},
|
|
151
|
+
close: async () => {
|
|
152
|
+
sqlite.close();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
state.db = db;
|
|
156
|
+
await initSchema(db);
|
|
157
|
+
logger.debug(`Crawler initialized with SQLite at ${state.dbPath}`);
|
|
150
158
|
}
|
|
151
159
|
if (state.llmsFullTxtPath) {
|
|
152
160
|
logger.debug(`Creating directory for llms-full.txt: ${dirname(state.llmsFullTxtPath)}`);
|
|
@@ -430,7 +438,7 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
|
|
|
430
438
|
await writeLlmsFiles();
|
|
431
439
|
state.prerenderedRoutes.clear();
|
|
432
440
|
if (state.db)
|
|
433
|
-
await state.db.close();
|
|
441
|
+
await state.db.close?.();
|
|
434
442
|
});
|
|
435
443
|
} else if (usePrerenderHook) {
|
|
436
444
|
nitro.hooks.hook("prerender:done", async () => {
|
|
@@ -444,28 +452,17 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
|
|
|
444
452
|
await writeLlmsFiles();
|
|
445
453
|
state.prerenderedRoutes.clear();
|
|
446
454
|
if (state.db)
|
|
447
|
-
await state.db.close();
|
|
455
|
+
await state.db.close?.();
|
|
448
456
|
});
|
|
449
457
|
}
|
|
450
458
|
});
|
|
451
459
|
}
|
|
452
460
|
|
|
453
461
|
function registerTypeTemplates(_ctx) {
|
|
454
|
-
addTemplate({
|
|
455
|
-
filename: "types/ai-ready-adapter.d.ts",
|
|
456
|
-
getContents: () => `declare module '#ai-ready/adapter' {
|
|
457
|
-
import type { Connector } from 'db0'
|
|
458
|
-
const connector: (config: unknown) => Connector
|
|
459
|
-
export default connector
|
|
460
|
-
}
|
|
461
|
-
`
|
|
462
|
-
});
|
|
463
462
|
addTypeTemplate({
|
|
464
463
|
filename: "types/nuxt-ai-ready-augments.d.ts",
|
|
465
464
|
getContents: () => `// Generated by nuxt-ai-ready
|
|
466
|
-
/// <reference path="./ai-ready-adapter.d.ts" />
|
|
467
465
|
/// <reference path="./ai-ready-virtual.d.ts" />
|
|
468
|
-
/// <reference path="./ai-ready-db-provider.d.ts" />
|
|
469
466
|
import type { MarkdownContext, PageIndexedContext } from 'nuxt-ai-ready'
|
|
470
467
|
import type { HTMLToMarkdownOptions } from 'mdream'
|
|
471
468
|
|
|
@@ -505,42 +502,26 @@ declare module '#ai-ready-virtual/logger.mjs' {
|
|
|
505
502
|
import type { ConsolaInstance } from 'consola'
|
|
506
503
|
export const logger: ConsolaInstance
|
|
507
504
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
addTemplate({
|
|
511
|
-
filename: "types/ai-ready-db-provider.d.ts",
|
|
512
|
-
getContents: () => `declare module '#ai-ready/db-provider' {
|
|
505
|
+
|
|
506
|
+
declare module '#ai-ready-virtual/db-provider.mjs' {
|
|
513
507
|
import type { H3Event } from 'h3'
|
|
514
|
-
import type {
|
|
515
|
-
export function
|
|
508
|
+
import type { DrizzleDatabase } from '#ai-ready/server/db/drizzle/client'
|
|
509
|
+
export function createClient(event?: H3Event): Promise<DrizzleDatabase>
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
declare module '#ai-ready-virtual/db-schema.mjs' {
|
|
513
|
+
export * from '#ai-ready/server/db/schema/sqlite'
|
|
516
514
|
}
|
|
517
515
|
`
|
|
518
516
|
});
|
|
519
517
|
}
|
|
520
518
|
|
|
521
|
-
async function resolveDatabaseAdapter(type) {
|
|
522
|
-
const connectors = {
|
|
523
|
-
d1: "db0/connectors/cloudflare-d1",
|
|
524
|
-
libsql: "db0/connectors/libsql/node"
|
|
525
|
-
};
|
|
526
|
-
if (type !== "sqlite" && connectors[type]) {
|
|
527
|
-
return connectors[type];
|
|
528
|
-
}
|
|
529
|
-
if (process.versions.bun) {
|
|
530
|
-
return "db0/connectors/bun-sqlite";
|
|
531
|
-
}
|
|
532
|
-
const nodeVersion = Number.parseInt(process.versions.node?.split(".")[0] || "0");
|
|
533
|
-
if (nodeVersion >= 22) {
|
|
534
|
-
return "db0/connectors/node-sqlite";
|
|
535
|
-
}
|
|
536
|
-
return "db0/connectors/better-sqlite3";
|
|
537
|
-
}
|
|
538
519
|
function refineDatabaseConfig(config, rootDir) {
|
|
539
520
|
const type = config.type || "sqlite";
|
|
540
|
-
if (type === "sqlite") {
|
|
521
|
+
if (type === "sqlite" || type === "bun") {
|
|
541
522
|
const filename = config.filename || ".data/ai-ready/pages.db";
|
|
542
523
|
return {
|
|
543
|
-
type
|
|
524
|
+
type,
|
|
544
525
|
filename: isAbsolute(filename) ? filename : join$1(rootDir, filename)
|
|
545
526
|
};
|
|
546
527
|
}
|
|
@@ -550,6 +531,13 @@ function refineDatabaseConfig(config, rootDir) {
|
|
|
550
531
|
bindingName: config.bindingName || "DB"
|
|
551
532
|
};
|
|
552
533
|
}
|
|
534
|
+
if (type === "neon") {
|
|
535
|
+
return {
|
|
536
|
+
type: "neon",
|
|
537
|
+
url: config.url
|
|
538
|
+
// Will fallback to POSTGRES_URL at runtime
|
|
539
|
+
};
|
|
540
|
+
}
|
|
553
541
|
return {
|
|
554
542
|
type: "libsql",
|
|
555
543
|
url: config.url,
|
|
@@ -610,24 +598,29 @@ const module$1 = defineNuxtModule({
|
|
|
610
598
|
nuxt.options.alias["#ai-ready"] = resolve("./runtime");
|
|
611
599
|
const preset = String(nuxt.options.nitro.preset || "");
|
|
612
600
|
const isCloudflare = preset.startsWith("cloudflare");
|
|
613
|
-
const
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
601
|
+
const isVercel = preset === "vercel" || preset === "vercel-edge";
|
|
602
|
+
const isVercelEdge = preset === "vercel-edge";
|
|
603
|
+
const isBun = preset === "bun";
|
|
604
|
+
const hasPostgresUrl = !!(process.env.POSTGRES_URL || process.env.DATABASE_URL || config.database?.url);
|
|
605
|
+
let dbType = config.database?.type;
|
|
606
|
+
if (!dbType) {
|
|
607
|
+
if (isCloudflare) {
|
|
608
|
+
dbType = "d1";
|
|
609
|
+
logger.debug(`Auto-detected Cloudflare preset "${preset}", using D1 database`);
|
|
610
|
+
} else if (isVercel && hasPostgresUrl) {
|
|
611
|
+
dbType = "neon";
|
|
612
|
+
logger.debug(`Auto-detected Vercel preset with POSTGRES_URL, using Neon serverless driver`);
|
|
613
|
+
} else if (isVercelEdge) {
|
|
614
|
+
logger.warn(`Vercel Edge has no filesystem. Set POSTGRES_URL (Vercel Postgres) or configure database.type: 'libsql' for full functionality.`);
|
|
615
|
+
dbType = "neon";
|
|
616
|
+
} else if (isBun) {
|
|
617
|
+
dbType = "bun";
|
|
618
|
+
logger.debug(`Auto-detected Bun preset, using bun:sqlite driver`);
|
|
619
|
+
} else {
|
|
620
|
+
dbType = "sqlite";
|
|
621
|
+
}
|
|
627
622
|
}
|
|
628
|
-
nuxt.options.
|
|
629
|
-
nuxt.options.nitro.alias["#ai-ready/db-provider"] = providerPath;
|
|
630
|
-
if (!nuxt.options.mcp?.name) {
|
|
623
|
+
if (nuxt.options.mcp !== false && !nuxt.options.mcp?.name) {
|
|
631
624
|
nuxt.options.mcp = nuxt.options.mcp || {};
|
|
632
625
|
nuxt.options.mcp.name = useSiteConfig().name;
|
|
633
626
|
}
|
|
@@ -636,9 +629,11 @@ const module$1 = defineNuxtModule({
|
|
|
636
629
|
resolve("./runtime/server/utils")
|
|
637
630
|
);
|
|
638
631
|
if (typeof config.contentSignal === "object") {
|
|
639
|
-
nuxt.options.robots
|
|
640
|
-
nuxt.options.robots
|
|
641
|
-
|
|
632
|
+
const robotsOpts = nuxt.options.robots !== false ? nuxt.options.robots : {};
|
|
633
|
+
nuxt.options.robots = robotsOpts;
|
|
634
|
+
const groups = robotsOpts.groups || [];
|
|
635
|
+
robotsOpts.groups = groups;
|
|
636
|
+
groups.push({
|
|
642
637
|
userAgent: "*",
|
|
643
638
|
contentUsage: [`train-ai=${config.contentSignal.aiTrain ? "y" : "n"}`],
|
|
644
639
|
contentSignal: [`ai-train=${config.contentSignal.aiTrain ? "yes" : "no"}`, `search=${config.contentSignal.search ? "yes" : "no"}`, `ai-input=${config.contentSignal.aiInput ? "yes" : "no"}`]
|
|
@@ -669,7 +664,7 @@ const module$1 = defineNuxtModule({
|
|
|
669
664
|
});
|
|
670
665
|
const mcpLink = {
|
|
671
666
|
title: "MCP",
|
|
672
|
-
href: withSiteUrl(nuxt.options.mcp?.route || "/mcp"),
|
|
667
|
+
href: withSiteUrl(nuxt.options.mcp !== false && nuxt.options.mcp?.route || "/mcp"),
|
|
673
668
|
description: "Model Context Protocol server endpoint for AI agent integration."
|
|
674
669
|
};
|
|
675
670
|
if (defaultLlmsTxtSections[0]) {
|
|
@@ -737,11 +732,11 @@ const module$1 = defineNuxtModule({
|
|
|
737
732
|
if (config.cron && !nuxt.options.dev) {
|
|
738
733
|
const cronSchedule = "*/5 * * * *";
|
|
739
734
|
const preset2 = String(nitroConfig.preset || "");
|
|
740
|
-
const
|
|
735
|
+
const isVercel2 = preset2 === "vercel" || preset2 === "vercel-edge";
|
|
741
736
|
const isCloudflarePages = preset2 === "cloudflare-pages" || preset2 === "cloudflare_pages";
|
|
742
737
|
if (isCloudflarePages) {
|
|
743
738
|
logger.warn("Cloudflare Pages does not support cron. Use external cron to call /__ai-ready/cron instead.");
|
|
744
|
-
} else if (
|
|
739
|
+
} else if (isVercel2) {
|
|
745
740
|
nitroConfig.vercel = nitroConfig.vercel || {};
|
|
746
741
|
nitroConfig.vercel.config = nitroConfig.vercel.config || {};
|
|
747
742
|
nitroConfig.vercel.config.crons = nitroConfig.vercel.config.crons || [];
|
|
@@ -824,6 +819,17 @@ export const logger = createConsola({
|
|
|
824
819
|
level: ${config.debug ? 4 : 3},
|
|
825
820
|
})
|
|
826
821
|
`;
|
|
822
|
+
const providerMap = {
|
|
823
|
+
sqlite: "#ai-ready/server/db/drizzle/providers/sqlite",
|
|
824
|
+
bun: "#ai-ready/server/db/drizzle/providers/bun",
|
|
825
|
+
d1: "#ai-ready/server/db/drizzle/providers/d1",
|
|
826
|
+
libsql: "#ai-ready/server/db/drizzle/providers/libsql",
|
|
827
|
+
neon: "#ai-ready/server/db/drizzle/providers/neon"
|
|
828
|
+
};
|
|
829
|
+
const providerPath = providerMap[dbType] || providerMap.sqlite;
|
|
830
|
+
nitroConfig.virtual["#ai-ready-virtual/db-provider.mjs"] = `export { createClient } from '${providerPath}'`;
|
|
831
|
+
const schemaPath = dbType === "neon" ? "#ai-ready/server/db/schema/postgres" : "#ai-ready/server/db/schema/sqlite";
|
|
832
|
+
nitroConfig.virtual["#ai-ready-virtual/db-schema.mjs"] = `export * from '${schemaPath}'`;
|
|
827
833
|
});
|
|
828
834
|
const database = refineDatabaseConfig(config.database || {}, nuxt.options.rootDir);
|
|
829
835
|
nuxt.options.runtimeConfig["nuxt-ai-ready"] = {
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export { countPages, getStaleRoutes, isPageFresh, pruneStaleRoutes, queryPages, searchPages, seedRoutes, streamPages, upsertPage, } from './server/db/queries.js';
|
|
1
|
+
export { closeDrizzle, useDrizzle, useRawDb } from './server/db/index.js';
|
|
2
|
+
export type { DatabaseDialect, DrizzleDatabase, RawExecutor } from './server/db/index.js';
|
|
3
|
+
export { countPages, getPageLastmods, getStaleRoutes, isPageFresh, pruneStaleRoutes, queryPages, searchPages, seedRoutes, streamPages, upsertPage, } from './server/db/queries.js';
|
|
4
4
|
export type { CountPagesOptions, PageData, PageEntry, PageRow, QueryPagesOptions, SearchPagesOptions, SearchResult, StreamPagesOptions, UpsertPageInput, } from './server/db/queries.js';
|
|
5
5
|
export { indexPage, indexPageByRoute } from './server/utils/indexPage.js';
|
|
6
6
|
export type { IndexPageOptions, IndexPageResult } from './server/utils/indexPage.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type * as schema from '#ai-ready-virtual/db-schema.mjs';
|
|
2
|
+
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
3
|
+
import type { BunSQLiteDatabase } from 'drizzle-orm/bun-sqlite';
|
|
4
|
+
import type { DrizzleD1Database } from 'drizzle-orm/d1';
|
|
5
|
+
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
|
|
6
|
+
import type { NeonHttpDatabase } from 'drizzle-orm/neon-http';
|
|
7
|
+
import type { H3Event } from 'h3';
|
|
8
|
+
export type DatabaseDialect = 'sqlite' | 'postgres';
|
|
9
|
+
type SQLiteDB = BetterSQLite3Database<typeof schema> | BunSQLiteDatabase<typeof schema> | LibSQLDatabase<typeof schema> | DrizzleD1Database<typeof schema>;
|
|
10
|
+
type PostgresDB = NeonHttpDatabase<typeof schema>;
|
|
11
|
+
export interface DrizzleDatabase {
|
|
12
|
+
dialect: DatabaseDialect;
|
|
13
|
+
db: SQLiteDB | PostgresDB;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Get Drizzle database instance
|
|
17
|
+
*/
|
|
18
|
+
export declare function useDrizzle(event?: H3Event): Promise<DrizzleDatabase>;
|
|
19
|
+
export declare function closeDrizzle(event?: H3Event): Promise<void>;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { closeDriver } from "./raw.js";
|
|
2
|
+
const DB_CONTEXT_KEY = "_aiReadyDrizzle";
|
|
3
|
+
let fallbackClient;
|
|
4
|
+
export async function useDrizzle(event) {
|
|
5
|
+
if (event?.context?.[DB_CONTEXT_KEY]) {
|
|
6
|
+
return event.context[DB_CONTEXT_KEY];
|
|
7
|
+
}
|
|
8
|
+
if (!event && fallbackClient) {
|
|
9
|
+
return fallbackClient;
|
|
10
|
+
}
|
|
11
|
+
const { createClient } = await import("#ai-ready-virtual/db-provider.mjs");
|
|
12
|
+
const client = await createClient(event);
|
|
13
|
+
if (event?.context) {
|
|
14
|
+
event.context[DB_CONTEXT_KEY] = client;
|
|
15
|
+
} else {
|
|
16
|
+
fallbackClient = client;
|
|
17
|
+
}
|
|
18
|
+
return client;
|
|
19
|
+
}
|
|
20
|
+
export async function closeDrizzle(event) {
|
|
21
|
+
if (event?.context?.[DB_CONTEXT_KEY]) {
|
|
22
|
+
const client = event.context[DB_CONTEXT_KEY];
|
|
23
|
+
closeDriver(client.db);
|
|
24
|
+
delete event.context[DB_CONTEXT_KEY];
|
|
25
|
+
} else if (!event && fallbackClient) {
|
|
26
|
+
closeDriver(fallbackClient.db);
|
|
27
|
+
fallbackClient = void 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle ORM database layer for nuxt-ai-ready
|
|
3
|
+
*/
|
|
4
|
+
export * from '#ai-ready-virtual/db-schema.mjs';
|
|
5
|
+
export { closeDrizzle, useDrizzle } from './client.js';
|
|
6
|
+
export type { DatabaseDialect, DrizzleDatabase } from './client.js';
|
|
7
|
+
export { completeCronRun, countPages, countPagesNeedingIndexNowSync, deleteInfoValue, deletePage, getAllPages, getContentHashes, getInfoValue, getNextSitemapToCrawl, getPageByRoute, getPageLastmods, getPagesNeedingIndexNowSync, getPendingPages, getRecentCronRuns, getSitemapStatus, initSchema, markIndexNowSynced, markPageIndexed, markRoutesPending, markSitemapCrawled, markSitemapError, resetSitemapErrors, searchPages, seedRoutes, setInfoValue, startCronRun, syncSitemaps, upsertPage, } from './queries.js';
|
|
8
|
+
export type { CronRunOutput, PageInput, PageMetaOutput, PageOutput, SitemapOutput, } from './queries.js';
|
|
9
|
+
export { useRawDb } from './raw.js';
|
|
10
|
+
export type { RawExecutor } from './raw.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export * from "#ai-ready-virtual/db-schema.mjs";
|
|
2
|
+
export { closeDrizzle, useDrizzle } from "./client.js";
|
|
3
|
+
export {
|
|
4
|
+
completeCronRun,
|
|
5
|
+
countPages,
|
|
6
|
+
countPagesNeedingIndexNowSync,
|
|
7
|
+
deleteInfoValue,
|
|
8
|
+
deletePage,
|
|
9
|
+
getAllPages,
|
|
10
|
+
getContentHashes,
|
|
11
|
+
getInfoValue,
|
|
12
|
+
getNextSitemapToCrawl,
|
|
13
|
+
getPageByRoute,
|
|
14
|
+
getPageLastmods,
|
|
15
|
+
getPagesNeedingIndexNowSync,
|
|
16
|
+
getPendingPages,
|
|
17
|
+
getRecentCronRuns,
|
|
18
|
+
getSitemapStatus,
|
|
19
|
+
initSchema,
|
|
20
|
+
markIndexNowSynced,
|
|
21
|
+
markPageIndexed,
|
|
22
|
+
markRoutesPending,
|
|
23
|
+
markSitemapCrawled,
|
|
24
|
+
markSitemapError,
|
|
25
|
+
resetSitemapErrors,
|
|
26
|
+
searchPages,
|
|
27
|
+
seedRoutes,
|
|
28
|
+
setInfoValue,
|
|
29
|
+
startCronRun,
|
|
30
|
+
syncSitemaps,
|
|
31
|
+
upsertPage
|
|
32
|
+
} from "./queries.js";
|
|
33
|
+
export { useRawDb } from "./raw.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import * as schema from "#ai-ready-virtual/db-schema.mjs";
|
|
3
|
+
import { Database } from "bun:sqlite";
|
|
4
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
5
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
6
|
+
import { dirname } from "pathe";
|
|
7
|
+
import { logger } from "../../../logger.js";
|
|
8
|
+
import { registerDriver } from "../raw.js";
|
|
9
|
+
export async function createClient(event) {
|
|
10
|
+
const config = useRuntimeConfig(event)["nuxt-ai-ready"];
|
|
11
|
+
const dbPath = config.database.filename || ".data/ai-ready/pages.db";
|
|
12
|
+
logger.debug(`[drizzle] Opening Bun SQLite database: ${dbPath}`);
|
|
13
|
+
await mkdir(dirname(dbPath), { recursive: true }).catch((err) => {
|
|
14
|
+
if (err.code === "EROFS" || err.code === "EACCES") {
|
|
15
|
+
throw new Error(
|
|
16
|
+
`[ai-ready] Cannot create database directory (read-only filesystem). On Vercel, set database.type: 'neon'. On Cloudflare, use 'd1'. Or configure database.url for LibSQL/Turso.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
throw err;
|
|
20
|
+
});
|
|
21
|
+
const sqlite = new Database(dbPath);
|
|
22
|
+
const db = drizzle(sqlite, { schema });
|
|
23
|
+
registerDriver(db, "better-sqlite3", sqlite);
|
|
24
|
+
return { dialect: "sqlite", db };
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as schema from "#ai-ready-virtual/db-schema.mjs";
|
|
2
|
+
import { drizzle } from "drizzle-orm/d1";
|
|
3
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
4
|
+
import { logger } from "../../../logger.js";
|
|
5
|
+
import { registerDriver } from "../raw.js";
|
|
6
|
+
export async function createClient(event) {
|
|
7
|
+
const config = useRuntimeConfig(event)["nuxt-ai-ready"];
|
|
8
|
+
const bindingName = config.database.bindingName || "DB";
|
|
9
|
+
logger.debug(`[drizzle] Using D1 binding: ${bindingName}`);
|
|
10
|
+
const cfEnv = event?.context?.cloudflare?.env;
|
|
11
|
+
const globalEnv = globalThis.__env__;
|
|
12
|
+
const d1 = cfEnv?.[bindingName] || globalEnv?.[bindingName];
|
|
13
|
+
if (!d1) {
|
|
14
|
+
throw new Error(`[ai-ready] D1 binding "${bindingName}" not found`);
|
|
15
|
+
}
|
|
16
|
+
const db = drizzle(d1, { schema });
|
|
17
|
+
registerDriver(db, "d1", d1);
|
|
18
|
+
return { dialect: "sqlite", db };
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as schema from "#ai-ready-virtual/db-schema.mjs";
|
|
2
|
+
import { createClient as createLibSQLClient } from "@libsql/client";
|
|
3
|
+
import { drizzle } from "drizzle-orm/libsql";
|
|
4
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
5
|
+
import { logger } from "../../../logger.js";
|
|
6
|
+
import { registerDriver } from "../raw.js";
|
|
7
|
+
export async function createClient(event) {
|
|
8
|
+
const config = useRuntimeConfig(event)["nuxt-ai-ready"];
|
|
9
|
+
const dbUrl = config.database.url || `file:${config.database.filename || ".data/ai-ready/pages.db"}`;
|
|
10
|
+
logger.debug(`[drizzle] Connecting to LibSQL: ${dbUrl}`);
|
|
11
|
+
const client = createLibSQLClient({ url: dbUrl, authToken: config.database.authToken });
|
|
12
|
+
const db = drizzle(client, { schema });
|
|
13
|
+
registerDriver(db, "libsql", client);
|
|
14
|
+
return { dialect: "sqlite", db };
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
export declare function createClient(event?: H3Event): Promise<{
|
|
3
|
+
dialect: "postgres";
|
|
4
|
+
db: import("drizzle-orm/neon-http").NeonHttpDatabase<any> & {
|
|
5
|
+
$client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
|
|
6
|
+
};
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as schema from "#ai-ready-virtual/db-schema.mjs";
|
|
2
|
+
import { neon } from "@neondatabase/serverless";
|
|
3
|
+
import { drizzle } from "drizzle-orm/neon-http";
|
|
4
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
5
|
+
import { logger } from "../../../logger.js";
|
|
6
|
+
import { registerDriver } from "../raw.js";
|
|
7
|
+
export async function createClient(event) {
|
|
8
|
+
const config = useRuntimeConfig(event)["nuxt-ai-ready"];
|
|
9
|
+
const connectionString = config.database.url || process.env.POSTGRES_URL || process.env.DATABASE_URL;
|
|
10
|
+
if (!connectionString) {
|
|
11
|
+
throw new Error("[ai-ready] Missing database URL. Set POSTGRES_URL or configure database.url");
|
|
12
|
+
}
|
|
13
|
+
logger.debug(`[drizzle] Connecting to Neon Postgres`);
|
|
14
|
+
const sqlFn = neon(connectionString);
|
|
15
|
+
const db = drizzle(sqlFn, { schema });
|
|
16
|
+
registerDriver(db, "neon", sqlFn);
|
|
17
|
+
return { dialect: "postgres", db };
|
|
18
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
import Database from 'better-sqlite3';
|
|
3
|
+
export declare function createClient(event?: H3Event): Promise<{
|
|
4
|
+
dialect: "sqlite";
|
|
5
|
+
db: import("drizzle-orm/better-sqlite3").BetterSQLite3Database<any> & {
|
|
6
|
+
$client: Database.Database;
|
|
7
|
+
};
|
|
8
|
+
}>;
|