nuxt-ai-ready 0.7.14 → 0.7.15

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 CHANGED
@@ -4,7 +4,7 @@
4
4
  "nuxt": ">=4.0.0"
5
5
  },
6
6
  "configKey": "aiReady",
7
- "version": "0.7.14",
7
+ "version": "0.7.15",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -163,6 +163,21 @@ export interface IndexNowStats {
163
163
  * Get IndexNow stats
164
164
  */
165
165
  export declare function getIndexNowStats(event: H3Event | undefined): Promise<IndexNowStats>;
166
+ export interface IndexNowLogEntry {
167
+ id: number;
168
+ submittedAt: number;
169
+ urlCount: number;
170
+ success: boolean;
171
+ error: string | null;
172
+ }
173
+ /**
174
+ * Log an IndexNow submission attempt (for debug mode)
175
+ */
176
+ export declare function logIndexNowSubmission(event: H3Event | undefined, urlCount: number, success: boolean, error?: string): Promise<void>;
177
+ /**
178
+ * Get recent IndexNow submission log entries
179
+ */
180
+ export declare function getIndexNowLog(event: H3Event | undefined, limit?: number): Promise<IndexNowLogEntry[]>;
166
181
  export interface CronRunRow {
167
182
  id: number;
168
183
  started_at: number;
@@ -381,6 +381,33 @@ export async function getIndexNowStats(event) {
381
381
  lastError: stats.indexnow_last_error || null
382
382
  };
383
383
  }
384
+ export async function logIndexNowSubmission(event, urlCount, success, error) {
385
+ const db = await getDb(event);
386
+ if (!db)
387
+ return;
388
+ await db.exec(
389
+ "INSERT INTO ai_ready_indexnow_log (submitted_at, url_count, success, error) VALUES (?, ?, ?, ?)",
390
+ [Date.now(), urlCount, success ? 1 : 0, error || null]
391
+ );
392
+ await db.exec(`
393
+ DELETE FROM ai_ready_indexnow_log WHERE id NOT IN (
394
+ SELECT id FROM ai_ready_indexnow_log ORDER BY submitted_at DESC LIMIT 100
395
+ )
396
+ `);
397
+ }
398
+ export async function getIndexNowLog(event, limit = 20) {
399
+ const db = await getDb(event);
400
+ if (!db)
401
+ return [];
402
+ const rows = await db.all("SELECT * FROM ai_ready_indexnow_log ORDER BY submitted_at DESC LIMIT ?", [limit]);
403
+ return rows.map((row) => ({
404
+ id: row.id,
405
+ submittedAt: row.submitted_at,
406
+ urlCount: row.url_count,
407
+ success: row.success === 1,
408
+ error: row.error
409
+ }));
410
+ }
384
411
  function rowToCronRun(row) {
385
412
  return {
386
413
  id: row.id,
@@ -1,3 +1,3 @@
1
- export declare const SCHEMA_VERSION = "v1.7.0";
1
+ export declare const SCHEMA_VERSION = "v1.8.0";
2
2
  export declare const DROP_TABLES_SQL: string[];
3
3
  export declare const ALL_SCHEMA_SQL: string[];
@@ -1,4 +1,4 @@
1
- export const SCHEMA_VERSION = "v1.7.0";
1
+ export const SCHEMA_VERSION = "v1.8.0";
2
2
  const PAGES_TABLE_SQL = `
3
3
  CREATE TABLE IF NOT EXISTS ai_ready_pages (
4
4
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -68,10 +68,20 @@ CREATE TABLE IF NOT EXISTS ai_ready_cron_runs (
68
68
  status TEXT DEFAULT 'running'
69
69
  )`;
70
70
  const CRON_RUNS_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_ai_ready_cron_runs_started ON ai_ready_cron_runs(started_at DESC)";
71
+ const INDEXNOW_LOG_TABLE_SQL = `
72
+ CREATE TABLE IF NOT EXISTS ai_ready_indexnow_log (
73
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
74
+ submitted_at INTEGER NOT NULL,
75
+ url_count INTEGER NOT NULL,
76
+ success INTEGER NOT NULL DEFAULT 0,
77
+ error TEXT
78
+ )`;
79
+ const INDEXNOW_LOG_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_ai_ready_indexnow_log_submitted ON ai_ready_indexnow_log(submitted_at DESC)";
71
80
  export const DROP_TABLES_SQL = [
72
81
  "DROP TABLE IF EXISTS ai_ready_pages_fts",
73
82
  "DROP TABLE IF EXISTS ai_ready_pages",
74
83
  "DROP TABLE IF EXISTS ai_ready_cron_runs",
84
+ "DROP TABLE IF EXISTS ai_ready_indexnow_log",
75
85
  "DROP TABLE IF EXISTS _ai_ready_info",
76
86
  // Legacy unprefixed tables (migration from v1.0.0)
77
87
  "DROP TABLE IF EXISTS pages_fts",
@@ -84,5 +94,7 @@ export const ALL_SCHEMA_SQL = [
84
94
  ...FTS_TRIGGERS_SQL,
85
95
  INFO_TABLE_SQL,
86
96
  CRON_RUNS_TABLE_SQL,
87
- CRON_RUNS_INDEX_SQL
97
+ CRON_RUNS_INDEX_SQL,
98
+ INDEXNOW_LOG_TABLE_SQL,
99
+ INDEXNOW_LOG_INDEX_SQL
88
100
  ];
@@ -34,6 +34,13 @@ interface DebugInfo {
34
34
  lastSubmittedAt: string | null;
35
35
  lastError: string | null;
36
36
  };
37
+ indexNowLog?: Array<{
38
+ id: number;
39
+ submittedAt: string;
40
+ urlCount: number;
41
+ success: boolean;
42
+ error: string | null;
43
+ }>;
37
44
  cronRuns?: CronRunInfo[];
38
45
  pageData: {
39
46
  source: string;
@@ -1,6 +1,6 @@
1
1
  import { createError, eventHandler, setHeader } from "h3";
2
2
  import { useRuntimeConfig } from "nitropack/runtime";
3
- import { countPages, countPagesNeedingIndexNowSync, getIndexNowStats, getRecentCronRuns, getSitemapSeededAt, queryPages } from "../db/queries.js";
3
+ import { countPages, countPagesNeedingIndexNowSync, getIndexNowLog, getIndexNowStats, getRecentCronRuns, getSitemapSeededAt, queryPages } from "../db/queries.js";
4
4
  export default eventHandler(async (event) => {
5
5
  const runtimeConfig = useRuntimeConfig(event)["nuxt-ai-ready"];
6
6
  if (!runtimeConfig.debug) {
@@ -105,6 +105,7 @@ export default eventHandler(async (event) => {
105
105
  }
106
106
  let runtimeSyncInfo;
107
107
  let indexNowInfo;
108
+ let indexNowLogInfo;
108
109
  let cronRunsInfo;
109
110
  if (!isDev && !isPrerender && !dbError) {
110
111
  try {
@@ -133,9 +134,10 @@ export default eventHandler(async (event) => {
133
134
  errors: run.errors
134
135
  }));
135
136
  if (runtimeConfig.indexNowKey) {
136
- const [indexNowPending, indexNowStats] = await Promise.all([
137
+ const [indexNowPending, indexNowStats, indexNowLogEntries] = await Promise.all([
137
138
  countPagesNeedingIndexNowSync(event),
138
- getIndexNowStats(event)
139
+ getIndexNowStats(event),
140
+ getIndexNowLog(event, 20)
139
141
  ]);
140
142
  indexNowInfo = {
141
143
  pending: indexNowPending,
@@ -143,6 +145,13 @@ export default eventHandler(async (event) => {
143
145
  lastSubmittedAt: indexNowStats.lastSubmittedAt ? new Date(indexNowStats.lastSubmittedAt).toISOString() : null,
144
146
  lastError: indexNowStats.lastError
145
147
  };
148
+ indexNowLogInfo = indexNowLogEntries.map((entry) => ({
149
+ id: entry.id,
150
+ submittedAt: new Date(entry.submittedAt).toISOString(),
151
+ urlCount: entry.urlCount,
152
+ success: entry.success,
153
+ error: entry.error
154
+ }));
146
155
  }
147
156
  } catch (err) {
148
157
  issues.push(`Runtime stats error: ${err.message || String(err)}`);
@@ -175,6 +184,7 @@ export default eventHandler(async (event) => {
175
184
  },
176
185
  runtimeSync: runtimeSyncInfo,
177
186
  indexNow: indexNowInfo,
187
+ indexNowLog: indexNowLogInfo,
178
188
  cronRuns: cronRunsInfo,
179
189
  pageData: {
180
190
  source,
@@ -4,6 +4,7 @@ import { useDatabase } from "../db/index.js";
4
4
  import {
5
5
  countPagesNeedingIndexNowSync,
6
6
  getPagesNeedingIndexNowSync,
7
+ logIndexNowSubmission,
7
8
  markIndexNowSynced,
8
9
  updateIndexNowStats
9
10
  } from "../db/queries.js";
@@ -85,6 +86,9 @@ export async function syncToIndexNow(event, limit = 100) {
85
86
  }
86
87
  const routes = pages.map((p) => p.route);
87
88
  const result = await submitToIndexNow(routes, { key: config.indexNowKey }, siteConfig.url);
89
+ if (config.debug) {
90
+ await logIndexNowSubmission(event, routes.length, result.success, result.error);
91
+ }
88
92
  if (result.success) {
89
93
  await setBackoffInfo(event, null);
90
94
  await markIndexNowSynced(event, routes);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-ai-ready",
3
3
  "type": "module",
4
- "version": "0.7.14",
4
+ "version": "0.7.15",
5
5
  "description": "Best practice AI & LLM discoverability for Nuxt sites.",
6
6
  "author": {
7
7
  "name": "Harlan Wilton",