nuxt-ai-ready 0.7.7 → 0.7.9
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/dist/module.json +1 -1
- package/dist/module.mjs +25 -14
- package/dist/runtime/server/db/index.d.ts +2 -2
- package/dist/runtime/server/db/index.js +1 -10
- package/dist/runtime/server/db/provider/d1.js +1 -22
- package/dist/runtime/server/db/shared.d.ts +1 -1
- package/dist/runtime/server/db/shared.js +27 -0
- package/dist/runtime/server/plugins/sitemap-seeder.js +11 -1
- package/dist/runtime/server/tasks/ai-ready-cron.js +1 -4
- package/dist/runtime/server/utils/batchIndex.d.ts +1 -1
- package/dist/runtime/server/utils/indexnow.d.ts +1 -1
- package/dist/runtime/server/utils/runCron.d.ts +1 -1
- package/package.json +5 -5
- package/dist/runtime/server/plugins/db-restore.d.ts +0 -2
- package/dist/runtime/server/plugins/db-restore.js +0 -26
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mkdir, writeFile, appendFile, stat, access } from 'node:fs/promises';
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
|
-
import { useLogger, useNuxt, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addServerHandler, addPlugin } from '@nuxt/kit';
|
|
3
|
+
import { useLogger, useNuxt, addTemplate, addTypeTemplate, defineNuxtModule, createResolver, hasNuxtModule, addServerHandler, addPlugin } from '@nuxt/kit';
|
|
4
4
|
import defu from 'defu';
|
|
5
5
|
import { useSiteConfig, installNuxtSiteConfig, withSiteUrl } from 'nuxt-site-config/kit';
|
|
6
6
|
import { readPackageJSON } from 'pkg-types';
|
|
@@ -333,9 +333,21 @@ function setupPrerenderHandler(dbPath, siteInfo, llmsTxtConfig) {
|
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
function registerTypeTemplates(_ctx) {
|
|
336
|
+
addTemplate({
|
|
337
|
+
filename: "types/ai-ready-adapter.d.ts",
|
|
338
|
+
getContents: () => `declare module '#ai-ready/adapter' {
|
|
339
|
+
import type { Connector } from 'db0'
|
|
340
|
+
const connector: (config: unknown) => Connector
|
|
341
|
+
export default connector
|
|
342
|
+
}
|
|
343
|
+
`
|
|
344
|
+
});
|
|
336
345
|
addTypeTemplate({
|
|
337
|
-
filename: "types/nuxt-ai-ready.d.ts",
|
|
346
|
+
filename: "types/nuxt-ai-ready-augments.d.ts",
|
|
338
347
|
getContents: () => `// Generated by nuxt-ai-ready
|
|
348
|
+
/// <reference path="./ai-ready-adapter.d.ts" />
|
|
349
|
+
/// <reference path="./ai-ready-virtual.d.ts" />
|
|
350
|
+
/// <reference path="./ai-ready-db-provider.d.ts" />
|
|
339
351
|
import type { MarkdownContext, PageIndexedContext } from 'nuxt-ai-ready'
|
|
340
352
|
import type { HTMLToMarkdownOptions } from 'mdream'
|
|
341
353
|
|
|
@@ -347,7 +359,12 @@ declare module 'nitropack/types' {
|
|
|
347
359
|
}
|
|
348
360
|
}
|
|
349
361
|
|
|
350
|
-
|
|
362
|
+
export {}
|
|
363
|
+
`
|
|
364
|
+
});
|
|
365
|
+
addTemplate({
|
|
366
|
+
filename: "types/ai-ready-virtual.d.ts",
|
|
367
|
+
getContents: () => `declare module '#ai-ready-virtual/read-page-data.mjs' {
|
|
351
368
|
export function readPageDataFromFilesystem(): Promise<{
|
|
352
369
|
pages: Array<{
|
|
353
370
|
route: string
|
|
@@ -365,20 +382,15 @@ declare module '#ai-ready-virtual/read-page-data.mjs' {
|
|
|
365
382
|
declare module '#ai-ready-virtual/page-data.mjs' {
|
|
366
383
|
export const pages: never[]
|
|
367
384
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
declare module '#ai-ready/db-provider' {
|
|
385
|
+
`
|
|
386
|
+
});
|
|
387
|
+
addTemplate({
|
|
388
|
+
filename: "types/ai-ready-db-provider.d.ts",
|
|
389
|
+
getContents: () => `declare module '#ai-ready/db-provider' {
|
|
376
390
|
import type { H3Event } from 'h3'
|
|
377
391
|
import type { Connector } from 'db0'
|
|
378
392
|
export function createConnector(event?: H3Event): Promise<Connector>
|
|
379
393
|
}
|
|
380
|
-
|
|
381
|
-
export {}
|
|
382
394
|
`
|
|
383
395
|
});
|
|
384
396
|
}
|
|
@@ -655,7 +667,6 @@ export const errorRoutes = []`;
|
|
|
655
667
|
indexNowKey
|
|
656
668
|
};
|
|
657
669
|
nuxt.options.nitro.plugins = nuxt.options.nitro.plugins || [];
|
|
658
|
-
nuxt.options.nitro.plugins.push(resolve("./runtime/server/plugins/db-restore"));
|
|
659
670
|
if (runtimeSyncEnabled)
|
|
660
671
|
nuxt.options.nitro.plugins.push(resolve("./runtime/server/plugins/sitemap-seeder"));
|
|
661
672
|
addServerHandler({
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { H3Event } from 'h3';
|
|
2
2
|
import type { DatabaseAdapter } from './shared.js';
|
|
3
3
|
/**
|
|
4
|
-
* Get the database adapter instance
|
|
5
|
-
*
|
|
4
|
+
* Get the database adapter instance (lazy init per-request)
|
|
5
|
+
* No global caching to avoid async operations at global scope
|
|
6
6
|
*/
|
|
7
7
|
export declare function useDatabase(event?: H3Event): Promise<DatabaseAdapter>;
|
|
8
8
|
export type { DatabaseAdapter } from './shared.js';
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { createConnector } from "#ai-ready/db-provider";
|
|
2
|
-
import { useNitroApp } from "nitropack/runtime";
|
|
3
2
|
import { createAdapter, initSchema } from "./shared.js";
|
|
4
|
-
|
|
5
|
-
export function useDatabase(event) {
|
|
6
|
-
const nitro = useNitroApp();
|
|
7
|
-
if (!nitro[DB_KEY]) {
|
|
8
|
-
nitro[DB_KEY] = initDatabase(event);
|
|
9
|
-
}
|
|
10
|
-
return nitro[DB_KEY];
|
|
11
|
-
}
|
|
12
|
-
async function initDatabase(event) {
|
|
3
|
+
export async function useDatabase(event) {
|
|
13
4
|
const connector = await createConnector(event);
|
|
14
5
|
if (!connector) {
|
|
15
6
|
throw new Error("Failed to initialize database connector");
|
|
@@ -3,26 +3,5 @@ import { useRuntimeConfig } from "nitropack/runtime";
|
|
|
3
3
|
export async function createConnector(event) {
|
|
4
4
|
const config = useRuntimeConfig(event)["nuxt-ai-ready"];
|
|
5
5
|
const bindingName = config.database.bindingName || "DB";
|
|
6
|
-
|
|
7
|
-
try {
|
|
8
|
-
const context = event?.context || useEvent?.()?.context;
|
|
9
|
-
cloudflareEnv = context?.cloudflare?.env;
|
|
10
|
-
} catch {
|
|
11
|
-
cloudflareEnv = globalThis.__env__;
|
|
12
|
-
}
|
|
13
|
-
const binding = cloudflareEnv?.[bindingName];
|
|
14
|
-
if (!binding) {
|
|
15
|
-
const debug = {
|
|
16
|
-
hasEvent: !!event,
|
|
17
|
-
hasContext: !!event?.context,
|
|
18
|
-
hasCloudflare: !!event?.context?.cloudflare,
|
|
19
|
-
hasCloudflareEnv: !!event?.context?.cloudflare?.env,
|
|
20
|
-
hasGlobalEnv: !!globalThis.__env__,
|
|
21
|
-
cloudflareEnvKeys: cloudflareEnv ? Object.keys(cloudflareEnv) : [],
|
|
22
|
-
bindingName
|
|
23
|
-
};
|
|
24
|
-
console.error(`[D1 Debug] Binding '${bindingName}' not found. Context:`, JSON.stringify(debug, null, 2));
|
|
25
|
-
throw new Error(`D1 binding '${bindingName}' not found in event.context.cloudflare.env or globalThis.__env__`);
|
|
26
|
-
}
|
|
27
|
-
return adapter({ binding });
|
|
6
|
+
return adapter({ bindingName });
|
|
28
7
|
}
|
|
@@ -13,7 +13,7 @@ export interface DatabaseAdapter {
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function createAdapter(connector: Connector): DatabaseAdapter;
|
|
15
15
|
/**
|
|
16
|
-
* Initialize database schema with version checking
|
|
16
|
+
* Initialize database schema with version checking and lazy restore
|
|
17
17
|
*/
|
|
18
18
|
export declare function initSchema(db: DatabaseAdapter): Promise<void>;
|
|
19
19
|
/**
|
|
@@ -35,6 +35,33 @@ export async function initSchema(db) {
|
|
|
35
35
|
"INSERT OR REPLACE INTO _ai_ready_info (id, version) VALUES (?, ?)",
|
|
36
36
|
["schema", SCHEMA_VERSION]
|
|
37
37
|
);
|
|
38
|
+
if (!import.meta.prerender && !import.meta.dev) {
|
|
39
|
+
await restoreFromDumpIfEmpty(db);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function restoreFromDumpIfEmpty(db) {
|
|
43
|
+
const row = await db.first("SELECT COUNT(*) as count FROM ai_ready_pages");
|
|
44
|
+
if (row && row.count > 0)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
let dumpData = null;
|
|
48
|
+
const cfEnv = globalThis.__env__;
|
|
49
|
+
if (cfEnv?.ASSETS) {
|
|
50
|
+
const response = await cfEnv.ASSETS.fetch("https://placeholder/__ai-ready/pages.dump");
|
|
51
|
+
if (response.ok)
|
|
52
|
+
dumpData = await response.text();
|
|
53
|
+
}
|
|
54
|
+
if (!dumpData) {
|
|
55
|
+
dumpData = await globalThis.$fetch("/__ai-ready/pages.dump", {
|
|
56
|
+
responseType: "text"
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
if (!dumpData)
|
|
60
|
+
return;
|
|
61
|
+
const rows = await decompressFromBase64(dumpData);
|
|
62
|
+
await importDbDump(db, rows);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
38
65
|
}
|
|
39
66
|
async function checkSchemaVersion(db) {
|
|
40
67
|
const info = await db.first(
|
|
@@ -9,7 +9,17 @@ export default defineNitroPlugin((nitro) => {
|
|
|
9
9
|
nitro.hooks.hook("request", async (event) => {
|
|
10
10
|
if (!seeding) {
|
|
11
11
|
seeding = seedFromSitemap(event).catch((err) => {
|
|
12
|
-
if (err.message?.includes("D1 binding")) {
|
|
12
|
+
if (err.message?.includes("D1 binding") || err.message?.includes("[d1]")) {
|
|
13
|
+
const config = useRuntimeConfig()["nuxt-ai-ready"];
|
|
14
|
+
if (config.debug) {
|
|
15
|
+
const debugInfo = {
|
|
16
|
+
hasGlobalEnv: !!globalThis.__env__,
|
|
17
|
+
globalEnvKeys: globalThis.__env__ ? Object.keys(globalThis.__env__) : [],
|
|
18
|
+
hasCloudflareContext: !!event.context?.cloudflare,
|
|
19
|
+
error: err.message
|
|
20
|
+
};
|
|
21
|
+
logger.info("[sitemap-seeder] D1 binding debug:", JSON.stringify(debugInfo, null, 2));
|
|
22
|
+
}
|
|
13
23
|
logger.info("[sitemap-seeder] Skipping runtime seeding - using static pages data");
|
|
14
24
|
} else {
|
|
15
25
|
logger.error("[sitemap-seeder] Failed to seed:", err);
|
|
@@ -8,10 +8,7 @@ export default defineTask({
|
|
|
8
8
|
async run({ payload }) {
|
|
9
9
|
if (import.meta.dev)
|
|
10
10
|
return { result: {} };
|
|
11
|
-
const
|
|
12
|
-
$fetch: globalThis.$fetch
|
|
13
|
-
};
|
|
14
|
-
const result = await runCron(mockEvent, {
|
|
11
|
+
const result = await runCron(void 0, {
|
|
15
12
|
batchSize: payload?.limit
|
|
16
13
|
});
|
|
17
14
|
return { result };
|
|
@@ -23,4 +23,4 @@ export interface BatchIndexResult {
|
|
|
23
23
|
* Batch index pending pages (max 50 per batch)
|
|
24
24
|
* Shared logic used by poll endpoint and scheduled task
|
|
25
25
|
*/
|
|
26
|
-
export declare function batchIndexPages(event: H3Event, options?: BatchIndexOptions): Promise<BatchIndexResult>;
|
|
26
|
+
export declare function batchIndexPages(event: H3Event | undefined, options?: BatchIndexOptions): Promise<BatchIndexResult>;
|
|
@@ -19,4 +19,4 @@ export declare function submitToIndexNow(routes: string[], config: {
|
|
|
19
19
|
* Submit pending pages to IndexNow
|
|
20
20
|
* Queries DB for pages needing sync, submits, marks as synced
|
|
21
21
|
*/
|
|
22
|
-
export declare function syncToIndexNow(event: H3Event, limit?: number): Promise<IndexNowResult>;
|
|
22
|
+
export declare function syncToIndexNow(event: H3Event | undefined, limit?: number): Promise<IndexNowResult>;
|
|
@@ -16,6 +16,6 @@ export interface CronResult {
|
|
|
16
16
|
/**
|
|
17
17
|
* Run cron job logic - shared between scheduled task and HTTP endpoint
|
|
18
18
|
*/
|
|
19
|
-
export declare function runCron(event: H3Event, options?: {
|
|
19
|
+
export declare function runCron(event: H3Event | undefined, options?: {
|
|
20
20
|
batchSize?: number;
|
|
21
21
|
}): Promise<CronResult>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-ai-ready",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.9",
|
|
5
5
|
"description": "Best practice AI & LLM discoverability for Nuxt sites.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"pathe": "^2.0.3",
|
|
58
58
|
"pkg-types": "^2.3.0",
|
|
59
59
|
"std-env": "3.10.0",
|
|
60
|
-
"ufo": "^1.6.
|
|
60
|
+
"ufo": "^1.6.3"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@antfu/eslint-config": "^7.0.
|
|
63
|
+
"@antfu/eslint-config": "^7.0.1",
|
|
64
64
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
65
65
|
"@headlessui/vue": "^1.7.23",
|
|
66
66
|
"@nuxt/content": "^3.10.0",
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
"@vue/test-utils": "^2.4.6",
|
|
79
79
|
"@vueuse/nuxt": "^14.1.0",
|
|
80
80
|
"agents": "^0.3.5",
|
|
81
|
-
"ai": "^6.0.
|
|
81
|
+
"ai": "^6.0.35",
|
|
82
82
|
"better-sqlite3": "^12.6.0",
|
|
83
83
|
"bumpp": "^10.4.0",
|
|
84
84
|
"eslint": "^9.39.2",
|
|
85
85
|
"execa": "^9.6.1",
|
|
86
|
-
"happy-dom": "^20.
|
|
86
|
+
"happy-dom": "^20.3.0",
|
|
87
87
|
"nuxt": "^4.2.2",
|
|
88
88
|
"nuxt-site-config": "^3.2.17",
|
|
89
89
|
"playwright": "^1.57.0",
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { defineNitroPlugin } from "nitropack/runtime";
|
|
2
|
-
import { useDatabase } from "../db/index.js";
|
|
3
|
-
import { countPages } from "../db/queries.js";
|
|
4
|
-
import { decompressFromBase64, importDbDump } from "../db/shared.js";
|
|
5
|
-
import { logger } from "../logger.js";
|
|
6
|
-
export default defineNitroPlugin(async () => {
|
|
7
|
-
if (import.meta.prerender)
|
|
8
|
-
return;
|
|
9
|
-
if (import.meta.dev)
|
|
10
|
-
return;
|
|
11
|
-
if (await countPages() > 0) {
|
|
12
|
-
logger.debug("[db-restore] Database already has data, skipping restore");
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
const dumpData = await globalThis.$fetch("/__ai-ready/pages.dump", {
|
|
16
|
-
responseType: "text"
|
|
17
|
-
}).catch(() => null);
|
|
18
|
-
if (!dumpData) {
|
|
19
|
-
logger.debug("[db-restore] No dump found, starting with empty database");
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
const db = await useDatabase();
|
|
23
|
-
const rows = await decompressFromBase64(dumpData);
|
|
24
|
-
await importDbDump(db, rows);
|
|
25
|
-
logger.info(`[db-restore] Restored ${rows.length} pages from dump`);
|
|
26
|
-
});
|