@sonordev/site-kit 1.2.7 → 1.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/analytics/index.js +6 -6
- package/dist/analytics/index.mjs +2 -2
- package/dist/{api-CWtoFJCO.d.mts → api-DTKSHh_w.d.mts} +1 -1
- package/dist/{api-CWtoFJCO.d.ts → api-DTKSHh_w.d.ts} +1 -1
- package/dist/blog/index.js +10 -10
- package/dist/blog/index.js.map +1 -1
- package/dist/blog/index.mjs +10 -10
- package/dist/blog/index.mjs.map +1 -1
- package/dist/blog/server.js +2 -2
- package/dist/blog/server.js.map +1 -1
- package/dist/blog/server.mjs +2 -2
- package/dist/blog/server.mjs.map +1 -1
- package/dist/{chunk-7RYCHO6D.mjs → chunk-2RHO4KSK.mjs} +9 -9
- package/dist/{chunk-7RYCHO6D.mjs.map → chunk-2RHO4KSK.mjs.map} +1 -1
- package/dist/{chunk-EEZCR6E6.js → chunk-2XOW276O.js} +5 -5
- package/dist/{chunk-EEZCR6E6.js.map → chunk-2XOW276O.js.map} +1 -1
- package/dist/{chunk-JTLOJLWQ.mjs → chunk-36Y7OWES.mjs} +4 -4
- package/dist/chunk-36Y7OWES.mjs.map +1 -0
- package/dist/{chunk-DQYMKR27.mjs → chunk-47Y3YSES.mjs} +10 -10
- package/dist/chunk-47Y3YSES.mjs.map +1 -0
- package/dist/{chunk-MV3QN7PW.mjs → chunk-5F7FFUPJ.mjs} +3 -3
- package/dist/{chunk-MV3QN7PW.mjs.map → chunk-5F7FFUPJ.mjs.map} +1 -1
- package/dist/{chunk-AFAO3TGS.mjs → chunk-5YDPPOUU.mjs} +10 -10
- package/dist/chunk-5YDPPOUU.mjs.map +1 -0
- package/dist/{chunk-D63MUKZ6.mjs → chunk-6YXRLC6W.mjs} +5 -5
- package/dist/chunk-6YXRLC6W.mjs.map +1 -0
- package/dist/{chunk-7RF6PVHA.mjs → chunk-7FKPJQVS.mjs} +33 -68
- package/dist/chunk-7FKPJQVS.mjs.map +1 -0
- package/dist/{chunk-BYLIU6XG.js → chunk-7ROZJDXE.js} +10 -10
- package/dist/chunk-7ROZJDXE.js.map +1 -0
- package/dist/{chunk-UWE5PCYJ.mjs → chunk-APZMXRI3.mjs} +3 -3
- package/dist/chunk-APZMXRI3.mjs.map +1 -0
- package/dist/{chunk-622GAQP5.js → chunk-BBITDUZQ.js} +6 -6
- package/dist/chunk-BBITDUZQ.js.map +1 -0
- package/dist/{chunk-DDKW2FNA.js → chunk-BFJDUTXK.js} +8 -8
- package/dist/chunk-BFJDUTXK.js.map +1 -0
- package/dist/chunk-C3A5HXHX.mjs +78 -0
- package/dist/chunk-C3A5HXHX.mjs.map +1 -0
- package/dist/{chunk-XZJOZJB6.js → chunk-CFEOOJUT.js} +12 -12
- package/dist/{chunk-XZJOZJB6.js.map → chunk-CFEOOJUT.js.map} +1 -1
- package/dist/{chunk-M2T6R7BA.mjs → chunk-DOSSLBNW.mjs} +4 -4
- package/dist/chunk-DOSSLBNW.mjs.map +1 -0
- package/dist/{chunk-OB7E654K.js → chunk-DY4K6X3A.js} +6 -6
- package/dist/chunk-DY4K6X3A.js.map +1 -0
- package/dist/{chunk-7UKPRW25.mjs → chunk-EISQ7LJG.mjs} +6 -6
- package/dist/chunk-EISQ7LJG.mjs.map +1 -0
- package/dist/{chunk-7557OTHW.js → chunk-EUNL6GAL.js} +5 -5
- package/dist/chunk-EUNL6GAL.js.map +1 -0
- package/dist/{chunk-KUGMH4ZF.js → chunk-G6VGUAK2.js} +4 -4
- package/dist/chunk-G6VGUAK2.js.map +1 -0
- package/dist/{chunk-XQQWI6WB.js → chunk-GVXZWXQ7.js} +10 -10
- package/dist/chunk-GVXZWXQ7.js.map +1 -0
- package/dist/{chunk-24277A3Q.mjs → chunk-HF2FWDBJ.mjs} +9 -9
- package/dist/chunk-HF2FWDBJ.mjs.map +1 -0
- package/dist/{chunk-72MQFHYJ.js → chunk-IFAW7JFO.js} +16 -16
- package/dist/chunk-IFAW7JFO.js.map +1 -0
- package/dist/{chunk-P3UWIUJS.mjs → chunk-IKIJEKU3.mjs} +16 -16
- package/dist/chunk-IKIJEKU3.mjs.map +1 -0
- package/dist/{chunk-PKN27UMH.mjs → chunk-JIDOXTX2.mjs} +3 -3
- package/dist/{chunk-PKN27UMH.mjs.map → chunk-JIDOXTX2.mjs.map} +1 -1
- package/dist/{chunk-7FUV73JZ.js → chunk-JM3ZR6LB.js} +9 -9
- package/dist/chunk-JM3ZR6LB.js.map +1 -0
- package/dist/{chunk-OIIKTGRL.mjs → chunk-JMNSED4O.mjs} +8 -8
- package/dist/chunk-JMNSED4O.mjs.map +1 -0
- package/dist/chunk-MG23BS36.js +82 -0
- package/dist/chunk-MG23BS36.js.map +1 -0
- package/dist/{chunk-TFLQX7K7.mjs → chunk-N24BPFF6.mjs} +6 -6
- package/dist/chunk-N24BPFF6.mjs.map +1 -0
- package/dist/{chunk-LIVWLY2P.js → chunk-PPRAW576.js} +3 -3
- package/dist/{chunk-LIVWLY2P.js.map → chunk-PPRAW576.js.map} +1 -1
- package/dist/{chunk-W4PALSGM.js → chunk-REMHGWXT.js} +3 -3
- package/dist/chunk-REMHGWXT.js.map +1 -0
- package/dist/{chunk-DW5UJKHH.js → chunk-RMOL4TZ6.js} +8 -8
- package/dist/chunk-RMOL4TZ6.js.map +1 -0
- package/dist/{chunk-KKU3K7RG.js → chunk-SLB5V4RT.js} +33 -67
- package/dist/chunk-SLB5V4RT.js.map +1 -0
- package/dist/{chunk-K23A4G76.mjs → chunk-SQSBAPWA.mjs} +8 -8
- package/dist/chunk-SQSBAPWA.mjs.map +1 -0
- package/dist/{chunk-WECQ6KOB.js → chunk-TG46LJFB.js} +4 -4
- package/dist/chunk-TG46LJFB.js.map +1 -0
- package/dist/{chunk-43GBM4SX.js → chunk-TKQLH33E.js} +3 -3
- package/dist/chunk-TKQLH33E.js.map +1 -0
- package/dist/{chunk-UYFDNX2F.js → chunk-TLHRV3LZ.js} +5 -5
- package/dist/chunk-TLHRV3LZ.js.map +1 -0
- package/dist/{chunk-6ZCISNAB.mjs → chunk-UPR5FEIO.mjs} +3 -3
- package/dist/chunk-UPR5FEIO.mjs.map +1 -0
- package/dist/{chunk-GCJXQ4AG.mjs → chunk-VZMDH3R4.mjs} +5 -5
- package/dist/chunk-VZMDH3R4.mjs.map +1 -0
- package/dist/{chunk-LBVWVP72.js → chunk-X4J33XQD.js} +7 -7
- package/dist/chunk-X4J33XQD.js.map +1 -0
- package/dist/{chunk-QXV4667R.mjs → chunk-XFOL6JDF.mjs} +5 -5
- package/dist/chunk-XFOL6JDF.mjs.map +1 -0
- package/dist/cli/index.js +80 -91
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +76 -87
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cms/index.d.mts +139 -0
- package/dist/cms/index.d.ts +139 -0
- package/dist/cms/index.js +409 -0
- package/dist/cms/index.js.map +1 -0
- package/dist/cms/index.mjs +388 -0
- package/dist/cms/index.mjs.map +1 -0
- package/dist/cms/server.d.mts +47 -0
- package/dist/cms/server.d.ts +47 -0
- package/dist/cms/server.js +21 -0
- package/dist/{server-api-GJPNRYUP.js.map → cms/server.js.map} +1 -1
- package/dist/cms/server.mjs +4 -0
- package/dist/{server-api-EWXKOQZA.mjs.map → cms/server.mjs.map} +1 -1
- package/dist/commerce/index.js +42 -42
- package/dist/commerce/index.mjs +1 -1
- package/dist/commerce/server.d.mts +1 -1
- package/dist/commerce/server.d.ts +1 -1
- package/dist/commerce/server.js.map +1 -1
- package/dist/commerce/server.mjs.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/index.mjs +1 -1
- package/dist/config/index.mjs.map +1 -1
- package/dist/engage/index.js +4 -4
- package/dist/engage/index.mjs +1 -1
- package/dist/forms/index.js +5 -5
- package/dist/forms/index.js.map +1 -1
- package/dist/forms/index.mjs +5 -5
- package/dist/forms/index.mjs.map +1 -1
- package/dist/generators-DOFWGRXS.js +37 -0
- package/dist/{generators-DTMO36DV.js.map → generators-DOFWGRXS.js.map} +1 -1
- package/dist/generators-R62APO62.mjs +4 -0
- package/dist/{generators-2XKQMPKH.mjs.map → generators-R62APO62.mjs.map} +1 -1
- package/dist/images/index.d.mts +1 -1
- package/dist/images/index.d.ts +1 -1
- package/dist/images/index.js +11 -11
- package/dist/images/index.mjs +2 -2
- package/dist/images/server.d.mts +3 -3
- package/dist/images/server.d.ts +3 -3
- package/dist/images/server.js +4 -4
- package/dist/images/server.mjs +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +81 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -28
- package/dist/index.mjs.map +1 -1
- package/dist/layout/index.d.mts +2 -2
- package/dist/layout/index.d.ts +2 -2
- package/dist/layout/index.js +17 -17
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/index.mjs +10 -10
- package/dist/layout/index.mjs.map +1 -1
- package/dist/llms/index.js +12 -12
- package/dist/llms/index.mjs +2 -2
- package/dist/manifest/index.js +4 -4
- package/dist/manifest/index.js.map +1 -1
- package/dist/manifest/index.mjs +3 -3
- package/dist/manifest/index.mjs.map +1 -1
- package/dist/middleware/index.js +3 -3
- package/dist/middleware/index.mjs +2 -2
- package/dist/{migrator-2MQHOFDQ.mjs → migrator-3WQB3KQ2.mjs} +3 -3
- package/dist/{migrator-2MQHOFDQ.mjs.map → migrator-3WQB3KQ2.mjs.map} +1 -1
- package/dist/migrator-HFVQYK5R.js +37 -0
- package/dist/{migrator-THJCF6MZ.js.map → migrator-HFVQYK5R.js.map} +1 -1
- package/dist/redirects/index.d.mts +2 -2
- package/dist/redirects/index.d.ts +2 -2
- package/dist/redirects/index.js +6 -6
- package/dist/redirects/index.mjs +2 -2
- package/dist/reputation/index.js +4 -4
- package/dist/reputation/index.mjs +1 -1
- package/dist/robots/index.d.mts +1 -1
- package/dist/robots/index.d.ts +1 -1
- package/dist/robots/index.js +3 -3
- package/dist/robots/index.js.map +1 -1
- package/dist/robots/index.mjs +2 -2
- package/dist/robots/index.mjs.map +1 -1
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.d.ts +1 -1
- package/dist/seo/index.js +43 -43
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +6 -6
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/register-sitemap-cli.js +18 -18
- package/dist/seo/register-sitemap-cli.js.map +1 -1
- package/dist/seo/register-sitemap-cli.mjs +18 -18
- package/dist/seo/register-sitemap-cli.mjs.map +1 -1
- package/dist/seo/server.d.mts +1 -1
- package/dist/seo/server.d.ts +1 -1
- package/dist/seo/server.js +10 -10
- package/dist/seo/server.js.map +1 -1
- package/dist/seo/server.mjs +8 -8
- package/dist/seo/server.mjs.map +1 -1
- package/dist/{server-api-GJPNRYUP.js → server-api-C5JXIROA.js} +21 -21
- package/dist/server-api-C5JXIROA.js.map +1 -0
- package/dist/{server-api-EWXKOQZA.mjs → server-api-HTSLBT6F.mjs} +3 -3
- package/dist/server-api-HTSLBT6F.mjs.map +1 -0
- package/dist/setup/client.js +7 -7
- package/dist/setup/client.mjs +2 -2
- package/dist/setup/index.js +9 -9
- package/dist/setup/index.mjs +3 -3
- package/dist/setup/server.js +2 -2
- package/dist/setup/server.mjs +1 -1
- package/dist/site-config/index.d.mts +1 -1
- package/dist/site-config/index.d.ts +1 -1
- package/dist/site-config/index.js +3 -3
- package/dist/site-config/index.mjs +1 -1
- package/dist/sitemap/index.d.mts +2 -2
- package/dist/sitemap/index.d.ts +2 -2
- package/dist/sitemap/index.js +10 -10
- package/dist/sitemap/index.js.map +1 -1
- package/dist/sitemap/index.mjs +8 -8
- package/dist/sitemap/index.mjs.map +1 -1
- package/dist/types-BG-x8yhh.d.mts +106 -0
- package/dist/types-BG-x8yhh.d.ts +106 -0
- package/package.json +13 -1
- package/dist/chunk-24277A3Q.mjs.map +0 -1
- package/dist/chunk-43GBM4SX.js.map +0 -1
- package/dist/chunk-622GAQP5.js.map +0 -1
- package/dist/chunk-6ZCISNAB.mjs.map +0 -1
- package/dist/chunk-72MQFHYJ.js.map +0 -1
- package/dist/chunk-7557OTHW.js.map +0 -1
- package/dist/chunk-7FUV73JZ.js.map +0 -1
- package/dist/chunk-7RF6PVHA.mjs.map +0 -1
- package/dist/chunk-7UKPRW25.mjs.map +0 -1
- package/dist/chunk-AFAO3TGS.mjs.map +0 -1
- package/dist/chunk-BYLIU6XG.js.map +0 -1
- package/dist/chunk-D63MUKZ6.mjs.map +0 -1
- package/dist/chunk-DDKW2FNA.js.map +0 -1
- package/dist/chunk-DQYMKR27.mjs.map +0 -1
- package/dist/chunk-DW5UJKHH.js.map +0 -1
- package/dist/chunk-GCJXQ4AG.mjs.map +0 -1
- package/dist/chunk-JTLOJLWQ.mjs.map +0 -1
- package/dist/chunk-K23A4G76.mjs.map +0 -1
- package/dist/chunk-KKU3K7RG.js.map +0 -1
- package/dist/chunk-KUGMH4ZF.js.map +0 -1
- package/dist/chunk-LBVWVP72.js.map +0 -1
- package/dist/chunk-M2T6R7BA.mjs.map +0 -1
- package/dist/chunk-OB7E654K.js.map +0 -1
- package/dist/chunk-OIIKTGRL.mjs.map +0 -1
- package/dist/chunk-P3UWIUJS.mjs.map +0 -1
- package/dist/chunk-QXV4667R.mjs.map +0 -1
- package/dist/chunk-TFLQX7K7.mjs.map +0 -1
- package/dist/chunk-UWE5PCYJ.mjs.map +0 -1
- package/dist/chunk-UYFDNX2F.js.map +0 -1
- package/dist/chunk-W4PALSGM.js.map +0 -1
- package/dist/chunk-WECQ6KOB.js.map +0 -1
- package/dist/chunk-XQQWI6WB.js.map +0 -1
- package/dist/generators-2XKQMPKH.mjs +0 -4
- package/dist/generators-DTMO36DV.js +0 -33
- package/dist/migrator-THJCF6MZ.js +0 -37
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/migrator/index.ts"],"names":["path","fs","match"],"mappings":"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","file":"chunk-JM3ZR6LB.js","sourcesContent":["/**\n * Code Migrator - Transforms existing forms to Site-Kit managed forms\n * \n * IMPORTANT: This migrator modifies files in-place using safe string operations.\n * It preserves existing code and only adds/modifies the minimum necessary.\n * \n * Key safety features:\n * - Always reads full file content before modifying\n * - Preserves 'use client' directives at top of file\n * - Adds imports after directives but before other imports\n * - Never overwrites entire file contents (except for form migration which is opt-in)\n */\n\nimport fs from 'fs/promises'\nimport path from 'path'\nimport { parse } from '@babel/parser'\nimport generate from '@babel/generator'\nimport traverse from '@babel/traverse'\nimport * as t from '@babel/types'\nimport type { ScanResults, DetectedForm, DetectedField } from '../scanner'\n\n// ============================================\n// Safe Import Insertion Helper\n// ============================================\n\n/**\n * Safely adds an import statement to a file, respecting 'use client'/'use server' directives\n * and avoiding duplicate imports.\n */\nfunction addImportSafely(content: string, importStatement: string): string {\n // Check if import already exists\n const importModule = importStatement.match(/from\\s+['\"]([^'\"]+)['\"]/)?.[1]\n if (importModule && content.includes(importModule)) {\n // Import from this module exists, might need to add to existing import\n return content\n }\n \n // Check for 'use client' or 'use server' directive at the start\n const directiveMatch = content.match(/^(['\"]use (client|server)['\"][\\s;]*\\n?)/)\n \n if (directiveMatch) {\n // Insert import AFTER the directive\n const directive = directiveMatch[0]\n const restOfFile = content.slice(directive.length)\n \n // Find first import or start of code\n const firstImportMatch = restOfFile.match(/^(import\\s+)/)\n if (firstImportMatch) {\n // Insert before first import but after directive\n return directive + importStatement + '\\n' + restOfFile\n } else {\n // No imports yet, add after directive with a newline\n return directive + importStatement + '\\n' + restOfFile\n }\n } else {\n // No directive, add import at the top\n // But check if there's already an import block at the top\n const firstImportMatch = content.match(/^(import\\s+)/)\n if (firstImportMatch) {\n return importStatement + '\\n' + content\n } else {\n return importStatement + '\\n\\n' + content\n }\n }\n}\n\n/**\n * Check if a file is a client component (has 'use client' directive at the top)\n */\nfunction isClientComponent(content: string): boolean {\n // Check first few lines for 'use client' directive\n const firstLines = content.split('\\n').slice(0, 5).join('\\n')\n return /['\"]use client['\"]/.test(firstLines)\n}\n\n/**\n * Adds a named export to an existing import statement from the same module\n */\nfunction addToExistingImport(content: string, namedExport: string, modulePath: string): string {\n // Pattern to find import from the module\n const importPattern = new RegExp(\n `(import\\\\s*\\\\{[^}]*)\\\\}\\\\s*from\\\\s*['\"]${modulePath.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}['\"]`,\n 'g'\n )\n \n if (importPattern.test(content)) {\n // Reset regex\n importPattern.lastIndex = 0\n return content.replace(importPattern, (match, imports) => {\n // Check if already imported\n if (imports.includes(namedExport)) {\n return match\n }\n // Add to imports\n return `${imports.trim()}, ${namedExport} } from '${modulePath}'`\n })\n }\n \n return content\n}\n\n/**\n * Insert ManagedSchema component into the JSX return statement of a page component.\n * Looks for the return statement and inserts ManagedSchema right after the opening tag/fragment.\n */\nfunction insertManagedSchemaIntoJSX(content: string, pagePath: string, isTypeScript: boolean): string {\n // Skip if ManagedSchema is already in the JSX (not just imported)\n if (content.includes('<ManagedSchema')) {\n return content\n }\n\n const projectIdSuffix = isTypeScript ? '!' : ''\n const schemaComponent = `<ManagedSchema\n projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${projectIdSuffix}}\n path=\"${pagePath}\"\n />`\n\n // Pattern to find: return ( followed by < or <>\n // This handles: return (<div>...) or return (<>...) or return (\\n <div>...)\n const returnPatterns = [\n // return (<> ... - fragment\n /return\\s*\\(\\s*<>/,\n // return ( <Fragment> ...\n /return\\s*\\(\\s*<Fragment>/,\n // return (<div ... or return (<main ... etc\n /return\\s*\\(\\s*<([a-zA-Z][a-zA-Z0-9]*)[^>]*>/,\n ]\n\n for (const pattern of returnPatterns) {\n const match = content.match(pattern)\n if (match && match.index !== undefined) {\n const insertPos = match.index + match[0].length\n // Insert ManagedSchema right after the opening tag\n content = content.slice(0, insertPos) + '\\n ' + schemaComponent + content.slice(insertPos)\n return content\n }\n }\n\n // Fallback: try to find any return statement with JSX\n const simpleReturnMatch = content.match(/return\\s*\\(/)\n if (simpleReturnMatch && simpleReturnMatch.index !== undefined) {\n // Find the first < after the return (\n const afterReturn = content.slice(simpleReturnMatch.index + simpleReturnMatch[0].length)\n const firstTagMatch = afterReturn.match(/^\\s*<([a-zA-Z>][^>]*)>?/)\n if (firstTagMatch) {\n const insertPos = simpleReturnMatch.index + simpleReturnMatch[0].length + firstTagMatch[0].length\n content = content.slice(0, insertPos) + '\\n ' + schemaComponent + content.slice(insertPos)\n return content\n }\n }\n\n return content\n}\n\n// ============================================\n// Types\n// ============================================\n\nexport interface MigrationResult {\n filePath: string\n success: boolean\n changes: string[]\n error?: string\n formId?: string\n}\n\nexport interface MigrationOptions {\n projectId: string\n apiKey: string\n dryRun?: boolean\n}\n\n// ============================================\n// Main Migrator\n// ============================================\n\nexport async function migrateFiles(\n scanResults: ScanResults,\n options: MigrationOptions\n): Promise<MigrationResult[]> {\n const results: MigrationResult[] = []\n\n // Migrate forms\n for (const form of scanResults.forms) {\n if (form.suggestedAction === 'manual') {\n results.push({\n filePath: form.filePath,\n success: false,\n changes: [],\n error: 'Form too complex for auto-migration',\n })\n continue\n }\n\n try {\n const result = await migrateForm(form, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: form.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Migrate widgets (simpler - just remove and add provider flag)\n for (const widget of scanResults.widgets) {\n try {\n const result = await migrateWidget(widget.filePath, widget, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: widget.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Migrate metadata\n for (const meta of scanResults.metadata || []) {\n try {\n const result = await migrateMetadata(meta.filePath, meta, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: meta.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Migrate schemas\n for (const schema of scanResults.schemas || []) {\n try {\n const result = await migrateSchema(schema.filePath, schema, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: schema.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Migrate FAQs\n for (const faq of scanResults.faqs || []) {\n try {\n const result = await migrateFAQ(faq.filePath, faq, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: faq.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Migrate sitemaps\n for (const sitemap of scanResults.sitemaps || []) {\n // Skip site-kit generated sitemaps\n if (sitemap.generator === 'site-kit') continue\n\n try {\n const result = await migrateSitemap(sitemap.filePath, sitemap, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: sitemap.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n // Report analytics (informational only)\n for (const analytics of scanResults.analytics || []) {\n try {\n const result = await migrateAnalytics(analytics.filePath, analytics, options)\n results.push(result)\n } catch (error: any) {\n results.push({\n filePath: analytics.filePath,\n success: false,\n changes: [],\n error: error.message,\n })\n }\n }\n\n return results\n}\n\n// ============================================\n// Form Migration\n// ============================================\n\n/**\n * Migrate a form to Site-Kit managed form\n * \n * SAFETY: Form migration is DESTRUCTIVE by design - it replaces the entire form component.\n * This is intentional because forms need to be completely restructured to use the useForm hook.\n * \n * However, we now:\n * 1. Create a backup of the original file (.backup)\n * 2. Only proceed if user explicitly confirms\n * 3. Log all changes for easy rollback\n */\nasync function migrateForm(\n form: DetectedForm,\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n const fullPath = path.resolve(process.cwd(), form.filePath)\n\n // Step 1: Create the form in Sonor\n const formSlug = generateSlug(form.componentName)\n \n // In dry run, don't create the form in API\n let formId: string | undefined\n if (!options.dryRun) {\n try {\n formId = await createFormInUptrade(form, formSlug, options)\n changes.push(`Created managed form: ${formSlug}`)\n } catch (error: any) {\n // Form might already exist\n changes.push(`Form may already exist: ${formSlug}`)\n }\n } else {\n changes.push(`[DRY RUN] Would create managed form: ${formSlug}`)\n }\n\n if (options.dryRun) {\n changes.push('[DRY RUN] Would create backup of original file')\n changes.push('[DRY RUN] Would replace form with Site-Kit managed form')\n return { filePath: form.filePath, success: true, changes, formId }\n }\n\n // Step 2: Read the original file and create backup\n const content = await fs.readFile(fullPath, 'utf-8')\n const backupPath = fullPath + '.backup'\n await fs.writeFile(backupPath, content, 'utf-8')\n changes.push(`Created backup: ${form.filePath}.backup`)\n \n // Step 3: Determine if file is TypeScript\n const isTypeScript = form.filePath.endsWith('.tsx') || form.filePath.endsWith('.ts')\n \n // Step 4: Generate new code (preserves TypeScript vs JavaScript)\n const newCode = generateMigratedFormCode(form, formSlug, isTypeScript)\n\n // Step 5: Write the file\n await fs.writeFile(fullPath, newCode, 'utf-8')\n changes.push('Replaced component with Site-Kit managed form')\n changes.push('Original saved to .backup file - delete when satisfied')\n\n return {\n filePath: form.filePath,\n success: true,\n changes,\n formId,\n }\n}\n\nfunction generateMigratedFormCode(form: DetectedForm, formSlug: string, isTypeScript: boolean = true): string {\n // Generate a clean, migrated component\n const componentName = form.componentName || 'MigratedForm'\n const classNameType = isTypeScript ? '{ className?: string }' : '{ className }'\n const ext = isTypeScript ? '.tsx' : '.jsx'\n\n return `/**\n * ${componentName}\n * \n * Migrated to @sonordev/site-kit\n * Managed form: ${formSlug}\n * \n * Original file backed up to: ${form.filePath}.backup\n */\n\n'use client'\n\nimport { useForm } from '@sonordev/site-kit/forms'\n\nexport function ${componentName}(${classNameType}) {\n const { \n form,\n fields, \n values, \n errors, \n setFieldValue, \n submit, \n isSubmitting,\n isComplete \n } = useForm('${formSlug}')\n\n if (isComplete) {\n return (\n <div className={className}>\n <p className=\"text-green-600\">{form?.successMessage || 'Thanks for your submission!'}</p>\n </div>\n )\n }\n\n return (\n <form \n onSubmit={(e) => { e.preventDefault(); submit() }} \n className={className}\n >\n {fields.map(field => (\n <div key={field.slug} className=\"mb-4\">\n <label className=\"block text-sm font-medium mb-1\">\n {field.label}\n {field.isRequired && <span className=\"text-red-500 ml-1\">*</span>}\n </label>\n \n {field.fieldType === 'textarea' ? (\n <textarea\n name={field.slug}\n placeholder={field.placeholder}\n value={String(values[field.slug] || '')}\n onChange={(e) => setFieldValue(field.slug, e.target.value)}\n className=\"w-full p-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n rows={4}\n />\n ) : field.fieldType === 'select' && field.options ? (\n <select\n name={field.slug}\n value={String(values[field.slug] || '')}\n onChange={(e) => setFieldValue(field.slug, e.target.value)}\n className=\"w-full p-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n >\n <option value=\"\">Select...</option>\n {field.options.map(opt => (\n <option key={opt.value} value={opt.value}>{opt.label}</option>\n ))}\n </select>\n ) : (\n <input\n type={field.fieldType}\n name={field.slug}\n placeholder={field.placeholder}\n value={String(values[field.slug] || '')}\n onChange={(e) => setFieldValue(field.slug, e.target.value)}\n className=\"w-full p-2 border rounded focus:ring-2 focus:ring-blue-500 focus:border-transparent\"\n />\n )}\n \n {errors[field.slug] && (\n <p className=\"mt-1 text-sm text-red-500\">{errors[field.slug]}</p>\n )}\n \n {field.helpText && (\n <p className=\"mt-1 text-xs text-gray-500\">{field.helpText}</p>\n )}\n </div>\n ))}\n \n <button \n type=\"submit\" \n disabled={isSubmitting}\n className=\"w-full py-2 px-4 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n {isSubmitting ? 'Submitting...' : (form?.submitButtonText || 'Submit')}\n </button>\n </form>\n )\n}\n\nexport default ${componentName}\n`\n}\n\nasync function createFormInUptrade(\n form: DetectedForm,\n slug: string,\n options: MigrationOptions\n): Promise<string> {\n // Call Portal API to create the form\n const response = await fetch('https://api.sonor.io/forms', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n body: JSON.stringify({\n projectId: options.projectId,\n slug,\n name: formatName(form.componentName),\n formType: detectFormType(form),\n successMessage: 'Thanks for your submission!',\n submitButtonText: 'Submit',\n fields: form.fields.map((f, i) => ({\n slug: f.name,\n label: formatLabel(f.name),\n fieldType: mapFieldType(f.type),\n placeholder: f.placeholder,\n isRequired: f.required,\n sortOrder: i,\n width: 'full',\n })),\n }),\n })\n\n if (!response.ok) {\n const error = await response.json()\n throw new Error(error.message || 'Failed to create form')\n }\n\n const data = await response.json()\n return data.id\n}\n\n// ============================================\n// Widget Migration\n// ============================================\n\nasync function migrateWidget(\n filePath: string,\n widget: any,\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n\n if (options.dryRun) {\n changes.push(`[DRY RUN] Would remove ${widget.widgetType} script`)\n changes.push('[DRY RUN] Would enable Engage in SiteKitProvider')\n return { filePath, success: true, changes }\n }\n\n const fullPath = path.resolve(process.cwd(), filePath)\n let content = await fs.readFile(fullPath, 'utf-8')\n\n // Remove the widget script based on type\n switch (widget.widgetType) {\n case 'intercom':\n content = content.replace(/<Script[^>]*intercom[^>]*\\/?>(?:<\\/Script>)?/gi, '{/* Intercom replaced with Sonor Engage */}')\n content = content.replace(/window\\.Intercom\\s*=\\s*[^;]+;/g, '')\n break\n case 'crisp':\n content = content.replace(/<Script[^>]*crisp[^>]*\\/?>(?:<\\/Script>)?/gi, '{/* Crisp replaced with Sonor Engage */}')\n break\n case 'drift':\n content = content.replace(/<Script[^>]*drift[^>]*\\/?>(?:<\\/Script>)?/gi, '{/* Drift replaced with Sonor Engage */}')\n break\n }\n\n await fs.writeFile(fullPath, content, 'utf-8')\n changes.push(`Removed ${widget.widgetType} script`)\n changes.push('Enable Engage in SiteKitProvider to add chat widget')\n\n return { filePath, success: true, changes }\n}\n\n// ============================================\n// Metadata Migration\n// ============================================\n\n/**\n * Match a balanced brace expression starting from a position\n * Returns the full matched content including braces, or null if no match\n */\nfunction matchBalancedBraces(content: string, startIndex: number): string | null {\n if (content[startIndex] !== '{') return null\n \n let depth = 0\n let i = startIndex\n \n while (i < content.length) {\n if (content[i] === '{') depth++\n else if (content[i] === '}') {\n depth--\n if (depth === 0) {\n return content.slice(startIndex, i + 1)\n }\n }\n i++\n }\n \n return null // Unbalanced braces\n}\n\n/**\n * Migrate Next.js metadata to getManagedMetadata\n * \n * SAFETY: This function:\n * - Reads full file content\n * - Skips client components (they can't have metadata exports)\n * - Only modifies the metadata export, preserving everything else\n * - Uses balanced brace matching to avoid cutting off content\n */\nexport async function migrateMetadata(\n filePath: string,\n metadata: { title?: string; description?: string; type: string },\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n const fullPath = path.resolve(process.cwd(), filePath)\n\n // Determine page path from file path\n let pagePath = filePath\n .replace(/^app\\//, '/')\n .replace(/^src\\/app\\//, '/')\n .replace(/\\/page\\.(tsx?|jsx?)$/, '')\n .replace(/\\/layout\\.(tsx?|jsx?)$/, '')\n .replace(/\\[([^\\]]+)\\]/g, ':$1')\n\n if (pagePath === '') pagePath = '/'\n\n let content = await fs.readFile(fullPath, 'utf-8')\n\n // Determine file extension for new files\n const isTypeScript = filePath.endsWith('.tsx') || filePath.endsWith('.ts')\n const ext = isTypeScript ? '.tsx' : '.jsx'\n\n // Handle client components - create a layout file instead\n if (isClientComponent(content)) {\n const dir = path.dirname(fullPath)\n const layoutPath = path.join(dir, `layout${ext}`)\n \n // Check if layout already exists\n try {\n await fs.access(layoutPath)\n // Layout exists, check if it already has getManagedMetadata\n const layoutContent = await fs.readFile(layoutPath, 'utf-8')\n if (layoutContent.includes('getManagedMetadata')) {\n changes.push('Layout already has managed metadata')\n return { filePath, success: true, changes }\n }\n changes.push('Layout exists but does not have managed metadata - add generateMetadata manually')\n return { filePath, success: true, changes }\n } catch {\n // Layout doesn't exist, we'll create it\n }\n\n if (options.dryRun) {\n changes.push(`[DRY RUN] Client component detected - would create layout${ext} with managed metadata`)\n changes.push(`[DRY RUN] Page path: ${pagePath}`)\n return { filePath, success: true, changes }\n }\n\n // Create page record in Portal API\n try {\n await createPageMetadata(pagePath, metadata, options)\n changes.push(`Created managed metadata for page: ${pagePath}`)\n } catch (error: any) {\n changes.push(`Page metadata may already exist: ${pagePath}`)\n }\n\n // Generate the layout name from the directory\n // Handle dynamic route segments like [slug] -> Slug, [...slug] -> Slug\n const dirName = path.basename(dir)\n .replace(/^\\[\\.\\.\\.([^\\]]+)\\]$/, '$1') // [...slug] -> slug\n .replace(/^\\[([^\\]]+)\\]$/, '$1') // [slug] -> slug\n const layoutName = dirName\n .split('-')\n .map(word => word.charAt(0).toUpperCase() + word.slice(1))\n .join('') + 'Layout'\n\n // Create layout file with managed metadata AND schema\n const layoutCode = `import { getManagedMetadata, ManagedSchema } from '@sonordev/site-kit/seo'\n\nexport async function generateMetadata() {\n return getManagedMetadata({\n projectId: process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${isTypeScript ? '!' : ''},\n path: '${pagePath}',\n fallback: {\n title: '${(metadata.title || 'Page Title').replace(/'/g, \"\\\\'\")}',\n description: '${(metadata.description || 'Page description').replace(/'/g, \"\\\\'\")}',\n },\n })\n}\n\nexport default function ${layoutName}({ children }${isTypeScript ? ': { children: React.ReactNode }' : ''}) {\n return (\n <>\n <ManagedSchema\n projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${isTypeScript ? '!' : ''}}\n path=\"${pagePath}\"\n />\n {children}\n </>\n )\n}\n`\n\n await fs.writeFile(layoutPath, layoutCode, 'utf-8')\n changes.push(`Created layout${ext} with managed metadata and schema (client component page)`)\n return { filePath, success: true, changes }\n }\n\n if (options.dryRun) {\n changes.push(`[DRY RUN] Would create managed metadata for page: ${pagePath}`)\n changes.push('[DRY RUN] Would add generateMetadata function (preserving rest of file)')\n return { filePath, success: true, changes }\n }\n\n // Create page record in Portal API\n try {\n await createPageMetadata(pagePath, metadata, options)\n changes.push(`Created managed metadata for page: ${pagePath}`)\n } catch (error: any) {\n // Page might already exist, that's ok\n changes.push(`Page metadata may already exist: ${pagePath}`)\n }\n\n // Handle pages with no metadata - add generateMetadata to the file\n if (metadata.type === 'no-metadata') {\n // Add import with ManagedSchema\n if (!content.includes(\"'@sonordev/site-kit/seo\") && !content.includes('\"@sonordev/site-kit/seo')) {\n content = addImportSafely(content, `import { getManagedMetadata, ManagedSchema } from '@sonordev/site-kit/seo'`)\n } else if (!content.includes('ManagedSchema')) {\n content = addToExistingImport(content, 'ManagedSchema', '@sonordev/site-kit/seo')\n }\n\n // Build the generateMetadata function\n const generateMetadataCode = `\nexport async function generateMetadata() {\n return getManagedMetadata({\n projectId: process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${isTypeScript ? '!' : ''},\n path: '${pagePath}',\n fallback: {\n title: '${(metadata.title || 'Page Title').replace(/'/g, \"\\\\'\")}',\n description: '${(metadata.description || 'Page description').replace(/'/g, \"\\\\'\")}',\n },\n })\n}\n`\n\n // Find a good place to add it - after imports, before the first export/function\n const importEndMatch = content.match(/^(import\\s+.*?['\"][^'\"]+['\"];?\\s*\\n)+/m)\n if (importEndMatch) {\n const insertPos = importEndMatch.index! + importEndMatch[0].length\n content = content.slice(0, insertPos) + generateMetadataCode + content.slice(insertPos)\n } else {\n // No imports, add at the beginning (after 'use client' if present)\n const useClientMatch = content.match(/^['\"]use client['\"];?\\s*\\n/)\n if (useClientMatch) {\n const insertPos = useClientMatch[0].length\n content = content.slice(0, insertPos) + generateMetadataCode + content.slice(insertPos)\n } else {\n content = generateMetadataCode + content\n }\n }\n\n // Insert ManagedSchema into the component's JSX\n content = insertManagedSchemaIntoJSX(content, pagePath, isTypeScript)\n changes.push('Added ManagedSchema component')\n\n await fs.writeFile(fullPath, content, 'utf-8')\n changes.push('Added generateMetadata function')\n return { filePath, success: true, changes }\n }\n\n // Replace static metadata export with getManagedMetadata\n if (metadata.type === 'next-metadata') {\n // Handle: export const metadata = { ... }\n // Use a safer approach: find the export start, then match balanced braces\n const metadataExportMatch = content.match(/export const metadata(?::\\s*Metadata)?\\s*=\\s*/)\n \n if (metadataExportMatch && metadataExportMatch.index !== undefined) {\n const braceStart = metadataExportMatch.index + metadataExportMatch[0].length\n const braceContent = matchBalancedBraces(content, braceStart)\n \n if (braceContent) {\n const fullMatch = metadataExportMatch[0] + braceContent\n \n // Add import safely with ManagedSchema\n if (!content.includes(\"'@sonordev/site-kit/seo\") && !content.includes('\"@sonordev/site-kit/seo')) {\n content = addImportSafely(content, `import { getManagedMetadata, ManagedSchema } from '@sonordev/site-kit/seo'`)\n } else if (!content.includes('ManagedSchema')) {\n content = addToExistingImport(content, 'ManagedSchema', '@sonordev/site-kit/seo')\n }\n\n // Build the replacement generateMetadata function\n const generateMetadataCode = `export async function generateMetadata() {\n return getManagedMetadata({\n projectId: process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${isTypeScript ? '!' : ''},\n path: '${pagePath}',\n fallback: {\n title: '${(metadata.title || 'Page Title').replace(/'/g, \"\\\\'\")}',\n description: '${(metadata.description || 'Page description').replace(/'/g, \"\\\\'\")}',\n },\n })\n}`\n\n // Replace only the metadata export\n content = content.replace(fullMatch, generateMetadataCode)\n changes.push('Replaced static metadata with getManagedMetadata')\n \n // Insert ManagedSchema into the component's JSX\n content = insertManagedSchemaIntoJSX(content, pagePath, isTypeScript)\n changes.push('Added ManagedSchema component')\n }\n }\n\n // Handle existing generateMetadata - just add a comment, don't modify\n if (content.includes('generateMetadata') && !content.includes('getManagedMetadata')) {\n changes.push('generateMetadata function detected - add getManagedMetadata manually for full control')\n }\n }\n\n await fs.writeFile(fullPath, content, 'utf-8')\n return { filePath, success: true, changes }\n}\n\nasync function createPageMetadata(\n pagePath: string,\n metadata: { title?: string; description?: string },\n options: MigrationOptions\n): Promise<void> {\n const response = await fetch('https://api.sonor.io/seo/pages', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n body: JSON.stringify({\n project_id: options.projectId,\n path: pagePath,\n managed_title: metadata.title,\n managed_meta_description: metadata.description,\n }),\n })\n\n if (!response.ok && response.status !== 409) {\n throw new Error(`Failed to create page: ${response.statusText}`)\n }\n}\n\n// ============================================\n// Schema Migration \n// ============================================\n\n/**\n * Extract JSON-LD schema content from a script tag\n */\nfunction extractSchemaJSON(content: string): { schemaType: string; schemaJson: object } | null {\n // Pattern to match script tag with JSON-LD content\n const scriptPatterns = [\n /<script\\s+type=[\"']application\\/ld\\+json[\"'][^>]*>([\\s\\S]*?)<\\/script>/i,\n /<Script\\s+[^>]*type=[\"']application\\/ld\\+json[\"'][^>]*>([\\s\\S]*?)<\\/Script>/i,\n ]\n \n for (const pattern of scriptPatterns) {\n const match = content.match(pattern)\n if (match && match[1]) {\n try {\n // Try to parse the JSON content\n let jsonStr = match[1].trim()\n \n // Handle JSX expression containers: {`...`} or {\"...\"}\n if (jsonStr.startsWith('{') && (jsonStr.includes('`') || jsonStr.includes('\"'))) {\n // Extract content between template literals or JSON.stringify\n const templateMatch = jsonStr.match(/\\{[`\"]([\\s\\S]*?)[`\"]\\}/)\n if (templateMatch) {\n jsonStr = templateMatch[1]\n }\n }\n \n // Handle dangerouslySetInnerHTML pattern\n const innerHTMLMatch = jsonStr.match(/dangerouslySetInnerHTML=\\{\\{\\s*__html:\\s*['\"`]([\\s\\S]*?)['\"`]\\s*\\}\\}/)\n if (innerHTMLMatch) {\n jsonStr = innerHTMLMatch[1]\n }\n \n // Try to parse as JSON\n const parsed = JSON.parse(jsonStr)\n return {\n schemaType: parsed['@type'] || 'Unknown',\n schemaJson: parsed,\n }\n } catch {\n // JSON parsing failed, schema might be dynamic\n return null\n }\n }\n }\n \n // Also try to find schema objects in code\n const schemaObjectMatch = content.match(/const\\s+\\w*[sS]chema\\w*\\s*=\\s*(\\{[\\s\\S]*?@context[\\s\\S]*?\\})\\s*;?/)\n if (schemaObjectMatch) {\n try {\n // This is tricky - the object might use JS syntax not JSON\n // For now, just extract the @type if we can\n const typeMatch = schemaObjectMatch[1].match(/@type[\"']?\\s*:\\s*[\"']([^\"']+)[\"']/)\n if (typeMatch) {\n return {\n schemaType: typeMatch[1],\n schemaJson: { '@type': typeMatch[1], '_note': 'Schema extracted from JS object - review in Portal' },\n }\n }\n } catch {\n return null\n }\n }\n \n return null\n}\n\n/**\n * Create schema record in Portal API\n */\nasync function createSchemaRecord(\n pagePath: string,\n schemaType: string,\n schemaJson: object,\n options: MigrationOptions\n): Promise<void> {\n const apiUrl = process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.sonor.io'\n \n const response = await fetch(`${apiUrl}/api/public/seo/register-schema`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': options.apiKey,\n },\n body: JSON.stringify({\n page_path: pagePath,\n schema_type: schemaType,\n schema_json: schemaJson,\n is_implemented: true,\n }),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Failed to create schema: ${response.status} ${errorText}`)\n }\n}\n\n/**\n * Migrate JSON-LD schema to ManagedSchema component\n * \n * This function:\n * 1. Extracts existing JSON-LD schema content\n * 2. Creates a managed schema record in the Portal database\n * 3. Replaces the script tag with ManagedSchema component\n * \n * SAFETY: Skips client components since ManagedSchema requires server rendering\n */\nexport async function migrateSchema(\n filePath: string,\n schema: { schemaType?: string; startLine: number; endLine: number },\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n const fullPath = path.resolve(process.cwd(), filePath)\n\n // Determine page path from file path\n let pagePath = filePath\n .replace(/^app\\//, '/')\n .replace(/^src\\/app\\//, '/')\n .replace(/\\/page\\.(tsx?|jsx?)$/, '')\n .replace(/\\[([^\\]]+)\\]/g, ':$1')\n\n if (pagePath === '') pagePath = '/'\n\n let content = await fs.readFile(fullPath, 'utf-8')\n\n // Skip client components - ManagedSchema requires server rendering\n if (isClientComponent(content)) {\n changes.push('Skipped: Client component cannot use ManagedSchema (requires server rendering)')\n changes.push('Consider moving schema to a parent server component or layout.tsx')\n return { filePath, success: true, changes }\n }\n\n // Extract existing schema content\n const extractedSchema = extractSchemaJSON(content)\n\n if (options.dryRun) {\n changes.push(`[DRY RUN] Would replace JSON-LD script with ManagedSchema component`)\n changes.push(`[DRY RUN] Schema type: ${extractedSchema?.schemaType || schema.schemaType || 'Unknown'}`)\n if (extractedSchema) {\n changes.push(`[DRY RUN] Would upload extracted schema to Portal`)\n }\n return { filePath, success: true, changes }\n }\n\n // Create schema record in Portal API with extracted content\n if (extractedSchema) {\n try {\n await createSchemaRecord(pagePath, extractedSchema.schemaType, extractedSchema.schemaJson, options)\n changes.push(`Created managed schema (${extractedSchema.schemaType}) for: ${pagePath}`)\n } catch (error: any) {\n changes.push(`Schema record may already exist for: ${pagePath}`)\n }\n }\n\n // Check if ManagedSchema is already in the JSX (may have been added by metadata migration)\n const alreadyHasManagedSchema = content.includes('<ManagedSchema')\n\n // Determine if file is TypeScript\n const isTypeScript = filePath.endsWith('.tsx') || filePath.endsWith('.ts')\n const projectIdSuffix = isTypeScript ? '!' : ''\n\n // Find JSON-LD scripts\n const jsonLdPattern = /<script\\s+type=[\"']application\\/ld\\+json[\"'][^>]*>[\\s\\S]*?<\\/script>/gi\n const scriptPattern = /<Script\\s+[^>]*type=[\"']application\\/ld\\+json[\"'][^>]*>[\\s\\S]*?<\\/Script>/gi\n\n const hasJsonLd = jsonLdPattern.test(content) || scriptPattern.test(content)\n \n if (hasJsonLd) {\n // Reset regex after test\n jsonLdPattern.lastIndex = 0\n scriptPattern.lastIndex = 0\n \n if (alreadyHasManagedSchema) {\n // ManagedSchema already exists (from metadata migration) - just remove the script tags\n content = content.replace(jsonLdPattern, '{/* JSON-LD migrated to ManagedSchema */}')\n content = content.replace(scriptPattern, '{/* JSON-LD migrated to ManagedSchema */}')\n changes.push('Removed JSON-LD script (ManagedSchema already present)')\n } else {\n // Add import for ManagedSchema safely\n if (!content.includes('ManagedSchema')) {\n if (content.includes(\"'@sonordev/site-kit/seo\") || content.includes('\"@sonordev/site-kit/seo')) {\n content = addToExistingImport(content, 'ManagedSchema', '@sonordev/site-kit/seo')\n } else {\n content = addImportSafely(content, `import { ManagedSchema } from '@sonordev/site-kit/seo'`)\n }\n changes.push('Added ManagedSchema import')\n }\n \n // Replace existing schema script with ManagedSchema component\n content = content.replace(jsonLdPattern, `<ManagedSchema \n projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${projectIdSuffix}}\n path=\"${pagePath}\"\n />`)\n content = content.replace(scriptPattern, `<ManagedSchema \n projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${projectIdSuffix}}\n path=\"${pagePath}\"\n />`)\n changes.push('Replaced JSON-LD script with ManagedSchema component')\n }\n }\n\n await fs.writeFile(fullPath, content, 'utf-8')\n return { filePath, success: true, changes }\n}\n\n// ============================================\n// FAQ Migration\n// ============================================\n\n/**\n * Extract FAQ items from various FAQ patterns in the code\n */\nfunction extractFAQItems(content: string, faqType: string): Array<{ question: string; answer: string }> {\n const items: Array<{ question: string; answer: string }> = []\n \n // Pattern for details/summary elements\n if (faqType === 'details-summary') {\n const detailsPattern = /<details[^>]*>[\\s\\S]*?<summary[^>]*>([\\s\\S]*?)<\\/summary>([\\s\\S]*?)<\\/details>/gi\n let match\n while ((match = detailsPattern.exec(content)) !== null) {\n const question = match[1].replace(/<[^>]+>/g, '').trim()\n const answer = match[2].replace(/<[^>]+>/g, '').trim()\n if (question && answer) {\n items.push({ question, answer })\n }\n }\n }\n \n // Pattern for accordion components with question/answer props\n const accordionItemPattern = /<(?:Accordion\\.Item|AccordionItem|FAQItem)[^>]*(?:question|title)=[\"'`]([^\"'`]+)[\"'`][^>]*>[\\s\\S]*?(?:answer|content)=[\"'`]([^\"'`]+)[\"'`]/gi\n let match\n while ((match = accordionItemPattern.exec(content)) !== null) {\n items.push({ question: match[1], answer: match[2] })\n }\n \n // Pattern for FAQ arrays/objects in code: { question: \"...\", answer: \"...\" }\n const faqArrayPattern = /\\{\\s*question:\\s*[\"'`]([^\"'`]+)[\"'`]\\s*,\\s*answer:\\s*[\"'`]([^\"'`]+)[\"'`]\\s*\\}/gi\n while ((match = faqArrayPattern.exec(content)) !== null) {\n items.push({ question: match[1], answer: match[2] })\n }\n \n // Alternative pattern: { q: \"...\", a: \"...\" }\n const shortFaqPattern = /\\{\\s*q:\\s*[\"'`]([^\"'`]+)[\"'`]\\s*,\\s*a:\\s*[\"'`]([^\"'`]+)[\"'`]\\s*\\}/gi\n while ((match = shortFaqPattern.exec(content)) !== null) {\n items.push({ question: match[1], answer: match[2] })\n }\n \n return items\n}\n\n/**\n * Create FAQ record in Portal API\n */\nasync function createFAQRecord(\n pagePath: string,\n items: Array<{ question: string; answer: string }>,\n options: MigrationOptions\n): Promise<void> {\n const apiUrl = process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.sonor.io'\n \n const response = await fetch(`${apiUrl}/api/public/seo/register-faq`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': options.apiKey,\n },\n body: JSON.stringify({\n path: pagePath,\n title: 'Frequently Asked Questions',\n items: items.map((item, index) => ({\n id: `faq-${index + 1}`,\n question: item.question,\n answer: item.answer,\n order: index,\n is_visible: true,\n })),\n include_schema: true,\n is_published: items.length > 0,\n }),\n })\n\n if (!response.ok) {\n const errorText = await response.text()\n throw new Error(`Failed to create FAQ: ${response.status} ${errorText}`)\n }\n}\n\n/**\n * Migrate FAQ section to ManagedFAQ component\n * \n * This function:\n * 1. Extracts FAQ content (questions/answers) from existing components\n * 2. Creates a managed FAQ record in the Portal database\n * 3. Inserts the ManagedFAQ component into the page\n * \n * SAFETY: Skips client components since ManagedFAQ requires server rendering\n */\nexport async function migrateFAQ(\n filePath: string,\n faq: { type: string; componentName?: string; hasSchema: boolean; startLine: number; endLine: number },\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n const fullPath = path.resolve(process.cwd(), filePath)\n\n // Determine page path from file path\n let pagePath = filePath\n .replace(/^app\\//, '/')\n .replace(/^src\\/app\\//, '/')\n .replace(/\\/page\\.(tsx?|jsx?)$/, '')\n .replace(/\\[([^\\]]+)\\]/g, ':$1')\n\n if (pagePath === '') pagePath = '/'\n\n let content = await fs.readFile(fullPath, 'utf-8')\n\n // Skip client components - ManagedFAQ requires server rendering\n if (isClientComponent(content)) {\n changes.push('Skipped: Client component cannot use ManagedFAQ (requires server rendering)')\n changes.push('Consider using ManagedFAQ in a parent server component or layout.tsx')\n return { filePath, success: true, changes }\n }\n\n // Extract FAQ items from the existing code\n const extractedItems = extractFAQItems(content, faq.type)\n \n if (options.dryRun) {\n changes.push(`[DRY RUN] Would extract ${extractedItems.length} FAQ items`)\n changes.push(`[DRY RUN] Would create managed FAQ record for path: ${pagePath}`)\n changes.push(`[DRY RUN] Would insert ManagedFAQ component`)\n changes.push(`[DRY RUN] FAQ type: ${faq.type}${faq.componentName ? ` (${faq.componentName})` : ''}`)\n return { filePath, success: true, changes }\n }\n\n // Create FAQ record in Portal API\n if (extractedItems.length > 0) {\n try {\n await createFAQRecord(pagePath, extractedItems, options)\n changes.push(`Created managed FAQ with ${extractedItems.length} items for: ${pagePath}`)\n } catch (error: any) {\n changes.push(`FAQ record may already exist for: ${pagePath}`)\n }\n } else {\n // Create empty FAQ record for manual population\n try {\n await createFAQRecord(pagePath, [], options)\n changes.push(`Created empty managed FAQ for: ${pagePath} (add items in Portal)`)\n } catch {\n changes.push(`FAQ record may already exist for: ${pagePath}`)\n }\n }\n\n // Add import for ManagedFAQ safely\n if (!content.includes('ManagedFAQ')) {\n if (content.includes(\"'@sonordev/site-kit/seo\") || content.includes('\"@sonordev/site-kit/seo')) {\n content = addToExistingImport(content, 'ManagedFAQ', '@sonordev/site-kit/seo')\n } else {\n content = addImportSafely(content, `import { ManagedFAQ } from '@sonordev/site-kit/seo'`)\n }\n changes.push('Added ManagedFAQ import')\n }\n\n // Determine if file is TypeScript for proper syntax\n const isTypeScript = filePath.endsWith('.tsx') || filePath.endsWith('.ts')\n const projectIdSuffix = isTypeScript ? '!' : ''\n\n const managedFAQComponent = `<ManagedFAQ\n projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID${projectIdSuffix}}\n path=\"${pagePath}\"\n />`\n\n // Try to insert ManagedFAQ component near the existing FAQ\n // Look for the FAQ component/section and insert before it\n if (faq.componentName) {\n // Look for the component tag and insert before it\n const componentPattern = new RegExp(`(<${faq.componentName}[^>]*>)`, 'i')\n if (componentPattern.test(content)) {\n content = content.replace(componentPattern, `{/* Managed FAQ - content controlled via Portal */}\\n ${managedFAQComponent}\\n {/* Original FAQ component (can be removed once migrated) */}\\n $1`)\n changes.push('Inserted ManagedFAQ component before existing FAQ')\n }\n } else if (faq.type === 'details-summary') {\n // For details/summary, look for the first <details> tag\n const detailsMatch = content.match(/<details[^>]*>/)\n if (detailsMatch && detailsMatch.index !== undefined) {\n content = content.slice(0, detailsMatch.index) + \n `{/* Managed FAQ - content controlled via Portal */}\\n ${managedFAQComponent}\\n {/* Original FAQ (can be removed once migrated) */}\\n ` + \n content.slice(detailsMatch.index)\n changes.push('Inserted ManagedFAQ component before details/summary FAQ')\n }\n }\n\n // If we couldn't insert near the FAQ, add a comment with instructions\n if (!changes.some(c => c.includes('Inserted ManagedFAQ'))) {\n changes.push(`Add ManagedFAQ to your page JSX: ${managedFAQComponent}`)\n }\n\n await fs.writeFile(fullPath, content, 'utf-8')\n return { filePath, success: true, changes }\n}\n\n// ============================================\n// Sitemap Migration\n// ============================================\n\n/**\n * Migrate sitemap configuration to Site-Kit managed sitemap\n */\nexport async function migrateSitemap(\n filePath: string,\n sitemap: { type: string; generator?: string },\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n const fullPath = path.resolve(process.cwd(), filePath)\n\n if (options.dryRun) {\n changes.push(`[DRY RUN] Would migrate ${sitemap.type} to Site-Kit sitemap`)\n if (sitemap.type === 'next-sitemap-config') {\n changes.push('[DRY RUN] Would update next-sitemap.config.js to use Site-Kit URLs')\n }\n return { filePath, success: true, changes }\n }\n\n // For next-sitemap configs, we can update the siteUrl and add additionalSitemaps\n if (sitemap.type === 'next-sitemap-config') {\n let content = await fs.readFile(fullPath, 'utf-8')\n\n // Add comment about Site-Kit integration\n if (!content.includes('Site-Kit')) {\n content = `/**\n * Site-Kit Integration\n * \n * Pages are automatically synced to Portal SEO module.\n * Manage URLs, priorities, and change frequencies in the Portal.\n */\n` + content\n }\n\n await fs.writeFile(fullPath, content, 'utf-8')\n changes.push('Added Site-Kit integration comment to sitemap config')\n changes.push('Configure sitemap settings in Portal SEO module for centralized management')\n }\n\n // For custom app/sitemap.ts files\n if (sitemap.type === 'custom-sitemap' && filePath.includes('sitemap')) {\n changes.push('Custom sitemap detected - consider using Site-Kit\\'s createSitemap helper')\n changes.push('Import: import { createSitemap } from \\'@sonordev/site-kit/seo\\'')\n }\n\n return { filePath, success: true, changes }\n}\n\n// ============================================\n// Analytics Migration\n// ============================================\n\n/**\n * Migrate analytics scripts (mostly informational - we don't remove existing analytics)\n */\nexport async function migrateAnalytics(\n filePath: string,\n analytics: { type: string; trackingId?: string },\n options: MigrationOptions\n): Promise<MigrationResult> {\n const changes: string[] = []\n\n // Analytics migration is mainly informational\n // We don't want to break existing tracking, but we note that SiteKitProvider can handle analytics\n if (options.dryRun) {\n changes.push(`[DRY RUN] Detected ${analytics.type}${analytics.trackingId ? ` (${analytics.trackingId})` : ''}`)\n changes.push('[DRY RUN] Would recommend moving to SiteKitProvider analytics')\n return { filePath, success: true, changes }\n }\n\n changes.push(`Detected ${analytics.type}${analytics.trackingId ? ` (${analytics.trackingId})` : ''}`)\n changes.push('SiteKitProvider supports analytics integration')\n changes.push('Configure analytics in project settings to consolidate tracking')\n \n // Don't actually modify the file - just report what was found\n return { filePath, success: true, changes }\n}\n\n// ============================================\n// Single File Migration\n// ============================================\n\n/**\n * Migrate a single file to Site-Kit\n */\nexport async function migrateFile(\n filePath: string,\n options: MigrationOptions\n): Promise<MigrationResult> {\n const fullPath = path.resolve(filePath)\n const relPath = path.relative(process.cwd(), fullPath)\n\n // Read and parse the file\n const content = await fs.readFile(fullPath, 'utf-8')\n \n // Simple detection: check if it looks like a form\n const hasFormTag = content.includes('<form') || content.includes('onSubmit')\n const hasWidget = /intercom|crisp|drift|hubspot|zendesk/i.test(content)\n\n if (!hasFormTag && !hasWidget) {\n return {\n filePath: relPath,\n success: false,\n changes: [],\n error: 'No migratable components found in file',\n }\n }\n\n // For widgets, do a simple replacement\n if (hasWidget) {\n const widgetType = content.toLowerCase().includes('intercom') ? 'intercom' as const :\n content.toLowerCase().includes('crisp') ? 'crisp' as const :\n content.toLowerCase().includes('drift') ? 'drift' as const :\n content.toLowerCase().includes('hubspot') ? 'hubspot' as const :\n content.toLowerCase().includes('zendesk') ? 'zendesk' as const :\n 'other' as const\n\n return migrateWidget(relPath, {\n filePath: relPath,\n widgetType,\n startLine: 0,\n endLine: 0,\n }, options)\n }\n\n // For forms, we need to scan first\n const { parse } = await import('@babel/parser')\n const ast = parse(content, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n })\n\n // Find form component name\n let componentName = 'Form'\n const traverse = (await import('@babel/traverse')).default\n traverse(ast, {\n ExportNamedDeclaration(path) {\n const decl = path.node.declaration\n if (decl && decl.type === 'FunctionDeclaration' && decl.id) {\n componentName = decl.id.name\n path.stop()\n }\n },\n ExportDefaultDeclaration(path) {\n const decl = path.node.declaration\n if (decl && decl.type === 'FunctionDeclaration' && decl.id) {\n componentName = decl.id.name\n path.stop()\n }\n },\n })\n\n const form: DetectedForm = {\n filePath: relPath,\n componentName,\n fields: [],\n hasValidation: false,\n formLibrary: 'native',\n submitsTo: null,\n complexity: 'simple',\n suggestedAction: 'auto-migrate',\n startLine: 0,\n endLine: 0,\n }\n\n return migrateForm(form, options)\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nfunction generateSlug(name: string): string {\n return name\n .replace(/([A-Z])/g, '-$1')\n .toLowerCase()\n .replace(/^-/, '')\n .replace(/form$/i, '')\n .replace(/-+/g, '-')\n .replace(/-$/, '') || 'form'\n}\n\nfunction formatName(name: string): string {\n return name\n .replace(/([A-Z])/g, ' $1')\n .replace(/^./, str => str.toUpperCase())\n .trim()\n}\n\nfunction formatLabel(name: string): string {\n return name\n .replace(/([A-Z])/g, ' $1')\n .replace(/_/g, ' ')\n .replace(/^./, str => str.toUpperCase())\n .trim()\n}\n\nfunction mapFieldType(type: string): string {\n const mapping: Record<string, string> = {\n 'text': 'text',\n 'email': 'email',\n 'tel': 'phone',\n 'phone': 'phone',\n 'number': 'number',\n 'textarea': 'textarea',\n 'select': 'select',\n 'checkbox': 'checkbox',\n 'radio': 'radio',\n 'date': 'date',\n 'file': 'file',\n 'url': 'url',\n 'password': 'text', // Don't use password for managed forms\n }\n return mapping[type] || 'text'\n}\n\nfunction detectFormType(form: DetectedForm): string {\n const name = form.componentName.toLowerCase()\n const fields = form.fields.map(f => f.name.toLowerCase()).join(' ')\n\n if (name.includes('contact') || fields.includes('message')) return 'contact'\n if (name.includes('newsletter') || name.includes('subscribe')) return 'newsletter'\n if (name.includes('quote') || name.includes('estimate')) return 'prospect'\n if (name.includes('support') || name.includes('help')) return 'support'\n if (name.includes('feedback')) return 'feedback'\n\n return 'contact'\n}\n"]}
|
|
@@ -4,14 +4,14 @@ import { join } from 'path';
|
|
|
4
4
|
|
|
5
5
|
// src/llms/api.ts
|
|
6
6
|
function getApiConfig() {
|
|
7
|
-
const apiUrl = typeof window !== "undefined" && window.__SITE_KIT_API_URL__ || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
8
|
-
const apiKey = typeof window !== "undefined" && window.__SITE_KIT_API_KEY__ || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
7
|
+
const apiUrl = typeof window !== "undefined" && window.__SITE_KIT_API_URL__ || process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io";
|
|
8
|
+
const apiKey = typeof window !== "undefined" && window.__SITE_KIT_API_KEY__ || process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
9
9
|
return { apiUrl, apiKey };
|
|
10
10
|
}
|
|
11
11
|
async function apiGet(endpoint) {
|
|
12
12
|
const { apiUrl, apiKey } = getApiConfig();
|
|
13
13
|
if (!apiKey) {
|
|
14
|
-
console.error("@sonordev/llms: No API key configured. Set
|
|
14
|
+
console.error("@sonordev/llms: No API key configured. Set SONOR_API_KEY.");
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
17
|
try {
|
|
@@ -56,8 +56,8 @@ var getPageSummaries = cache(async (projectId, limit) => {
|
|
|
56
56
|
return result?.pages || [];
|
|
57
57
|
});
|
|
58
58
|
async function getOptimizedLLMsTxt(options) {
|
|
59
|
-
const apiUrl = options?.apiUrl || typeof process !== "undefined" && process.env?.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
60
|
-
const apiKey = options?.apiKey || typeof process !== "undefined" && (process.env?.UPTRADE_API_KEY || process.env?.NEXT_PUBLIC_UPTRADE_API_KEY) || "";
|
|
59
|
+
const apiUrl = options?.apiUrl || typeof process !== "undefined" && (process.env?.SONOR_API_URL || process.env?.UPTRADE_API_URL || process.env?.NEXT_PUBLIC_UPTRADE_API_URL) || "https://api.sonor.io";
|
|
60
|
+
const apiKey = options?.apiKey || typeof process !== "undefined" && (process.env?.SONOR_API_KEY || process.env?.UPTRADE_API_KEY || process.env?.NEXT_PUBLIC_UPTRADE_API_KEY) || "";
|
|
61
61
|
if (!apiKey) {
|
|
62
62
|
console.error("@sonordev/llms: No API key configured for getOptimizedLLMsTxt");
|
|
63
63
|
return null;
|
|
@@ -163,7 +163,7 @@ async function generateLLMsTxt(options) {
|
|
|
163
163
|
}
|
|
164
164
|
if (includeEntities) {
|
|
165
165
|
try {
|
|
166
|
-
const { getEntities, getPrimaryEntity } = await import('./server-api-
|
|
166
|
+
const { getEntities, getPrimaryEntity } = await import('./server-api-HTSLBT6F.mjs');
|
|
167
167
|
const [entities, primaryEntity] = await Promise.all([
|
|
168
168
|
getEntities().then((e) => e.slice(0, maxEntities)),
|
|
169
169
|
getPrimaryEntity()
|
|
@@ -376,5 +376,5 @@ async function writeLLMsTxtToPublic(options = {}) {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
export { generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, writeLLMsTxtToPublic };
|
|
379
|
-
//# sourceMappingURL=chunk-
|
|
380
|
-
//# sourceMappingURL=chunk-
|
|
379
|
+
//# sourceMappingURL=chunk-JMNSED4O.mjs.map
|
|
380
|
+
//# sourceMappingURL=chunk-JMNSED4O.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/llms/api.ts","../src/llms/generateLLMsTxt.ts","../src/llms/writeLLMsTxt.ts"],"names":[],"mappings":";;;;;AAcA,SAAS,YAAA,GAAe;AAEtB,EAAA,MAAM,MAAA,GAAU,OAAO,MAAA,KAAW,WAAA,IAAgB,OAAe,oBAAA,IAC5D,OAAA,CAAQ,GAAA,CAAI,aAAA,IACZ,OAAA,CAAQ,GAAA,CAAI,eAAA,IACZ,OAAA,CAAQ,IAAI,2BAAA,IACZ,sBAAA;AAEL,EAAA,MAAM,MAAA,GAAU,OAAO,MAAA,KAAW,WAAA,IAAgB,OAAe,oBAAA,IAC5D,OAAA,CAAQ,GAAA,CAAI,aAAA,IACZ,OAAA,CAAQ,GAAA,CAAI,eAAA,IACZ,OAAA,CAAQ,IAAI,2BAAA,IACZ,EAAA;AAEL,EAAA,OAAO,EAAE,QAAQ,MAAA,EAAO;AAC1B;AAEA,eAAe,OAAU,QAAA,EAAqC;AAC5D,EAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,YAAA,EAAa;AAExC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,MAAM,2DAA2D,CAAA;AACzE,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,MAAM,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI;AAAA,MACnD,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,WAAA,EAAa;AAAA,OACf;AAAA,MACA,IAAA,EAAM,EAAE,UAAA,EAAY,IAAA;AAAK;AAAA,KACX,CAAA;AAEhB,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,2BAAA,EAA8B,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AACjE,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,kCAAkC,KAAK,CAAA;AACrD,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAYO,IAAM,WAAA,GAAc,KAAA,CAAM,OAC/B,SAAA,KACqC;AACrC,EAAA,OAAO,OAAyB,CAAA,qBAAA,CAAuB,CAAA;AACzD,CAAC;AAKM,IAAM,eAAA,GAAkB,KAAA,CAAM,OACnC,SAAA,KACoC;AACpC,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAsC,CAAA,yBAAA,CAA2B,CAAA;AACtF,EAAA,OAAO,QAAQ,QAAA,IAAY,IAAA;AAC7B,CAAC;AAKM,IAAM,WAAA,GAAc,KAAA,CAAM,OAC/B,SAAA,KAC0B;AAC1B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAmC,CAAA,yBAAA,CAA2B,CAAA;AACnF,EAAA,OAAO,MAAA,EAAQ,YAAY,EAAC;AAC9B,CAAC;AAKM,IAAM,WAAA,GAAc,KAAA,CAAM,OAC/B,SAAA,EACA,KAAA,KAC0B;AAC1B,EAAA,MAAM,QAAA,GAAW,KAAA,GACb,CAAA,2BAAA,EAA8B,KAAK,CAAA,CAAA,GACnC,sBAAA;AACJ,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAA8B,QAAQ,CAAA;AAC3D,EAAA,OAAO,MAAA,EAAQ,OAAO,EAAC;AACzB,CAAC;AAKM,IAAM,gBAAA,GAAmB,KAAA,CAAM,OACpC,SAAA,EACA,KAAA,KAC8B;AAC9B,EAAA,MAAM,QAAA,GAAW,KAAA,GACb,CAAA,6BAAA,EAAgC,KAAK,CAAA,CAAA,GACrC,wBAAA;AACJ,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAoC,QAAQ,CAAA;AACjE,EAAA,OAAO,MAAA,EAAQ,SAAS,EAAC;AAC3B,CAAC;AAMD,eAAsB,oBAAoB,OAAA,EAIf;AACzB,EAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAClB,OAAO,YAAY,WAAA,KAAgB,OAAA,CAAQ,GAAA,EAAK,aAAA,IAAiB,OAAA,CAAQ,GAAA,EAAK,eAAA,IAAmB,OAAA,CAAQ,KAAK,2BAAA,CAAA,IAC/G,sBAAA;AACL,EAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAClB,OAAO,YAAY,WAAA,KAAgB,OAAA,CAAQ,GAAA,EAAK,aAAA,IAAiB,OAAA,CAAQ,GAAA,EAAK,eAAA,IAAmB,OAAA,CAAQ,KAAK,2BAAA,CAAA,IAC/G,EAAA;AAEL,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,MAAM,+DAA+D,CAAA;AAC7E,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAA,GAAW,OAAA,EAAS,IAAA,GAAO,gCAAA,GAAmC,sBAAA;AAEpE,EAAA,IAAI;AACF,IAAA,MAAM,WAAW,MAAM,KAAA,CAAM,GAAG,MAAM,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI;AAAA,MACnD,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,YAAA;AAAA,QAChB,WAAA,EAAa;AAAA;AACf,KACD,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,OAAA,CAAQ,MAAM,CAAA,yCAAA,EAA4C,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,QAAA,CAAS,UAAU,CAAA,CAAE,CAAA;AAClG,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,uDAAuD,KAAK,CAAA;AAC1E,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC5IA,SAAS,aAAA,CACP,QACA,KAAA,EACyB;AACzB,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AACnB,EAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AACpB,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,MAAA,CAAO,QAAA,IAAY,KAAA,CAAM,QAAA;AAAA,IACnC,OAAA,EAAS,MAAA,CAAO,OAAA,IAAW,KAAA,CAAM,OAAA;AAAA,IACjC,QAAA,EAAA,CAAW,OAAO,QAAA,EAAU,MAAA,GAAS,OAAO,QAAA,GAAW,KAAA,CAAM,aAAa,EAAC;AAAA,IAC3E,GAAA,EAAA,CAAM,OAAO,GAAA,EAAK,MAAA,GAAS,OAAO,GAAA,GAAM,KAAA,CAAM,QAAQ,EAAC;AAAA,IACvD,KAAA,EAAA,CAAQ,OAAO,KAAA,EAAO,MAAA,GAAS,OAAO,KAAA,GAAQ,KAAA,CAAM,UAAU;AAAC,GACjE;AACF;AAqBA,eAAsB,gBACpB,OAAA,EACyB;AACzB,EAAA,MAAM;AAAA,IACJ,SAAA;AAAA,IACA,YAAA;AAAA,IACA,mBAAA,GAAsB,IAAA;AAAA,IACtB,eAAA,GAAkB,IAAA;AAAA,IAClB,UAAA,GAAa,IAAA;AAAA,IACb,YAAA,GAAe,IAAA;AAAA,IACf,cAAA,GAAiB,IAAA;AAAA,IACjB,eAAA,GAAkB,IAAA;AAAA,IAClB,WAAA,GAAc,EAAA;AAAA,IACd,QAAA,GAAW,EAAA;AAAA,IACX,WAAA,GAAc,EAAA;AAAA,IACd,iBAAiB;AAAC,GACpB,GAAI,OAAA;AAGJ,EAAA,IAAI,IAAA,GAAO,MAAM,WAAA,CAAY,SAAS,CAAA;AAGtC,EAAA,MAAM,WAAW,YAAA,KAAiB,CAAC,IAAA,IAAQ,CAAC,KAAK,QAAA,EAAU,MAAA,CAAA;AAC3D,EAAA,IAAI,YAAY,YAAA,EAAc;AAC5B,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,YAAA,EAAa;AACjC,MAAA,IAAA,GAAO,aAAA,CAAc,IAAA,IAAQ,IAAA,EAAM,KAAK,CAAA;AAAA,IAC1C,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAA,CAAK,mCAAmC,GAAG,CAAA;AAAA,IACrD;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAA,EAAM;AAET,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,2CAAA;AAAA,MACV,QAAA,EAAU;AAAA,QACR,YAAA,EAAA,iBAAc,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QACrC,YAAY,SAAA,IAAa,EAAA;AAAA,QACzB,UAAU;AAAC;AACb,KACF;AAAA,EACF;AAEA,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,eAAyB,EAAC;AAKhC,EAAA,IAAI,mBAAA,IAAuB,KAAK,QAAA,EAAU;AACxC,IAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,IAAA,CAAK,QAAQ,CAAA;AAClD,IAAA,QAAA,CAAS,KAAK,MAAM,CAAA;AACpB,IAAA,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,EAC5B;AAKA,EAAA,IAAI,mBAAA,IAAuB,IAAA,CAAK,QAAA,EAAU,WAAA,EAAa;AACrD,IAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,IAAA,CAAK,QAAQ,CAAA;AAChD,IAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AACnB,IAAA,YAAA,CAAa,KAAK,OAAO,CAAA;AAAA,EAC3B;AAKA,EAAA,IAAI,eAAA,IAAmB,IAAA,CAAK,QAAA,EAAU,MAAA,GAAS,CAAA,EAAG;AAChD,IAAA,MAAM,QAAA,GAAW,uBAAA,CAAwB,IAAA,CAAK,QAAQ,CAAA;AACtD,IAAA,QAAA,CAAS,KAAK,QAAQ,CAAA;AACtB,IAAA,YAAA,CAAa,KAAK,UAAU,CAAA;AAAA,EAC9B;AAKA,EAAA,IAAI,cAAA,IAAkB,KAAK,OAAA,EAAS;AAClC,IAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,IAAA,CAAK,OAAO,CAAA;AACnD,IAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AACrB,IAAA,YAAA,CAAa,KAAK,SAAS,CAAA;AAAA,EAC7B;AAKA,EAAA,IAAI,UAAA,IAAc,IAAA,CAAK,GAAA,EAAK,MAAA,GAAS,CAAA,EAAG;AACtC,IAAA,MAAM,MAAM,kBAAA,CAAmB,IAAA,CAAK,IAAI,KAAA,CAAM,CAAA,EAAG,WAAW,CAAC,CAAA;AAC7D,IAAA,QAAA,CAAS,KAAK,GAAG,CAAA;AACjB,IAAA,YAAA,CAAa,KAAK,KAAK,CAAA;AAAA,EACzB;AAKA,EAAA,IAAI,YAAA,IAAgB,IAAA,CAAK,KAAA,EAAO,MAAA,GAAS,CAAA,EAAG;AAC1C,IAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,CAAK,QAAA,EAAU,OAAA,IAAW,EAAE,CAAA;AAC9F,IAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AACnB,IAAA,YAAA,CAAa,KAAK,OAAO,CAAA;AAAA,EAC3B;AAKA,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA,IAAI;AAEF,MAAA,MAAM,EAAE,WAAA,EAAa,gBAAA,EAAiB,GAAI,MAAM,OAAO,2BAAmB,CAAA;AAC1E,MAAA,MAAM,CAAC,QAAA,EAAU,aAAa,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,QAClD,WAAA,GAAc,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,KAAA,CAAM,CAAA,EAAG,WAAW,CAAC,CAAA;AAAA,QAC/C,gBAAA;AAAiB,OAClB,CAAA;AACD,MAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,IAAK,aAAA,EAAe;AACxC,QAAA,MAAM,aAAA,GAAgB,qBAAA,CAAsB,QAAA,EAAU,aAAA,EAAe,KAAK,CAAA;AAC1E,QAAA,QAAA,CAAS,KAAK,aAAa,CAAA;AAC3B,QAAA,YAAA,CAAa,KAAK,iBAAiB,CAAA;AAAA,MACrC;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAKA,EAAA,KAAA,MAAW,UAAU,cAAA,EAAgB;AACnC,IAAA,QAAA,CAAS,IAAA,CAAK,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK;;AAAA,EAAO,MAAA,CAAO,OAAO,CAAA,CAAE,CAAA;AACvD,IAAA,YAAA,CAAa,IAAA,CAAK,OAAO,KAAA,CAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAC,CAAA;AAAA,EACnE;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,QAAA,CAAS,IAAA,CAAK,aAAa,CAAA;AAAA,IACrC,QAAA,EAAU;AAAA,MACR,YAAA,EAAA,iBAAc,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MACrC,YAAY,SAAA,IAAa,EAAA;AAAA,MACzB,QAAA,EAAU;AAAA;AACZ,GACF;AACF;AAMA,eAAsB,oBACpB,OAAA,EACyB;AACzB,EAAA,OAAO,eAAA,CAAgB;AAAA,IACrB,GAAG,OAAA;AAAA,IACH,mBAAA,EAAqB,IAAA;AAAA,IACrB,eAAA,EAAiB,IAAA;AAAA,IACjB,UAAA,EAAY,IAAA;AAAA,IACZ,YAAA,EAAc,IAAA;AAAA,IACd,cAAA,EAAgB,IAAA;AAAA,IAChB,eAAA,EAAiB,IAAA;AAAA,IACjB,WAAA,EAAa,GAAA;AAAA,IACb,QAAA,EAAU,GAAA;AAAA,IACV,WAAA,EAAa;AAAA,GACd,CAAA;AACH;AAMA,SAAS,sBAAsB,QAAA,EAAmC;AAChE,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,QAAA,CAAS,IAAI,CAAA,CAAE,CAAA;AAC/B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAGb,EAAA,MAAM,OAAA,GAAU,SAAS,OAAA,IAAW,QAAA,CAAS,YAAY,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AACrE,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AAEzB,EAAA,IAAI,SAAS,QAAA,EAAU;AACrB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,QAAA,CAAS,QAAQ,CAAA,CAAE,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,SAAS,YAAA,EAAc;AACzB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,EAAqB,QAAA,CAAS,YAAY,CAAA,CAAE,CAAA;AAAA,EACzD;AAEA,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,qBAAqB,QAAA,EAAmC;AAC/D,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,UAAU,CAAA;AACrB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA,CAAK,SAAS,WAAW,CAAA;AAE/B,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,QAAA,CAAS,OAAO,CAAA,CAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,wBAAwB,QAAA,EAAgC;AAC/D,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,aAAa,CAAA;AACxB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,QAAQ,GAAA,EAAK;AACf,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,KAAA,EAAQ,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,QAAQ,GAAG,CAAA,KAAA,EAAQ,OAAA,CAAQ,WAAW,CAAA,CAAE,CAAA;AAAA,IAC9E,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,CAAA,IAAA,EAAO,OAAA,CAAQ,IAAI,CAAA,IAAA,EAAO,OAAA,CAAQ,WAAW,CAAA,CAAE,CAAA;AAAA,IAC5D;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,uBAAuB,OAAA,EAAiC;AAC/D,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,wBAAwB,CAAA;AACnC,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,KAAK,CAAA,CAAE,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,KAAK,CAAA,CAAE,CAAA;AAAA,EAC5C;AACA,EAAA,IAAI,OAAA,CAAQ,OAAA,IAAW,OAAA,CAAQ,IAAA,EAAM;AACnC,IAAA,MAAM,YAAA,GAAe;AAAA,MACnB,OAAA,CAAQ,OAAA;AAAA,MACR,OAAA,CAAQ,IAAA;AAAA,MACR,OAAA,CAAQ,KAAA;AAAA,MACR,OAAA,CAAQ,WAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACV,CAAE,OAAO,OAAO,CAAA;AAChB,IAAA,KAAA,CAAM,KAAK,CAAA,eAAA,EAAkB,YAAA,CAAa,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EACxD;AACA,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,OAAA,CAAQ,KAAK,CAAA,CAAE,CAAA;AAAA,EAC5C;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,mBAAmB,GAAA,EAA2B;AACrD,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,+BAA+B,CAAA;AAC1C,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,KAAA,MAAW,QAAQ,GAAA,EAAK;AACtB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAO,IAAA,CAAK,QAAQ,CAAA,CAAE,CAAA;AACjC,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA;AACtB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AAEA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA,EAAK;AAC/B;AAEA,SAAS,oBAAA,CAAqB,OAAyB,OAAA,EAAyB;AAC9E,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,GAAI,IAAA,CAAK,IAAA,GAAO,CAAA,EAAG,OAAO,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,CAAA;AAC7E,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,KAAA,CAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAK,KAAK,GAAG,CAAA,GAAA,EAAM,IAAA,CAAK,WAAW,CAAA,CAAE,CAAA;AAAA,IAC7D,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,KAAK,CAAA,GAAA,EAAM,IAAA,CAAK,KAAK,CAAA,EAAA,EAAK,GAAG,CAAA,CAAA,CAAG,CAAA;AAAA,IACxC;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,qBAAA,CACP,QAAA,EACA,aAAA,EACA,QAAA,EACQ;AACR,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,KAAK,oBAAoB,CAAA;AAC/B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAGb,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAO,aAAA,CAAc,IAAI,CAAA,UAAA,CAAY,CAAA;AAChD,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,YAAA,EAAe,aAAA,CAAc,WAAW,CAAA,CAAE,CAAA;AACrD,IAAA,IAAI,cAAc,WAAA,EAAa;AAC7B,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiB,aAAA,CAAc,WAAW,CAAA,CAAE,CAAA;AAAA,IACzD;AAOA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AAGA,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAyB;AAC7C,EAAA,KAAA,MAAW,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI,aAAA,IAAiB,MAAA,CAAO,EAAA,KAAO,aAAA,CAAc,EAAA,EAAI;AACrD,IAAA,MAAM,OAAO,MAAA,CAAO,WAAA;AACpB,IAAA,IAAI,CAAC,QAAQ,GAAA,CAAI,IAAI,GAAG,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,EAAE,CAAA;AAC5C,IAAA,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,CAAG,IAAA,CAAK,MAAM,CAAA;AAAA,EAChC;AAEA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,OAAA,EAAS;AACnC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,aAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,GAAA;AAC7D,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAO,KAAK,CAAA,CAAE,CAAA;AACzB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,MAAW,UAAU,KAAA,EAAO;AAC1B,MAQO;AACL,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAAA,MAC/B;AAAA,IACF;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AAEA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA,EAAK;AAC/B;ACrXA,eAAsB,oBAAA,CACpB,OAAA,GAA+B,EAAC,EACiC;AACjE,EAAA,MAAM;AAAA,IACJ,SAAA,GAAY,QAAA;AAAA,IACZ,IAAA,GAAO,KAAA;AAAA,IACP,MAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA,GAAkB,IAAA;AAAA,IAClB;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,MAAM,OAAO,OAAA,KAAY,WAAA,GAAc,OAAA,CAAQ,KAAI,GAAI,GAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAK,SAAS,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,EAAS,UAAU,CAAA;AACzC,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,EAAS,eAAe,CAAA;AAGlD,EAAA,IAAI,CAAC,UAAA,CAAW,OAAO,CAAA,EAAG;AACxB,IAAA,SAAA,CAAU,OAAA,EAAS,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,UAAA,GAAa,EAAE,MAAA,EAAQ,MAAA,EAAO;AAGpC,EAAA,IAAI,QAAA,GAAW,MAAM,mBAAA,CAAoB,EAAE,GAAG,UAAA,EAAY,IAAA,EAAM,OAAO,CAAA;AACvE,EAAA,IAAI,SAAA,GAAY,CAAC,CAAC,QAAA;AAElB,EAAA,IAAI,CAAC,YAAY,eAAA,EAAiB;AAChC,IAAA,OAAA,CAAQ,KAAK,mEAAmE,CAAA;AAChF,IAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,EAAE,cAAc,CAAA;AACrD,IAAA,QAAA,GAAW,MAAA,CAAO,QAAA;AAAA,EACpB;AAEA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAA,CAAQ,MAAM,wCAAwC,CAAA;AACtD,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,WAAW,KAAA,EAAM;AAAA,EAC5D;AAEA,EAAA,aAAA,CAAc,QAAA,EAAU,UAAU,OAAO,CAAA;AACzC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,6BAAA,EAAgC,QAAQ,CAAA,CAAE,CAAA;AAEtD,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAI,YAAA,GAAe,MAAM,mBAAA,CAAoB,EAAE,GAAG,UAAA,EAAY,IAAA,EAAM,MAAM,CAAA;AAC1E,IAAA,IAAI,CAAC,gBAAgB,eAAA,EAAiB;AACpC,MAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoB,EAAE,cAAc,CAAA;AACzD,MAAA,YAAA,GAAe,MAAA,CAAO,QAAA;AAAA,IACxB;AACA,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,aAAA,CAAc,YAAA,EAAc,cAAc,OAAO,CAAA;AACjD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kCAAA,EAAqC,YAAY,CAAA,CAAE,CAAA;AAAA,IACjE;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,UAAU,SAAA,EAAU;AACpD","file":"chunk-JMNSED4O.mjs","sourcesContent":["/**\n * @sonordev/site-kit/llms - API Functions\n * \n * Data fetching for LLM visibility content.\n * Pulls from Signal knowledge base and project data.\n */\n\nimport { cache } from 'react'\nimport type { LLMsDataResponse, LLMBusinessInfo, LLMContactInfo, LLMService, LLMFAQItem, LLMPageSummary } from './types'\n\n// ============================================\n// API Config\n// ============================================\n\nfunction getApiConfig() {\n // Use site-kit globals if available, otherwise fall back to env vars\n const apiUrl = (typeof window !== 'undefined' && (window as any).__SITE_KIT_API_URL__)\n || process.env.SONOR_API_URL\n || process.env.UPTRADE_API_URL\n || process.env.NEXT_PUBLIC_UPTRADE_API_URL\n || 'https://api.sonor.io'\n\n const apiKey = (typeof window !== 'undefined' && (window as any).__SITE_KIT_API_KEY__)\n || process.env.SONOR_API_KEY\n || process.env.UPTRADE_API_KEY\n || process.env.NEXT_PUBLIC_UPTRADE_API_KEY\n || ''\n \n return { apiUrl, apiKey }\n}\n\nasync function apiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getApiConfig()\n \n if (!apiKey) {\n console.error('@sonordev/llms: No API key configured. Set SONOR_API_KEY.')\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: 3600 }, // Next.js fetch cache\n } as RequestInit)\n \n if (!response.ok) {\n console.error(`@sonordev/llms: API error: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/llms: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch all LLM visibility data for a project - cached per request\n * This is the main data source for llms.txt generation\n * \n * @param projectId - Optional project ID (API key identifies project if omitted)\n */\nexport const getLLMsData = cache(async (\n projectId?: string\n): Promise<LLMsDataResponse | null> => {\n return apiGet<LLMsDataResponse>(`/api/public/llms/data`)\n})\n\n/**\n * Fetch business info only - cached per request\n */\nexport const getBusinessInfo = cache(async (\n projectId?: string\n): Promise<LLMBusinessInfo | null> => {\n const result = await apiGet<{ business: LLMBusinessInfo }>(`/api/public/llms/business`)\n return result?.business || null\n})\n\n/**\n * Fetch services list - cached per request\n */\nexport const getServices = cache(async (\n projectId?: string\n): Promise<LLMService[]> => {\n const result = await apiGet<{ services: LLMService[] }>(`/api/public/llms/services`)\n return result?.services || []\n})\n\n/**\n * Fetch FAQ items - cached per request\n */\nexport const getFAQItems = cache(async (\n projectId?: string,\n limit?: number\n): Promise<LLMFAQItem[]> => {\n const endpoint = limit \n ? `/api/public/llms/faq?limit=${limit}`\n : '/api/public/llms/faq'\n const result = await apiGet<{ faq: LLMFAQItem[] }>(endpoint)\n return result?.faq || []\n})\n\n/**\n * Fetch page summaries for sitemap - cached per request\n */\nexport const getPageSummaries = cache(async (\n projectId?: string,\n limit?: number\n): Promise<LLMPageSummary[]> => {\n const endpoint = limit \n ? `/api/public/llms/pages?limit=${limit}`\n : '/api/public/llms/pages'\n const result = await apiGet<{ pages: LLMPageSummary[] }>(endpoint)\n return result?.pages || []\n})\n\n/**\n * Fetch AI-optimized llms.txt markdown from Portal API (build-time)\n * Used by writeLLMsTxtToPublic for static file generation\n */\nexport async function getOptimizedLLMsTxt(options?: {\n full?: boolean\n apiUrl?: string\n apiKey?: string\n}): Promise<string | null> {\n const apiUrl = options?.apiUrl\n || (typeof process !== 'undefined' && (process.env?.SONOR_API_URL || process.env?.UPTRADE_API_URL || process.env?.NEXT_PUBLIC_UPTRADE_API_URL))\n || 'https://api.sonor.io'\n const apiKey = options?.apiKey\n || (typeof process !== 'undefined' && (process.env?.SONOR_API_KEY || process.env?.UPTRADE_API_KEY || process.env?.NEXT_PUBLIC_UPTRADE_API_KEY))\n || ''\n\n if (!apiKey) {\n console.error('@sonordev/llms: No API key configured for getOptimizedLLMsTxt')\n return null\n }\n\n const endpoint = options?.full ? '/api/public/llms/txt?full=true' : '/api/public/llms/txt'\n\n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'text/plain',\n 'x-api-key': apiKey,\n },\n })\n\n if (!response.ok) {\n console.error(`@sonordev/llms: Optimized txt API error: ${response.status} ${response.statusText}`)\n return null\n }\n\n return await response.text()\n } catch (error) {\n console.error('@sonordev/llms: Failed to fetch optimized llms.txt:', error)\n return null\n }\n}\n","/**\n * @sonordev/site-kit/llms - llms.txt Generator\n * \n * Generates llms.txt content following the llms.txt specification.\n * https://llmstxt.org/\n * \n * The llms.txt file provides a markdown-formatted overview of a website\n * specifically designed for LLM consumption. It helps AI systems understand\n * what a business does, what services it offers, and how to answer questions.\n */\n\nimport { getLLMsData } from './api'\nimport type {\n GenerateLLMSTxtOptions,\n LLMSTxtContent,\n LLMsDataResponse,\n LLMBusinessInfo,\n LLMContactInfo,\n LLMService,\n LLMFAQItem,\n LLMPageSummary\n} from './types'\nimport type { SEOEntity } from '../seo/types'\n\n/**\n * Merge Portal data with local data. Portal fields take precedence; local fills gaps when Portal is empty.\n */\nfunction mergeLLMsData(\n portal: Partial<LLMsDataResponse> | null,\n local: LLMsDataResponse | null\n): LLMsDataResponse | null {\n if (!local) return portal as LLMsDataResponse | null\n if (!portal) return local\n return {\n business: portal.business ?? local.business,\n contact: portal.contact ?? local.contact,\n services: (portal.services?.length ? portal.services : local.services) ?? [],\n faq: (portal.faq?.length ? portal.faq : local.faq) ?? [],\n pages: (portal.pages?.length ? portal.pages : local.pages) ?? [],\n }\n}\n\n/**\n * Generate llms.txt content from Portal data\n * \n * @example\n * ```ts\n * // app/llms.txt/route.ts\n * import { generateLLMsTxt } from '@sonordev/site-kit/llms'\n * \n * export async function GET() {\n * const { markdown } = await generateLLMsTxt({\n * projectId: process.env.UPTRADE_PROJECT_ID!\n * })\n * \n * return new Response(markdown, {\n * headers: { 'Content-Type': 'text/plain; charset=utf-8' }\n * })\n * }\n * ```\n */\nexport async function generateLLMsTxt(\n options: GenerateLLMSTxtOptions\n): Promise<LLMSTxtContent> {\n const {\n projectId,\n getLocalData,\n includeBusinessInfo = true,\n includeServices = true,\n includeFAQ = true,\n includePages = true,\n includeContact = true,\n includeEntities = true,\n maxFAQItems = 20,\n maxPages = 50,\n maxEntities = 50,\n customSections = [],\n } = options\n\n // Fetch from Portal first\n let data = await getLLMsData(projectId)\n\n // Use local data when Portal returns null or empty services\n const useLocal = getLocalData && (!data || !data.services?.length)\n if (useLocal && getLocalData) {\n try {\n const local = await getLocalData()\n data = mergeLLMsData(data ?? null, local)\n } catch (err) {\n console.warn('[site-kit] getLocalData failed:', err)\n }\n }\n \n if (!data) {\n // Return minimal content if no data\n return {\n markdown: '# Website\\n\\n> Information not available.',\n metadata: {\n generated_at: new Date().toISOString(),\n project_id: projectId || '',\n sections: [],\n }\n }\n }\n\n const sections: string[] = []\n const sectionNames: string[] = []\n\n // ========================================\n // Header Section (H1 + blockquote summary)\n // ========================================\n if (includeBusinessInfo && data.business) {\n const header = generateHeaderSection(data.business)\n sections.push(header)\n sectionNames.push('header')\n }\n\n // ========================================\n // About Section\n // ========================================\n if (includeBusinessInfo && data.business?.description) {\n const about = generateAboutSection(data.business)\n sections.push(about)\n sectionNames.push('about')\n }\n\n // ========================================\n // Services Section\n // ========================================\n if (includeServices && data.services?.length > 0) {\n const services = generateServicesSection(data.services)\n sections.push(services)\n sectionNames.push('services')\n }\n\n // ========================================\n // Contact Section\n // ========================================\n if (includeContact && data.contact) {\n const contact = generateContactSection(data.contact)\n sections.push(contact)\n sectionNames.push('contact')\n }\n\n // ========================================\n // FAQ Section\n // ========================================\n if (includeFAQ && data.faq?.length > 0) {\n const faq = generateFAQSection(data.faq.slice(0, maxFAQItems))\n sections.push(faq)\n sectionNames.push('faq')\n }\n\n // ========================================\n // Pages Section (sitemap-like index)\n // ========================================\n if (includePages && data.pages?.length > 0) {\n const pages = generatePagesSection(data.pages.slice(0, maxPages), data.business?.website || '')\n sections.push(pages)\n sectionNames.push('pages')\n }\n\n // ========================================\n // Knowledge Graph / Entity Section\n // ========================================\n if (includeEntities) {\n try {\n // Dynamic import to avoid pulling server-only code when not needed\n const { getEntities, getPrimaryEntity } = await import('../seo/server-api')\n const [entities, primaryEntity] = await Promise.all([\n getEntities().then(e => e.slice(0, maxEntities)),\n getPrimaryEntity(),\n ])\n if (entities.length > 0 || primaryEntity) {\n const entitySection = generateEntitySection(entities, primaryEntity, false)\n sections.push(entitySection)\n sectionNames.push('knowledge-graph')\n }\n } catch {\n // Entity graph unavailable (e.g., no Signal API) — skip silently\n }\n }\n\n // ========================================\n // Custom Sections\n // ========================================\n for (const custom of customSections) {\n sections.push(`## ${custom.title}\\n\\n${custom.content}`)\n sectionNames.push(custom.title.toLowerCase().replace(/\\s+/g, '-'))\n }\n\n return {\n markdown: sections.join('\\n\\n---\\n\\n'),\n metadata: {\n generated_at: new Date().toISOString(),\n project_id: projectId || '',\n sections: sectionNames,\n }\n }\n}\n\n/**\n * Generate llms-full.txt with comprehensive knowledge dump\n * Use this for AI systems that can handle larger context\n */\nexport async function generateLLMsFullTxt(\n options: GenerateLLMSTxtOptions\n): Promise<LLMSTxtContent> {\n return generateLLMsTxt({\n ...options,\n includeBusinessInfo: true,\n includeServices: true,\n includeFAQ: true,\n includePages: true,\n includeContact: true,\n includeEntities: true,\n maxFAQItems: 100,\n maxPages: 200,\n maxEntities: 200,\n })\n}\n\n// ============================================\n// Section Generators\n// ============================================\n\nfunction generateHeaderSection(business: LLMBusinessInfo): string {\n const lines: string[] = []\n \n // H1 with business name\n lines.push(`# ${business.name}`)\n lines.push('')\n \n // Blockquote summary (per llms.txt spec)\n const summary = business.tagline || business.description.split('.')[0]\n lines.push(`> ${summary}`)\n \n if (business.industry) {\n lines.push('')\n lines.push(`**Industry:** ${business.industry}`)\n }\n \n if (business.service_area) {\n lines.push(`**Service Area:** ${business.service_area}`)\n }\n \n if (business.website) {\n lines.push(`**Website:** ${business.website}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateAboutSection(business: LLMBusinessInfo): string {\n const lines: string[] = []\n \n lines.push('## About')\n lines.push('')\n lines.push(business.description)\n \n if (business.founded) {\n lines.push('')\n lines.push(`Established: ${business.founded}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateServicesSection(services: LLMService[]): string {\n const lines: string[] = []\n \n lines.push('## Services')\n lines.push('')\n \n for (const service of services) {\n if (service.url) {\n lines.push(`- **[${service.name}](${service.url})**: ${service.description}`)\n } else {\n lines.push(`- **${service.name}**: ${service.description}`)\n }\n }\n\n return lines.join('\\n')\n}\n\nfunction generateContactSection(contact: LLMContactInfo): string {\n const lines: string[] = []\n \n lines.push('## Contact Information')\n lines.push('')\n \n if (contact.phone) {\n lines.push(`- **Phone:** ${contact.phone}`)\n }\n if (contact.email) {\n lines.push(`- **Email:** ${contact.email}`)\n }\n if (contact.address || contact.city) {\n const addressParts = [\n contact.address,\n contact.city,\n contact.state,\n contact.postal_code,\n contact.country\n ].filter(Boolean)\n lines.push(`- **Address:** ${addressParts.join(', ')}`)\n }\n if (contact.hours) {\n lines.push(`- **Hours:** ${contact.hours}`)\n }\n\n return lines.join('\\n')\n}\n\nfunction generateFAQSection(faq: LLMFAQItem[]): string {\n const lines: string[] = []\n \n lines.push('## Frequently Asked Questions')\n lines.push('')\n \n for (const item of faq) {\n lines.push(`### ${item.question}`)\n lines.push('')\n lines.push(item.answer)\n lines.push('')\n }\n\n return lines.join('\\n').trim()\n}\n\nfunction generatePagesSection(pages: LLMPageSummary[], baseUrl: string): string {\n const lines: string[] = []\n \n lines.push('## Site Pages')\n lines.push('')\n \n for (const page of pages) {\n const url = page.path.startsWith('http') ? page.path : `${baseUrl}${page.path}`\n if (page.description) {\n lines.push(`- [${page.title}](${url}): ${page.description}`)\n } else {\n lines.push(`- [${page.title}](${url})`)\n }\n }\n\n return lines.join('\\n')\n}\n\nfunction generateEntitySection(\n entities: SEOEntity[],\n primaryEntity: SEOEntity | null,\n detailed: boolean\n): string {\n const lines: string[] = []\n\n lines.push('## Knowledge Graph')\n lines.push('')\n\n // Primary entity first\n if (primaryEntity) {\n lines.push(`### ${primaryEntity.name} (Primary)`)\n lines.push('')\n lines.push(`- **Type:** ${primaryEntity.entity_type}`)\n if (primaryEntity.schema_type) {\n lines.push(`- **Schema:** ${primaryEntity.schema_type}`)\n }\n if (detailed && primaryEntity.knows_about?.length) {\n lines.push(`- **Knows About:** ${primaryEntity.knows_about.join(', ')}`)\n }\n if (detailed && primaryEntity.same_as?.length) {\n lines.push(`- **Same As:** ${primaryEntity.same_as.join(', ')}`)\n }\n lines.push('')\n }\n\n // Group remaining entities by type\n const grouped = new Map<string, SEOEntity[]>()\n for (const entity of entities) {\n if (primaryEntity && entity.id === primaryEntity.id) continue\n const type = entity.entity_type\n if (!grouped.has(type)) grouped.set(type, [])\n grouped.get(type)!.push(entity)\n }\n\n for (const [type, group] of grouped) {\n const label = type.charAt(0).toUpperCase() + type.slice(1) + 's'\n lines.push(`### ${label}`)\n lines.push('')\n for (const entity of group) {\n if (detailed) {\n lines.push(`- **${entity.name}**`)\n if (entity.knows_about?.length) {\n lines.push(` - Knows About: ${entity.knows_about.join(', ')}`)\n }\n if (entity.same_as?.length) {\n lines.push(` - Same As: ${entity.same_as.join(', ')}`)\n }\n } else {\n lines.push(`- ${entity.name}`)\n }\n }\n lines.push('')\n }\n\n return lines.join('\\n').trim()\n}\n\nexport default generateLLMsTxt\n","/**\n * @sonordev/site-kit/llms - Build-Time Write\n *\n * Fetches AI-optimized llms.txt from Portal API and writes to public/llms.txt\n * at build time. Integrates with sitemap flow when optimizedLLMsTxt is enabled.\n */\n\nimport { writeFileSync, mkdirSync, existsSync } from 'fs'\nimport { join } from 'path'\nimport { getOptimizedLLMsTxt } from './api'\nimport { generateLLMsTxt, generateLLMsFullTxt } from './generateLLMsTxt'\nimport type { LLMsDataResponse } from './types'\n\nexport interface WriteLLMsTxtOptions {\n /** Output directory (default: public, relative to cwd) */\n outputDir?: string\n /** Write llms-full.txt as well */\n full?: boolean\n /** Portal API URL */\n apiUrl?: string\n /** Portal API key */\n apiKey?: string\n /** Fallback to non-optimized when API fails */\n fallbackToLocal?: boolean\n /** When Portal returns empty services/faq/pages, use this to supply local site data */\n getLocalData?: () => Promise<LLMsDataResponse | null>\n}\n\n/**\n * Fetch optimized llms.txt from Portal and write to public/llms.txt\n * Called at build time after sitemap sync (when optimizedLLMsTxt is enabled)\n */\nexport async function writeLLMsTxtToPublic(\n options: WriteLLMsTxtOptions = {}\n): Promise<{ success: boolean; path: string; optimized: boolean }> {\n const {\n outputDir = 'public',\n full = false,\n apiUrl,\n apiKey,\n fallbackToLocal = true,\n getLocalData,\n } = options\n\n const cwd = typeof process !== 'undefined' ? process.cwd() : '.'\n const outPath = join(cwd, outputDir)\n const llmsPath = join(outPath, 'llms.txt')\n const llmsFullPath = join(outPath, 'llms-full.txt')\n\n // Ensure output directory exists\n if (!existsSync(outPath)) {\n mkdirSync(outPath, { recursive: true })\n }\n\n const apiOptions = { apiUrl, apiKey }\n\n // Fetch optimized content\n let markdown = await getOptimizedLLMsTxt({ ...apiOptions, full: false })\n let optimized = !!markdown\n\n if (!markdown && fallbackToLocal) {\n console.warn('[site-kit] Optimized llms.txt unavailable, using local generation')\n const result = await generateLLMsTxt({ getLocalData })\n markdown = result.markdown\n }\n\n if (!markdown) {\n console.error('[site-kit] Failed to generate llms.txt')\n return { success: false, path: llmsPath, optimized: false }\n }\n\n writeFileSync(llmsPath, markdown, 'utf-8')\n console.log(`[site-kit] Wrote llms.txt to ${llmsPath}`)\n\n if (full) {\n let fullMarkdown = await getOptimizedLLMsTxt({ ...apiOptions, full: true })\n if (!fullMarkdown && fallbackToLocal) {\n const result = await generateLLMsFullTxt({ getLocalData })\n fullMarkdown = result.markdown\n }\n if (fullMarkdown) {\n writeFileSync(llmsFullPath, fullMarkdown, 'utf-8')\n console.log(`[site-kit] Wrote llms-full.txt to ${llmsFullPath}`)\n }\n }\n\n return { success: true, path: llmsPath, optimized }\n}\n"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkZSMWDLMK_js = require('./chunk-ZSMWDLMK.js');
|
|
4
|
+
require('server-only');
|
|
5
|
+
|
|
6
|
+
var { cache } = chunkZSMWDLMK_js.__require("react");
|
|
7
|
+
function getSecureApiConfig() {
|
|
8
|
+
const apiUrl = process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io";
|
|
9
|
+
const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"@sonordev/site-kit/cms: SONOR_API_KEY (or UPTRADE_API_KEY) environment variable is required"
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return { apiUrl, apiKey };
|
|
16
|
+
}
|
|
17
|
+
async function secureApiPost(endpoint, body = {}) {
|
|
18
|
+
const { apiUrl, apiKey } = getSecureApiConfig();
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(`${apiUrl}${endpoint}`, {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: {
|
|
23
|
+
"Content-Type": "application/json",
|
|
24
|
+
"x-api-key": apiKey
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify(body),
|
|
27
|
+
next: { revalidate: 60 }
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
let detail = response.statusText;
|
|
31
|
+
try {
|
|
32
|
+
const err = await response.json().catch(() => ({}));
|
|
33
|
+
if (err?.message) detail = err.message;
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
console.error(
|
|
37
|
+
`@sonordev/cms: API error ${response.status} ${endpoint}: ${detail}`
|
|
38
|
+
);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
return await response.json();
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error("@sonordev/cms: Network error:", error);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
var getCmsPage = cache(
|
|
48
|
+
async (path) => {
|
|
49
|
+
const result = await secureApiPost("/api/public/cms/page", { path });
|
|
50
|
+
if (!result?.found || !result.page) return null;
|
|
51
|
+
return result.page;
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
var getCmsSection = cache(
|
|
55
|
+
async (sectionId) => {
|
|
56
|
+
const result = await secureApiPost("/api/public/cms/section", { sectionId });
|
|
57
|
+
if (!result?.found || !result.section) return null;
|
|
58
|
+
return result.section;
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
var getCmsPageMetadata = cache(
|
|
62
|
+
async (path) => {
|
|
63
|
+
const page = await getCmsPage(path);
|
|
64
|
+
if (!page) return null;
|
|
65
|
+
const seo = page.seo || {};
|
|
66
|
+
return {
|
|
67
|
+
title: seo.title || page.title,
|
|
68
|
+
description: seo.description,
|
|
69
|
+
robots: seo.noindex ? { index: false } : void 0,
|
|
70
|
+
openGraph: {
|
|
71
|
+
title: seo.title || page.title,
|
|
72
|
+
description: seo.description
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
exports.getCmsPage = getCmsPage;
|
|
79
|
+
exports.getCmsPageMetadata = getCmsPageMetadata;
|
|
80
|
+
exports.getCmsSection = getCmsSection;
|
|
81
|
+
//# sourceMappingURL=chunk-MG23BS36.js.map
|
|
82
|
+
//# sourceMappingURL=chunk-MG23BS36.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cms/server-api.ts"],"names":["__require"],"mappings":"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","file":"chunk-MG23BS36.js","sourcesContent":["/**\n * @sonordev/site-kit/cms - Server-Only API Functions\n *\n * Fetches CMS page/section data from Portal API.\n * Uses the same secure API pattern as seo/server-api.ts.\n */\n\n// React.cache is available in React 19+ / Next.js RSC\n// eslint-disable-next-line @typescript-eslint/no-var-requires\nconst { cache } = require('react') as { cache: <T extends (...args: any[]) => any>(fn: T) => T }\nimport 'server-only'\nimport type { CmsPageData, CmsSectionData, CmsPageSeo } from './types'\n\n// ============================================\n// Server-Only API Config\n// ============================================\n\nfunction getSecureApiConfig() {\n const apiUrl =\n process.env.SONOR_API_URL ||\n process.env.UPTRADE_API_URL ||\n process.env.NEXT_PUBLIC_UPTRADE_API_URL ||\n 'https://api.sonor.io'\n const apiKey =\n process.env.SONOR_API_KEY ||\n process.env.UPTRADE_API_KEY ||\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ||\n ''\n\n if (!apiKey) {\n throw new Error(\n '@sonordev/site-kit/cms: SONOR_API_KEY (or UPTRADE_API_KEY) environment variable is required',\n )\n }\n\n return { apiUrl, apiKey }\n}\n\nasync function secureApiPost<T>(\n endpoint: string,\n body: Record<string, unknown> = {},\n): Promise<T | null> {\n const { apiUrl, apiKey } = getSecureApiConfig()\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 },\n } as RequestInit)\n\n if (!response.ok) {\n let detail = response.statusText\n try {\n const err = await response.json().catch(() => ({}))\n if (err?.message) detail = err.message\n } catch {\n /* ignore */\n }\n console.error(\n `@sonordev/cms: API error ${response.status} ${endpoint}: ${detail}`,\n )\n return null\n }\n\n return await response.json()\n } catch (error) {\n console.error('@sonordev/cms: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch a published CMS page by path — cached per request.\n * Returns the full page with all sections and their Portable Text content.\n * @server-only\n */\nexport const getCmsPage = cache(\n async (path: string): Promise<CmsPageData | null> => {\n const result = await secureApiPost<{\n found: boolean\n page: CmsPageData | null\n }>('/api/public/cms/page', { path })\n\n if (!result?.found || !result.page) return null\n return result.page\n },\n)\n\n/**\n * Fetch a single published CMS section by ID — cached per request.\n * @server-only\n */\nexport const getCmsSection = cache(\n async (sectionId: string): Promise<CmsSectionData | null> => {\n const result = await secureApiPost<{\n found: boolean\n section: CmsSectionData | null\n }>('/api/public/cms/section', { sectionId })\n\n if (!result?.found || !result.section) return null\n return result.section\n },\n)\n\n/**\n * Fetch CMS page and return Next.js Metadata object.\n * Use in generateMetadata() for CMS-managed pages.\n *\n * @example\n * ```ts\n * import { getCmsPageMetadata } from '@sonordev/site-kit/cms/server'\n *\n * export async function generateMetadata({ params }) {\n * return getCmsPageMetadata(`/${params.slug}`)\n * }\n * ```\n * @server-only\n */\nexport const getCmsPageMetadata = cache(\n async (\n path: string,\n ): Promise<{\n title?: string\n description?: string\n robots?: { index: boolean }\n openGraph?: { title?: string; description?: string }\n } | null> => {\n const page = await getCmsPage(path)\n if (!page) return null\n\n const seo: CmsPageSeo = page.seo || {}\n\n return {\n title: seo.title || page.title,\n description: seo.description,\n robots: seo.noindex ? { index: false } : undefined,\n openGraph: {\n title: seo.title || page.title,\n description: seo.description,\n },\n }\n },\n)\n"]}
|
|
@@ -37,15 +37,15 @@ async function fetchFaviconData(apiUrl, apiKey) {
|
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
async function getManagedFaviconUrl(apiKey, apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
41
|
-
const key = apiKey ?? process.env.
|
|
40
|
+
async function getManagedFaviconUrl(apiKey, apiUrl = process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io") {
|
|
41
|
+
const key = apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY;
|
|
42
42
|
if (!key) return null;
|
|
43
43
|
const data = await fetchFaviconData(apiUrl, key);
|
|
44
44
|
return data?.public_url ?? null;
|
|
45
45
|
}
|
|
46
46
|
async function ManagedFavicon({
|
|
47
|
-
apiKey = process.env.NEXT_PUBLIC_UPTRADE_API_KEY,
|
|
48
|
-
apiUrl = process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
47
|
+
apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY,
|
|
48
|
+
apiUrl = process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io",
|
|
49
49
|
fallback = "/favicon.ico",
|
|
50
50
|
themeColor = "#4bbf39"
|
|
51
51
|
}) {
|
|
@@ -64,5 +64,5 @@ async function ManagedFavicon({
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
export { ManagedFavicon, fetchFaviconData, getManagedFaviconUrl };
|
|
67
|
-
//# sourceMappingURL=chunk-
|
|
68
|
-
//# sourceMappingURL=chunk-
|
|
67
|
+
//# sourceMappingURL=chunk-N24BPFF6.mjs.map
|
|
68
|
+
//# sourceMappingURL=chunk-N24BPFF6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/images/ManagedFavicon.tsx"],"names":[],"mappings":"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","file":"chunk-N24BPFF6.mjs","sourcesContent":["/**\n * ManagedFavicon Component\n * \n * Server component that renders favicon link tags using the project's logo.\n * When a logo is uploaded in Project Settings, it's automatically synced\n * to the 'favicon' slot in site_managed_images.\n * \n * Usage:\n * ```tsx\n * import { ManagedFavicon } from '@sonordev/site-kit/images'\n * \n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <head>\n * <ManagedFavicon />\n * </head>\n * <body>{children}</body>\n * </html>\n * )\n * }\n * ```\n * \n * Supports:\n * - SVG favicons (best for modern browsers, scales perfectly)\n * - PNG favicons with multiple sizes\n * - Apple touch icons\n * - Theme color for mobile browsers\n */\n\nimport React from 'react'\n\nexport interface ManagedFaviconProps {\n /**\n * API key for Portal API authentication\n * Defaults to SONOR_API_KEY env var\n */\n apiKey?: string\n \n /**\n * API URL (defaults to https://api.sonor.io)\n */\n apiUrl?: string\n \n /**\n * Fallback favicon URL if no managed favicon is set\n */\n fallback?: string\n \n /**\n * Theme color for mobile browser chrome\n * Defaults to #4bbf39 (Sonor brand primary)\n */\n themeColor?: string\n}\n\ninterface FaviconData {\n public_url?: string\n mime_type?: string\n is_placeholder?: boolean\n}\n\n/** If url is relative (e.g. /uploads/... from API), resolve against base so production can load it. */\nfunction toAbsoluteFaviconUrl(url: string | undefined, apiBase: string): string | undefined {\n if (!url) return undefined\n if (url.startsWith('http://') || url.startsWith('https://')) return url\n const base = apiBase.replace(/\\/$/, '')\n return url.startsWith('/') ? `${base}${url}` : `${base}/${url}`\n}\n\n/**\n * Server-side fetch of favicon data.\n * Exported for use in generateMetadata (single source for favicon URL).\n */\nexport async function fetchFaviconData(apiUrl: string, apiKey: string): Promise<FaviconData | null> {\n try {\n const res = await fetch(`${apiUrl}/public/images/slot/favicon`, {\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 3600 }, // Cache 1hr – favicon rarely changes, allows static generation\n })\n\n if (!res.ok) {\n console.warn('[ManagedFavicon] Failed to fetch:', res.status)\n return null\n }\n\n const data = await res.json()\n if (data.image && !data.is_placeholder) {\n const raw = data.image.public_url || data.image.external_url\n const public_url = toAbsoluteFaviconUrl(raw, apiUrl)\n return {\n public_url: public_url || undefined,\n mime_type: data.image.file?.mime_type,\n is_placeholder: false,\n }\n }\n return null\n } catch (err) {\n console.error('[ManagedFavicon] Error fetching favicon:', err)\n return null\n }\n}\n\n/**\n * Return the managed favicon URL for the project (from API key).\n * Use in generateMetadata to set metadata.icons so favicon is consistent across all sites.\n */\nexport async function getManagedFaviconUrl(\n apiKey?: string,\n apiUrl: string = process.env.SONOR_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.sonor.io'\n): Promise<string | null> {\n const key = apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY\n if (!key) return null\n const data = await fetchFaviconData(apiUrl, key)\n return data?.public_url ?? null\n}\n\nexport async function ManagedFavicon({\n apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY,\n apiUrl = process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.sonor.io',\n fallback = '/favicon.ico',\n themeColor = '#4bbf39',\n}: ManagedFaviconProps) {\n // Fetch favicon data during SSR\n const faviconData = apiKey && apiUrl ? await fetchFaviconData(apiUrl, apiKey) : null\n \n const faviconUrl = faviconData?.public_url || fallback\n const mimeType = faviconData?.mime_type || 'image/x-icon'\n const isSvg = mimeType === 'image/svg+xml' || faviconUrl.endsWith('.svg')\n\n return (\n <>\n {/* Primary favicon */}\n {isSvg ? (\n <link rel=\"icon\" type=\"image/svg+xml\" href={faviconUrl} />\n ) : (\n <>\n <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href={faviconUrl} />\n <link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href={faviconUrl} />\n </>\n )}\n \n {/* Apple touch icon (for iOS home screen) */}\n <link rel=\"apple-touch-icon\" sizes=\"180x180\" href={faviconUrl} />\n \n {/* Theme color for mobile browsers */}\n <meta name=\"theme-color\" content={themeColor} />\n </>\n )\n}"]}
|
|
@@ -6,7 +6,7 @@ var react = require('react');
|
|
|
6
6
|
// src/SitemapSync.tsx
|
|
7
7
|
function getApiConfig() {
|
|
8
8
|
if (typeof window === "undefined") return { apiUrl: "", apiKey: "" };
|
|
9
|
-
const apiUrl = window.__SITE_KIT_API_URL__ || "https://api.
|
|
9
|
+
const apiUrl = window.__SITE_KIT_API_URL__ || "https://api.sonor.io";
|
|
10
10
|
const apiKey = window.__SITE_KIT_API_KEY__ || "";
|
|
11
11
|
return { apiUrl, apiKey };
|
|
12
12
|
}
|
|
@@ -134,5 +134,5 @@ function SitemapSync({
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
exports.SitemapSync = SitemapSync;
|
|
137
|
-
//# sourceMappingURL=chunk-
|
|
138
|
-
//# sourceMappingURL=chunk-
|
|
137
|
+
//# sourceMappingURL=chunk-PPRAW576.js.map
|
|
138
|
+
//# sourceMappingURL=chunk-PPRAW576.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/SitemapSync.tsx"],"names":["useRef","useEffect"],"mappings":"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","file":"chunk-LIVWLY2P.js","sourcesContent":["/**\n * SitemapSync - Automatically sync sitemap.xml to Portal API\n *\n * Client-only component. Lives at package root so the main entry does not\n * pull in seo/ (and server-only code). For use in SiteKitProvider and\n * from @sonordev/site-kit/seo.\n *\n * @example\n * ```tsx\n * import { SitemapSync } from '@sonordev/site-kit'\n * // or\n * import { SitemapSync } from '@sonordev/site-kit/seo'\n * ```\n */\n\n'use client'\n\nimport { useEffect, useRef } from 'react'\n\ninterface SitemapSyncProps {\n /** Custom sitemap URL (defaults to /sitemap.xml) */\n sitemapUrl?: string\n /** How often to re-sync in minutes (0 = only on mount, default: 60) */\n syncInterval?: number\n /** Enable debug logging */\n debug?: boolean\n}\n\ninterface SitemapEntry {\n path: string\n lastmod?: string\n changefreq?: string\n priority?: number\n}\n\nfunction getApiConfig() {\n if (typeof window === 'undefined') return { apiUrl: '', apiKey: '' }\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__ || 'https://api.uptrademedia.com'\n const apiKey = (window as any).__SITE_KIT_API_KEY__ || ''\n return { apiUrl, apiKey }\n}\n\nasync function parseSitemap(sitemapUrl: string, debug: boolean): Promise<SitemapEntry[]> {\n try {\n const response = await fetch(sitemapUrl)\n if (!response.ok) {\n if (debug) console.warn('[SitemapSync] Failed to fetch sitemap:', response.status)\n return []\n }\n\n const text = await response.text()\n const parser = new DOMParser()\n const doc = parser.parseFromString(text, 'application/xml')\n\n const parseError = doc.querySelector('parsererror')\n if (parseError) {\n if (debug) console.warn('[SitemapSync] Sitemap parse error:', parseError.textContent)\n return []\n }\n\n const urls = doc.querySelectorAll('url')\n const entries: SitemapEntry[] = []\n\n urls.forEach(url => {\n const loc = url.querySelector('loc')?.textContent\n if (!loc) return\n\n let path: string\n try {\n const urlObj = new URL(loc)\n path = urlObj.pathname\n } catch {\n path = loc.startsWith('/') ? loc : `/${loc}`\n }\n\n if (path !== '/' && path.endsWith('/')) {\n path = path.slice(0, -1)\n }\n\n const lastmod = url.querySelector('lastmod')?.textContent || undefined\n const changefreq = url.querySelector('changefreq')?.textContent || undefined\n const priorityStr = url.querySelector('priority')?.textContent\n const priority = priorityStr ? parseFloat(priorityStr) : undefined\n\n entries.push({ path, lastmod, changefreq, priority })\n })\n\n if (debug) {\n console.log(`[SitemapSync] Parsed ${entries.length} entries from sitemap`)\n }\n\n return entries\n } catch (error) {\n if (debug) console.error('[SitemapSync] Error parsing sitemap:', error)\n return []\n }\n}\n\nasync function syncToPortal(\n entries: SitemapEntry[],\n apiUrl: string,\n apiKey: string,\n debug: boolean\n): Promise<{ success: boolean; created: number; updated: number }> {\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key configured')\n return { success: false, created: 0, updated: 0 }\n }\n\n if (entries.length === 0) {\n if (debug) console.log('[SitemapSync] No entries to sync')\n return { success: true, 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: entries.map(e => ({\n path: e.path,\n priority: e.priority,\n changefreq: e.changefreq,\n })),\n }),\n })\n\n if (!response.ok) {\n if (debug) console.error('[SitemapSync] API error:', response.status, response.statusText)\n return { success: false, created: 0, updated: 0 }\n }\n\n const result = await response.json()\n\n if (debug) {\n console.log(`[SitemapSync] Synced: ${result.created} created, ${result.updated} updated`)\n }\n\n return {\n success: true,\n created: result.created || 0,\n updated: result.updated || 0,\n }\n } catch (error) {\n if (debug) console.error('[SitemapSync] Sync error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport function SitemapSync({\n sitemapUrl = '/sitemap.xml',\n syncInterval = 60,\n debug = false,\n}: SitemapSyncProps) {\n const hasSyncedRef = useRef(false)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n useEffect(() => {\n const doSync = async () => {\n const { apiUrl, apiKey } = getApiConfig()\n\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key found')\n return\n }\n\n if (debug) console.log('[SitemapSync] Starting sitemap sync...')\n\n const entries = await parseSitemap(sitemapUrl, debug)\n\n if (entries.length > 0) {\n await syncToPortal(entries, apiUrl, apiKey, debug)\n }\n }\n\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n doSync()\n }\n\n if (syncInterval > 0) {\n intervalRef.current = setInterval(doSync, syncInterval * 60 * 1000)\n }\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n }\n }\n }, [sitemapUrl, syncInterval, debug])\n\n return null\n}\n\nexport default SitemapSync\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/SitemapSync.tsx"],"names":["useRef","useEffect"],"mappings":"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","file":"chunk-PPRAW576.js","sourcesContent":["/**\n * SitemapSync - Automatically sync sitemap.xml to Portal API\n *\n * Client-only component. Lives at package root so the main entry does not\n * pull in seo/ (and server-only code). For use in SiteKitProvider and\n * from @sonordev/site-kit/seo.\n *\n * @example\n * ```tsx\n * import { SitemapSync } from '@sonordev/site-kit'\n * // or\n * import { SitemapSync } from '@sonordev/site-kit/seo'\n * ```\n */\n\n'use client'\n\nimport { useEffect, useRef } from 'react'\n\ninterface SitemapSyncProps {\n /** Custom sitemap URL (defaults to /sitemap.xml) */\n sitemapUrl?: string\n /** How often to re-sync in minutes (0 = only on mount, default: 60) */\n syncInterval?: number\n /** Enable debug logging */\n debug?: boolean\n}\n\ninterface SitemapEntry {\n path: string\n lastmod?: string\n changefreq?: string\n priority?: number\n}\n\nfunction getApiConfig() {\n if (typeof window === 'undefined') return { apiUrl: '', apiKey: '' }\n\n const apiUrl = (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n const apiKey = (window as any).__SITE_KIT_API_KEY__ || ''\n return { apiUrl, apiKey }\n}\n\nasync function parseSitemap(sitemapUrl: string, debug: boolean): Promise<SitemapEntry[]> {\n try {\n const response = await fetch(sitemapUrl)\n if (!response.ok) {\n if (debug) console.warn('[SitemapSync] Failed to fetch sitemap:', response.status)\n return []\n }\n\n const text = await response.text()\n const parser = new DOMParser()\n const doc = parser.parseFromString(text, 'application/xml')\n\n const parseError = doc.querySelector('parsererror')\n if (parseError) {\n if (debug) console.warn('[SitemapSync] Sitemap parse error:', parseError.textContent)\n return []\n }\n\n const urls = doc.querySelectorAll('url')\n const entries: SitemapEntry[] = []\n\n urls.forEach(url => {\n const loc = url.querySelector('loc')?.textContent\n if (!loc) return\n\n let path: string\n try {\n const urlObj = new URL(loc)\n path = urlObj.pathname\n } catch {\n path = loc.startsWith('/') ? loc : `/${loc}`\n }\n\n if (path !== '/' && path.endsWith('/')) {\n path = path.slice(0, -1)\n }\n\n const lastmod = url.querySelector('lastmod')?.textContent || undefined\n const changefreq = url.querySelector('changefreq')?.textContent || undefined\n const priorityStr = url.querySelector('priority')?.textContent\n const priority = priorityStr ? parseFloat(priorityStr) : undefined\n\n entries.push({ path, lastmod, changefreq, priority })\n })\n\n if (debug) {\n console.log(`[SitemapSync] Parsed ${entries.length} entries from sitemap`)\n }\n\n return entries\n } catch (error) {\n if (debug) console.error('[SitemapSync] Error parsing sitemap:', error)\n return []\n }\n}\n\nasync function syncToPortal(\n entries: SitemapEntry[],\n apiUrl: string,\n apiKey: string,\n debug: boolean\n): Promise<{ success: boolean; created: number; updated: number }> {\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key configured')\n return { success: false, created: 0, updated: 0 }\n }\n\n if (entries.length === 0) {\n if (debug) console.log('[SitemapSync] No entries to sync')\n return { success: true, 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: entries.map(e => ({\n path: e.path,\n priority: e.priority,\n changefreq: e.changefreq,\n })),\n }),\n })\n\n if (!response.ok) {\n if (debug) console.error('[SitemapSync] API error:', response.status, response.statusText)\n return { success: false, created: 0, updated: 0 }\n }\n\n const result = await response.json()\n\n if (debug) {\n console.log(`[SitemapSync] Synced: ${result.created} created, ${result.updated} updated`)\n }\n\n return {\n success: true,\n created: result.created || 0,\n updated: result.updated || 0,\n }\n } catch (error) {\n if (debug) console.error('[SitemapSync] Sync error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\nexport function SitemapSync({\n sitemapUrl = '/sitemap.xml',\n syncInterval = 60,\n debug = false,\n}: SitemapSyncProps) {\n const hasSyncedRef = useRef(false)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n useEffect(() => {\n const doSync = async () => {\n const { apiUrl, apiKey } = getApiConfig()\n\n if (!apiKey) {\n if (debug) console.warn('[SitemapSync] No API key found')\n return\n }\n\n if (debug) console.log('[SitemapSync] Starting sitemap sync...')\n\n const entries = await parseSitemap(sitemapUrl, debug)\n\n if (entries.length > 0) {\n await syncToPortal(entries, apiUrl, apiKey, debug)\n }\n }\n\n if (!hasSyncedRef.current) {\n hasSyncedRef.current = true\n doSync()\n }\n\n if (syncInterval > 0) {\n intervalRef.current = setInterval(doSync, syncInterval * 60 * 1000)\n }\n\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n }\n }\n }, [sitemapUrl, syncInterval, debug])\n\n return null\n}\n\nexport default SitemapSync\n"]}
|
|
@@ -14,7 +14,7 @@ function useSignal() {
|
|
|
14
14
|
return context;
|
|
15
15
|
}
|
|
16
16
|
function getApiConfig() {
|
|
17
|
-
const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.
|
|
17
|
+
const apiUrl = typeof window !== "undefined" ? window.__SITE_KIT_API_URL__ || "https://api.sonor.io" : "https://api.sonor.io";
|
|
18
18
|
const apiKey = typeof window !== "undefined" ? window.__SITE_KIT_API_KEY__ : void 0;
|
|
19
19
|
return { apiUrl, apiKey };
|
|
20
20
|
}
|
|
@@ -346,5 +346,5 @@ exports.useSignalConfig = useSignalConfig;
|
|
|
346
346
|
exports.useSignalEvent = useSignalEvent;
|
|
347
347
|
exports.useSignalExperiment = useSignalExperiment;
|
|
348
348
|
exports.useSignalOutcome = useSignalOutcome;
|
|
349
|
-
//# sourceMappingURL=chunk-
|
|
350
|
-
//# sourceMappingURL=chunk-
|
|
349
|
+
//# sourceMappingURL=chunk-REMHGWXT.js.map
|
|
350
|
+
//# sourceMappingURL=chunk-REMHGWXT.js.map
|