nuxt-ai-ready 1.8.0 → 2.0.1

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.
Files changed (68) hide show
  1. package/README.md +0 -1
  2. package/dist/chunks/agent-skills.mjs +1 -1
  3. package/dist/chunks/prerender.mjs +7 -83
  4. package/dist/cli.mjs +1 -63
  5. package/dist/devtools/lib/ai-ready/types.ts +0 -1
  6. package/dist/module.d.mts +17 -8
  7. package/dist/module.json +1 -1
  8. package/dist/module.mjs +1 -1
  9. package/dist/runtime/server/db/drizzle/client.d.ts +4 -4
  10. package/dist/runtime/server/db/drizzle/index.d.ts +1 -1
  11. package/dist/runtime/server/db/drizzle/index.js +0 -3
  12. package/dist/runtime/server/db/drizzle/providers/bun.d.ts +1 -1
  13. package/dist/runtime/server/db/drizzle/providers/bun.js +1 -2
  14. package/dist/runtime/server/db/drizzle/providers/d1.d.ts +1 -1
  15. package/dist/runtime/server/db/drizzle/providers/d1.js +1 -2
  16. package/dist/runtime/server/db/drizzle/providers/libsql.d.ts +1 -1
  17. package/dist/runtime/server/db/drizzle/providers/libsql.js +1 -2
  18. package/dist/runtime/server/db/drizzle/providers/neon.d.ts +1 -1
  19. package/dist/runtime/server/db/drizzle/providers/neon.js +1 -2
  20. package/dist/runtime/server/db/drizzle/providers/node-sqlite.d.ts +8 -0
  21. package/dist/runtime/server/db/drizzle/providers/node-sqlite.js +15 -0
  22. package/dist/runtime/server/db/drizzle/providers/sqlite.d.ts +1 -1
  23. package/dist/runtime/server/db/drizzle/providers/sqlite.js +1 -2
  24. package/dist/runtime/server/db/drizzle/queries.d.ts +0 -18
  25. package/dist/runtime/server/db/drizzle/queries.js +2 -71
  26. package/dist/runtime/server/db/drizzle/raw.d.ts +1 -1
  27. package/dist/runtime/server/db/drizzle/raw.js +27 -0
  28. package/dist/runtime/server/db/queries.d.ts +0 -70
  29. package/dist/runtime/server/db/queries.js +10 -170
  30. package/dist/runtime/server/db/schema/postgres.d.ts +292 -722
  31. package/dist/runtime/server/db/schema/postgres.js +1 -13
  32. package/dist/runtime/server/db/schema/sqlite.d.ts +174 -620
  33. package/dist/runtime/server/db/schema/sqlite.js +1 -13
  34. package/dist/runtime/server/db/schema-sql.d.ts +1 -1
  35. package/dist/runtime/server/db/schema-sql.js +2 -12
  36. package/dist/runtime/server/db/shared.d.ts +0 -1
  37. package/dist/runtime/server/db/shared.js +4 -6
  38. package/dist/runtime/server/middleware/markdown.js +42 -106
  39. package/dist/runtime/server/plugins/markdown-negotiation.d.ts +13 -0
  40. package/dist/runtime/server/plugins/markdown-negotiation.js +45 -0
  41. package/dist/runtime/server/routes/__ai-ready/devtools.get.js +1 -2
  42. package/dist/runtime/server/routes/__ai-ready/status.get.js +1 -20
  43. package/dist/runtime/server/routes/__ai-ready-debug.get.js +2 -47
  44. package/dist/runtime/server/tasks/ai-ready-cron.js +1 -1
  45. package/dist/runtime/server/utils/content-negotiation.d.ts +2 -3
  46. package/dist/runtime/server/utils/cron-plan.d.ts +0 -3
  47. package/dist/runtime/server/utils/cron-plan.js +2 -5
  48. package/dist/runtime/server/utils/frontmatter.d.ts +1 -0
  49. package/dist/runtime/server/utils/frontmatter.js +22 -0
  50. package/dist/runtime/server/utils/markdown-request.d.ts +17 -1
  51. package/dist/runtime/server/utils/markdown-request.js +20 -11
  52. package/dist/runtime/server/utils/negotiation-decision.d.ts +39 -0
  53. package/dist/runtime/server/utils/negotiation-decision.js +30 -0
  54. package/dist/runtime/server/utils/negotiation-response.d.ts +34 -0
  55. package/dist/runtime/server/utils/negotiation-response.js +108 -0
  56. package/dist/runtime/server/utils/runCron.d.ts +0 -5
  57. package/dist/runtime/server/utils/runCron.js +4 -32
  58. package/dist/runtime/types.d.ts +51 -13
  59. package/dist/shared/{nuxt-ai-ready.B6l-68o5.mjs → nuxt-ai-ready.D8qbnNrv.mjs} +159 -84
  60. package/package.json +18 -18
  61. package/dist/runtime/server/routes/__ai-ready/indexnow.post.d.ts +0 -2
  62. package/dist/runtime/server/routes/__ai-ready/indexnow.post.js +0 -14
  63. package/dist/runtime/server/routes/indexnow-key.get.d.ts +0 -6
  64. package/dist/runtime/server/routes/indexnow-key.get.js +0 -9
  65. package/dist/runtime/server/utils/indexnow-shared.d.ts +0 -70
  66. package/dist/runtime/server/utils/indexnow-shared.js +0 -87
  67. package/dist/runtime/server/utils/indexnow.d.ts +0 -30
  68. package/dist/runtime/server/utils/indexnow.js +0 -119
