@sonordev/site-kit 2.8.1 → 2.9.0

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 (81) hide show
  1. package/dist/blog/index.js +2 -1
  2. package/dist/blog/index.js.map +1 -1
  3. package/dist/blog/index.mjs +2 -1
  4. package/dist/blog/index.mjs.map +1 -1
  5. package/dist/{chunk-5SQ4NRPH.mjs → chunk-3AEOGV6V.mjs} +6 -4
  6. package/dist/chunk-3AEOGV6V.mjs.map +1 -0
  7. package/dist/chunk-662YHKWW.mjs +10 -0
  8. package/dist/chunk-662YHKWW.mjs.map +1 -0
  9. package/dist/{chunk-MNOVPHL6.mjs → chunk-72MRAYAS.mjs} +19 -14
  10. package/dist/chunk-72MRAYAS.mjs.map +1 -0
  11. package/dist/{chunk-MWE2HRPU.js → chunk-D5XTX5EB.js} +19 -14
  12. package/dist/chunk-D5XTX5EB.js.map +1 -0
  13. package/dist/{chunk-AT2ZF3TL.mjs → chunk-FMZOZQBV.mjs} +91 -15
  14. package/dist/chunk-FMZOZQBV.mjs.map +1 -0
  15. package/dist/{chunk-ZQINTH5K.js → chunk-I2GTT2DG.js} +91 -15
  16. package/dist/chunk-I2GTT2DG.js.map +1 -0
  17. package/dist/{chunk-PKUTYMN7.js → chunk-J25JPU77.js} +2 -2
  18. package/dist/chunk-J25JPU77.js.map +1 -0
  19. package/dist/chunk-J7QI3GDX.js +12 -0
  20. package/dist/chunk-J7QI3GDX.js.map +1 -0
  21. package/dist/{chunk-L7XPPFSS.mjs → chunk-QDKQZ5XH.mjs} +2 -2
  22. package/dist/chunk-QDKQZ5XH.mjs.map +1 -0
  23. package/dist/{chunk-PAF5IGGF.js → chunk-XNUPJC6R.js} +6 -4
  24. package/dist/chunk-XNUPJC6R.js.map +1 -0
  25. package/dist/commerce/index.d.mts +3 -3
  26. package/dist/commerce/index.d.ts +3 -3
  27. package/dist/commerce/server.d.mts +1 -1
  28. package/dist/commerce/server.d.ts +1 -1
  29. package/dist/index.d.mts +5 -191
  30. package/dist/index.d.ts +5 -191
  31. package/dist/index.js +13 -13
  32. package/dist/index.mjs +1 -1
  33. package/dist/layout/index.js +3 -3
  34. package/dist/layout/index.mjs +1 -1
  35. package/dist/llms/index.d.mts +18 -4
  36. package/dist/llms/index.d.ts +18 -4
  37. package/dist/llms/index.js +26 -51
  38. package/dist/llms/index.js.map +1 -1
  39. package/dist/llms/index.mjs +16 -41
  40. package/dist/llms/index.mjs.map +1 -1
  41. package/dist/seo/index.d.mts +10 -205
  42. package/dist/seo/index.d.ts +10 -205
  43. package/dist/seo/index.js +16 -15
  44. package/dist/seo/index.js.map +1 -1
  45. package/dist/seo/index.mjs +7 -6
  46. package/dist/seo/index.mjs.map +1 -1
  47. package/dist/seo/server.d.mts +2 -106
  48. package/dist/seo/server.d.ts +2 -106
  49. package/dist/seo/server.js +56 -197
  50. package/dist/seo/server.js.map +1 -1
  51. package/dist/seo/server.mjs +2 -183
  52. package/dist/seo/server.mjs.map +1 -1
  53. package/dist/server-l6LMNvF1.d.ts +360 -0
  54. package/dist/server-mX5At_6x.d.mts +360 -0
  55. package/dist/sitemap/index.d.mts +1 -1
  56. package/dist/sitemap/index.d.ts +1 -1
  57. package/dist/sitemap/index.js +2 -2
  58. package/dist/sitemap/index.mjs +1 -1
  59. package/dist/sync/index.d.mts +213 -0
  60. package/dist/sync/index.d.ts +213 -0
  61. package/dist/sync/index.js +13 -13
  62. package/dist/sync/index.mjs +1 -1
  63. package/dist/{types-DYyIAgQg.d.ts → types-DPsbBKiu.d.mts} +1 -1
  64. package/dist/{types-DYyIAgQg.d.mts → types-DPsbBKiu.d.ts} +1 -1
  65. package/dist/{types-J7Z_FqmV.d.mts → types-DhCAWUmd.d.mts} +8 -0
  66. package/dist/{types-B0xmgGw-.d.ts → types-iZM4Lz71.d.mts} +1 -1
  67. package/dist/{types-B0xmgGw-.d.mts → types-iZM4Lz71.d.ts} +1 -1
  68. package/dist/{types-0NuBL1Gg.d.ts → types-xcP_owwn.d.ts} +8 -0
  69. package/dist/{useEventModal-CJLCmH5Y.d.ts → useEventModal-CcxNZOvp.d.ts} +2 -2
  70. package/dist/{useEventModal-4W_y1SYY.d.mts → useEventModal-qJfX_1XG.d.mts} +2 -2
  71. package/package.json +2 -2
  72. package/dist/chunk-5SQ4NRPH.mjs.map +0 -1
  73. package/dist/chunk-AT2ZF3TL.mjs.map +0 -1
  74. package/dist/chunk-L7XPPFSS.mjs.map +0 -1
  75. package/dist/chunk-MNOVPHL6.mjs.map +0 -1
  76. package/dist/chunk-MWE2HRPU.js.map +0 -1
  77. package/dist/chunk-PAF5IGGF.js.map +0 -1
  78. package/dist/chunk-PKUTYMN7.js.map +0 -1
  79. package/dist/chunk-ZQINTH5K.js.map +0 -1
  80. package/dist/routing-C7gmHWm9.d.ts +0 -163
  81. package/dist/routing-trNzR1Pz.d.mts +0 -163
