nuxt-ai-ready 1.7.7 → 1.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.
@@ -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.DJimiOHi.mjs';
5
+ import { A as AGENT_SKILLS_SCHEMA } from '../shared/nuxt-ai-ready.DF6WiyQh.mjs';
6
6
  import 'node:module';
7
7
  import '@nuxt/kit';
8
8
  import 'defu';
@@ -5,7 +5,7 @@ import { colorize } from 'consola/utils';
5
5
  import { resolveLocaleFromRoute } from 'nuxtseo-shared/i18n-runtime';
6
6
  import { collectSitemap } from 'sitemapd/parse';
7
7
  import { withLeadingSlash, withBase, joinURL } from 'ufo';
8
- import { l as logger, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.DJimiOHi.mjs';
8
+ import { l as logger, M as MARKDOWN_LINK_AVAILABILITY_FILE } from '../shared/nuxt-ai-ready.DF6WiyQh.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';
@@ -122,18 +122,7 @@ async function initCrawler(state) {
122
122
  if (state.dbPath) {
123
123
  logger.debug(`Creating directory for SQLite: ${dirname(state.dbPath)}`);
124
124
  await mkdir(dirname(state.dbPath), { recursive: true });
125
- const { default: Database } = await import('better-sqlite3');
126
- const sqlite = new Database(state.dbPath);
127
- const db = {
128
- all: async (sql, params = []) => sqlite.prepare(sql).all(...params),
129
- first: async (sql, params = []) => sqlite.prepare(sql).get(...params),
130
- exec: async (sql, params = []) => {
131
- sqlite.prepare(sql).run(...params);
132
- },
133
- close: async () => {
134
- sqlite.close();
135
- }
136
- };
125
+ const db = await createPrerenderDatabase(state.dbPath);
137
126
  state.db = db;
138
127
  await initSchema(db, { ftsTokenizer: state.ftsTokenizer });
139
128
  logger.debug(`Crawler initialized with SQLite at ${state.dbPath} (tokenizer: ${state.ftsTokenizer || "default"})`);
@@ -148,6 +137,38 @@ async function initCrawler(state) {
148
137
  }
149
138
  state.initialized = true;
150
139
  }
140
+ async function createPrerenderDatabase(dbPath) {
141
+ const nodeVersion = Number.parseInt(process.versions.node?.split(".")[0] || "0");
142
+ if (nodeVersion >= 22) {
143
+ const { DatabaseSync } = await import('node:sqlite');
144
+ const sqlite2 = new DatabaseSync(dbPath);
145
+ return {
146
+ all: async (sql, params = []) => sqlite2.prepare(sql).all(...params),
147
+ first: async (sql, params = []) => sqlite2.prepare(sql).get(...params),
148
+ exec: async (sql, params = []) => {
149
+ if (params.length)
150
+ sqlite2.prepare(sql).run(...params);
151
+ else
152
+ sqlite2.exec(sql);
153
+ },
154
+ close: async () => {
155
+ sqlite2.close();
156
+ }
157
+ };
158
+ }
159
+ const { default: Database } = await import('better-sqlite3');
160
+ const sqlite = new Database(dbPath);
161
+ return {
162
+ all: async (sql, params = []) => sqlite.prepare(sql).all(...params),
163
+ first: async (sql, params = []) => sqlite.prepare(sql).get(...params),
164
+ exec: async (sql, params = []) => {
165
+ sqlite.prepare(sql).run(...params);
166
+ },
167
+ close: async () => {
168
+ sqlite.close();
169
+ }
170
+ };
171
+ }
151
172
  function flattenHeadings(headings) {
152
173
  return (headings || []).map((h) => Object.entries(h).map(([tag, text]) => `${tag}:${text}`).join("")).join("|");
153
174
  }
@@ -488,4 +509,4 @@ function setupPrerenderHandler(options, dbPath, siteInfo, llmsTxtConfig, indexNo
488
509
  });
489
510
  }
490
511
 
491
- export { detectSitemapPrerender, setupPrerenderHandler };
512
+ export { createPrerenderDatabase, detectSitemapPrerender, setupPrerenderHandler };
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=4.0.0"
5
5
  },
6
6
  "configKey": "aiReady",
