@sonordev/site-kit 1.2.7 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-QETK4P5G.mjs +142 -0
- package/dist/chunk-QETK4P5G.mjs.map +1 -0
- 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-VTECURKB.js +144 -0
- package/dist/chunk-VTECURKB.js.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/client.d.mts +18 -0
- package/dist/layout/client.d.ts +18 -0
- package/dist/layout/client.js +18 -0
- package/dist/layout/client.js.map +1 -0
- package/dist/layout/client.mjs +9 -0
- package/dist/layout/client.mjs.map +1 -0
- package/dist/layout/index.d.mts +4 -27
- package/dist/layout/index.d.ts +4 -27
- package/dist/layout/index.js +15 -145
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/index.mjs +11 -141
- 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-5RCOK10v.d.mts +25 -0
- package/dist/types-5RCOK10v.d.ts +25 -0
- 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,142 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { SignalBridge } from './chunk-UPR5FEIO.mjs';
|
|
3
|
+
import { SitemapSync } from './chunk-JIDOXTX2.mjs';
|
|
4
|
+
import { AnalyticsProvider } from './chunk-DOSSLBNW.mjs';
|
|
5
|
+
import { EngageWidget } from './chunk-EISQ7LJG.mjs';
|
|
6
|
+
import { createContext, useState, useRef, useCallback, Suspense, useMemo } from 'react';
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function generateId() {
|
|
10
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
11
|
+
return crypto.randomUUID();
|
|
12
|
+
}
|
|
13
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
14
|
+
const r = Math.random() * 16 | 0;
|
|
15
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function getOrCreateVisitorId() {
|
|
19
|
+
if (typeof window === "undefined") return "";
|
|
20
|
+
const key = "_uptrade_vid";
|
|
21
|
+
let visitorId = localStorage.getItem(key);
|
|
22
|
+
if (!visitorId) {
|
|
23
|
+
visitorId = generateId();
|
|
24
|
+
localStorage.setItem(key, visitorId);
|
|
25
|
+
}
|
|
26
|
+
return visitorId;
|
|
27
|
+
}
|
|
28
|
+
function getOrCreateSessionId(timeoutMinutes = 30) {
|
|
29
|
+
if (typeof window === "undefined") return "";
|
|
30
|
+
const key = "_uptrade_sid";
|
|
31
|
+
const timeKey = "_uptrade_stime";
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
const timeoutMs = timeoutMinutes * 60 * 1e3;
|
|
34
|
+
const existingSession = sessionStorage.getItem(key);
|
|
35
|
+
const lastActivity = sessionStorage.getItem(timeKey);
|
|
36
|
+
if (existingSession && lastActivity) {
|
|
37
|
+
const elapsed = now - parseInt(lastActivity, 10);
|
|
38
|
+
if (elapsed < timeoutMs) {
|
|
39
|
+
sessionStorage.setItem(timeKey, now.toString());
|
|
40
|
+
return existingSession;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const newSession = generateId();
|
|
44
|
+
sessionStorage.setItem(key, newSession);
|
|
45
|
+
sessionStorage.setItem(timeKey, now.toString());
|
|
46
|
+
return newSession;
|
|
47
|
+
}
|
|
48
|
+
var SiteKitIdentityContext = createContext(null);
|
|
49
|
+
function SiteKitIdentityProvider({
|
|
50
|
+
visitorId,
|
|
51
|
+
sessionId,
|
|
52
|
+
children
|
|
53
|
+
}) {
|
|
54
|
+
const value = useMemo(() => ({ visitorId, sessionId }), [visitorId, sessionId]);
|
|
55
|
+
return /* @__PURE__ */ jsx(SiteKitIdentityContext.Provider, { value, children });
|
|
56
|
+
}
|
|
57
|
+
function SiteKitClientProviders({
|
|
58
|
+
children,
|
|
59
|
+
apiKey,
|
|
60
|
+
apiUrl,
|
|
61
|
+
projectId,
|
|
62
|
+
analytics = true,
|
|
63
|
+
engage = true,
|
|
64
|
+
signal = false,
|
|
65
|
+
sitemapSync = true,
|
|
66
|
+
debug = false
|
|
67
|
+
}) {
|
|
68
|
+
if (typeof window !== "undefined") {
|
|
69
|
+
window.__SITE_KIT_API_URL__ = apiUrl;
|
|
70
|
+
window.__SITE_KIT_API_KEY__ = apiKey;
|
|
71
|
+
window.__SITE_KIT_DEBUG__ = debug;
|
|
72
|
+
}
|
|
73
|
+
const [visitorId] = useState(() => getOrCreateVisitorId());
|
|
74
|
+
const [sessionId] = useState(() => getOrCreateSessionId());
|
|
75
|
+
const pageMetadataRef = useRef(null);
|
|
76
|
+
const onPageMetadata = useCallback((metadata) => {
|
|
77
|
+
pageMetadataRef.current = metadata;
|
|
78
|
+
}, []);
|
|
79
|
+
let content = /* @__PURE__ */ jsx(Fragment, { children });
|
|
80
|
+
if (signal) {
|
|
81
|
+
const signalConfig = typeof signal === "object" ? signal : {};
|
|
82
|
+
content = /* @__PURE__ */ jsx(
|
|
83
|
+
SignalBridge,
|
|
84
|
+
{
|
|
85
|
+
enabled: true,
|
|
86
|
+
realtime: signalConfig.realtime !== false,
|
|
87
|
+
experiments: signalConfig.experiments !== false,
|
|
88
|
+
behaviorTracking: signalConfig.behaviorTracking !== false,
|
|
89
|
+
visitorId,
|
|
90
|
+
sessionId,
|
|
91
|
+
pageMetadataRef,
|
|
92
|
+
children: content
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
if (analytics) {
|
|
97
|
+
const analyticsConfig = typeof analytics === "object" ? analytics : {};
|
|
98
|
+
content = /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
|
|
99
|
+
AnalyticsProvider,
|
|
100
|
+
{
|
|
101
|
+
apiUrl,
|
|
102
|
+
apiKey,
|
|
103
|
+
trackPageViews: analyticsConfig.trackPageViews !== false,
|
|
104
|
+
trackWebVitals: analyticsConfig.trackWebVitals !== false,
|
|
105
|
+
trackScrollDepth: analyticsConfig.trackScrollDepth !== false,
|
|
106
|
+
trackClicks: analyticsConfig.trackClicks !== false,
|
|
107
|
+
debug,
|
|
108
|
+
externalVisitorId: visitorId,
|
|
109
|
+
externalSessionId: sessionId,
|
|
110
|
+
onPageMetadata,
|
|
111
|
+
children: content
|
|
112
|
+
}
|
|
113
|
+
) });
|
|
114
|
+
}
|
|
115
|
+
if (engage) {
|
|
116
|
+
const engageConfig = typeof engage === "object" ? engage : {};
|
|
117
|
+
content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
118
|
+
content,
|
|
119
|
+
/* @__PURE__ */ jsx(
|
|
120
|
+
EngageWidget,
|
|
121
|
+
{
|
|
122
|
+
apiUrl,
|
|
123
|
+
apiKey,
|
|
124
|
+
projectId,
|
|
125
|
+
position: engageConfig.position || "bottom-right",
|
|
126
|
+
chatEnabled: engageConfig.chatEnabled !== false
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] });
|
|
130
|
+
}
|
|
131
|
+
if (sitemapSync) {
|
|
132
|
+
content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
133
|
+
content,
|
|
134
|
+
/* @__PURE__ */ jsx(SitemapSync, { debug })
|
|
135
|
+
] });
|
|
136
|
+
}
|
|
137
|
+
return /* @__PURE__ */ jsx(SiteKitIdentityProvider, { visitorId, sessionId, children: content });
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export { SiteKitClientProviders };
|
|
141
|
+
//# sourceMappingURL=chunk-QETK4P5G.mjs.map
|
|
142
|
+
//# sourceMappingURL=chunk-QETK4P5G.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/identity.tsx","../src/layout/SiteKitClientProviders.tsx"],"names":["jsx"],"mappings":"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","file":"chunk-QETK4P5G.mjs","sourcesContent":["/**\n * @sonordev/site-kit/shared — Unified Identity Management\n *\n * Single source of truth for visitor and session IDs across\n * Analytics, Signal, and Engage modules.\n *\n * Storage keys:\n * localStorage: _uptrade_vid (visitor ID, persists ~forever)\n * sessionStorage: _uptrade_sid (session ID, per-tab)\n * sessionStorage: _uptrade_stime (last activity timestamp for timeout)\n */\n\n'use client'\n\nimport React, { createContext, useContext, useMemo } from 'react'\n\n// ============================================\n// ID Generation\n// ============================================\n\nfunction generateId(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID()\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16)\n })\n}\n\n/**\n * Get or create a persistent visitor ID.\n * Stored in localStorage under `_uptrade_vid`.\n */\nexport function getOrCreateVisitorId(): string {\n if (typeof window === 'undefined') return ''\n\n const key = '_uptrade_vid'\n let visitorId = localStorage.getItem(key)\n\n if (!visitorId) {\n visitorId = generateId()\n localStorage.setItem(key, visitorId)\n }\n\n return visitorId\n}\n\n/**\n * Get or create a session ID with inactivity timeout.\n * Stored in sessionStorage under `_uptrade_sid`.\n * Session expires after `timeoutMinutes` of inactivity (default 30).\n */\nexport function getOrCreateSessionId(timeoutMinutes = 30): string {\n if (typeof window === 'undefined') return ''\n\n const key = '_uptrade_sid'\n const timeKey = '_uptrade_stime'\n const now = Date.now()\n const timeoutMs = timeoutMinutes * 60 * 1000\n\n const existingSession = sessionStorage.getItem(key)\n const lastActivity = sessionStorage.getItem(timeKey)\n\n if (existingSession && lastActivity) {\n const elapsed = now - parseInt(lastActivity, 10)\n if (elapsed < timeoutMs) {\n // Session still active — refresh timestamp\n sessionStorage.setItem(timeKey, now.toString())\n return existingSession\n }\n }\n\n // New session (first visit or timeout expired)\n const newSession = generateId()\n sessionStorage.setItem(key, newSession)\n sessionStorage.setItem(timeKey, now.toString())\n return newSession\n}\n\n// ============================================\n// React Context\n// ============================================\n\nexport interface SiteKitIdentity {\n visitorId: string\n sessionId: string\n}\n\nconst SiteKitIdentityContext = createContext<SiteKitIdentity | null>(null)\n\nexport interface SiteKitIdentityProviderProps {\n visitorId: string\n sessionId: string\n children: React.ReactNode\n}\n\nexport function SiteKitIdentityProvider({\n visitorId,\n sessionId,\n children,\n}: SiteKitIdentityProviderProps) {\n const value = useMemo(() => ({ visitorId, sessionId }), [visitorId, sessionId])\n\n return (\n <SiteKitIdentityContext.Provider value={value}>\n {children}\n </SiteKitIdentityContext.Provider>\n )\n}\n\n/**\n * Access the shared visitor/session identity.\n * Falls back to generating IDs directly if used outside of SiteKitIdentityProvider.\n */\nexport function useSiteKitIdentity(): SiteKitIdentity {\n const context = useContext(SiteKitIdentityContext)\n if (context) return context\n\n // Fallback for standalone usage outside SiteKitLayout\n return {\n visitorId: getOrCreateVisitorId(),\n sessionId: getOrCreateSessionId(),\n }\n}\n","'use client'\n\n/**\n * SiteKitClientProviders — Client Island\n *\n * This is the 'use client' boundary for SiteKitLayout.\n * It composes the client-only providers (Analytics, Engage, Signal, SitemapSync)\n * that require React context or browser APIs.\n *\n * All modules share a unified identity (visitor ID + session ID) via\n * SiteKitIdentityProvider, ensuring consistent tracking across Analytics,\n * Signal, and Engage.\n *\n * Props are passed down from the server-side SiteKitLayout component,\n * which reads env vars at render time.\n */\n\nimport React, { Suspense, useCallback, useRef, useState, type ReactNode } from 'react'\nimport { AnalyticsProvider } from '../analytics/AnalyticsProvider'\nimport { EngageWidget } from '../engage/EngageWidget'\nimport { SignalBridge } from '../signal/SignalBridge'\nimport { SitemapSync } from '../SitemapSync'\nimport {\n SiteKitIdentityProvider,\n getOrCreateVisitorId,\n getOrCreateSessionId,\n} from '../shared/identity'\nimport type { AnalyticsConfig, EngageConfig, SignalConfig } from './types'\n\nexport interface SiteKitClientProvidersProps {\n children: ReactNode\n apiKey: string\n apiUrl: string\n projectId?: string\n analytics?: boolean | AnalyticsConfig\n engage?: boolean | EngageConfig\n signal?: boolean | SignalConfig\n sitemapSync?: boolean\n debug?: boolean\n}\n\nexport function SiteKitClientProviders({\n children,\n apiKey,\n apiUrl,\n projectId,\n analytics = true,\n engage = true,\n signal = false,\n sitemapSync = true,\n debug = false,\n}: SiteKitClientProvidersProps) {\n // Set window globals for modules that still read from them\n if (typeof window !== 'undefined') {\n ;(window as any).__SITE_KIT_API_URL__ = apiUrl\n ;(window as any).__SITE_KIT_API_KEY__ = apiKey\n ;(window as any).__SITE_KIT_DEBUG__ = debug\n }\n\n // Unified identity — single source of truth for all modules\n const [visitorId] = useState(() => getOrCreateVisitorId())\n const [sessionId] = useState(() => getOrCreateSessionId())\n\n // Page metadata bridge: Analytics writes, Signal reads\n const pageMetadataRef = useRef<Record<string, unknown> | null>(null)\n const onPageMetadata = useCallback((metadata: Record<string, unknown>) => {\n pageMetadataRef.current = metadata\n }, [])\n\n let content = <>{children}</>\n\n // Wrap with SignalBridge if enabled\n if (signal) {\n const signalConfig: SignalConfig =\n typeof signal === 'object' ? signal : {}\n content = (\n <SignalBridge\n enabled\n realtime={signalConfig.realtime !== false}\n experiments={signalConfig.experiments !== false}\n behaviorTracking={signalConfig.behaviorTracking !== false}\n visitorId={visitorId}\n sessionId={sessionId}\n pageMetadataRef={pageMetadataRef}\n >\n {content}\n </SignalBridge>\n )\n }\n\n // Wrap with Analytics if enabled\n if (analytics) {\n const analyticsConfig: AnalyticsConfig =\n typeof analytics === 'object' ? analytics : {}\n content = (\n <Suspense fallback={null}>\n <AnalyticsProvider\n apiUrl={apiUrl}\n apiKey={apiKey}\n trackPageViews={analyticsConfig.trackPageViews !== false}\n trackWebVitals={analyticsConfig.trackWebVitals !== false}\n trackScrollDepth={analyticsConfig.trackScrollDepth !== false}\n trackClicks={analyticsConfig.trackClicks !== false}\n debug={debug}\n externalVisitorId={visitorId}\n externalSessionId={sessionId}\n onPageMetadata={onPageMetadata}\n >\n {content}\n </AnalyticsProvider>\n </Suspense>\n )\n }\n\n // Add Engage widget if enabled (renders alongside, doesn't wrap)\n if (engage) {\n const engageConfig: EngageConfig =\n typeof engage === 'object' ? engage : {}\n content = (\n <>\n {content}\n <EngageWidget\n apiUrl={apiUrl}\n apiKey={apiKey}\n projectId={projectId}\n position={engageConfig.position || 'bottom-right'}\n chatEnabled={engageConfig.chatEnabled !== false}\n />\n </>\n )\n }\n\n // Add SitemapSync if enabled\n if (sitemapSync) {\n content = (\n <>\n {content}\n <SitemapSync debug={debug} />\n </>\n )\n }\n\n return (\n <SiteKitIdentityProvider visitorId={visitorId} sessionId={sessionId}>\n {content}\n </SiteKitIdentityProvider>\n )\n}\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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/signal/SignalBridge.tsx"],"names":["createContext","useContext","useState","useRef","useCallback","useEffect","useMemo"],"mappings":"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","file":"chunk-REMHGWXT.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalBridge\n * \n * Central coordination layer for Signal AI integration.\n * Handles config fetching, SSE streaming, experiment assignment, and outcome tracking.\n */\n\n'use client'\n\nimport React, { createContext, useContext, useState, useEffect, useCallback, useRef, useMemo } from 'react'\nimport type { \n SignalConfig, \n SignalContextValue, \n SignalBridgeProps,\n SignalEvent,\n SignalOutcome,\n ExperimentAssignment \n} from './types'\n\n// ============================================\n// Context\n// ============================================\n\nconst SignalContext = createContext<SignalContextValue | null>(null)\n\nexport function useSignal(): SignalContextValue {\n const context = useContext(SignalContext)\n if (!context) {\n throw new Error('useSignal must be used within a SignalBridge')\n }\n return context\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined' \n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey = typeof window !== 'undefined' \n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\nfunction getVisitorId(): string {\n if (typeof window === 'undefined') return ''\n \n const key = '_uptrade_vid'\n let visitorId = localStorage.getItem(key)\n \n if (!visitorId) {\n visitorId = crypto.randomUUID()\n localStorage.setItem(key, visitorId)\n }\n \n return visitorId\n}\n\nfunction getSessionId(): string {\n if (typeof window === 'undefined') return ''\n \n const key = '_uptrade_sid'\n let sessionId = sessionStorage.getItem(key)\n \n if (!sessionId) {\n sessionId = crypto.randomUUID()\n sessionStorage.setItem(key, sessionId)\n }\n \n return sessionId\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\nfunction getBrowser(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Firefox')) return 'Firefox'\n if (ua.includes('Edg')) return 'Edge'\n if (ua.includes('Chrome')) return 'Chrome'\n if (ua.includes('Safari')) return 'Safari'\n return 'Other'\n}\n\nfunction getOS(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Windows')) return 'Windows'\n if (ua.includes('Mac')) return 'macOS'\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n if (ua.includes('Android')) return 'Android'\n if (ua.includes('Linux')) return 'Linux'\n return 'Other'\n}\n\n// ============================================\n// SignalBridge Component\n// ============================================\n\nexport function SignalBridge({\n enabled = true,\n realtime = true,\n experiments = true,\n behaviorTracking = true,\n visitorId: externalVisitorId,\n sessionId: externalSessionId,\n pageMetadataRef,\n children,\n}: SignalBridgeProps) {\n const [config, setConfig] = useState<SignalConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n \n // Refs for SSE and tracking\n const eventSourceRef = useRef<EventSource | null>(null)\n const eventQueueRef = useRef<Partial<SignalEvent>[]>([])\n const flushTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const assignmentsRef = useRef<Map<string, ExperimentAssignment>>(new Map())\n \n // Behavioral tracking state\n const pageLoadTimeRef = useRef<number>(Date.now())\n const scrollDepthRef = useRef<number>(0)\n const clickCountRef = useRef<number>(0)\n \n const { apiUrl, apiKey } = getApiConfig()\n\n // Use external IDs from shared identity, fall back to internal generation\n const resolvedVisitorId = externalVisitorId || getVisitorId()\n const resolvedSessionId = externalSessionId || getSessionId()\n\n // ============================================\n // Config Fetching\n // ============================================\n\n const fetchConfig = useCallback(async () => {\n if (!apiKey || !enabled) {\n setLoading(false)\n return\n }\n\n try {\n const response = await fetch(`${apiUrl}/api/public/signal/config`, {\n headers: {\n 'x-api-key': apiKey,\n 'x-visitor-id': resolvedVisitorId,\n },\n })\n \n if (!response.ok) {\n throw new Error(`Failed to fetch Signal config: ${response.statusText}`)\n }\n \n const data = await response.json()\n setConfig(data.config)\n setError(null)\n \n // Load experiment assignments\n if (experiments && data.config?.experiments) {\n for (const exp of data.config.experiments) {\n if (exp.status === 'running') {\n await loadExperimentAssignment(exp.id)\n }\n }\n }\n } catch (err) {\n console.error('[Signal] Config fetch error:', err)\n setError(err as Error)\n } finally {\n setLoading(false)\n }\n }, [apiUrl, apiKey, enabled, experiments, resolvedVisitorId])\n\n // ============================================\n // SSE Real-time Updates\n // ============================================\n \n const connectSSE = useCallback(() => {\n if (!apiKey || !enabled || !realtime) return\n \n // Close existing connection\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n \n const url = `${apiUrl}/api/public/signal/stream?key=${apiKey}`\n const eventSource = new EventSource(url)\n \n eventSource.addEventListener('config_update', (e) => {\n try {\n const { config: newConfig, version } = JSON.parse(e.data)\n setConfig(prev => {\n if (prev?.version !== version) {\n console.log('[Signal] Config updated to version:', version)\n return newConfig\n }\n return prev\n })\n } catch (err) {\n console.error('[Signal] SSE parse error:', err)\n }\n })\n \n eventSource.addEventListener('experiment_update', (e) => {\n try {\n const { experiment_id, action } = JSON.parse(e.data)\n if (action === 'started' || action === 'updated') {\n loadExperimentAssignment(experiment_id)\n } else if (action === 'stopped') {\n assignmentsRef.current.delete(experiment_id)\n }\n } catch (err) {\n console.error('[Signal] Experiment update error:', err)\n }\n })\n \n eventSource.onerror = () => {\n console.warn('[Signal] SSE connection error, reconnecting...')\n eventSource.close()\n // Reconnect after 5 seconds\n setTimeout(connectSSE, 5000)\n }\n \n eventSourceRef.current = eventSource\n }, [apiUrl, apiKey, enabled, realtime])\n\n // ============================================\n // Experiment Assignment\n // ============================================\n \n const loadExperimentAssignment = useCallback(async (experimentId: string): Promise<ExperimentAssignment | null> => {\n // Check localStorage first\n const storageKey = `_signal_exp_${experimentId}`\n const stored = localStorage.getItem(storageKey)\n \n if (stored) {\n try {\n const assignment = JSON.parse(stored) as ExperimentAssignment\n if (assignment.expires > Date.now()) {\n assignmentsRef.current.set(experimentId, assignment)\n return assignment\n }\n } catch {\n // Invalid stored data, continue to fetch\n }\n }\n \n // Fetch from API\n try {\n const response = await fetch(`${apiUrl}/api/public/signal/experiment/${experimentId}`, {\n headers: {\n 'x-api-key': apiKey!,\n 'x-visitor-id': resolvedVisitorId,\n },\n })\n \n if (!response.ok) return null\n \n const assignment = await response.json() as ExperimentAssignment\n \n // Store assignment\n localStorage.setItem(storageKey, JSON.stringify(assignment))\n assignmentsRef.current.set(experimentId, assignment)\n \n return assignment\n } catch (err) {\n console.error('[Signal] Experiment assignment error:', err)\n return null\n }\n }, [apiUrl, apiKey])\n \n const getExperiment = useCallback((experimentId: string): ExperimentAssignment | null => {\n return assignmentsRef.current.get(experimentId) || null\n }, [])\n\n // ============================================\n // Event Tracking\n // ============================================\n \n const flushEvents = useCallback(async () => {\n if (eventQueueRef.current.length === 0) return\n \n const events = [...eventQueueRef.current]\n eventQueueRef.current = []\n \n try {\n await fetch(`${apiUrl}/api/public/signal/events`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey!,\n },\n body: JSON.stringify({\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n events,\n }),\n })\n } catch (err) {\n // Re-queue failed events\n eventQueueRef.current = [...events, ...eventQueueRef.current]\n console.error('[Signal] Event flush error:', err)\n }\n }, [apiUrl, apiKey])\n \n const trackEvent = useCallback((event: Partial<SignalEvent>) => {\n if (!enabled || !apiKey) return\n \n // Enrich event with context\n const enrichedEvent: Partial<SignalEvent> = {\n ...event,\n page_url: window.location.href,\n page_path: window.location.pathname,\n referrer: document.referrer,\n device_type: getDeviceType(),\n browser: getBrowser(),\n os: getOS(),\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n time_on_page: Date.now() - pageLoadTimeRef.current,\n scroll_depth: scrollDepthRef.current,\n click_count: clickCountRef.current,\n experiments: Array.from(assignmentsRef.current.values()).map(a => ({\n experiment_id: a.experiment_id,\n variant_key: a.variant_key,\n })),\n // Merge page metadata from Analytics if available\n page_metadata: pageMetadataRef?.current ?? undefined,\n timestamp: new Date().toISOString(),\n }\n \n eventQueueRef.current.push(enrichedEvent)\n \n // Debounce flush\n if (flushTimeoutRef.current) {\n clearTimeout(flushTimeoutRef.current)\n }\n flushTimeoutRef.current = setTimeout(flushEvents, 1000)\n }, [enabled, apiKey, flushEvents])\n\n // ============================================\n // Outcome Tracking\n // ============================================\n \n const trackOutcome = useCallback(async (outcome: SignalOutcome) => {\n if (!enabled || !apiKey) return\n \n try {\n await fetch(`${apiUrl}/api/public/signal/outcome`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({\n ...outcome,\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n experiments: Array.from(assignmentsRef.current.keys()),\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n }),\n })\n } catch (err) {\n console.error('[Signal] Outcome tracking error:', err)\n }\n }, [apiUrl, apiKey, enabled])\n\n // ============================================\n // Behavioral Tracking\n // ============================================\n \n useEffect(() => {\n if (!behaviorTracking || typeof window === 'undefined') return\n \n // Track scroll depth\n const handleScroll = () => {\n const scrollTop = window.scrollY\n const docHeight = document.documentElement.scrollHeight - window.innerHeight\n const depth = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0\n scrollDepthRef.current = Math.max(scrollDepthRef.current, depth)\n }\n \n // Track clicks\n const handleClick = () => {\n clickCountRef.current++\n }\n \n // Reset on page change\n const handlePageChange = () => {\n pageLoadTimeRef.current = Date.now()\n scrollDepthRef.current = 0\n clickCountRef.current = 0\n }\n \n window.addEventListener('scroll', handleScroll, { passive: true })\n window.addEventListener('click', handleClick)\n \n // Flush on visibility change or unload\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n flushEvents()\n }\n }\n \n document.addEventListener('visibilitychange', handleVisibilityChange)\n window.addEventListener('beforeunload', flushEvents)\n \n return () => {\n window.removeEventListener('scroll', handleScroll)\n window.removeEventListener('click', handleClick)\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n window.removeEventListener('beforeunload', flushEvents)\n }\n }, [behaviorTracking, flushEvents])\n\n // ============================================\n // Initialization\n // ============================================\n \n useEffect(() => {\n fetchConfig()\n }, [fetchConfig])\n \n useEffect(() => {\n if (config && realtime) {\n connectSSE()\n }\n \n return () => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n }\n }, [config, realtime, connectSSE])\n\n // ============================================\n // Context Value\n // ============================================\n \n const contextValue = useMemo<SignalContextValue>(() => ({\n config,\n loading,\n error,\n trackEvent,\n trackOutcome,\n getExperiment,\n refreshConfig: fetchConfig,\n }), [config, loading, error, trackEvent, trackOutcome, getExperiment, fetchConfig])\n\n return (\n <SignalContext.Provider value={contextValue}>\n {children}\n </SignalContext.Provider>\n )\n}\n\n// ============================================\n// Convenience Hooks\n// ============================================\n\n/**\n * Hook to access Signal config\n */\nexport function useSignalConfig(): SignalConfig | null {\n const { config } = useSignal()\n return config\n}\n\n/**\n * Hook for tracking events\n */\nexport function useSignalEvent() {\n const { trackEvent } = useSignal()\n return trackEvent\n}\n\n/**\n * Hook for tracking outcomes/conversions\n */\nexport function useSignalOutcome() {\n const { trackOutcome } = useSignal()\n return { trackOutcome }\n}\n\n/**\n * Hook for experiment assignment\n */\nexport function useSignalExperiment(experimentId: string): {\n assignment: ExperimentAssignment | null\n variant: string | null\n isControl: boolean\n} {\n const { getExperiment, config } = useSignal()\n const assignment = getExperiment(experimentId)\n \n // Check if experiment is running\n const experiment = config?.experiments?.find(e => e.id === experimentId)\n const isRunning = experiment?.status === 'running'\n \n return {\n assignment: isRunning ? assignment : null,\n variant: isRunning && assignment ? assignment.variant_key : null,\n isControl: !assignment || assignment.variant_key === 'control',\n }\n}\n"]}
|
|
@@ -5,15 +5,15 @@ require('server-only');
|
|
|
5
5
|
|
|
6
6
|
// src/seo/server-api.ts
|
|
7
7
|
function getSecureApiConfig() {
|
|
8
|
-
const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
9
|
-
const apiKey = process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
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
10
|
if (!apiKey) {
|
|
11
|
-
throw new Error("@sonordev/seo:
|
|
11
|
+
throw new Error("@sonordev/seo: SONOR_API_KEY (or UPTRADE_API_KEY) environment variable is required for server-side SEO functions");
|
|
12
12
|
}
|
|
13
13
|
return { apiUrl, apiKey };
|
|
14
14
|
}
|
|
15
15
|
function getProjectIdFromKey(apiKey) {
|
|
16
|
-
const match = apiKey.match(/^
|
|
16
|
+
const match = apiKey.match(/^(?:sonor|uptrade)_([0-9a-f-]{36})_/);
|
|
17
17
|
return match ? match[1] : null;
|
|
18
18
|
}
|
|
19
19
|
async function secureApiPost(endpoint, body = {}) {
|
|
@@ -129,8 +129,8 @@ var ensureMetadata = react.cache(async (path) => {
|
|
|
129
129
|
return secureApiPost("/api/public/seo/ensure-metadata", { path });
|
|
130
130
|
});
|
|
131
131
|
function getSignalApiConfig() {
|
|
132
|
-
const apiUrl = process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.
|
|
133
|
-
const apiKey = process.env.UPTRADE_API_KEY || "";
|
|
132
|
+
const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.sonor.io";
|
|
133
|
+
const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
|
|
134
134
|
return { apiUrl, apiKey };
|
|
135
135
|
}
|
|
136
136
|
async function signalApiGet(endpoint) {
|
|
@@ -217,5 +217,5 @@ exports.getVisibilityScore = getVisibilityScore;
|
|
|
217
217
|
exports.getVisibilitySummary = getVisibilitySummary;
|
|
218
218
|
exports.recordABImpression = recordABImpression;
|
|
219
219
|
exports.registerSitemap = registerSitemap;
|
|
220
|
-
//# sourceMappingURL=chunk-
|
|
221
|
-
//# sourceMappingURL=chunk-
|
|
220
|
+
//# sourceMappingURL=chunk-RMOL4TZ6.js.map
|
|
221
|
+
//# sourceMappingURL=chunk-RMOL4TZ6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/seo/server-api.ts"],"names":["cache"],"mappings":"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","file":"chunk-RMOL4TZ6.js","sourcesContent":["/**\n * @sonordev/site-kit/seo - Server-Only API Functions\n * \n * SECURITY: These functions use private environment variables\n * and should ONLY be imported in server-side code (RSC, API routes, server actions).\n * \n * DO NOT import this file in client components or it will expose API keys.\n */\n\nimport { cache } from 'react'\nimport 'server-only' // This ensures the module can only be imported server-side\n\n// ============================================\n// Server-Only API Config\n// ============================================\n\n/**\n * Config for portal API calls. Project is resolved by the portal from the API key;\n * sites never send or read project ID.\n */\nfunction getSecureApiConfig() {\n const apiUrl = process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || 'https://api.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || ''\n\n if (!apiKey) {\n throw new Error('@sonordev/seo: SONOR_API_KEY (or UPTRADE_API_KEY) environment variable is required for server-side SEO functions')\n }\n\n return { apiUrl, apiKey }\n}\n\n/** Derive project ID from API key for Signal API only (format: sonor_{uuid}_{secret} or uptrade_{uuid}_{secret}). Not used for portal. */\nfunction getProjectIdFromKey(apiKey: string): string | null {\n const match = apiKey.match(/^(?:sonor|uptrade)_([0-9a-f-]{36})_/)\n return match ? match[1] : null\n}\n\nasync function secureApiPost<T>(endpoint: string, body: Record<string, any> = {}): 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 }, // Cache for 60 seconds\n })\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(`@sonordev/seo: API error ${response.status} ${endpoint}: ${detail}`)\n return null\n }\n\n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\nasync function secureApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSecureApiConfig()\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: 60 },\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: API error ${response.status}: ${response.statusText}`)\n return null\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Network error:', error)\n return null\n }\n}\n\n// ============================================\n// Secure Cached Data Fetchers\n// ============================================\n\n/**\n * Fetch SEO page data - cached per request\n * @server-only\n */\nexport const getSEOPageData = cache(async (path: string) => {\n const result = await secureApiPost<{ page: any; project: any }>('/api/public/seo/page', { path })\n return {\n page: result?.page || null,\n project: result?.project || null,\n }\n})\n\n/**\n * Fetch schema markups for a page - cached per request\n * @server-only\n */\nexport const getSchemaMarkups = cache(async (\n path: string,\n options?: { includeTypes?: string[]; excludeTypes?: string[] }\n) => {\n const result = await secureApiPost<{ schemas: any[] }>('/api/public/seo/schemas', {\n path,\n includeTypes: options?.includeTypes,\n excludeTypes: options?.excludeTypes,\n })\n return result?.schemas || []\n})\n\n/**\n * Fetch FAQ data for a page - cached per request\n * @server-only\n */\nexport const getFAQData = cache(async (path: string) => {\n const result = await secureApiPost<{ faq: any }>('/api/public/seo/faq', { path })\n return result?.faq || null\n})\n\n/**\n * Fetch internal links for a page - cached per request\n * @server-only\n */\nexport const getInternalLinks = cache(async (\n sourcePath: string,\n options?: { position?: string; limit?: number }\n) => {\n const result = await secureApiPost<{ links: any[] }>('/api/public/seo/internal-links', {\n sourcePath,\n position: options?.position,\n limit: options?.limit,\n })\n return result?.links || []\n})\n\n/**\n * Fetch content block - cached per request\n * @server-only\n */\nexport const getContentBlock = cache(async (path: string, section: string) => {\n const result = await secureApiPost<{ content: any }>('/api/public/seo/content', { path, section })\n return result?.content || null\n})\n\n/**\n * Fetch A/B test and determine variant - cached per request\n * @server-only\n */\nexport const getABTest = cache(async (path: string, field: string) => {\n const result = await secureApiPost<{ test: any }>('/api/public/seo/ab-test', { path, field })\n return result?.test || null\n})\n\n/**\n * Record A/B test impression\n * @server-only\n */\nexport async function recordABImpression(\n testId: string,\n variant: 'a' | 'b',\n sessionId?: string\n): Promise<void> {\n await secureApiPost('/api/public/seo/ab-impression', { testId, variant, sessionId })\n}\n\n/**\n * Fetch redirect for a path - cached per request\n * @server-only\n */\nexport const getRedirectData = cache(async (path: string) => {\n const result = await secureApiPost<{ redirect: any }>('/api/public/seo/redirect', { path })\n return result?.redirect || null\n})\n\n/**\n * Fetch managed scripts - cached per request\n * @server-only\n */\nexport const getManagedScripts = cache(async (position: string, currentPath?: string) => {\n const result = await secureApiPost<{ scripts: any[] }>('/api/public/seo/scripts', {\n position,\n currentPath,\n })\n return result?.scripts || []\n})\n\n/**\n * Fetch robots directive for a page - cached per request\n * @server-only\n */\nexport const getRobotsData = cache(async (path: string) => {\n const result = await secureApiPost<{ page: any }>('/api/public/seo/page', { path })\n return result?.page?.managed_robots || null\n})\n\n/**\n * Fetch sitemap entries - cached per request\n * @server-only\n */\nexport const getSitemapEntries = cache(async (options?: { publishedOnly?: boolean }) => {\n const result = await secureApiPost<{ entries: any[] }>('/api/public/seo/sitemap', {\n publishedOnly: options?.publishedOnly,\n })\n return result?.entries || []\n})\n\n/**\n * Register/sync sitemap entries from the client site\n * Call this at build time to populate seo_pages from your sitemap.xml\n * @server-only\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts (run at build time)\n * import { registerSitemap } from '@sonordev/seo/server'\n * \n * await registerSitemap([\n * { path: '/', priority: 1.0, changefreq: 'daily' },\n * { path: '/about', priority: 0.8, changefreq: 'weekly' },\n * ])\n * ```\n */\nexport async function registerSitemap(\n entries: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>\n): Promise<{ success: boolean; created: number; updated: number }> {\n const { apiUrl, apiKey } = getSecureApiConfig()\n\n try {\n const response = await fetch(`${apiUrl}/api/public/seo/register-sitemap`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n body: JSON.stringify({ entries }),\n })\n \n if (!response.ok) {\n console.error(`@sonordev/seo: Sitemap registration failed: ${response.statusText}`)\n return { success: false, created: 0, updated: 0 }\n }\n \n return await response.json()\n } catch (error) {\n console.error('@sonordev/seo: Sitemap registration error:', error)\n return { success: false, created: 0, updated: 0 }\n }\n}\n\n// ============================================\n// Signal-Powered Metadata Fallback\n// ============================================\n\n/**\n * Ensure metadata exists for a page by triggering Signal AI optimization.\n * If the page has no managed_title or managed_meta_description, Signal will\n * generate them and save to the database via Portal proxy.\n *\n * Idempotent — returns existing metadata if already populated.\n * @server-only\n */\nexport const ensureMetadata = cache(async (path: string): Promise<{\n managed_title?: string\n managed_meta_description?: string\n managed_keywords?: string[]\n managed_schema?: Record<string, unknown>\n} | null> => {\n return secureApiPost('/api/public/seo/ensure-metadata', { path })\n})\n\n// ============================================\n// AI Visibility & Entity Graph API (Signal)\n// ============================================\n\nfunction getSignalApiConfig() {\n const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || 'https://signal.sonor.io'\n const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || ''\n return { apiUrl, apiKey }\n}\n\nasync function signalApiGet<T>(endpoint: string): Promise<T | null> {\n const { apiUrl, apiKey } = getSignalApiConfig()\n \n if (!apiKey) {\n return null\n }\n \n try {\n const response = await fetch(`${apiUrl}${endpoint}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n next: { revalidate: 300 }, // Cache for 5 minutes\n })\n \n if (!response.ok) {\n return null\n }\n \n const result = await response.json()\n return result?.data || result\n } catch (error) {\n console.error('@sonordev/seo: Signal API error:', error)\n return null\n }\n}\n\n/**\n * Entity types for the knowledge graph\n */\nexport type EntityType = \n | 'organization'\n | 'person'\n | 'service'\n | 'product'\n | 'location'\n | 'concept'\n | 'credential'\n\n/**\n * Entity from the knowledge graph\n */\nexport interface SEOEntity {\n id: string\n project_id: string\n entity_type: EntityType\n name: string\n slug: string\n properties: Record<string, unknown>\n knows_about: string[]\n same_as: string[]\n schema_type?: string\n is_primary: boolean\n}\n\n/**\n * Fetch entities for a project - cached per request\n * Returns the entity graph for enhanced schema markup\n * @server-only\n */\nexport const getEntities = cache(async (\n options?: { type?: EntityType }\n): Promise<SEOEntity[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n let endpoint = `/skills/seo/entities/${projectId}`\n if (options?.type) {\n endpoint += `?type=${options.type}`\n }\n const result = await signalApiGet<SEOEntity[]>(endpoint)\n return result || []\n})\n\n/**\n * Fetch primary entity (the business) - cached per request\n * @server-only\n */\nexport const getPrimaryEntity = cache(async (): Promise<SEOEntity | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet<SEOEntity>(`/skills/seo/entities/${projectId}/primary`)\n})\n\n/**\n * Fetch entity-enhanced schema for a page\n * Returns Organization schema with knowsAbout, areaServed, employee, etc.\n * @server-only\n */\nexport const getEntityEnhancedSchema = cache(async (pagePath: string): Promise<object[]> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return []\n const result = await signalApiGet<{ schemas: object[] }>(\n `/skills/seo/schema/${projectId}/entity-enhanced?pagePath=${encodeURIComponent(pagePath)}`\n )\n return result?.schemas || []\n})\n\n/**\n * Get AI visibility score for a page\n * @server-only\n */\nexport const getVisibilityScore = cache(async (\n pagePath: string\n): Promise<{\n overall_score: number\n entity_coverage: number\n answer_density: number\n chunk_readability: number\n authority_signals: number\n schema_completeness: number\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n const result = await signalApiGet<any[]>(`/skills/seo/visibility/${projectId}`)\n if (!result) return null\n return result.find(s => s.page_path === pagePath) || null\n})\n\n/**\n * Get AI visibility summary for project\n * @server-only\n */\nexport const getVisibilitySummary = cache(async (): Promise<{\n overall_score: number\n total_entities: number\n pages_analyzed: number\n top_recommendations: Array<{ priority: string; type: string; message: string }>\n} | null> => {\n const { apiKey } = getSecureApiConfig()\n const projectId = getProjectIdFromKey(apiKey)\n if (!projectId) return null\n return signalApiGet(`/skills/seo/visibility/${projectId}/summary`)\n})\n"]}
|
|
@@ -16,39 +16,33 @@ async function generateEnvFile(options) {
|
|
|
16
16
|
existingContent = await fs__default.default.readFile(envPath, "utf-8");
|
|
17
17
|
} catch {
|
|
18
18
|
}
|
|
19
|
-
const newVars = {
|
|
20
|
-
"NEXT_PUBLIC_UPTRADE_PROJECT_ID": options.projectId,
|
|
21
|
-
"NEXT_PUBLIC_SUPABASE_URL": options.supabaseUrl,
|
|
22
|
-
"NEXT_PUBLIC_SUPABASE_ANON_KEY": options.supabaseAnonKey,
|
|
23
|
-
"UPTRADE_API_KEY": options.apiKey
|
|
24
|
-
};
|
|
25
19
|
const lines = existingContent.split("\n");
|
|
26
20
|
const existingVars = {};
|
|
27
21
|
for (const line of lines) {
|
|
28
|
-
if (line.startsWith("#") || line.trim() === "")
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
22
|
+
if (line.startsWith("#") || line.trim() === "") continue;
|
|
31
23
|
const [key, ...valueParts] = line.split("=");
|
|
32
24
|
if (key) {
|
|
33
25
|
existingVars[key.trim()] = valueParts.join("=").trim();
|
|
34
26
|
}
|
|
35
27
|
}
|
|
36
|
-
|
|
28
|
+
const sonorKeys = [
|
|
29
|
+
"SONOR_API_KEY",
|
|
30
|
+
"NEXT_PUBLIC_UPTRADE_PROJECT_ID",
|
|
31
|
+
"NEXT_PUBLIC_SUPABASE_URL",
|
|
32
|
+
"NEXT_PUBLIC_SUPABASE_ANON_KEY",
|
|
33
|
+
"UPTRADE_API_KEY",
|
|
34
|
+
"NEXT_PUBLIC_UPTRADE_API_KEY"
|
|
35
|
+
];
|
|
36
|
+
let newContent = `# Sonor Site-Kit Configuration
|
|
37
37
|
# Generated by @sonordev/site-kit setup wizard
|
|
38
|
+
#
|
|
39
|
+
# Only SONOR_API_KEY is required. SiteKitLayout reads it server-side
|
|
40
|
+
# and injects all necessary config to client components automatically.
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
NEXT_PUBLIC_UPTRADE_PROJECT_ID=${newVars["NEXT_PUBLIC_UPTRADE_PROJECT_ID"]}
|
|
41
|
-
|
|
42
|
-
# Supabase Configuration
|
|
43
|
-
NEXT_PUBLIC_SUPABASE_URL=${newVars["NEXT_PUBLIC_SUPABASE_URL"]}
|
|
44
|
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=${newVars["NEXT_PUBLIC_SUPABASE_ANON_KEY"]}
|
|
45
|
-
|
|
46
|
-
# Uptrade API Key (for server-side operations)
|
|
47
|
-
UPTRADE_API_KEY=${newVars["UPTRADE_API_KEY"]}
|
|
42
|
+
SONOR_API_KEY=${options.apiKey}
|
|
48
43
|
|
|
49
44
|
`;
|
|
50
|
-
const
|
|
51
|
-
const otherVars = Object.entries(existingVars).filter(([key]) => !uptradeKeys.includes(key));
|
|
45
|
+
const otherVars = Object.entries(existingVars).filter(([key]) => !sonorKeys.includes(key));
|
|
52
46
|
if (otherVars.length > 0) {
|
|
53
47
|
newContent += "# Other Environment Variables\n";
|
|
54
48
|
for (const [key, value] of otherVars) {
|
|
@@ -77,66 +71,37 @@ function addImportSafely(content, importStatement) {
|
|
|
77
71
|
}
|
|
78
72
|
}
|
|
79
73
|
}
|
|
80
|
-
|
|
74
|
+
var generateProvider = generateLayout;
|
|
75
|
+
async function generateLayout() {
|
|
81
76
|
const layoutPath = await findLayoutFile();
|
|
82
77
|
if (!layoutPath) {
|
|
83
78
|
throw new Error("Could not find layout.tsx file");
|
|
84
79
|
}
|
|
85
80
|
const content = await fs__default.default.readFile(layoutPath, "utf-8");
|
|
86
|
-
if (content.includes("SiteKitProvider")) {
|
|
81
|
+
if (content.includes("SiteKitLayout") || content.includes("SiteKitProvider")) {
|
|
87
82
|
return;
|
|
88
83
|
}
|
|
89
84
|
const backupPath = layoutPath + ".backup";
|
|
90
85
|
await fs__default.default.writeFile(backupPath, content, "utf-8");
|
|
91
|
-
let newContent =
|
|
92
|
-
|
|
93
|
-
`import {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
newContent = addImportSafely(newContent, stmt);
|
|
97
|
-
}
|
|
98
|
-
if (!newContent.includes("ManagedFavicon")) {
|
|
99
|
-
if (/<head[\s>]/.test(newContent)) {
|
|
100
|
-
newContent = newContent.replace(/(<head[^>]*>)(\s*)/, "$1\n <ManagedFavicon />\n $2");
|
|
101
|
-
} else {
|
|
102
|
-
newContent = newContent.replace(
|
|
103
|
-
/(<html[^>]*>)(\s*)(<body)/,
|
|
104
|
-
"$1$2<head>\n <ManagedFavicon />\n </head>$2$3"
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
const childrenPattern = /(\s*){children}/;
|
|
86
|
+
let newContent = addImportSafely(
|
|
87
|
+
content,
|
|
88
|
+
`import { SiteKitLayout } from '@sonordev/site-kit/layout'`
|
|
89
|
+
);
|
|
90
|
+
const childrenPattern = /(\s*)\{children\}/;
|
|
109
91
|
const childrenMatch = newContent.match(childrenPattern);
|
|
110
92
|
if (childrenMatch) {
|
|
111
|
-
const indent = childrenMatch[1] || "
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
${indent} projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID!}
|
|
115
|
-
${indent} supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL!}
|
|
116
|
-
${indent} supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}
|
|
117
|
-
${indent} analytics={{ enabled: true }}
|
|
118
|
-
${indent} engage={{ enabled: true }}
|
|
119
|
-
${indent} forms={{ enabled: true }}
|
|
120
|
-
${indent}>
|
|
121
|
-
${indent} {children}
|
|
122
|
-
${indent}</SiteKitProvider>`;
|
|
123
|
-
newContent = newContent.replace(childrenPattern, providerWrap);
|
|
93
|
+
const indent = childrenMatch[1] || " ";
|
|
94
|
+
const layoutWrap = `${indent}<SiteKitLayout>${indent} {children}${indent}</SiteKitLayout>`;
|
|
95
|
+
newContent = newContent.replace(childrenPattern, layoutWrap);
|
|
124
96
|
} else {
|
|
125
97
|
const bodyPattern = /(<body[^>]*>)([\s\S]*?)(<\/body>)/;
|
|
126
98
|
const bodyMatch = newContent.match(bodyPattern);
|
|
127
99
|
if (bodyMatch) {
|
|
128
100
|
const bodyContent = bodyMatch[2];
|
|
129
101
|
const wrappedContent = `
|
|
130
|
-
<
|
|
131
|
-
projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID!}
|
|
132
|
-
supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL!}
|
|
133
|
-
supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}
|
|
134
|
-
analytics={{ enabled: true }}
|
|
135
|
-
engage={{ enabled: true }}
|
|
136
|
-
forms={{ enabled: true }}
|
|
137
|
-
>
|
|
102
|
+
<SiteKitLayout>
|
|
138
103
|
${bodyContent.trim()}
|
|
139
|
-
</
|
|
104
|
+
</SiteKitLayout>
|
|
140
105
|
`;
|
|
141
106
|
newContent = newContent.replace(bodyPattern, `$1${wrappedContent}$3`);
|
|
142
107
|
}
|
|
@@ -165,7 +130,7 @@ async function generateSetupRoute() {
|
|
|
165
130
|
const routeDir = path__default.default.join(process.cwd(), "app", "_uptrade", "setup");
|
|
166
131
|
await fs__default.default.mkdir(routeDir, { recursive: true });
|
|
167
132
|
const pageContent = `/**
|
|
168
|
-
*
|
|
133
|
+
* Sonor Setup Wizard
|
|
169
134
|
*
|
|
170
135
|
* This route is automatically removed after setup is complete.
|
|
171
136
|
* Visit /_uptrade/setup to configure Site-Kit.
|
|
@@ -267,7 +232,7 @@ function generateSitemapContent(baseUrl) {
|
|
|
267
232
|
* Automatically discovers pages from the app directory and syncs
|
|
268
233
|
* them to Portal API for SEO tracking and analytics validation.
|
|
269
234
|
*
|
|
270
|
-
* Generated by
|
|
235
|
+
* Generated by Sonor Site-Kit Setup Wizard
|
|
271
236
|
*/
|
|
272
237
|
|
|
273
238
|
import { createSitemap } from '@sonordev/site-kit/sitemap'
|
|
@@ -327,10 +292,11 @@ async function removeNextSitemapDependency() {
|
|
|
327
292
|
}
|
|
328
293
|
|
|
329
294
|
exports.generateEnvFile = generateEnvFile;
|
|
295
|
+
exports.generateLayout = generateLayout;
|
|
330
296
|
exports.generateProvider = generateProvider;
|
|
331
297
|
exports.generateSetupRoute = generateSetupRoute;
|
|
332
298
|
exports.migrateSitemap = migrateSitemap;
|
|
333
299
|
exports.removeNextSitemapDependency = removeNextSitemapDependency;
|
|
334
300
|
exports.selfDestruct = selfDestruct;
|
|
335
|
-
//# sourceMappingURL=chunk-
|
|
336
|
-
//# sourceMappingURL=chunk-
|
|
301
|
+
//# sourceMappingURL=chunk-SLB5V4RT.js.map
|
|
302
|
+
//# sourceMappingURL=chunk-SLB5V4RT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/generators/index.ts"],"names":["path","fs"],"mappings":"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","file":"chunk-SLB5V4RT.js","sourcesContent":["/**\n * Code Generators - Creates SiteKitLayout setup and env files\n */\n\nimport fs from 'fs/promises'\nimport path from 'path'\n\n// ============================================\n// Types\n// ============================================\n\ninterface EnvOptions {\n apiKey: string\n /** @deprecated Legacy — no longer needed. SiteKitLayout extracts projectId from the API key. */\n projectId?: string\n /** @deprecated Legacy — no longer needed. SiteKitLayout connects to Supabase internally. */\n supabaseUrl?: string\n /** @deprecated Legacy — no longer needed. SiteKitLayout connects to Supabase internally. */\n supabaseAnonKey?: string\n}\n\n// ============================================\n// Env File Generator\n// ============================================\n\nexport async function generateEnvFile(options: EnvOptions): Promise<void> {\n const envPath = path.join(process.cwd(), '.env.local')\n\n // Check if file exists and read existing content\n let existingContent = ''\n try {\n existingContent = await fs.readFile(envPath, 'utf-8')\n } catch {\n // File doesn't exist, that's fine\n }\n\n // Parse existing content\n const lines = existingContent.split('\\n')\n const existingVars: Record<string, string> = {}\n\n for (const line of lines) {\n if (line.startsWith('#') || line.trim() === '') continue\n const [key, ...valueParts] = line.split('=')\n if (key) {\n existingVars[key.trim()] = valueParts.join('=').trim()\n }\n }\n\n // Only SONOR_API_KEY is needed — SiteKitLayout reads it server-side,\n // extracts the project ID from the key prefix, and injects config to client.\n // Legacy vars (NEXT_PUBLIC_UPTRADE_PROJECT_ID, NEXT_PUBLIC_SUPABASE_*) are no longer required.\n const sonorKeys = [\n 'SONOR_API_KEY',\n 'NEXT_PUBLIC_UPTRADE_PROJECT_ID',\n 'NEXT_PUBLIC_SUPABASE_URL',\n 'NEXT_PUBLIC_SUPABASE_ANON_KEY',\n 'UPTRADE_API_KEY',\n 'NEXT_PUBLIC_UPTRADE_API_KEY',\n ]\n\n // Generate new content — single env var\n let newContent = `# Sonor Site-Kit Configuration\n# Generated by @sonordev/site-kit setup wizard\n#\n# Only SONOR_API_KEY is required. SiteKitLayout reads it server-side\n# and injects all necessary config to client components automatically.\n\nSONOR_API_KEY=${options.apiKey}\n\n`\n\n // Preserve any existing vars that aren't Sonor-related\n const otherVars = Object.entries(existingVars)\n .filter(([key]) => !sonorKeys.includes(key))\n\n if (otherVars.length > 0) {\n newContent += '# Other Environment Variables\\n'\n for (const [key, value] of otherVars) {\n newContent += `${key}=${value}\\n`\n }\n }\n\n await fs.writeFile(envPath, newContent, 'utf-8')\n}\n\n// ============================================\n// Provider Generator\n// ============================================\n\n/**\n * Safely adds an import statement to a file, respecting 'use client'/'use server' directives\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 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 return directive + importStatement + '\\n' + restOfFile\n } else {\n // No directive, add import at the top before other imports\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 * @deprecated Use generateLayout() instead. SiteKitProvider forces all children\n * client-side, breaking Next.js Server Components. Kept for backwards compatibility.\n */\nexport const generateProvider = generateLayout\n\n/**\n * Injects SiteKitLayout into the root layout.tsx.\n *\n * SiteKitLayout is a Server Component that:\n * - Reads SONOR_API_KEY server-side (no NEXT_PUBLIC_ vars needed)\n * - Extracts the project ID from the API key prefix\n * - Renders server concerns (favicon, managed scripts) as RSC\n * - Delegates client concerns (analytics, engage, forms) to a client island\n * - Does NOT break Server Components (unlike the deprecated SiteKitProvider)\n */\nexport async function generateLayout(): Promise<void> {\n // Find the layout file\n const layoutPath = await findLayoutFile()\n if (!layoutPath) {\n throw new Error('Could not find layout.tsx file')\n }\n\n const content = await fs.readFile(layoutPath, 'utf-8')\n\n // Check if SiteKitLayout or SiteKitProvider is already added\n if (content.includes('SiteKitLayout') || content.includes('SiteKitProvider')) {\n return // Already configured\n }\n\n // Create backup first\n const backupPath = layoutPath + '.backup'\n await fs.writeFile(backupPath, content, 'utf-8')\n\n // Add import safely (respects 'use client' directive)\n let newContent = addImportSafely(\n content,\n `import { SiteKitLayout } from '@sonordev/site-kit/layout'`,\n )\n\n // Wrap {children} with SiteKitLayout\n const childrenPattern = /(\\s*)\\{children\\}/\n const childrenMatch = newContent.match(childrenPattern)\n\n if (childrenMatch) {\n const indent = childrenMatch[1] || ' '\n const layoutWrap = `${indent}<SiteKitLayout>${indent} {children}${indent}</SiteKitLayout>`\n newContent = newContent.replace(childrenPattern, layoutWrap)\n } else {\n // Try wrapping body content\n const bodyPattern = /(<body[^>]*>)([\\s\\S]*?)(<\\/body>)/\n const bodyMatch = newContent.match(bodyPattern)\n\n if (bodyMatch) {\n const bodyContent = bodyMatch[2]\n const wrappedContent = `\n <SiteKitLayout>\n ${bodyContent.trim()}\n </SiteKitLayout>\n `\n newContent = newContent.replace(bodyPattern, `$1${wrappedContent}$3`)\n }\n }\n\n await fs.writeFile(layoutPath, newContent, 'utf-8')\n}\n\n// ============================================\n// Helpers\n// ============================================\n\nasync function findLayoutFile(): Promise<string | null> {\n const possiblePaths = [\n 'src/app/layout.tsx',\n 'app/layout.tsx',\n 'src/app/layout.jsx',\n 'app/layout.jsx',\n ]\n\n for (const relativePath of possiblePaths) {\n const fullPath = path.join(process.cwd(), relativePath)\n try {\n await fs.access(fullPath)\n return fullPath\n } catch {\n continue\n }\n }\n\n return null\n}\n\n// ============================================\n// Setup Route Generator (for visual wizard)\n// ============================================\n\nexport async function generateSetupRoute(): Promise<void> {\n const routeDir = path.join(process.cwd(), 'app', '_uptrade', 'setup')\n \n // Create directory\n await fs.mkdir(routeDir, { recursive: true })\n\n // Create page.tsx\n const pageContent = `/**\n * Sonor Setup Wizard\n * \n * This route is automatically removed after setup is complete.\n * Visit /_uptrade/setup to configure Site-Kit.\n */\n\nimport { SetupWizard } from '@sonordev/site-kit/setup'\n\nexport default function SetupPage() {\n return <SetupWizard />\n}\n`\n\n await fs.writeFile(path.join(routeDir, 'page.tsx'), pageContent, 'utf-8')\n}\n\n// ============================================\n// Self-Destruct\n// ============================================\n\nexport async function selfDestruct(): Promise<void> {\n // Remove setup route\n const setupDir = path.join(process.cwd(), 'app', '_uptrade')\n try {\n await fs.rm(setupDir, { recursive: true, force: true })\n } catch {\n // Directory might not exist\n }\n\n // Remove UptradeSetup from layout if present\n const layoutPath = await findLayoutFile()\n if (layoutPath) {\n let content = await fs.readFile(layoutPath, 'utf-8')\n \n // Remove import\n content = content.replace(/import\\s*{\\s*UptradeSetup\\s*}\\s*from\\s*['\"]@sonordev\\/site-kit\\/setup['\"][;\\n]?/g, '')\n \n // Remove component usage\n content = content.replace(/\\s*{process\\.env\\.NODE_ENV\\s*===\\s*['\"]development['\"]\\s*&&\\s*<UptradeSetup\\s*\\/>}\\s*/g, '\\n')\n content = content.replace(/<UptradeSetup\\s*\\/>/g, '')\n \n await fs.writeFile(layoutPath, content, 'utf-8')\n }\n}\n\n// ============================================\n// Sitemap Generator\n// ============================================\n\ninterface SitemapMigrationOptions {\n baseUrl: string\n existingSitemaps: Array<{\n filePath: string\n type: string\n generator?: string\n }>\n deleteExisting: boolean\n}\n\n/**\n * Generate site-kit sitemap and optionally remove existing sitemap files\n */\nexport async function migrateSitemap(options: SitemapMigrationOptions): Promise<{\n deleted: string[]\n created: string\n}> {\n const deleted: string[] = []\n\n // Delete existing sitemap files if requested\n if (options.deleteExisting) {\n for (const existing of options.existingSitemaps) {\n // Skip if it's already site-kit\n if (existing.generator === 'site-kit') continue\n\n const fullPath = path.join(process.cwd(), existing.filePath)\n try {\n await fs.unlink(fullPath)\n deleted.push(existing.filePath)\n } catch {\n // File might not exist or be locked\n }\n }\n\n // Also delete next-sitemap config files\n const configFiles = [\n 'next-sitemap.config.js',\n 'next-sitemap.config.mjs', \n 'next-sitemap.config.ts',\n ]\n for (const config of configFiles) {\n const fullPath = path.join(process.cwd(), config)\n try {\n await fs.access(fullPath)\n await fs.unlink(fullPath)\n deleted.push(config)\n } catch {\n // File doesn't exist\n }\n }\n\n // Delete static sitemap.xml if it exists in public\n const staticSitemap = path.join(process.cwd(), 'public', 'sitemap.xml')\n try {\n await fs.access(staticSitemap)\n await fs.unlink(staticSitemap)\n deleted.push('public/sitemap.xml')\n } catch {\n // File doesn't exist\n }\n\n // Delete sitemap index if exists\n const staticSitemapIndex = path.join(process.cwd(), 'public', 'sitemap-0.xml')\n try {\n await fs.access(staticSitemapIndex)\n // Find all sitemap-N.xml files\n const publicDir = path.join(process.cwd(), 'public')\n const files = await fs.readdir(publicDir)\n for (const file of files) {\n if (file.match(/^sitemap-\\d+\\.xml$/)) {\n await fs.unlink(path.join(publicDir, file))\n deleted.push(`public/${file}`)\n }\n }\n } catch {\n // File doesn't exist\n }\n }\n\n // Generate new sitemap.ts using site-kit\n const sitemapPath = await findSitemapLocation()\n const sitemapContent = generateSitemapContent(options.baseUrl)\n\n await fs.mkdir(path.dirname(sitemapPath), { recursive: true })\n await fs.writeFile(sitemapPath, sitemapContent, 'utf-8')\n\n return {\n deleted,\n created: path.relative(process.cwd(), sitemapPath),\n }\n}\n\n/**\n * Find where to put the sitemap file\n */\nasync function findSitemapLocation(): Promise<string> {\n // Check if using src/app or app\n const srcApp = path.join(process.cwd(), 'src', 'app', 'sitemap.ts')\n const app = path.join(process.cwd(), 'app', 'sitemap.ts')\n\n try {\n await fs.access(path.join(process.cwd(), 'src', 'app'))\n return srcApp\n } catch {\n return app\n }\n}\n\n/**\n * Generate sitemap.ts content\n */\nfunction generateSitemapContent(baseUrl: string): string {\n return `/**\n * Sitemap Generator - Powered by @sonordev/site-kit\n * \n * Automatically discovers pages from the app directory and syncs\n * them to Portal API for SEO tracking and analytics validation.\n * \n * Generated by Sonor Site-Kit Setup Wizard\n */\n\nimport { createSitemap } from '@sonordev/site-kit/sitemap'\n\nexport default createSitemap({\n baseUrl: '${baseUrl}',\n \n // Optional: Exclude patterns (these are excluded by default)\n // exclude: ['/admin/*', '/api/*'],\n \n // Optional: Override priorities for specific paths\n // priorities: {\n // '/': 1.0,\n // '/about': 0.8,\n // '/contact': 0.7,\n // },\n \n // Optional: Add dynamic routes not discoverable from file system\n // additionalPaths: async () => {\n // // Example: Fetch blog posts from database\n // // const posts = await getBlogPosts()\n // // return posts.map(post => ({ path: \\`/blog/\\${post.slug}\\`, priority: 0.7 }))\n // return []\n // },\n})\n`\n}\n\n/**\n * Remove next-sitemap from package.json dependencies\n */\nexport async function removeNextSitemapDependency(): Promise<boolean> {\n const packageJsonPath = path.join(process.cwd(), 'package.json')\n \n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8')\n const pkg = JSON.parse(content)\n \n let modified = false\n \n if (pkg.dependencies?.['next-sitemap']) {\n delete pkg.dependencies['next-sitemap']\n modified = true\n }\n \n if (pkg.devDependencies?.['next-sitemap']) {\n delete pkg.devDependencies['next-sitemap']\n modified = true\n }\n\n // Also remove from scripts if present\n if (pkg.scripts) {\n for (const [key, value] of Object.entries(pkg.scripts)) {\n if (typeof value === 'string' && value.includes('next-sitemap')) {\n delete pkg.scripts[key]\n modified = true\n }\n }\n }\n\n if (modified) {\n await fs.writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + '\\n', 'utf-8')\n }\n\n return modified\n } catch {\n return false\n }\n}\n\n"]}
|
|
@@ -3,15 +3,15 @@ import 'server-only';
|
|
|
3
3
|
|
|
4
4
|
// src/seo/server-api.ts
|
|
5
5
|
function getSecureApiConfig() {
|
|
6
|
-
const apiUrl = process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.
|
|
7
|
-
const apiKey = process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
6
|
+
const apiUrl = process.env.SONOR_API_URL || process.env.UPTRADE_API_URL || process.env.NEXT_PUBLIC_UPTRADE_API_URL || "https://api.sonor.io";
|
|
7
|
+
const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || process.env.NEXT_PUBLIC_UPTRADE_API_KEY || "";
|
|
8
8
|
if (!apiKey) {
|
|
9
|
-
throw new Error("@sonordev/seo:
|
|
9
|
+
throw new Error("@sonordev/seo: SONOR_API_KEY (or UPTRADE_API_KEY) environment variable is required for server-side SEO functions");
|
|
10
10
|
}
|
|
11
11
|
return { apiUrl, apiKey };
|
|
12
12
|
}
|
|
13
13
|
function getProjectIdFromKey(apiKey) {
|
|
14
|
-
const match = apiKey.match(/^
|
|
14
|
+
const match = apiKey.match(/^(?:sonor|uptrade)_([0-9a-f-]{36})_/);
|
|
15
15
|
return match ? match[1] : null;
|
|
16
16
|
}
|
|
17
17
|
async function secureApiPost(endpoint, body = {}) {
|
|
@@ -127,8 +127,8 @@ var ensureMetadata = cache(async (path) => {
|
|
|
127
127
|
return secureApiPost("/api/public/seo/ensure-metadata", { path });
|
|
128
128
|
});
|
|
129
129
|
function getSignalApiConfig() {
|
|
130
|
-
const apiUrl = process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.
|
|
131
|
-
const apiKey = process.env.UPTRADE_API_KEY || "";
|
|
130
|
+
const apiUrl = process.env.SONOR_SIGNAL_URL || process.env.SIGNAL_API_URL || process.env.NEXT_PUBLIC_SIGNAL_API_URL || "https://signal.sonor.io";
|
|
131
|
+
const apiKey = process.env.SONOR_API_KEY || process.env.UPTRADE_API_KEY || "";
|
|
132
132
|
return { apiUrl, apiKey };
|
|
133
133
|
}
|
|
134
134
|
async function signalApiGet(endpoint) {
|
|
@@ -198,5 +198,5 @@ var getVisibilitySummary = cache(async () => {
|
|
|
198
198
|
});
|
|
199
199
|
|
|
200
200
|
export { ensureMetadata, getABTest, getContentBlock, getEntities, getEntityEnhancedSchema, getFAQData, getInternalLinks, getManagedScripts, getPrimaryEntity, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, getVisibilityScore, getVisibilitySummary, recordABImpression, registerSitemap };
|
|
201
|
-
//# sourceMappingURL=chunk-
|
|
202
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-SQSBAPWA.mjs.map
|
|
202
|
+
//# sourceMappingURL=chunk-SQSBAPWA.mjs.map
|