@@ -1,215 +1,74 @@
1
1
  'use strict';
2
2
 
3
- var chunkPAF5IGGF_js = require('../chunk-PAF5IGGF.js');
4
- require('../chunk-VU4GL5ZG.js');
3
+ var chunkXNUPJC6R_js = require('../chunk-XNUPJC6R.js');
4
+ var chunkVU4GL5ZG_js = require('../chunk-VU4GL5ZG.js');
5
5
  require('../chunk-ZSMWDLMK.js');
6
- var react = require('react');
7
6
 
8
- if (process.env.NODE_ENV === "development") {
9
- console.warn(
10
- "@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. Please migrate to server-api.ts for better security. See: packages/site-kit/src/seo/README.md#migration"
11
- );
12
- }
13
- function getApiConfig() {
14
- const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
15
- const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
16
- return { apiUrl, apiKey };
17
- }
18
- async function apiPost(endpoint, body = {}) {
19
- const { apiUrl, apiKey } = getApiConfig();
20
- if (!apiKey) {
21
- console.error("@sonordev/seo: No API key configured. Set SONOR_API_KEY.");
22
- return null;
23
- }
24
- try {
25
- const response = await fetch(`${apiUrl}${endpoint}`, {
26
- method: "POST",
27
- headers: {
28
- "Content-Type": "application/json",
29
- "x-api-key": apiKey
30
- },
31
- body: JSON.stringify(body),
32
- next: { revalidate: 60 }
33
- // Cache for 60 seconds
34
- });
35
- if (!response.ok) {
36
- console.error(`@sonordev/seo: API error: ${response.statusText}`);
37
- return null;
38
- }
39
- return await response.json();
40
- } catch (error) {
41
- console.error("@sonordev/seo: Network error:", error);
42
- return null;
43
- }
44
- }
45
- var getSEOPageData = react.cache(async (projectId, path) => {
46
- const result = await apiPost("/api/public/seo/page", { path });
47
- return result?.page || null;
48
- });
49
- var getSchemaMarkups = react.cache(async (projectId, path, options) => {
50
- const result = await apiPost("/api/public/seo/schemas", {
51
- path,
52
- includeTypes: options?.includeTypes,
53
- excludeTypes: options?.excludeTypes
54
- });
55
- return result?.schemas || [];
56
- });
57
- var getFAQData = react.cache(async (projectId, path) => {
58
- const result = await apiPost("/api/public/seo/faq", { path });
59
- return result?.faq || null;
60
- });
61
- var getInternalLinks = react.cache(async (projectId, sourcePath, options) => {
62
- const result = await apiPost("/api/public/seo/internal-links", {
63
- sourcePath,
64
- position: options?.position,
65
- limit: options?.limit
66
- });
67
- return result?.links || [];
68
- });
69
- var getContentBlock = react.cache(async (projectId, path, section) => {
70
- const result = await apiPost("/api/public/seo/content", { path, section });
71
- return result?.content || null;
72
- });
73
- var getABTest = react.cache(async (projectId, path, field) => {
74
- const result = await apiPost("/api/public/seo/ab-test", { path, field });
75
- return result?.test || null;
76
- });
77
- async function recordABImpression(testId, variant, sessionId) {
78
- await apiPost("/api/public/seo/ab-impression", { testId, variant, sessionId });
79
- }
80
- var getRedirectData = react.cache(async (projectId, path) => {
81
- const result = await apiPost("/api/public/seo/redirect", { path });
82
- return result?.redirect || null;
83
- });
84
- var getManagedScripts = react.cache(async (projectId, position, currentPath) => {
85
- const result = await apiPost("/api/public/seo/scripts", {
86
- position,
87
- currentPath
88
- });
89
- return result?.scripts || [];
90
- });
91
- var getRobotsData = react.cache(async (projectId, path) => {
92
- const result = await apiPost("/api/public/seo/page", { path });
93
- return result?.page?.managed_robots || null;
94
- });
95
- var getSitemapEntries = react.cache(async (projectId, options) => {
96
- const result = await apiPost("/api/public/seo/sitemap", {
97
- publishedOnly: options?.publishedOnly
98
- });
99
- return result?.entries || [];
100
- });
101
- async function registerSitemap(entries, options) {
102
- const { apiUrl, apiKey } = getApiConfig();
103
- if (!apiKey) {
104
- console.error("@sonordev/seo: No API key configured. Set SONOR_API_KEY.");
105
- return { success: false, created: 0, updated: 0 };
106
- }
107
- try {
108
- const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {
109
- method: "POST",
110
- headers: {
111
- "Content-Type": "application/json",
112
- "x-api-key": apiKey
113
- },
114
- body: JSON.stringify({
115
- entries,
116
- optimize_meta: options?.optimize_meta !== false
117
- // Default to true
118
- })
119
- });
120
- if (!response.ok) {
121
- console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`);
122
- return { success: false, created: 0, updated: 0 };
123
- }
124
- return await response.json();
125
- } catch (error) {
126
- console.error("@sonordev/seo: Sitemap registration error:", error);
127
- return { success: false, created: 0, updated: 0 };
128
- }
129
- }
130
- function getSignalApiConfig() {
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 || process.env.UPTRADE_API_KEY || "";
133
- return { apiUrl, apiKey };
134
- }
135
- async function signalApiGet(endpoint) {
136
- const { apiUrl, apiKey } = getSignalApiConfig();
137
- if (!apiKey) {
138
- return null;
139
- }
140
- try {
141
- const response = await fetch(`${apiUrl}${endpoint}`, {
142
- method: "GET",
143
- headers: {
144
- "Content-Type": "application/json",
145
- "x-api-key": apiKey
146
- },
147
- next: { revalidate: 300 }
148
- // Cache for 5 minutes
149
- });
150
- if (!response.ok) {
151
- return null;
152
- }
153
- const result = await response.json();
154
- return result?.data || result;
155
- } catch (error) {
156
- console.error("@sonordev/seo: Signal API error:", error);
157
- return null;
158
- }
159
- }
160
- react.cache(async (projectId, options) => {
161
- let endpoint = `/skills/seo/entities/${projectId}`;
162
- if (options?.type) {
163
- endpoint += `?type=${options.type}`;
164
- }
165
- const result = await signalApiGet(endpoint);
166
- return result || [];
167
- });
168
- react.cache(async (projectId) => {
169
- return signalApiGet(`/skills/seo/entities/${projectId}/primary`);
170
- });
171
- react.cache(async (projectId, pagePath) => {
172
- const result = await signalApiGet(
173
- `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`
174
- );
175
- return result?.schemas || [];
176
- });
177
- react.cache(async (projectId, pagePath) => {
178
- const result = await signalApiGet(`/skills/seo/visibility/${projectId}`);
179
- if (!result) return null;
180
- return result.find((s) => s.page_path === pagePath) || null;
181
- });
182
- react.cache(async (projectId) => {
183
- return signalApiGet(`/skills/seo/visibility/${projectId}/summary`);
184
- });
7
+
185
8
 
186
9
  Object.defineProperty(exports, "generateSitemap", {
187
10
  enumerable: true,
188
- get: function () { return chunkPAF5IGGF_js.generateSitemap; }
11
+ get: function () { return chunkXNUPJC6R_js.generateSitemap; }
189
12
  });
190
13
  Object.defineProperty(exports, "getManagedMetadata", {
191
14
  enumerable: true,
192
- get: function () { return chunkPAF5IGGF_js.getManagedMetadata; }
15
+ get: function () { return chunkXNUPJC6R_js.getManagedMetadata; }
193
16
  });
194
17
  Object.defineProperty(exports, "getManagedMetadataWithAB", {
195
18
  enumerable: true,
196
- get: function () { return chunkPAF5IGGF_js.getManagedMetadataWithAB; }
19
+ get: function () { return chunkXNUPJC6R_js.getManagedMetadataWithAB; }
197
20
  });
198
21
  Object.defineProperty(exports, "registerLocalSitemap", {
199
22
  enumerable: true,
200
- get: function () { return chunkPAF5IGGF_js.registerLocalSitemap; }
201
- });
202
- exports.getABTest = getABTest;
203
- exports.getContentBlock = getContentBlock;
204
- exports.getFAQData = getFAQData;
205
- exports.getInternalLinks = getInternalLinks;
206
- exports.getManagedScripts = getManagedScripts;
207
- exports.getRedirectData = getRedirectData;
208
- exports.getRobotsData = getRobotsData;
209
- exports.getSEOPageData = getSEOPageData;
210
- exports.getSchemaMarkups = getSchemaMarkups;
211
- exports.getSitemapEntries = getSitemapEntries;
212
- exports.recordABImpression = recordABImpression;
213
- exports.registerSitemap = registerSitemap;
23
+ get: function () { return chunkXNUPJC6R_js.registerLocalSitemap; }
24
+ });
25
+ Object.defineProperty(exports, "getABTest", {
26
+ enumerable: true,
27
+ get: function () { return chunkVU4GL5ZG_js.getABTest; }
28
+ });
29
+ Object.defineProperty(exports, "getContentBlock", {
30
+ enumerable: true,
31
+ get: function () { return chunkVU4GL5ZG_js.getContentBlock; }
32
+ });
33
+ Object.defineProperty(exports, "getFAQData", {
34
+ enumerable: true,
35
+ get: function () { return chunkVU4GL5ZG_js.getFAQData; }
36
+ });
37
+ Object.defineProperty(exports, "getInternalLinks", {
38
+ enumerable: true,
39
+ get: function () { return chunkVU4GL5ZG_js.getInternalLinks; }
40
+ });
41
+ Object.defineProperty(exports, "getManagedScripts", {
42
+ enumerable: true,
43
+ get: function () { return chunkVU4GL5ZG_js.getManagedScripts; }
44
+ });
45
+ Object.defineProperty(exports, "getRedirectData", {
46
+ enumerable: true,
47
+ get: function () { return chunkVU4GL5ZG_js.getRedirectData; }
48
+ });
49
+ Object.defineProperty(exports, "getRobotsData", {
50
+ enumerable: true,
51
+ get: function () { return chunkVU4GL5ZG_js.getRobotsData; }
52
+ });
53
+ Object.defineProperty(exports, "getSEOPageData", {
54
+ enumerable: true,
55
+ get: function () { return chunkVU4GL5ZG_js.getSEOPageData; }
56
+ });
57
+ Object.defineProperty(exports, "getSchemaMarkups", {
58
+ enumerable: true,
59
+ get: function () { return chunkVU4GL5ZG_js.getSchemaMarkups; }
60
+ });
61
+ Object.defineProperty(exports, "getSitemapEntries", {
62
+ enumerable: true,
63
+ get: function () { return chunkVU4GL5ZG_js.getSitemapEntries; }
64
+ });
65
+ Object.defineProperty(exports, "recordABImpression", {
66
+ enumerable: true,
67
+ get: function () { return chunkVU4GL5ZG_js.recordABImpression; }
68
+ });
69
+ Object.defineProperty(exports, "registerSitemap", {
70
+ enumerable: true,
71
+ get: function () { return chunkVU4GL5ZG_js.registerSitemap; }
72
+ });
214
73
  //# sourceMappingURL=server.js.map
215
74
  //# sourceMappingURL=server.js.map
@@ -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 || 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
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server.js"}
@@ -1,186 +1,5 @@
1
- export { generateSitemap, getManagedMetadata, getManagedMetadataWithAB, registerLocalSitemap } from '../chunk-5SQ4NRPH.mjs';
2
- import '../chunk-TUFP3FGI.mjs';
1
+ export { generateSitemap, getManagedMetadata, getManagedMetadataWithAB, registerLocalSitemap } from '../chunk-3AEOGV6V.mjs';
2
+ export { getABTest, getContentBlock, getFAQData, getInternalLinks, getManagedScripts, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, recordABImpression, registerSitemap } from '../chunk-TUFP3FGI.mjs';
3
3
  import '../chunk-4XPGGLVP.mjs';
4
- import { cache } from 'react';
5
-
6
- if (process.env.NODE_ENV === "development") {
7
- console.warn(
8
- "@sonordev/seo: WARNING - You are using the deprecated api.ts which exposes API keys. Please migrate to server-api.ts for better security. See: packages/site-kit/src/seo/README.md#migration"
9
- );
10
- }
11
- function getApiConfig() {
12
- const apiUrl = process.env.SONOR_API_URL || "https://api.sonor.io";
13
- const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
14
- return { apiUrl, apiKey };
15
- }
16
- async function apiPost(endpoint, body = {}) {
17
- const { apiUrl, apiKey } = getApiConfig();
18
- if (!apiKey) {
19
- console.error("@sonordev/seo: No API key configured. Set SONOR_API_KEY.");
20
- return null;
21
- }
22
- try {
23
- const response = await fetch(`${apiUrl}${endpoint}`, {
24
- method: "POST",
25
- headers: {
26
- "Content-Type": "application/json",
27
- "x-api-key": apiKey
28
- },
29
- body: JSON.stringify(body),
30
- next: { revalidate: 60 }
31
- // Cache for 60 seconds
32
- });
33
- if (!response.ok) {
34
- console.error(`@sonordev/seo: API error: ${response.statusText}`);
35
- return null;
36
- }
37
- return await response.json();
38
- } catch (error) {
39
- console.error("@sonordev/seo: Network error:", error);
40
- return null;
41
- }
42
- }
43
- var getSEOPageData = cache(async (projectId, path) => {
44
- const result = await apiPost("/api/public/seo/page", { path });
45
- return result?.page || null;
46
- });
47
- var getSchemaMarkups = cache(async (projectId, path, options) => {
48
- const result = await apiPost("/api/public/seo/schemas", {
49
- path,
50
- includeTypes: options?.includeTypes,
51
- excludeTypes: options?.excludeTypes
52
- });
53
- return result?.schemas || [];
54
- });
55
- var getFAQData = cache(async (projectId, path) => {
56
- const result = await apiPost("/api/public/seo/faq", { path });
57
- return result?.faq || null;
58
- });
59
- var getInternalLinks = cache(async (projectId, sourcePath, options) => {
60
- const result = await apiPost("/api/public/seo/internal-links", {
61
- sourcePath,
62
- position: options?.position,
63
- limit: options?.limit
64
- });
65
- return result?.links || [];
66
- });
67
- var getContentBlock = cache(async (projectId, path, section) => {
68
- const result = await apiPost("/api/public/seo/content", { path, section });
69
- return result?.content || null;
70
- });
71
- var getABTest = cache(async (projectId, path, field) => {
72
- const result = await apiPost("/api/public/seo/ab-test", { path, field });
73
- return result?.test || null;
74
- });
75
- async function recordABImpression(testId, variant, sessionId) {
76
- await apiPost("/api/public/seo/ab-impression", { testId, variant, sessionId });
77
- }
78
- var getRedirectData = cache(async (projectId, path) => {
79
- const result = await apiPost("/api/public/seo/redirect", { path });
80
- return result?.redirect || null;
81
- });
82
- var getManagedScripts = cache(async (projectId, position, currentPath) => {
83
- const result = await apiPost("/api/public/seo/scripts", {
84
- position,
85
- currentPath
86
- });
87
- return result?.scripts || [];
88
- });
89
- var getRobotsData = cache(async (projectId, path) => {
90
- const result = await apiPost("/api/public/seo/page", { path });
91
- return result?.page?.managed_robots || null;
92
- });
93
- var getSitemapEntries = cache(async (projectId, options) => {
94
- const result = await apiPost("/api/public/seo/sitemap", {
95
- publishedOnly: options?.publishedOnly
96
- });
97
- return result?.entries || [];
98
- });
99
- async function registerSitemap(entries, options) {
100
- const { apiUrl, apiKey } = getApiConfig();
101
- if (!apiKey) {
102
- console.error("@sonordev/seo: No API key configured. Set SONOR_API_KEY.");
103
- return { success: false, created: 0, updated: 0 };
104
- }
105
- try {
106
- const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {
107
- method: "POST",
108
- headers: {
109
- "Content-Type": "application/json",
110
- "x-api-key": apiKey
111
- },
112
- body: JSON.stringify({
113
- entries,
114
- optimize_meta: options?.optimize_meta !== false
115
- // Default to true
116
- })
117
- });
118
- if (!response.ok) {
119
- console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`);
120
- return { success: false, created: 0, updated: 0 };
121
- }
122
- return await response.json();
123
- } catch (error) {
124
- console.error("@sonordev/seo: Sitemap registration error:", error);
125
- return { success: false, created: 0, updated: 0 };
126
- }
127
- }
128
- function getSignalApiConfig() {
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 || process.env.UPTRADE_API_KEY || "";
131
- return { apiUrl, apiKey };
132
- }
133
- async function signalApiGet(endpoint) {
134
- const { apiUrl, apiKey } = getSignalApiConfig();
135
- if (!apiKey) {
136
- return null;
137
- }
138
- try {
139
- const response = await fetch(`${apiUrl}${endpoint}`, {
140
- method: "GET",
141
- headers: {
142
- "Content-Type": "application/json",
143
- "x-api-key": apiKey
144
- },
145
- next: { revalidate: 300 }
146
- // Cache for 5 minutes
147
- });
148
- if (!response.ok) {
149
- return null;
150
- }
151
- const result = await response.json();
152
- return result?.data || result;
153
- } catch (error) {
154
- console.error("@sonordev/seo: Signal API error:", error);
155
- return null;
156
- }
157
- }
158
- cache(async (projectId, options) => {
159
- let endpoint = `/skills/seo/entities/${projectId}`;
160
- if (options?.type) {
161
- endpoint += `?type=${options.type}`;
162
- }
163
- const result = await signalApiGet(endpoint);
164
- return result || [];
165
- });
166
- cache(async (projectId) => {
167
- return signalApiGet(`/skills/seo/entities/${projectId}/primary`);
168
- });
169
- cache(async (projectId, pagePath) => {
170
- const result = await signalApiGet(
171
- `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`
172
- );
173
- return result?.schemas || [];
174
- });
175
- cache(async (projectId, pagePath) => {
176
- const result = await signalApiGet(`/skills/seo/visibility/${projectId}`);
177
- if (!result) return null;
178
- return result.find((s) => s.page_path === pagePath) || null;
179
- });
180
- cache(async (projectId) => {
181
- return signalApiGet(`/skills/seo/visibility/${projectId}/summary`);
182
- });
183
-
184
- export { getABTest, getContentBlock, getFAQData, getInternalLinks, getManagedScripts, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, recordABImpression, registerSitemap };
185
4
  //# sourceMappingURL=server.mjs.map
186
5
  //# sourceMappingURL=server.mjs.map
@@ -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 || 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
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"server.mjs"}