7
- "version": "1.7.7",
7
+ "version": "1.7.9",
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.DJimiOHi.mjs';
10
+ export { m as default } from './shared/nuxt-ai-ready.DF6WiyQh.mjs';
11
11
  import '../dist/runtime/server/utils/discovery-response.js';
12
12
  import 'node:url';
13
13
  import 'pathe';
@@ -12,6 +12,71 @@ import { MCP_SERVER_CARD_MEDIA_TYPE, AI_CATALOG_MEDIA_TYPE } from '../../dist/ru
12
12
  import { isAbsolute, join as join$1 } from 'pathe';
13
13
  import { resolveI18nConfig, toRuntimeI18nConfig as toRuntimeI18nConfig$1 } from 'nuxtseo-shared/i18n';
14
14
 
15
+ const SELECT_PAGE_DATA = "SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages";
16
+ function createBuildPageDataVirtual(options) {
17
+ if (options.dev) {
18
+ return `
19
+ export async function readPageDataFromFilesystem() { return { pages: [], errorRoutes: [] } }
20
+ export async function readMarkdownLinkAvailabilityFromFilesystem() { return { runtimeMarkdownAvailable: false, paths: [] } }
21
+ `;
22
+ }
23
+ const readRows = options.nodeMajor >= 22 ? `const { DatabaseSync } = await import('node' + ':sqlite')
24
+ const db = new DatabaseSync(dbPath, { open: true })
25
+ const rows = db.prepare(${JSON.stringify(SELECT_PAGE_DATA)}).all()
26
+ db.close()` : `const Database = (await import('better-sqlite3')).default
27
+ const db = new Database(dbPath, { readonly: true })
28
+ const rows = db.prepare(${JSON.stringify(SELECT_PAGE_DATA)}).all()
29
+ db.close()`;
30
+ return `
31
+ export async function readMarkdownLinkAvailabilityFromFilesystem() {
32
+ if (!import.meta.prerender) {
33
+ return { runtimeMarkdownAvailable: false, paths: [] }
34
+ }
35
+
36
+ const { readFile } = await import('node:fs/promises')
37
+ try {
38
+ const availability = JSON.parse(await readFile(${JSON.stringify(options.markdownLinkAvailabilityPath)}, 'utf8'))
39
+ return {
40
+ runtimeMarkdownAvailable: availability?.runtimeMarkdownAvailable === true,
41
+ paths: Array.isArray(availability?.paths) ? availability.paths.filter(path => typeof path === 'string') : [],
42
+ }
43
+ }
44
+ catch (error) {
45
+ console.warn('[nuxt-ai-ready] Failed to read Markdown link availability; keeping canonical links.', error)
46
+ return { runtimeMarkdownAvailable: false, paths: [] }
47
+ }
48
+ }
49
+
50
+ export async function readPageDataFromFilesystem() {
51
+ if (!import.meta.prerender) {
52
+ return { pages: [], errorRoutes: [] }
53
+ }
54
+
55
+ const dbPath = ${JSON.stringify(options.buildDbPath)}
56
+ const { existsSync } = await import('node:fs')
57
+ if (!existsSync(dbPath)) {
58
+ return { pages: [], errorRoutes: [] }
59
+ }
60
+
61
+ ${readRows}
62
+
63
+ const pages = rows.filter(r => !r.is_error).map(r => ({
64
+ route: r.route,
65
+ title: r.title,
66
+ description: r.description,
67
+ markdown: r.markdown,
68
+ headings: r.headings,
69
+ keywords: JSON.parse(r.keywords || '[]'),
70
+ updatedAt: r.updated_at,
71
+ locale: r.locale || '',
72
+ }))
73
+ const errorRoutes = rows.filter(r => r.is_error).map(r => r.route)
74
+
75
+ return { pages, errorRoutes }
76
+ }
77
+ `;
78
+ }
79
+
15
80
  const logger = useLogger("nuxt-ai-ready");
16
81
 
