@sonordev/site-kit 2.0.0 → 2.0.2

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 (89) hide show
  1. package/dist/SitemapSync-DXIV5TXI.mjs +4 -0
  2. package/dist/{SitemapSync-YK6IXOSY.mjs.map → SitemapSync-DXIV5TXI.mjs.map} +1 -1
  3. package/dist/SitemapSync-Z4NDW2S7.js +13 -0
  4. package/dist/{SitemapSync-FKYWGDAD.js.map → SitemapSync-Z4NDW2S7.js.map} +1 -1
  5. package/dist/blog/index.d.mts +6 -4
  6. package/dist/blog/index.d.ts +6 -4
  7. package/dist/blog/index.js +305 -20
  8. package/dist/blog/index.js.map +1 -1
  9. package/dist/blog/index.mjs +305 -21
  10. package/dist/blog/index.mjs.map +1 -1
  11. package/dist/blog/server.d.mts +41 -2
  12. package/dist/blog/server.d.ts +41 -2
  13. package/dist/blog/server.js +126 -685
  14. package/dist/blog/server.js.map +1 -1
  15. package/dist/blog/server.mjs +1 -663
  16. package/dist/blog/server.mjs.map +1 -1
  17. package/dist/{chunk-UD5447TC.js → chunk-6LZEGXDE.js} +3 -3
  18. package/dist/{chunk-UD5447TC.js.map → chunk-6LZEGXDE.js.map} +1 -1
  19. package/dist/{chunk-BVUOATPG.js → chunk-A7RCX6OI.js} +7 -7
  20. package/dist/{chunk-BVUOATPG.js.map → chunk-A7RCX6OI.js.map} +1 -1
  21. package/dist/{chunk-QW4RQHSK.js → chunk-ACBDH4RK.js} +15 -3
  22. package/dist/chunk-ACBDH4RK.js.map +1 -0
  23. package/dist/{chunk-TSK35UHV.mjs → chunk-HA5OXTXW.mjs} +15 -3
  24. package/dist/chunk-HA5OXTXW.mjs.map +1 -0
  25. package/dist/{chunk-RLNG67S5.js → chunk-ITPVKQB6.js} +74 -4
  26. package/dist/chunk-ITPVKQB6.js.map +1 -0
  27. package/dist/{chunk-DWI5ZKPM.mjs → chunk-IYQUFQYM.mjs} +4 -4
  28. package/dist/{chunk-DWI5ZKPM.mjs.map → chunk-IYQUFQYM.mjs.map} +1 -1
  29. package/dist/chunk-JUWYIDIA.js +823 -0
  30. package/dist/chunk-JUWYIDIA.js.map +1 -0
  31. package/dist/{chunk-OM6R7CDP.mjs → chunk-L7XPPFSS.mjs} +3 -3
  32. package/dist/{chunk-OM6R7CDP.mjs.map → chunk-L7XPPFSS.mjs.map} +1 -1
  33. package/dist/{chunk-I34XL5VJ.js → chunk-PKUTYMN7.js} +5 -5
  34. package/dist/{chunk-I34XL5VJ.js.map → chunk-PKUTYMN7.js.map} +1 -1
  35. package/dist/{chunk-WN2PUL6B.mjs → chunk-RVAFAOBA.mjs} +3 -3
  36. package/dist/{chunk-WN2PUL6B.mjs.map → chunk-RVAFAOBA.mjs.map} +1 -1
  37. package/dist/chunk-S2WK4LL7.mjs +791 -0
  38. package/dist/chunk-S2WK4LL7.mjs.map +1 -0
  39. package/dist/{chunk-J4U3IEXL.mjs → chunk-TUFP3FGI.mjs} +4 -4
  40. package/dist/chunk-TUFP3FGI.mjs.map +1 -0
  41. package/dist/{chunk-FCXQECM7.js → chunk-VU4GL5ZG.js} +4 -4
  42. package/dist/chunk-VU4GL5ZG.js.map +1 -0
  43. package/dist/{chunk-W7RZ3OTA.mjs → chunk-Z6EHHJWU.mjs} +74 -4
  44. package/dist/chunk-Z6EHHJWU.mjs.map +1 -0
  45. package/dist/index.d.mts +1 -1
  46. package/dist/index.d.ts +1 -1
  47. package/dist/layout/client.js +2 -2
  48. package/dist/layout/client.mjs +1 -1
  49. package/dist/layout/index.js +6 -6
  50. package/dist/layout/index.mjs +3 -3
  51. package/dist/llms/index.d.mts +2 -2
  52. package/dist/llms/index.d.ts +2 -2
  53. package/dist/llms/index.js +12 -12
  54. package/dist/llms/index.mjs +2 -2
  55. package/dist/seo/client.js +2 -2
  56. package/dist/seo/client.mjs +1 -1
  57. package/dist/seo/index.js +42 -42
  58. package/dist/seo/index.mjs +5 -5
  59. package/dist/seo/register-sitemap-cli.js +14 -1
  60. package/dist/seo/register-sitemap-cli.js.map +1 -1
  61. package/dist/seo/register-sitemap-cli.mjs +14 -1
  62. package/dist/seo/register-sitemap-cli.mjs.map +1 -1
  63. package/dist/seo/server.js +6 -6
  64. package/dist/seo/server.js.map +1 -1
  65. package/dist/seo/server.mjs +4 -4
  66. package/dist/seo/server.mjs.map +1 -1
  67. package/dist/{server-api-UIZU4JM3.mjs → server-api-O7SSHYQS.mjs} +3 -3
  68. package/dist/{server-api-UIZU4JM3.mjs.map → server-api-O7SSHYQS.mjs.map} +1 -1
  69. package/dist/{server-api-36R24YWN.js → server-api-W4BXUFCT.js} +21 -21
  70. package/dist/{server-api-36R24YWN.js.map → server-api-W4BXUFCT.js.map} +1 -1
  71. package/dist/sitemap/index.d.mts +34 -2
  72. package/dist/sitemap/index.d.ts +34 -2
  73. package/dist/sitemap/index.js +53 -6
  74. package/dist/sitemap/index.js.map +1 -1
  75. package/dist/sitemap/index.mjs +52 -6
  76. package/dist/sitemap/index.mjs.map +1 -1
  77. package/dist/{types-Blb2QNkV.d.ts → types-BxzT7yhf.d.mts} +22 -1
  78. package/dist/{types-Blb2QNkV.d.mts → types-BxzT7yhf.d.ts} +22 -1
  79. package/dist/{types-D08004rU.d.mts → types-DuvkNnu0.d.mts} +25 -1
  80. package/dist/{types-D08004rU.d.ts → types-DuvkNnu0.d.ts} +25 -1
  81. package/package.json +1 -1
  82. package/dist/SitemapSync-FKYWGDAD.js +0 -13
  83. package/dist/SitemapSync-YK6IXOSY.mjs +0 -4
  84. package/dist/chunk-FCXQECM7.js.map +0 -1
  85. package/dist/chunk-J4U3IEXL.mjs.map +0 -1
  86. package/dist/chunk-QW4RQHSK.js.map +0 -1
  87. package/dist/chunk-RLNG67S5.js.map +0 -1
  88. package/dist/chunk-TSK35UHV.mjs.map +0 -1
  89. package/dist/chunk-W7RZ3OTA.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/seo/register-sitemap-cli-impl.ts","../../src/seo/register-sitemap-cli.ts"],"names":["cwd","dotenvConfig","path"],"mappings":"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","file":"register-sitemap-cli.mjs","sourcesContent":["/**\n * Standalone implementation for uptrade-register-sitemap CLI.\n * Does NOT import from server-api or routing, so it can run in Node without\n * pulling in server-only (which throws when required outside Next.js server context).\n */\n\nimport fs from 'fs'\nimport path from 'path'\n\nfunction getApiConfig(): { apiUrl: string; apiKey: string } {\n const apiUrl =\n process.env.SONOR_API_URL ||\n 'https://api.sonor.io'\n const apiKey =\n process.env.SONOR_API_KEY ||\n ''\n return { apiUrl, apiKey }\n}\n\nfunction discoverNextJsRoutes(\n appDir: string,\n basePath: string = ''\n): Array<{ path: string; priority: number }> {\n const entries: Array<{ path: string; priority: number }> = []\n\n const items = fs.readdirSync(appDir, { withFileTypes: true })\n\n for (const item of items) {\n if (item.name.startsWith('_') || item.name.startsWith('.')) continue\n if (item.name === 'api') continue\n if (item.name === 'node_modules') continue\n\n const itemPath = path.join(appDir, item.name)\n\n if (item.isDirectory()) {\n const hasPage =\n fs.existsSync(path.join(itemPath, 'page.tsx')) ||\n fs.existsSync(path.join(itemPath, 'page.js')) ||\n fs.existsSync(path.join(itemPath, 'page.jsx'))\n\n const isRouteGroup = item.name.startsWith('(') && item.name.endsWith(')')\n const isDynamic = item.name.startsWith('[') && item.name.endsWith(']')\n\n let routePath = basePath\n if (!isRouteGroup && !isDynamic) {\n routePath = `${basePath}/${item.name}`\n }\n\n if (hasPage && !isDynamic) {\n const priority = routePath === '' ? 1.0 : 0.8\n entries.push({ path: routePath || '/', priority })\n }\n\n if (!isDynamic) {\n const subEntries = discoverNextJsRoutes(\n itemPath,\n isRouteGroup ? basePath : routePath\n )\n entries.push(...subEntries)\n }\n }\n }\n\n if (basePath === '') {\n const hasRootPage =\n fs.existsSync(path.join(appDir, 'page.tsx')) ||\n fs.existsSync(path.join(appDir, 'page.js')) ||\n fs.existsSync(path.join(appDir, 'page.jsx'))\n if (hasRootPage) {\n entries.unshift({ path: '/', priority: 1.0 })\n }\n }\n\n return entries\n}\n\nasync function registerSitemapViaApi(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: string\n }>,\n optimizeMeta: boolean\n): Promise<{\n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: { triggered: boolean; pages_queued: number } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n if (!apiKey) {\n console.warn(\n '[Sonor] No API key (SONOR_API_KEY)',\n )\n return { success: false, created: 0, updated: 0 }\n }\n\n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ entries, optimize_meta: optimizeMeta, mode: 'full-replace' }),\n })\n\n if (!response.ok) {\n console.error(`[Sonor] Sitemap registration failed: ${response.status} ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n\n return await response.json()\n } catch (error) {\n console.error('[Sonor] Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport type RegisterLocalSitemapOptions = {\n entries?: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>\n autoDiscover?: boolean\n optimize_meta?: boolean\n}\n\nexport type RegisterLocalSitemapResult = {\n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}\n\nexport async function registerLocalSitemap(\n options: RegisterLocalSitemapOptions\n): Promise<RegisterLocalSitemapResult> {\n let entries = options.entries || []\n\n if (options.autoDiscover && entries.length === 0) {\n const cwd = process.cwd()\n const appDirs = [\n path.join(cwd, 'app'),\n path.join(cwd, 'src', 'app'),\n ]\n for (const appDir of appDirs) {\n if (fs.existsSync(appDir)) {\n entries = discoverNextJsRoutes(appDir)\n console.log(`[Sonor] Auto-discovered ${entries.length} routes from ${path.relative(cwd, appDir)}`)\n break\n }\n }\n }\n\n if (entries.length === 0) {\n console.warn('[Sonor] No sitemap entries to register')\n return { success: true, created: 0, updated: 0 }\n }\n\n console.log(`[Sonor] Registering ${entries.length} sitemap entries...`)\n const payload = entries.map((e) => ({\n path: e.path,\n title: e.title,\n priority: e.priority,\n changefreq: e.changefreq,\n }))\n const result = await registerSitemapViaApi(\n payload,\n options.optimize_meta !== false\n )\n\n if (result.success) {\n console.log(`[Sonor] Sitemap registered: ${result.created} new, ${result.updated} updated`)\n }\n\n return result\n}\n","#!/usr/bin/env node\n/**\n * CLI script to register sitemap entries at build time\n * \n * Usage:\n * npx sonor-register-sitemap\n * npx sonor-register-sitemap --auto-discover\n * npx sonor-register-sitemap --no-optimize # Skip Signal AI meta optimization\n *\n * Or in package.json:\n * {\n * \"scripts\": {\n * \"postbuild\": \"sonor-register-sitemap --auto-discover\"\n * }\n * }\n */\n\nimport path from 'path'\nimport { config as dotenvConfig } from 'dotenv'\nimport { registerLocalSitemap } from './register-sitemap-cli-impl'\n\n// npm postbuild runs outside Next.js — env from .env* is not loaded automatically\nconst cwd = process.cwd()\ndotenvConfig({ path: path.join(cwd, '.env') })\ndotenvConfig({ path: path.join(cwd, '.env.local'), override: true })\nif (process.env.NODE_ENV === 'production') {\n dotenvConfig({ path: path.join(cwd, '.env.production') })\n dotenvConfig({ path: path.join(cwd, '.env.production.local'), override: true })\n}\n\nasync function main() {\n const args = process.argv.slice(2)\n const autoDiscover = args.includes('--auto-discover') || args.includes('-a')\n const skipOptimize = args.includes('--no-optimize') || args.includes('--skip-optimize')\n \n console.log('[Sonor] Registering sitemap entries...')\n \n try {\n const result = await registerLocalSitemap({\n autoDiscover,\n optimize_meta: !skipOptimize,\n })\n \n if (result.success) {\n console.log(`[Sonor] ✓ Sitemap registered successfully`)\n console.log(`[Sonor] Created: ${result.created}`)\n console.log(`[Sonor] Updated: ${result.updated}`)\n if (result.removed !== undefined && result.removed > 0) {\n console.log(`[Sonor] Removed: ${result.removed}`)\n }\n if (result.meta_optimization?.triggered) {\n console.log(`[Sonor] ✓ Signal AI meta optimization triggered for ${result.meta_optimization.pages_queued} pages`)\n console.log(`[Sonor] (Running in background - check Portal SEO module for results)`)\n }\n process.exit(0)\n } else {\n console.error('[Sonor] ✗ Failed to register sitemap')\n process.exit(1)\n }\n } catch (error) {\n console.error('[Sonor] ✗ Error:', error)\n process.exit(1)\n }\n}\n\nmain()\n"]}
1
+ {"version":3,"sources":["../../src/seo/register-sitemap-cli-impl.ts","../../src/seo/register-sitemap-cli.ts"],"names":["cwd","dotenvConfig","path"],"mappings":"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","file":"register-sitemap-cli.mjs","sourcesContent":["/**\n * Standalone implementation for uptrade-register-sitemap CLI.\n * Does NOT import from server-api or routing, so it can run in Node without\n * pulling in server-only (which throws when required outside Next.js server context).\n */\n\nimport fs from 'fs'\nimport path from 'path'\n\n/**\n * Infer page type from URL path pattern for Signal context.\n */\nfunction inferPageTypeFromPath(urlPath: string): string {\n if (urlPath === '/' || urlPath === '') return 'homepage'\n if (/^\\/services(\\/|$)/i.test(urlPath)) return 'service'\n if (/^\\/compare(\\/|$)/i.test(urlPath)) return 'comparison'\n if (/^\\/(insights|blog)(\\/|$)/i.test(urlPath)) return 'blog'\n if (/^\\/industries(\\/|$)/i.test(urlPath)) return 'industry'\n if (/^\\/work(\\/|$)/i.test(urlPath)) return 'portfolio'\n if (/^\\/faq(\\/|$)/i.test(urlPath)) return 'faq'\n if (/^\\/pricing(\\/|$)/i.test(urlPath)) return 'pricing'\n return 'page'\n}\n\nfunction getApiConfig(): { apiUrl: string; apiKey: string } {\n const apiUrl =\n process.env.SONOR_API_URL ||\n 'https://api.sonor.io'\n const apiKey =\n process.env.SONOR_API_KEY ||\n ''\n return { apiUrl, apiKey }\n}\n\nfunction discoverNextJsRoutes(\n appDir: string,\n basePath: string = ''\n): Array<{ path: string; priority: number }> {\n const entries: Array<{ path: string; priority: number }> = []\n\n const items = fs.readdirSync(appDir, { withFileTypes: true })\n\n for (const item of items) {\n if (item.name.startsWith('_') || item.name.startsWith('.')) continue\n if (item.name === 'api') continue\n if (item.name === 'node_modules') continue\n\n const itemPath = path.join(appDir, item.name)\n\n if (item.isDirectory()) {\n const hasPage =\n fs.existsSync(path.join(itemPath, 'page.tsx')) ||\n fs.existsSync(path.join(itemPath, 'page.js')) ||\n fs.existsSync(path.join(itemPath, 'page.jsx'))\n\n const isRouteGroup = item.name.startsWith('(') && item.name.endsWith(')')\n const isDynamic = item.name.startsWith('[') && item.name.endsWith(']')\n\n let routePath = basePath\n if (!isRouteGroup && !isDynamic) {\n routePath = `${basePath}/${item.name}`\n }\n\n if (hasPage && !isDynamic) {\n const priority = routePath === '' ? 1.0 : 0.8\n entries.push({ path: routePath || '/', priority })\n }\n\n if (!isDynamic) {\n const subEntries = discoverNextJsRoutes(\n itemPath,\n isRouteGroup ? basePath : routePath\n )\n entries.push(...subEntries)\n }\n }\n }\n\n if (basePath === '') {\n const hasRootPage =\n fs.existsSync(path.join(appDir, 'page.tsx')) ||\n fs.existsSync(path.join(appDir, 'page.js')) ||\n fs.existsSync(path.join(appDir, 'page.jsx'))\n if (hasRootPage) {\n entries.unshift({ path: '/', priority: 1.0 })\n }\n }\n\n return entries\n}\n\nasync function registerSitemapViaApi(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: string\n description?: string\n pageType?: string\n }>,\n optimizeMeta: boolean\n): Promise<{\n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: { triggered: boolean; pages_queued: number } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n if (!apiKey) {\n console.warn(\n '[Sonor] No API key (SONOR_API_KEY)',\n )\n return { success: false, created: 0, updated: 0 }\n }\n\n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ entries, optimize_meta: optimizeMeta, mode: 'full-replace' }),\n })\n\n if (!response.ok) {\n console.error(`[Sonor] Sitemap registration failed: ${response.status} ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n\n return await response.json()\n } catch (error) {\n console.error('[Sonor] Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport type RegisterLocalSitemapOptions = {\n entries?: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n description?: string\n pageType?: string\n }>\n autoDiscover?: boolean\n optimize_meta?: boolean\n}\n\nexport type RegisterLocalSitemapResult = {\n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}\n\nexport async function registerLocalSitemap(\n options: RegisterLocalSitemapOptions\n): Promise<RegisterLocalSitemapResult> {\n let entries = options.entries || []\n\n if (options.autoDiscover && entries.length === 0) {\n const cwd = process.cwd()\n const appDirs = [\n path.join(cwd, 'app'),\n path.join(cwd, 'src', 'app'),\n ]\n for (const appDir of appDirs) {\n if (fs.existsSync(appDir)) {\n entries = discoverNextJsRoutes(appDir)\n console.log(`[Sonor] Auto-discovered ${entries.length} routes from ${path.relative(cwd, appDir)}`)\n break\n }\n }\n }\n\n if (entries.length === 0) {\n console.warn('[Sonor] No sitemap entries to register')\n return { success: true, created: 0, updated: 0 }\n }\n\n console.log(`[Sonor] Registering ${entries.length} sitemap entries...`)\n const payload = entries.map((e) => ({\n path: e.path,\n title: e.title,\n priority: e.priority,\n changefreq: e.changefreq,\n ...(e.description ? { description: e.description } : {}),\n pageType: e.pageType ?? inferPageTypeFromPath(e.path),\n }))\n const result = await registerSitemapViaApi(\n payload,\n options.optimize_meta !== false\n )\n\n if (result.success) {\n console.log(`[Sonor] Sitemap registered: ${result.created} new, ${result.updated} updated`)\n }\n\n return result\n}\n","#!/usr/bin/env node\n/**\n * CLI script to register sitemap entries at build time\n * \n * Usage:\n * npx sonor-register-sitemap\n * npx sonor-register-sitemap --auto-discover\n * npx sonor-register-sitemap --no-optimize # Skip Signal AI meta optimization\n *\n * Or in package.json:\n * {\n * \"scripts\": {\n * \"postbuild\": \"sonor-register-sitemap --auto-discover\"\n * }\n * }\n */\n\nimport path from 'path'\nimport { config as dotenvConfig } from 'dotenv'\nimport { registerLocalSitemap } from './register-sitemap-cli-impl'\n\n// npm postbuild runs outside Next.js — env from .env* is not loaded automatically\nconst cwd = process.cwd()\ndotenvConfig({ path: path.join(cwd, '.env') })\ndotenvConfig({ path: path.join(cwd, '.env.local'), override: true })\nif (process.env.NODE_ENV === 'production') {\n dotenvConfig({ path: path.join(cwd, '.env.production') })\n dotenvConfig({ path: path.join(cwd, '.env.production.local'), override: true })\n}\n\nasync function main() {\n const args = process.argv.slice(2)\n const autoDiscover = args.includes('--auto-discover') || args.includes('-a')\n const skipOptimize = args.includes('--no-optimize') || args.includes('--skip-optimize')\n \n console.log('[Sonor] Registering sitemap entries...')\n \n try {\n const result = await registerLocalSitemap({\n autoDiscover,\n optimize_meta: !skipOptimize,\n })\n \n if (result.success) {\n console.log(`[Sonor] ✓ Sitemap registered successfully`)\n console.log(`[Sonor] Created: ${result.created}`)\n console.log(`[Sonor] Updated: ${result.updated}`)\n if (result.removed !== undefined && result.removed > 0) {\n console.log(`[Sonor] Removed: ${result.removed}`)\n }\n if (result.meta_optimization?.triggered) {\n console.log(`[Sonor] ✓ Signal AI meta optimization triggered for ${result.meta_optimization.pages_queued} pages`)\n console.log(`[Sonor] (Running in background - check Portal SEO module for results)`)\n }\n process.exit(0)\n } else {\n console.error('[Sonor] ✗ Failed to register sitemap')\n process.exit(1)\n }\n } catch (error) {\n console.error('[Sonor] ✗ Error:', error)\n process.exit(1)\n }\n}\n\nmain()\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkBVUOATPG_js = require('../chunk-BVUOATPG.js');
4
- require('../chunk-FCXQECM7.js');
3
+ var chunkA7RCX6OI_js = require('../chunk-A7RCX6OI.js');
4
+ require('../chunk-VU4GL5ZG.js');
5
5
  require('../chunk-ZSMWDLMK.js');
6
6
  var react = require('react');
7
7
 
@@ -12,7 +12,7 @@ if (process.env.NODE_ENV === "development") {
12
12
  }
13
13
  function getApiConfig() {
14
14
  const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
15
- const apiKey = process.env.SONOR_API_KEY || "";
15
+ const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
16
16
  return { apiUrl, apiKey };
17
17
  }
18
18
  async function apiPost(endpoint, body = {}) {
@@ -129,7 +129,7 @@ async function registerSitemap(entries, options) {
129
129
  }
130
130
  function getSignalApiConfig() {
131
131
  const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.sonor.io";
132
- const apiKey = process.env.SONOR_API_KEY || "";
132
+ const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
133
133
  return { apiUrl, apiKey };
134
134
  }
135
135
  async function signalApiGet(endpoint) {
@@ -185,11 +185,11 @@ react.cache(async (projectId) => {
185
185
 
186
186
  Object.defineProperty(exports, "generateSitemap", {
187
187
  enumerable: true,
188
- get: function () { return chunkBVUOATPG_js.generateSitemap; }
188
+ get: function () { return chunkA7RCX6OI_js.generateSitemap; }
189
189
  });
190
190
  Object.defineProperty(exports, "registerLocalSitemap", {
191
191
  enumerable: true,
192
- get: function () { return chunkBVUOATPG_js.registerLocalSitemap; }
192
+ get: function () { return chunkA7RCX6OI_js.registerLocalSitemap; }
193
193
  });
194
194
  exports.getABTest = getABTest;
195
195
  exports.getContentBlock = getContentBlock;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/seo/api.ts"],"names":["cache"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @sonordev/site-kit/seo - API Functions\n * \n * ⚠️ DEPRECATED: This file exposes API keys in client bundles.\n * Use `server-api.ts` instead for server-side operations.\n * \n * This file is kept for backward compatibility but will be removed in a future version.\n * \n * Migration guide:\n * - Replace: import { getSEOPageData } from '@sonordev/seo/api'\n * - With: import { getSEOPageData } from '@sonordev/seo/server'\n * - Use private env var: SONOR_API_KEY\n */\n\nimport { cache } from 'react'\n\n// Show deprecation warning in development\nif (process.env.NODE_ENV === 'development') {\n console.warn(\n '@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. ' +\n 'Please migrate to server-api.ts for better security. ' +\n 'See: packages/site-kit/src/seo/README.md#migration'\n )\n}\n\n// ============================================\n// API Config (DEPRECATED)\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function apiPost<T>(endpoint: string, body: Record<string, any> = {}): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify(body),\n next: { revalidate: 60 }, // Cache for 60 seconds\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n */\nexport const getSEOPageData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page || null\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n */\nexport const getSchemaMarkups = cache(async (\n projectId: string,\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await apiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n */\nexport const getFAQData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n */\nexport const getInternalLinks = cache(async (\n projectId: string,\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await apiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n */\nexport const getContentBlock = cache(async (\n projectId: string,\n path: string,\n section: string\n) => {\n const result = await apiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n */\nexport const getABTest = cache(async (\n projectId: string,\n path: string,\n field: string\n) => {\n const result = await apiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await apiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n */\nexport const getRedirectData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n */\nexport const getManagedScripts = cache(async (\n projectId: string,\n position: string,\n currentPath?: string\n) => {\n const result = await apiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n */\nexport const getRobotsData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n */\nexport const getSitemapEntries = cache(async (\n projectId: string,\n options?: { publishedOnly?: boolean }\n) => {\n const result = await apiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * \n * After registration, Signal AI will automatically generate optimized\n * meta titles and descriptions for pages that don't have them yet.\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ], { optimize_meta: true })\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /** Trigger Signal AI to generate optimized meta titles/descriptions (default: true) */\n optimize_meta?: boolean\n }\n): Promise<{ \n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return { success: false, created: 0, updated: 0 }\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ \n entries,\n optimize_meta: options?.optimize_meta !== false, // Default to true\n }),\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// AI Visibility & Entity Graph API\n// ============================================\n\n/**\n * Get Signal API config for AI visibility features\n */\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n */\nexport const getEntities = cache(async (\n projectId: string,\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n */\nexport const getPrimaryEntity = cache(async (\n projectId: string\n): Promise<SEOEntity | null> => {\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n */\nexport const getEntityEnhancedSchema = cache(async (\n projectId: string,\n pagePath: string\n): Promise<object[]> => {\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n */\nexport const getVisibilityScore = cache(async (\n projectId: string,\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n */\nexport const getVisibilitySummary = cache(async (\n projectId: string\n): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
1
+ {"version":3,"sources":["../../src/seo/api.ts"],"names":["cache"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @sonordev/site-kit/seo - API Functions\n * \n * ⚠️ DEPRECATED: This file exposes API keys in client bundles.\n * Use `server-api.ts` instead for server-side operations.\n * \n * This file is kept for backward compatibility but will be removed in a future version.\n * \n * Migration guide:\n * - Replace: import { getSEOPageData } from '@sonordev/seo/api'\n * - With: import { getSEOPageData } from '@sonordev/seo/server'\n * - Use private env var: SONOR_API_KEY\n */\n\nimport { cache } from 'react'\n\n// Show deprecation warning in development\nif (process.env.NODE_ENV === 'development') {\n console.warn(\n '@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. ' +\n 'Please migrate to server-api.ts for better security. ' +\n 'See: packages/site-kit/src/seo/README.md#migration'\n )\n}\n\n// ============================================\n// API Config (DEPRECATED)\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function apiPost<T>(endpoint: string, body: Record<string, any> = {}): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify(body),\n next: { revalidate: 60 }, // Cache for 60 seconds\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n */\nexport const getSEOPageData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page || null\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n */\nexport const getSchemaMarkups = cache(async (\n projectId: string,\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await apiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n */\nexport const getFAQData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n */\nexport const getInternalLinks = cache(async (\n projectId: string,\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await apiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n */\nexport const getContentBlock = cache(async (\n projectId: string,\n path: string,\n section: string\n) => {\n const result = await apiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n */\nexport const getABTest = cache(async (\n projectId: string,\n path: string,\n field: string\n) => {\n const result = await apiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await apiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n */\nexport const getRedirectData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n */\nexport const getManagedScripts = cache(async (\n projectId: string,\n position: string,\n currentPath?: string\n) => {\n const result = await apiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n */\nexport const getRobotsData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n */\nexport const getSitemapEntries = cache(async (\n projectId: string,\n options?: { publishedOnly?: boolean }\n) => {\n const result = await apiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * \n * After registration, Signal AI will automatically generate optimized\n * meta titles and descriptions for pages that don't have them yet.\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ], { optimize_meta: true })\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /** Trigger Signal AI to generate optimized meta titles/descriptions (default: true) */\n optimize_meta?: boolean\n }\n): Promise<{ \n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return { success: false, created: 0, updated: 0 }\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ \n entries,\n optimize_meta: options?.optimize_meta !== false, // Default to true\n }),\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// AI Visibility & Entity Graph API\n// ============================================\n\n/**\n * Get Signal API config for AI visibility features\n */\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n */\nexport const getEntities = cache(async (\n projectId: string,\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n */\nexport const getPrimaryEntity = cache(async (\n projectId: string\n): Promise<SEOEntity | null> => {\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n */\nexport const getEntityEnhancedSchema = cache(async (\n projectId: string,\n pagePath: string\n): Promise<object[]> => {\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n */\nexport const getVisibilityScore = cache(async (\n projectId: string,\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n */\nexport const getVisibilitySummary = cache(async (\n projectId: string\n): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
@@ -1,5 +1,5 @@
1
- export { generateSitemap, registerLocalSitemap } from '../chunk-DWI5ZKPM.mjs';
2
- import '../chunk-J4U3IEXL.mjs';
1
+ export { generateSitemap, registerLocalSitemap } from '../chunk-IYQUFQYM.mjs';
2
+ import '../chunk-TUFP3FGI.mjs';
3
3
  import '../chunk-4XPGGLVP.mjs';
4
4
  import { cache } from 'react';
5
5
 
@@ -10,7 +10,7 @@ if (process.env.NODE_ENV === "development") {
10
10
  }
11
11
  function getApiConfig() {
12
12
  const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
13
- const apiKey = process.env.SONOR_API_KEY || "";
13
+ const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
14
14
  return { apiUrl, apiKey };
15
15
  }
16
16
  async function apiPost(endpoint, body = {}) {
@@ -127,7 +127,7 @@ async function registerSitemap(entries, options) {
127
127
  }
128
128
  function getSignalApiConfig() {
129
129
  const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.sonor.io";
130
- const apiKey = process.env.SONOR_API_KEY || "";
130
+ const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
131
131
  return { apiUrl, apiKey };
132
132
  }
133
133
  async function signalApiGet(endpoint) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/seo/api.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @sonordev/site-kit/seo - API Functions\n * \n * ⚠️ DEPRECATED: This file exposes API keys in client bundles.\n * Use `server-api.ts` instead for server-side operations.\n * \n * This file is kept for backward compatibility but will be removed in a future version.\n * \n * Migration guide:\n * - Replace: import { getSEOPageData } from '@sonordev/seo/api'\n * - With: import { getSEOPageData } from '@sonordev/seo/server'\n * - Use private env var: SONOR_API_KEY\n */\n\nimport { cache } from 'react'\n\n// Show deprecation warning in development\nif (process.env.NODE_ENV === 'development') {\n console.warn(\n '@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. ' +\n 'Please migrate to server-api.ts for better security. ' +\n 'See: packages/site-kit/src/seo/README.md#migration'\n )\n}\n\n// ============================================\n// API Config (DEPRECATED)\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function apiPost<T>(endpoint: string, body: Record<string, any> = {}): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify(body),\n next: { revalidate: 60 }, // Cache for 60 seconds\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n */\nexport const getSEOPageData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page || null\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n */\nexport const getSchemaMarkups = cache(async (\n projectId: string,\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await apiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n */\nexport const getFAQData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n */\nexport const getInternalLinks = cache(async (\n projectId: string,\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await apiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n */\nexport const getContentBlock = cache(async (\n projectId: string,\n path: string,\n section: string\n) => {\n const result = await apiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n */\nexport const getABTest = cache(async (\n projectId: string,\n path: string,\n field: string\n) => {\n const result = await apiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await apiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n */\nexport const getRedirectData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n */\nexport const getManagedScripts = cache(async (\n projectId: string,\n position: string,\n currentPath?: string\n) => {\n const result = await apiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n */\nexport const getRobotsData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n */\nexport const getSitemapEntries = cache(async (\n projectId: string,\n options?: { publishedOnly?: boolean }\n) => {\n const result = await apiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * \n * After registration, Signal AI will automatically generate optimized\n * meta titles and descriptions for pages that don't have them yet.\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ], { optimize_meta: true })\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /** Trigger Signal AI to generate optimized meta titles/descriptions (default: true) */\n optimize_meta?: boolean\n }\n): Promise<{ \n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return { success: false, created: 0, updated: 0 }\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ \n entries,\n optimize_meta: options?.optimize_meta !== false, // Default to true\n }),\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// AI Visibility & Entity Graph API\n// ============================================\n\n/**\n * Get Signal API config for AI visibility features\n */\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n */\nexport const getEntities = cache(async (\n projectId: string,\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n */\nexport const getPrimaryEntity = cache(async (\n projectId: string\n): Promise<SEOEntity | null> => {\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n */\nexport const getEntityEnhancedSchema = cache(async (\n projectId: string,\n pagePath: string\n): Promise<object[]> => {\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n */\nexport const getVisibilityScore = cache(async (\n projectId: string,\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n */\nexport const getVisibilitySummary = cache(async (\n projectId: string\n): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
1
+ {"version":3,"sources":["../../src/seo/api.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @sonordev/site-kit/seo - API Functions\n * \n * ⚠️ DEPRECATED: This file exposes API keys in client bundles.\n * Use `server-api.ts` instead for server-side operations.\n * \n * This file is kept for backward compatibility but will be removed in a future version.\n * \n * Migration guide:\n * - Replace: import { getSEOPageData } from '@sonordev/seo/api'\n * - With: import { getSEOPageData } from '@sonordev/seo/server'\n * - Use private env var: SONOR_API_KEY\n */\n\nimport { cache } from 'react'\n\n// Show deprecation warning in development\nif (process.env.NODE_ENV === 'development') {\n console.warn(\n '@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. ' +\n 'Please migrate to server-api.ts for better security. ' +\n 'See: packages/site-kit/src/seo/README.md#migration'\n )\n}\n\n// ============================================\n// API Config (DEPRECATED)\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = process.env.SONOR_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function apiPost<T>(endpoint: string, body: Record<string, any> = {}): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify(body),\n next: { revalidate: 60 }, // Cache for 60 seconds\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n */\nexport const getSEOPageData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page || null\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n */\nexport const getSchemaMarkups = cache(async (\n projectId: string,\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await apiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n */\nexport const getFAQData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n */\nexport const getInternalLinks = cache(async (\n projectId: string,\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await apiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n */\nexport const getContentBlock = cache(async (\n projectId: string,\n path: string,\n section: string\n) => {\n const result = await apiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n */\nexport const getABTest = cache(async (\n projectId: string,\n path: string,\n field: string\n) => {\n const result = await apiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await apiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n */\nexport const getRedirectData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n */\nexport const getManagedScripts = cache(async (\n projectId: string,\n position: string,\n currentPath?: string\n) => {\n const result = await apiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n */\nexport const getRobotsData = cache(async (\n projectId: string,\n path: string\n) => {\n const result = await apiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n */\nexport const getSitemapEntries = cache(async (\n projectId: string,\n options?: { publishedOnly?: boolean }\n) => {\n const result = await apiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * \n * After registration, Signal AI will automatically generate optimized\n * meta titles and descriptions for pages that don't have them yet.\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ], { optimize_meta: true })\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>,\n options?: {\n /** Trigger Signal AI to generate optimized meta titles/descriptions (default: true) */\n optimize_meta?: boolean\n }\n): Promise<{ \n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/seo: No API key configured. Set SONOR_API_KEY.')\n return { success: false, created: 0, updated: 0 }\n }\n \n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ \n entries,\n optimize_meta: options?.optimize_meta !== false, // Default to true\n }),\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// AI Visibility & Entity Graph API\n// ============================================\n\n/**\n * Get Signal API config for AI visibility features\n */\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n */\nexport const getEntities = cache(async (\n projectId: string,\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n */\nexport const getPrimaryEntity = cache(async (\n projectId: string\n): Promise<SEOEntity | null> => {\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n */\nexport const getEntityEnhancedSchema = cache(async (\n projectId: string,\n pagePath: string\n): Promise<object[]> => {\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n */\nexport const getVisibilityScore = cache(async (\n projectId: string,\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n */\nexport const getVisibilitySummary = cache(async (\n projectId: string\n): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
@@ -1,4 +1,4 @@
1
- export { ensureMetadata, getABTest, getContentBlock, getEntities, getEntityEnhancedSchema, getFAQData, getInternalLinks, getManagedScripts, getPrimaryEntity, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, getVisibilityScore, getVisibilitySummary, recordABImpression, registerSitemap } from './chunk-J4U3IEXL.mjs';
1
+ export { ensureMetadata, getABTest, getContentBlock, getEntities, getEntityEnhancedSchema, getFAQData, getInternalLinks, getManagedScripts, getPrimaryEntity, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, getVisibilityScore, getVisibilitySummary, recordABImpression, registerSitemap } from './chunk-TUFP3FGI.mjs';
2
2
  import './chunk-4XPGGLVP.mjs';
3
- //# sourceMappingURL=server-api-UIZU4JM3.mjs.map
4
- //# sourceMappingURL=server-api-UIZU4JM3.mjs.map
3
+ //# sourceMappingURL=server-api-O7SSHYQS.mjs.map
4
+ //# sourceMappingURL=server-api-O7SSHYQS.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"server-api-UIZU4JM3.mjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server-api-O7SSHYQS.mjs"}
@@ -1,81 +1,81 @@
1
1
  'use strict';
2
2
 
3
- var chunkFCXQECM7_js = require('./chunk-FCXQECM7.js');
3
+ var chunkVU4GL5ZG_js = require('./chunk-VU4GL5ZG.js');
4
4
  require('./chunk-ZSMWDLMK.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "ensureMetadata", {
9
9
  enumerable: true,
10
- get: function () { return chunkFCXQECM7_js.ensureMetadata; }
10
+ get: function () { return chunkVU4GL5ZG_js.ensureMetadata; }
11
11
  });
12
12
  Object.defineProperty(exports, "getABTest", {
13
13
  enumerable: true,
14
- get: function () { return chunkFCXQECM7_js.getABTest; }
14
+ get: function () { return chunkVU4GL5ZG_js.getABTest; }
15
15
  });
16
16
  Object.defineProperty(exports, "getContentBlock", {
17
17
  enumerable: true,
18
- get: function () { return chunkFCXQECM7_js.getContentBlock; }
18
+ get: function () { return chunkVU4GL5ZG_js.getContentBlock; }
19
19
  });
20
20
  Object.defineProperty(exports, "getEntities", {
21
21
  enumerable: true,
22
- get: function () { return chunkFCXQECM7_js.getEntities; }
22
+ get: function () { return chunkVU4GL5ZG_js.getEntities; }
23
23
  });
24
24
  Object.defineProperty(exports, "getEntityEnhancedSchema", {
25
25
  enumerable: true,
26
- get: function () { return chunkFCXQECM7_js.getEntityEnhancedSchema; }
26
+ get: function () { return chunkVU4GL5ZG_js.getEntityEnhancedSchema; }
27
27
  });
28
28
  Object.defineProperty(exports, "getFAQData", {
29
29
  enumerable: true,
30
- get: function () { return chunkFCXQECM7_js.getFAQData; }
30
+ get: function () { return chunkVU4GL5ZG_js.getFAQData; }
31
31
  });
32
32
  Object.defineProperty(exports, "getInternalLinks", {
33
33
  enumerable: true,
34
- get: function () { return chunkFCXQECM7_js.getInternalLinks; }
34
+ get: function () { return chunkVU4GL5ZG_js.getInternalLinks; }
35
35
  });
36
36
  Object.defineProperty(exports, "getManagedScripts", {
37
37
  enumerable: true,
38
- get: function () { return chunkFCXQECM7_js.getManagedScripts; }
38
+ get: function () { return chunkVU4GL5ZG_js.getManagedScripts; }
39
39
  });
40
40
  Object.defineProperty(exports, "getPrimaryEntity", {
41
41
  enumerable: true,
42
- get: function () { return chunkFCXQECM7_js.getPrimaryEntity; }
42
+ get: function () { return chunkVU4GL5ZG_js.getPrimaryEntity; }
43
43
  });
44
44
  Object.defineProperty(exports, "getRedirectData", {
45
45
  enumerable: true,
46
- get: function () { return chunkFCXQECM7_js.getRedirectData; }
46
+ get: function () { return chunkVU4GL5ZG_js.getRedirectData; }
47
47
  });
48
48
  Object.defineProperty(exports, "getRobotsData", {
49
49
  enumerable: true,
50
- get: function () { return chunkFCXQECM7_js.getRobotsData; }
50
+ get: function () { return chunkVU4GL5ZG_js.getRobotsData; }
51
51
  });
52
52
  Object.defineProperty(exports, "getSEOPageData", {
53
53
  enumerable: true,
54
- get: function () { return chunkFCXQECM7_js.getSEOPageData; }
54
+ get: function () { return chunkVU4GL5ZG_js.getSEOPageData; }
55
55
  });
56
56
  Object.defineProperty(exports, "getSchemaMarkups", {
57
57
  enumerable: true,
58
- get: function () { return chunkFCXQECM7_js.getSchemaMarkups; }
58
+ get: function () { return chunkVU4GL5ZG_js.getSchemaMarkups; }
59
59
  });
60
60
  Object.defineProperty(exports, "getSitemapEntries", {
61
61
  enumerable: true,
62
- get: function () { return chunkFCXQECM7_js.getSitemapEntries; }
62
+ get: function () { return chunkVU4GL5ZG_js.getSitemapEntries; }
63
63
  });
64
64
  Object.defineProperty(exports, "getVisibilityScore", {
65
65
  enumerable: true,
66
- get: function () { return chunkFCXQECM7_js.getVisibilityScore; }
66
+ get: function () { return chunkVU4GL5ZG_js.getVisibilityScore; }
67
67
  });
68
68
  Object.defineProperty(exports, "getVisibilitySummary", {
69
69
  enumerable: true,
70
- get: function () { return chunkFCXQECM7_js.getVisibilitySummary; }
70
+ get: function () { return chunkVU4GL5ZG_js.getVisibilitySummary; }
71
71
  });
72
72
  Object.defineProperty(exports, "recordABImpression", {
73
73
  enumerable: true,
74
- get: function () { return chunkFCXQECM7_js.recordABImpression; }
74
+ get: function () { return chunkVU4GL5ZG_js.recordABImpression; }
75
75
  });
76
76
  Object.defineProperty(exports, "registerSitemap", {
77
77
  enumerable: true,
78
- get: function () { return chunkFCXQECM7_js.registerSitemap; }
78
+ get: function () { return chunkVU4GL5ZG_js.registerSitemap; }
79
79
  });
80
- //# sourceMappingURL=server-api-36R24YWN.js.map
81
- //# sourceMappingURL=server-api-36R24YWN.js.map
80
+ //# sourceMappingURL=server-api-W4BXUFCT.js.map
81
+ //# sourceMappingURL=server-api-W4BXUFCT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"server-api-36R24YWN.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server-api-W4BXUFCT.js"}
@@ -1,4 +1,4 @@
1
- import { L as LLMsDataResponse } from '../types-Blb2QNkV.mjs';
1
+ import { L as LLMsDataResponse } from '../types-BxzT7yhf.mjs';
2
2
 
3
3
  /**
4
4
  * @sonordev/site-kit - Sitemap Generator
@@ -22,11 +22,16 @@ import { L as LLMsDataResponse } from '../types-Blb2QNkV.mjs';
22
22
  * })
23
23
  * ```
24
24
  */
25
+ type PageType = 'homepage' | 'service' | 'comparison' | 'blog' | 'industry' | 'portfolio' | 'faq' | 'pricing' | 'page';
25
26
  interface SitemapEntry {
26
27
  url: string;
27
28
  lastModified?: Date | string;
28
29
  changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
29
30
  priority?: number;
31
+ /** Optional page description for Signal context */
32
+ description?: string;
33
+ /** Inferred or explicit page type for Signal context */
34
+ pageType?: PageType;
30
35
  }
31
36
  interface SitemapConfig {
32
37
  /** Base URL for the site (optional when apiKey is set; then resolved from Portal project-info) */
@@ -42,6 +47,7 @@ interface SitemapConfig {
42
47
  path: string;
43
48
  priority?: number;
44
49
  changeFrequency?: SitemapEntry['changeFrequency'];
50
+ description?: string;
45
51
  }>>;
46
52
  /**
47
53
  * Explicit values for dynamic route segments.
@@ -100,6 +106,32 @@ declare function syncSitemapToPortal(entries: SitemapEntry[], apiUrl: string, ap
100
106
  * })
101
107
  * ```
102
108
  */
109
+ /**
110
+ * Fetches published portfolio items from Portal API and returns them as sitemap paths.
111
+ * Use this in createSitemap's additionalPaths to include portfolio routes.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * import { createSitemap, getPortfolioPaths } from '@sonordev/site-kit/sitemap'
116
+ *
117
+ * export default createSitemap({
118
+ * baseUrl: 'https://example.com',
119
+ * additionalPaths: async () => [
120
+ * ...(await getPortfolioPaths()),
121
+ * ]
122
+ * })
123
+ * ```
124
+ */
125
+ declare function getPortfolioPaths(options?: {
126
+ apiUrl?: string;
127
+ apiKey?: string;
128
+ basePath?: string;
129
+ priority?: number;
130
+ }): Promise<Array<{
131
+ path: string;
132
+ priority: number;
133
+ changeFrequency: 'weekly';
134
+ }>>;
103
135
  declare function createSitemap(config: SitemapConfig): () => SitemapEntry[] | Promise<SitemapEntry[]>;
104
136
 
105
- export { type SitemapConfig, type SitemapEntry, type SyncSitemapOptions, createSitemap, syncSitemapToPortal };
137
+ export { type PageType, type SitemapConfig, type SitemapEntry, type SyncSitemapOptions, createSitemap, getPortfolioPaths, syncSitemapToPortal };
@@ -1,4 +1,4 @@
1
- import { L as LLMsDataResponse } from '../types-Blb2QNkV.js';
1
+ import { L as LLMsDataResponse } from '../types-BxzT7yhf.js';
2
2
 
3
3
  /**
4
4
  * @sonordev/site-kit - Sitemap Generator
@@ -22,11 +22,16 @@ import { L as LLMsDataResponse } from '../types-Blb2QNkV.js';
22
22
  * })
23
23
  * ```
24
24
  */
25
+ type PageType = 'homepage' | 'service' | 'comparison' | 'blog' | 'industry' | 'portfolio' | 'faq' | 'pricing' | 'page';
25
26
  interface SitemapEntry {
26
27
  url: string;
27
28
  lastModified?: Date | string;
28
29
  changeFrequency?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never';
29
30
  priority?: number;
31
+ /** Optional page description for Signal context */
32
+ description?: string;
33
+ /** Inferred or explicit page type for Signal context */
34
+ pageType?: PageType;
30
35
  }
31
36
  interface SitemapConfig {
32
37
  /** Base URL for the site (optional when apiKey is set; then resolved from Portal project-info) */
@@ -42,6 +47,7 @@ interface SitemapConfig {
42
47
  path: string;
43
48
  priority?: number;
44
49
  changeFrequency?: SitemapEntry['changeFrequency'];
50
+ description?: string;
45
51
  }>>;
46
52
  /**
47
53
  * Explicit values for dynamic route segments.
@@ -100,6 +106,32 @@ declare function syncSitemapToPortal(entries: SitemapEntry[], apiUrl: string, ap
100
106
  * })
101
107
  * ```
102
108
  */
109
+ /**
110
+ * Fetches published portfolio items from Portal API and returns them as sitemap paths.
111
+ * Use this in createSitemap's additionalPaths to include portfolio routes.
112
+ *
113
+ * @example
114
+ * ```ts
115
+ * import { createSitemap, getPortfolioPaths } from '@sonordev/site-kit/sitemap'
116
+ *
117
+ * export default createSitemap({
118
+ * baseUrl: 'https://example.com',
119
+ * additionalPaths: async () => [
120
+ * ...(await getPortfolioPaths()),
121
+ * ]
122
+ * })
123
+ * ```
124
+ */
125
+ declare function getPortfolioPaths(options?: {
126
+ apiUrl?: string;
127
+ apiKey?: string;
128
+ basePath?: string;
129
+ priority?: number;
130
+ }): Promise<Array<{
131
+ path: string;
132
+ priority: number;
133
+ changeFrequency: 'weekly';
134
+ }>>;
103
135
  declare function createSitemap(config: SitemapConfig): () => SitemapEntry[] | Promise<SitemapEntry[]>;
104
136
 
105
- export { type SitemapConfig, type SitemapEntry, type SyncSitemapOptions, createSitemap, syncSitemapToPortal };
137
+ export { type PageType, type SitemapConfig, type SitemapEntry, type SyncSitemapOptions, createSitemap, getPortfolioPaths, syncSitemapToPortal };