package/README.md CHANGED
@@ -26,7 +26,6 @@ Nuxt AI Ready implements both. It converts your pages to markdown, generates llm
26
26
  - 🧠 **Agent Skills**: Publish verified local or external skills through the v0.2.0 discovery index
27
27
  - 🧩 **[WebMCP](https://nuxtseo.com/ai-ready/guides/webmcp)**: Give browser agents access to built-in site tools or your own tools with `useWebMcpTool()`
28
28
  - 🗄️ **Runtime Indexing**: Index pages on-demand without prerendering, with SQLite/D1/LibSQL support
29
- - 🔔 **[IndexNow](https://nuxtseo.com/ai-ready/guides/indexnow)**: Instantly notify Bing, Yandex, and other search engines when pages change
30
29
  - 🌏 **[i18n Aware](https://nuxtseo.com/ai-ready/guides/i18n)**: Auto-detects [`@nuxtjs/i18n`](https://i18n.nuxtjs.org/) for hreflang `Link` headers, locale-tagged frontmatter, and an Available Languages section in `llms.txt`
31
30
  - 🧠 **[RAG Ready](https://nuxtseo.com/ai-ready/advanced/rag-example)**: Markdown output optimized for vectorizing and semantic search
32
31
 
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { realpath, readFile } from 'node:fs/promises';
3
3
  import { resolve, isAbsolute, relative, sep } from 'node:path';
4
4
  import { parseDocument } from 'yaml';
5
- import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.B6l-68o5.mjs';
5
+ import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.D8qbnNrv.mjs';
6
6
  import 'node:module';
7
7
  import '@nuxt/kit';
8
8
  import 'defu';
@@ -4,12 +4,11 @@ import { useNuxt, hasNuxtModule, resolveFiles } from '@nuxt/kit';
4
4
  import { colorize } from 'consola/utils';
5
5
  import { resolveLocaleFromRoute } from 'nuxtseo-shared/i18n-runtime';
6
6
  import { collectSitemap } from 'sitemapd/parse';
7
- import { withLeadingSlash, withBase, joinURL } from 'ufo';
8
- import { l as logger, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.B6l-68o5.mjs';
7
+ import { withLeadingSlash, joinURL, withBase } from 'ufo';
8
+ import { l as logger, s as supportsNativeNodeSqlite, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.D8qbnNrv.mjs';
9
9
  import { normalizePagePath, toMarkdownPath } from '../../dist/runtime/markdown-path.js';
10
10
  import { toLogicalRoute, toDeployedRoute } from '../../dist/runtime/route-path.js';
11
11
  import { initSchema, computeContentHash, insertPage, queryAllPages, exportDbDump } from '../../dist/runtime/server/db/shared.js';
12
- import { comparePageHashes, submitToIndexNowShared } from '../../dist/runtime/server/utils/indexnow-shared.js';
13
12
  import { buildLlmsFullTxtHeader, formatPageForLlmsFullTxt } from '../../dist/runtime/server/utils/llms-full.js';
14
13
  import 'node:crypto';
15
14
  import 'node:module';
@@ -22,7 +21,6 @@ import '../../dist/runtime/server/utils/discovery-response.js';
22
21
  import 'pathe';
23
22
  import 'nuxtseo-shared/i18n';
24
23
 
25
- const BUILD_FETCH_TIMEOUT = 15e3;
26
24
  const PRERENDER_PAGE_TIMEOUT = 3e4;
27
25
  const RE_HTML_MD_EXT = /\.(html|md)$/;
28
26
  const RE_INDEX_SUFFIX = /\/index$/;
@@ -61,46 +59,7 @@ async function findOutputMarkdownPaths(publicDir, baseURL, srcDir, ignoredPaths,
61
59
  }
62
60
  return [...paths].sort();
63
61
  }
64
- async function fetchPreviousMeta(siteUrl, indexNow) {
65
- const metaUrl = withBase("/__ai-ready/pages.meta.json", siteUrl);
66
- logger.info(`Fetching previous build meta from ${metaUrl}`);
67
- const controller = new AbortController();
68
- const timeoutId = setTimeout(() => controller.abort(), BUILD_FETCH_TIMEOUT);
69
- const prevMeta = await fetch(metaUrl, { signal: controller.signal }).then((r) => r.ok ? r.json() : null).catch((err) => {
70
- if (err.name === "AbortError") {
71
- logger.warn(`Timeout fetching previous meta (${BUILD_FETCH_TIMEOUT}ms)`);
72
- }
73
- return null;
74
- }).finally(() => clearTimeout(timeoutId));
75
- if (!prevMeta?.pages) {
76
- logger.info("First deploy or no previous meta - will index all pages");
77
- return null;
78
- }
79
- logger.info(`Previous build: ${prevMeta.pageCount} pages (buildId: ${prevMeta.buildId})`);
80
- if (indexNow) {
81
- const keyUrl = withBase(`/${indexNow}.txt`, siteUrl);
82
- const keyLive = await fetch(keyUrl, { signal: AbortSignal.timeout(5e3) }).then((r) => r.ok).catch(() => false);
83
- if (!keyLive) {
84
- logger.info("IndexNow key file not live yet - IndexNow submission will be skipped");
85
- }
86
- }
87
- return prevMeta;
88
- }
89
- async function submitIndexNow(changedRoutes, addedRoutes, siteUrl, indexNow) {
90
- const allRoutes = [...changedRoutes, ...addedRoutes];
91
- if (allRoutes.length === 0) {
92
- logger.debug("[indexnow] No content changes detected");
93
- return;
94
- }
95
- logger.info(`[indexnow] Submitting ${allRoutes.length} changed pages (${changedRoutes.length} modified, ${addedRoutes.length} new)`);
96
- const result = await submitToIndexNowShared(allRoutes, indexNow, siteUrl, { logger });
97
- if (result.success) {
98
- logger.info(`[indexnow] Successfully notified search engines of ${allRoutes.length} changes`);
99
- } else {
100
- logger.warn(`[indexnow] Failed to submit: ${result.error}`);
101
- }
102
- }
103
- function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, indexNow, concurrency = 10, ftsTokenizer, i18n) {
62
+ function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, concurrency = 10, ftsTokenizer, i18n) {
104
63
  return {
105
64
  prerenderedRoutes: /* @__PURE__ */ new Set(),
106
65
  errorRoutes: /* @__PURE__ */ new Set(),
@@ -110,7 +69,6 @@ function createCrawlerState(dbPath, llmsFullTxtPath, siteInfo, llmsTxtConfig, in
110
69
  llmsFullTxtPath,
111
70
  siteInfo,
112
71
  llmsTxtConfig,
113
- indexNow,
114
72
  concurrency,
115
73
  ftsTokenizer,
116
74
  i18n
@@ -169,8 +127,7 @@ function createSqliteAdapter(sqlite) {
169
127
  };
170
128
  }
171
129
  async function createPrerenderDatabase(dbPath) {
172
- const nodeVersion = Number.parseInt(process.versions.node?.split(".")[0] || "0");
173
- if (nodeVersion >= 22) {
130
+ if (supportsNativeNodeSqlite(process.versions.node || "")) {
174
131
  const { DatabaseSync } = await import('node:sqlite');
175
132
  const sqlite2 = new DatabaseSync(dbPath);
176
133
  for (const pragma of PRERENDER_PRAGMAS)
@@ -341,7 +298,7 @@ async function prerenderRoute(nitro, route) {
341
298
  nitro._prerenderedRoutes.push(_route);
342
299
  return stat(filePath);
343
300
  }
344
- function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNow, extras = {}) {
301
+ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, extras = {}) {
345
302
  const nuxt = useNuxt();
346
303
  nuxt.hooks.hook("nitro:init", async (nitro) => {
347
304
  const llmsFullTxtPath = join(nitro.options.output.publicDir, "llms-full.txt");
@@ -350,7 +307,6 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
350
307
  llmsFullTxtPath,
351
308
  siteInfo,
352
309
  llmsTxtConfig,
353
- indexNow,
354
310
  options.prerender?.concurrency,
355
311
  extras.ftsTokenizer,
356
312
  extras.i18n
@@ -423,47 +379,15 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
423
379
  logger.debug(`Writing pages.dump: ${dumpPath} (${(dumpData.length / 1024).toFixed(1)}kb)`);
424
380
  await writeFile(dumpPath, dumpData, "utf-8");
425
381
  logger.debug(`Created database dump at __ai-ready/pages.dump (${(dumpData.length / 1024).toFixed(1)}kb compressed)`);
426
- const pageHashes = {};
427
- for (const p of pages) {
428
- if (p.contentHash)
429
- pageHashes[p.route] = p.contentHash;
430
- }
431
- let prevMeta = null;
432
- if (state.siteInfo?.url) {
433
- prevMeta = await fetchPreviousMeta(state.siteInfo.url, state.indexNow || "");
434
- }
435
- const { changed, added, removed } = comparePageHashes(pageHashes, prevMeta);
436
- const debug = useNuxt().options.runtimeConfig["nuxt-ai-ready"]?.debug;
437
- const changes = {
438
- changed: changed.length,
439
- added: added.length,
440
- removed: removed.length
441
- };
442
- if (debug) {
443
- if (changed.length > 0)
444
- changes.changedRoutes = changed;
445
- if (added.length > 0)
446
- changes.addedRoutes = added;
447
- if (removed.length > 0)
448
- changes.removedRoutes = removed;
449
- }
450
382
  const buildId = Date.now().toString(36);
451
383
  const metaContent = JSON.stringify({
452
384
  buildId,
453
385
  pageCount: pages.length,
454
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
455
- changes: prevMeta ? changes : void 0,
456
- pages: pageHashes
386
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
457
387
  });
458
388
  logger.debug(`Writing pages.meta.json (${(metaContent.length / 1024).toFixed(1)}kb)`);
459
389
  await writeFile(join(publicDataDir, "pages.meta.json"), metaContent, "utf-8");
460
- logger.debug(`Wrote build metadata: buildId=${buildId}, ${Object.keys(pageHashes).length} page hashes`);
461
- if (prevMeta && (changed.length > 0 || added.length > 0 || removed.length > 0)) {
462
- logger.info(`Content changes: ${changed.length} modified, ${added.length} new, ${removed.length} removed`);
463
- }
464
- if (state.indexNow && state.siteInfo?.url && prevMeta) {
465
- await submitIndexNow(changed, added, state.siteInfo.url, state.indexNow);
466
- }
390
+ logger.debug(`Wrote build metadata: buildId=${buildId}`);
467
391
  }
468
392
  if (state.dbPath && state.llmsTxtConfig?.markdownLinks) {
469
393
  const availabilityFile = join(dirname(state.dbPath), MARKDOWN_LINK_AVAILABILITY_FILE);
package/dist/cli.mjs CHANGED
@@ -42,7 +42,7 @@ const main = defineCommand({
42
42
  status: () => defineCommand({
43
43
  meta: {
44
44
  name: "status",
45
- description: "Show indexing status and IndexNow sync progress"
45
+ description: "Show indexing status and sync progress"
46
46
  },
47
47
  args: {
48
48
  url: {
@@ -85,23 +85,6 @@ const main = defineCommand({
85
85
  }
86
86
  }
87
87
  }
88
- if (res.indexNow) {
89
- consola.log("");
90
- consola.info(colors.bold("IndexNow:"));
91
- consola.info(` Pending: ${colors.yellow(res.indexNow.pending?.toString() || "0")}`);
92
- consola.info(` Total submitted: ${colors.green(res.indexNow.totalSubmitted?.toString() || "0")}`);
93
- if (res.indexNow.lastSubmittedAt) {
94
- const date = new Date(res.indexNow.lastSubmittedAt);
95
- consola.info(` Last sync: ${colors.dim(date.toISOString())}`);
96
- }
97
- if (res.indexNow.lastError) {
98
- consola.info(` Last error: ${colors.red(res.indexNow.lastError)}`);
99
- }
100
- if (res.indexNow.backoff?.active) {
101
- const remainMin = Math.ceil((res.indexNow.backoff.remainingMs || 0) / 6e4);
102
- consola.warn(` Backoff: ${colors.yellow(`${remainMin}m remaining`)} (attempt ${res.indexNow.backoff.attempt})`);
103
- }
104
- }
105
88
  if (res.cron) {
106
89
  consola.log("");
107
90
  consola.info(colors.bold("Cron:"));
@@ -285,51 +268,6 @@ const main = defineCommand({
285
268
  consola.success(`Pruned: ${colors.green(res.pruned?.toString() || "0")} routes`);
286
269
  }
287
270
  }
288
- }),
289
- indexnow: () => defineCommand({
290
- meta: {
291
- name: "indexnow",
292
- description: "Trigger IndexNow sync"
293
- },
294
- args: {
295
- url: {
296
- type: "string",
297
- alias: "u",
298
- description: "Site URL (default: http://localhost:3000)",
299
- default: "http://localhost:3000"
300
- },
301
- limit: {
302
- type: "string",
303
- alias: "l",
304
- description: "Max URLs to submit",
305
- default: "100"
306
- },
307
- cwd: {
308
- type: "string",
309
- description: "Working directory",
310
- default: "."
311
- }
312
- },
313
- async run({ args }) {
314
- const cwd = resolve(args.cwd || ".");
315
- const secret = await requireSecret(cwd);
316
- if (!secret)
317
- return;
318
- const params = new URLSearchParams({
319
- limit: args.limit || "100"
320
- });
321
- const url = `${args.url}/__ai-ready/indexnow?${params}`;
322
- consola.info(`Triggering IndexNow sync at ${args.url}...`);
323
- const res = await fetchJson(url, { method: "POST", headers: authHeaders(secret) });
324
- if (!res)
325
- return;
326
- if (res.success) {
327
- consola.success(`Submitted: ${colors.green(res.submitted?.toString() || "0")} URLs`);
328
- consola.info(`Remaining: ${colors.yellow(res.remaining?.toString() || "0")}`);
329
- } else {
330
- consola.error(`Failed: ${res.error || "Unknown error"}`);
331
- }
332
- }
333
271
  })
334
272
  }
335
273
  });
@@ -1,7 +1,6 @@
1
1
  export interface DevtoolsConfig {
2
2
  database: { type: string }
3
3
  runtimeSync: { enabled: boolean, ttl: number, batchSize: number, pruneTtl: number }
4
- indexNow: boolean
5
4
  sitemapPrerendered: boolean
6
5
  markdownCacheHeaders: { maxAge: number, swr: boolean }
7
6
  llmsTxtCacheSeconds: number
package/dist/module.d.mts CHANGED
@@ -31,6 +31,22 @@ interface ResolvedApiCatalogConfig {
31
31
  };
32
32
  }
33
33
 
34
+ type DatabaseType = 'sqlite' | 'bun' | 'd1' | 'libsql' | 'neon';
35
+ /**
36
+ * Database state after parsing. Every consumer reads `_tag` first, so a
37
+ * disabled database can never carry a driver, a path, or credentials.
38
+ */
39
+ type ResolvedDatabase = {
40
+ _tag: 'Disabled';
41
+ } | {
42
+ _tag: 'Enabled';
43
+ type: DatabaseType;
44
+ filename?: string;
45
+ bindingName?: string;
46
+ url?: string;
47
+ authToken?: string;
48
+ };
49
+
34
50
  interface ResolvedWebMcpConfig {
35
51
  tools: ResolvedWebMcpToolsConfig;
36
52
  exposedTo?: string[];
@@ -71,13 +87,7 @@ interface ModulePublicRuntimeConfig {
71
87
  version: string;
72
88
  mdreamOptions: ModuleOptions['mdreamOptions'];
73
89
  markdownCacheHeaders: Required<NonNullable<ModuleOptions['markdownCacheHeaders']>>;
74
- database: {
75
- type: 'sqlite' | 'bun' | 'd1' | 'libsql' | 'neon';
76
- filename?: string;
77
- bindingName?: string;
78
- url?: string;
79
- authToken?: string;
80
- };
90
+ database: ResolvedDatabase;
81
91
  runtimeSync: {
82
92
  enabled: boolean;
83
93
  ttl: number;
@@ -85,7 +95,6 @@ interface ModulePublicRuntimeConfig {
85
95
  pruneTtl: number;
86
96
  };
87
97
  runtimeSyncSecret?: string;
88
- indexNow?: string;
89
98
  sitemapPrerendered: boolean;
90
99
  i18n?: RuntimeI18nConfig | null;
91
100
  ftsTokenizer?: string;
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=4.0.0"
5
5
  },
6
6
  "configKey": "aiReady",
7
- "version": "1.8.0",
7
+ "version": "2.0.1",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -7,7 +7,7 @@ import 'defu';
7
7
  import 'nuxt-site-config/kit';
8
8
  import 'nuxtseo-shared/kit';
9
9
  import 'pkg-types';
10
- export { m as default } from './shared/nuxt-ai-ready.B6l-68o5.mjs';
10
+ export { m as default } from './shared/nuxt-ai-ready.D8qbnNrv.mjs';
11
11
  import '../dist/runtime/server/utils/discovery-response.js';
12
12
  import 'node:url';
13
13
  import 'pathe';
@@ -1,13 +1,13 @@
1
1
  import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
2
- import type { BunSQLiteDatabase } from 'drizzle-orm/bun-sqlite';
2
+ import type { SQLiteBunDatabase } from 'drizzle-orm/bun-sqlite';
3
3
  import type { DrizzleD1Database } from 'drizzle-orm/d1';
4
4
  import type { LibSQLDatabase } from 'drizzle-orm/libsql';
5
5
  import type { NeonHttpDatabase } from 'drizzle-orm/neon-http';
6
- import type * as schema from '#ai-ready-virtual/db-schema.mjs';
6
+ import type { NodeSQLiteDatabase } from 'drizzle-orm/node-sqlite';
7
7
  import type { H3Event } from '#nuxtseo/h3';
8
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>;
9
+ type SQLiteDB = BetterSQLite3Database | SQLiteBunDatabase | LibSQLDatabase | DrizzleD1Database | NodeSQLiteDatabase;
10
+ type PostgresDB = NeonHttpDatabase;
11
11
  export interface DrizzleDatabase {
12
12
  dialect: DatabaseDialect;
13
13
  db: SQLiteDB | PostgresDB;
@@ -4,7 +4,7 @@
4
4
  export * from '#ai-ready-virtual/db-schema.mjs';
5
5
  export { closeDrizzle, useDrizzle } from './client.js';
6
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, markSitemapCrawlPartial, markSitemapError, markSitemapSeeded, resetSitemapErrors, searchPages, seedRoutes, setInfoValue, startCronRun, syncSitemaps, upsertPage, } from './queries.js';
7
+ export { completeCronRun, countPages, deleteInfoValue, deletePage, getAllPages, getContentHashes, getInfoValue, getNextSitemapToCrawl, getPageByRoute, getPageLastmods, getPendingPages, getRecentCronRuns, getSitemapStatus, initSchema, markPageIndexed, markRoutesPending, markSitemapCrawled, markSitemapCrawlPartial, markSitemapError, markSitemapSeeded, resetSitemapErrors, searchPages, seedRoutes, setInfoValue, startCronRun, syncSitemaps, upsertPage, } from './queries.js';
8
8
  export type { CronRunOutput, PageInput, PageMetaOutput, PageOutput, SitemapOutput, } from './queries.js';
9
9
  export { useRawDb } from './raw.js';
10
10
  export type { RawExecutor } from './raw.js';
@@ -3,7 +3,6 @@ export { closeDrizzle, useDrizzle } from "./client.js";
3
3
  export {
4
4
  completeCronRun,
5
5
  countPages,
6
- countPagesNeedingIndexNowSync,
7
6
  deleteInfoValue,
8
7
  deletePage,
9
8
  getAllPages,
@@ -12,12 +11,10 @@ export {
12
11
  getNextSitemapToCrawl,
13
12
  getPageByRoute,
14
13
  getPageLastmods,
15
- getPagesNeedingIndexNowSync,
16
14
  getPendingPages,
17
15
  getRecentCronRuns,
18
16
  getSitemapStatus,
19
17
  initSchema,
20
- markIndexNowSynced,
21
18
  markPageIndexed,
22
19
  markRoutesPending,
23
20
  markSitemapCrawled,
@@ -1,7 +1,7 @@
1
1
  import type { H3Event } from '#nuxtseo/h3';
2
2
  export declare function createClient(event?: H3Event): Promise<{
3
3
  dialect: "sqlite";
4
- db: import("drizzle-orm/bun-sqlite").BunSQLiteDatabase<any> & {
4
+ db: import("drizzle-orm/bun-sqlite").SQLiteBunDatabase<import("drizzle-orm").EmptyRelations> & {
5
5
  $client: any;
6
6
  };
7
7
  }>;
@@ -1,6 +1,5 @@
1
1
  import { Database } from "bun:sqlite";
2
2
  import { drizzle } from "drizzle-orm/bun-sqlite";
3
- import * as schema from "#ai-ready-virtual/db-schema.mjs";
4
3
  import { useRuntimeConfig } from "#nuxtseo/nitro";
5
4
  import { logger } from "../../../logger.js";
6
5
  import { registerDriver } from "../raw.js";
@@ -10,7 +9,7 @@ export async function createClient(event) {
10
9
  const dbPath = await resolveWritableDbPath(config.database.filename || ".data/ai-ready/pages.db");
11
10
  logger.debug(`[drizzle] Opening Bun SQLite database: ${dbPath}`);
12
11
  const sqlite = new Database(dbPath);
13
- const db = drizzle(sqlite, { schema });
12
+ const db = drizzle({ client: sqlite });
14
13
  registerDriver(db, "better-sqlite3", sqlite);
15
14
  return { dialect: "sqlite", db };
16
15
  }
@@ -1,7 +1,7 @@
1
1
  import type { H3Event } from '#nuxtseo/h3';
2
2
  export declare function createClient(event?: H3Event): Promise<{
3
3
  dialect: "sqlite";
4
- db: import("drizzle-orm/d1").DrizzleD1Database<any> & {
4
+ db: import("drizzle-orm/d1").DrizzleD1Database<import("drizzle-orm").EmptyRelations> & {
5
5
  $client: any;
6
6
  };
7
7
  }>;
@@ -1,5 +1,4 @@
1
1
  import { drizzle } from "drizzle-orm/d1";
2
- import * as schema from "#ai-ready-virtual/db-schema.mjs";
3
2
  import { useRuntimeConfig } from "#nuxtseo/nitro";
4
3
  import { logger } from "../../../logger.js";
5
4
  import { registerDriver } from "../raw.js";
@@ -13,7 +12,7 @@ export async function createClient(event) {
13
12
  if (!d1) {
14
13
  throw new Error(`[ai-ready] D1 binding "${bindingName}" not found`);
15
14
  }
16
- const db = drizzle(d1, { schema });
15
+ const db = drizzle(d1);
17
16
  registerDriver(db, "d1", d1);
18
17
  return { dialect: "sqlite", db };
19
18
  }
@@ -1,7 +1,7 @@
1
1
  import type { H3Event } from '#nuxtseo/h3';
2
2
  export declare function createClient(event?: H3Event): Promise<{
3
3
  dialect: "sqlite";
4
- db: import("drizzle-orm/libsql").LibSQLDatabase<any> & {
4
+ db: import("drizzle-orm/libsql").LibSQLDatabase<import("drizzle-orm").EmptyRelations> & {
5
5
  $client: import("@libsql/client").Client;
6
6
  };
7
7
  }>;
@@ -1,6 +1,5 @@
1
1
  import { createClient as createLibSQLClient } from "@libsql/client";
2
2
  import { drizzle } from "drizzle-orm/libsql";
3
- import * as schema from "#ai-ready-virtual/db-schema.mjs";
4
3
  import { useRuntimeConfig } from "#nuxtseo/nitro";
5
4
  import { logger } from "../../../logger.js";
6
5
  import { registerDriver } from "../raw.js";
@@ -14,7 +13,7 @@ export async function createClient(event) {
14
13
  }
15
14
  logger.debug(`[drizzle] Connecting to LibSQL: ${dbUrl}`);
16
15
  const client = createLibSQLClient({ url: dbUrl, authToken: config.database.authToken });
17
- const db = drizzle(client, { schema });
16
+ const db = drizzle({ client });
18
17
  registerDriver(db, "libsql", client);
19
18
  return { dialect: "sqlite", db };
20
19
  }
@@ -1,7 +1,7 @@
1
1
  import type { H3Event } from '#nuxtseo/h3';
2
2
  export declare function createClient(event?: H3Event): Promise<{
3
3
  dialect: "postgres";
4
- db: import("drizzle-orm/neon-http").NeonHttpDatabase<any> & {
4
+ db: import("drizzle-orm/neon-http").NeonHttpDatabase<import("drizzle-orm").EmptyRelations> & {
5
5
  $client: import("@neondatabase/serverless").NeonQueryFunction<false, false>;
6
6
  };
7
7
  }>;
@@ -1,6 +1,5 @@
1
1
  import { neon } from "@neondatabase/serverless";
2
2
  import { drizzle } from "drizzle-orm/neon-http";
3
- import * as schema from "#ai-ready-virtual/db-schema.mjs";
4
3
  import { useRuntimeConfig } from "#nuxtseo/nitro";
5
4
  import { logger } from "../../../logger.js";
6
5
  import { registerDriver } from "../raw.js";
@@ -12,7 +11,7 @@ export async function createClient(event) {
12
11
  }
13
12
  logger.debug(`[drizzle] Connecting to Neon Postgres`);
14
13
  const sqlFn = neon(connectionString);
15
- const db = drizzle(sqlFn, { schema });
14
+ const db = drizzle({ client: sqlFn });
16
15
  registerDriver(db, "neon", sqlFn);
17
16
  return { dialect: "postgres", db };
18
17
  }
@@ -0,0 +1,8 @@
1
+ import type { H3Event } from '#nuxtseo/h3';
2
+ import { DatabaseSync } from 'node:sqlite';
3
+ export declare function createClient(event?: H3Event): Promise<{
4
+ dialect: "sqlite";
5
+ db: import("drizzle-orm/node-sqlite").NodeSQLiteDatabase<import("drizzle-orm").EmptyRelations> & {
6
+ $client: DatabaseSync;
7
+ };
8
+ }>;
@@ -0,0 +1,15 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import { drizzle } from "drizzle-orm/node-sqlite";
3
+ import { useRuntimeConfig } from "#nuxtseo/nitro";
4
+ import { logger } from "../../../logger.js";
5
+ import { registerDriver } from "../raw.js";
6
+ import { resolveWritableDbPath } from "./dbPath.js";
7
+ export async function createClient(event) {
8
+ const config = useRuntimeConfig(event)["nuxt-ai-ready"];
9
+ const dbPath = await resolveWritableDbPath(config.database.filename || ".data/ai-ready/pages.db");
10
+ logger.debug(`[drizzle] Opening native SQLite database: ${dbPath}`);
11
+ const sqlite = new DatabaseSync(dbPath);
12
+ const db = drizzle({ client: sqlite });
13
+ registerDriver(db, "node-sqlite", sqlite);
14
+ return { dialect: "sqlite", db };
15
+ }
@@ -2,7 +2,7 @@ import type { H3Event } from '#nuxtseo/h3';
2
2
  import Database from 'better-sqlite3';
3
3
  export declare function createClient(event?: H3Event): Promise<{
4
4
  dialect: "sqlite";
5
- db: import("drizzle-orm/better-sqlite3").BetterSQLite3Database<any> & {
5
+ db: import("drizzle-orm/better-sqlite3").BetterSQLite3Database<import("drizzle-orm").EmptyRelations> & {
6
6
  $client: Database.Database;
7
7
  };
8
8
  }>;
@@ -1,6 +1,5 @@
1
1
  import Database from "better-sqlite3";
2
2
  import { drizzle } from "drizzle-orm/better-sqlite3";
3
- import * as schema from "#ai-ready-virtual/db-schema.mjs";
4
3
  import { useRuntimeConfig } from "#nuxtseo/nitro";
5
4
  import { logger } from "../../../logger.js";
6
5
  import { registerDriver } from "../raw.js";
@@ -10,7 +9,7 @@ export async function createClient(event) {
10
9
  const dbPath = await resolveWritableDbPath(config.database.filename || ".data/ai-ready/pages.db");
11
10
  logger.debug(`[drizzle] Opening SQLite database: ${dbPath}`);
12
11
  const sqlite = new Database(dbPath);
13
- const db = drizzle(sqlite, { schema });
12
+ const db = drizzle({ client: sqlite });
14
13
  registerDriver(db, "better-sqlite3", sqlite);
15
14
  return { dialect: "sqlite", db };
16
15
  }
@@ -105,20 +105,6 @@ export declare function deleteInfoValue(event: H3Event | undefined, key: string)
105
105
  * table (Postgres has no FTS5; tokenizer comparison is SQLite-only).
106
106
  */
107
107
  export declare function initSchema(event?: H3Event): Promise<void>;
108
- /**
109
- * Get pages needing IndexNow sync
110
- */
111
- export declare function getPagesNeedingIndexNowSync(event: H3Event | undefined, limit?: number): Promise<{
112
- route: string;
113
- }[]>;
114
- /**
115
- * Count pages needing IndexNow sync
116
- */
117
- export declare function countPagesNeedingIndexNowSync(event: H3Event | undefined): Promise<number>;
118
- /**
119
- * Mark pages as synced to IndexNow
120
- */
121
- export declare function markIndexNowSynced(event: H3Event | undefined, routes: string[]): Promise<void>;
122
108
  export interface CronRunOutput {
123
109
  id: number;
124
110
  startedAt: number;
@@ -126,8 +112,6 @@ export interface CronRunOutput {
126
112
  durationMs: number | null;
127
113
  pagesIndexed: number;
128
114
  pagesRemaining: number;
129
- indexNowSubmitted: number;
130
- indexNowRemaining: number;
131
115
  errors: string[];
132
116
  status: 'running' | 'success' | 'partial' | 'error';
133
117
  }
@@ -141,8 +125,6 @@ export declare function startCronRun(event: H3Event | undefined): Promise<number
141
125
  export declare function completeCronRun(event: H3Event | undefined, runId: number, result: {
142
126
  pagesIndexed: number;
143
127
  pagesRemaining: number;
144
- indexNowSubmitted: number;
145
- indexNowRemaining: number;
146
128
  errors: string[];
147
129
  }): Promise<void>;
148
130
  /**