17
82
  function resolveModuleEntryUrl(url) {
@@ -1306,72 +1371,12 @@ ${details}`);
1306
1371
  nitroConfig.virtual["#ai-ready-virtual/agent-skills.mjs"] = agentSkillsResult._tag === "Enabled" ? `export const agentSkillsIndex = ${JSON.stringify(agentSkillsResult.index)}
1307
1372
  export const localAgentSkillArtifacts = ${JSON.stringify(agentSkillsResult.localArtifacts)}` : "export const agentSkillsIndex = null\nexport const localAgentSkillArtifacts = {}";
1308
1373
  const markdownLinkAvailabilityPath = join(dirname(buildDbPath), MARKDOWN_LINK_AVAILABILITY_FILE);
1309
- nitroConfig.virtual["#ai-ready-virtual/read-page-data.mjs"] = nuxt.options.dev ? `
1310
- export async function readPageDataFromFilesystem() { return { pages: [], errorRoutes: [] } }
1311
- export async function readMarkdownLinkAvailabilityFromFilesystem() { return { runtimeMarkdownAvailable: false, paths: [] } }
1312
- ` : `
1313
- export async function readMarkdownLinkAvailabilityFromFilesystem() {
1314
- if (!import.meta.prerender) {
1315
- return { runtimeMarkdownAvailable: false, paths: [] }
1316
- }
1317
-
1318
- const { readFile } = await import('node:fs/promises')
1319
- try {
1320
- const availability = JSON.parse(await readFile(${JSON.stringify(markdownLinkAvailabilityPath)}, 'utf8'))
1321
- return {
1322
- runtimeMarkdownAvailable: availability?.runtimeMarkdownAvailable === true,
1323
- paths: Array.isArray(availability?.paths) ? availability.paths.filter(path => typeof path === 'string') : [],
1324
- }
1325
- }
1326
- catch (error) {
1327
- console.warn('[nuxt-ai-ready] Failed to read Markdown link availability; keeping canonical links.', error)
1328
- return { runtimeMarkdownAvailable: false, paths: [] }
1329
- }
1330
- }
1331
-
1332
- export async function readPageDataFromFilesystem() {
1333
- if (!import.meta.prerender) {
1334
- return { pages: [], errorRoutes: [] }
1335
- }
1336
-
1337
- const dbPath = ${JSON.stringify(buildDbPath)}
1338
-
1339
- // Check if database file exists
1340
- const { existsSync } = await import('node:fs')
1341
- if (!existsSync(dbPath)) {
1342
- return { pages: [], errorRoutes: [] }
1343
- }
1344
-
1345
- let rows = []
1346
- const nodeVersion = Number.parseInt(process.versions.node?.split('.')[0] || '0')
1347
- if (nodeVersion >= 22) {
1348
- const { DatabaseSync } = await import('node' + ':sqlite')
1349
- const db = new DatabaseSync(dbPath, { open: true })
1350
- rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages').all()
1351
- db.close()
1352
- }
1353
- else {
1354
- const Database = (await import('better-sqlite3')).default
1355
- const db = new Database(dbPath, { readonly: true })
1356
- rows = db.prepare('SELECT route, title, description, markdown, headings, keywords, updated_at, is_error, locale FROM ai_ready_pages').all()
1357
- db.close()
1358
- }
1359
-
1360
- const pages = rows.filter(r => !r.is_error).map(r => ({
1361
- route: r.route,
1362
- title: r.title,
1363
- description: r.description,
1364
- markdown: r.markdown,
1365
- headings: r.headings,
1366
- keywords: JSON.parse(r.keywords || '[]'),
1367
- updatedAt: r.updated_at,
1368
- locale: r.locale || '',
1369
- }))
1370
- const errorRoutes = rows.filter(r => r.is_error).map(r => r.route)
1371
-
1372
- return { pages, errorRoutes }
1373
- }
1374
- `;
1374
+ nitroConfig.virtual["#ai-ready-virtual/read-page-data.mjs"] = createBuildPageDataVirtual({
1375
+ buildDbPath,
1376
+ markdownLinkAvailabilityPath,
1377
+ nodeMajor: Number.parseInt(process.versions.node?.split(".")[0] || "0"),
1378
+ dev: nuxt.options.dev
1379
+ });
1375
1380
  nitroConfig.virtual["#ai-ready-virtual/page-data.mjs"] = `export const pages = []
1376
1381
  export const errorRoutes = []`;
1377
1382
  nitroConfig.virtual["#ai-ready-virtual/logger.mjs"] = `
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-ai-ready",
3
3
  "type": "module",
4
- "version": "1.7.7",
4
+ "version": "1.7.9",
5
5
  "description": "Best practice AI & LLM discoverability for Nuxt sites.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",