@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
package/dist/layout/index.d.mts
CHANGED
|
@@ -27,9 +27,9 @@ interface SignalConfig {
|
|
|
27
27
|
|
|
28
28
|
interface SiteKitLayoutProps {
|
|
29
29
|
children: React.ReactNode;
|
|
30
|
-
/** Portal API key. Defaults to
|
|
30
|
+
/** Portal API key. Defaults to SONOR_API_KEY env var. */
|
|
31
31
|
apiKey?: string;
|
|
32
|
-
/** Portal API URL. Defaults to env or https://api.
|
|
32
|
+
/** Portal API URL. Defaults to env or https://api.sonor.io */
|
|
33
33
|
apiUrl?: string;
|
|
34
34
|
/** Project ID (for Engage chat room routing). Auto-resolved if not provided. */
|
|
35
35
|
projectId?: string;
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -27,9 +27,9 @@ interface SignalConfig {
|
|
|
27
27
|
|
|
28
28
|
interface SiteKitLayoutProps {
|
|
29
29
|
children: React.ReactNode;
|
|
30
|
-
/** Portal API key. Defaults to
|
|
30
|
+
/** Portal API key. Defaults to SONOR_API_KEY env var. */
|
|
31
31
|
apiKey?: string;
|
|
32
|
-
/** Portal API URL. Defaults to env or https://api.
|
|
32
|
+
/** Portal API URL. Defaults to env or https://api.sonor.io */
|
|
33
33
|
apiUrl?: string;
|
|
34
34
|
/** Project ID (for Engage chat room routing). Auto-resolved if not provided. */
|
|
35
35
|
projectId?: string;
|
package/dist/layout/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
require('../chunk-
|
|
8
|
-
var
|
|
9
|
-
var
|
|
3
|
+
var chunkREMHGWXT_js = require('../chunk-REMHGWXT.js');
|
|
4
|
+
var chunkDY4K6X3A_js = require('../chunk-DY4K6X3A.js');
|
|
5
|
+
var chunk2XOW276O_js = require('../chunk-2XOW276O.js');
|
|
6
|
+
var chunkPPRAW576_js = require('../chunk-PPRAW576.js');
|
|
7
|
+
require('../chunk-RMOL4TZ6.js');
|
|
8
|
+
var chunkTG46LJFB_js = require('../chunk-TG46LJFB.js');
|
|
9
|
+
var chunkBBITDUZQ_js = require('../chunk-BBITDUZQ.js');
|
|
10
10
|
require('../chunk-ZSMWDLMK.js');
|
|
11
11
|
var react = require('react');
|
|
12
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -85,7 +85,7 @@ function SiteKitClientProviders({
|
|
|
85
85
|
if (signal) {
|
|
86
86
|
const signalConfig = typeof signal === "object" ? signal : {};
|
|
87
87
|
content = /* @__PURE__ */ jsxRuntime.jsx(
|
|
88
|
-
|
|
88
|
+
chunkREMHGWXT_js.SignalBridge,
|
|
89
89
|
{
|
|
90
90
|
enabled: true,
|
|
91
91
|
realtime: signalConfig.realtime !== false,
|
|
@@ -101,7 +101,7 @@ function SiteKitClientProviders({
|
|
|
101
101
|
if (analytics) {
|
|
102
102
|
const analyticsConfig = typeof analytics === "object" ? analytics : {};
|
|
103
103
|
content = /* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
104
|
-
|
|
104
|
+
chunkTG46LJFB_js.AnalyticsProvider,
|
|
105
105
|
{
|
|
106
106
|
apiUrl,
|
|
107
107
|
apiKey,
|
|
@@ -122,7 +122,7 @@ function SiteKitClientProviders({
|
|
|
122
122
|
content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
123
123
|
content,
|
|
124
124
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
125
|
-
|
|
125
|
+
chunkBBITDUZQ_js.EngageWidget,
|
|
126
126
|
{
|
|
127
127
|
apiUrl,
|
|
128
128
|
apiKey,
|
|
@@ -136,7 +136,7 @@ function SiteKitClientProviders({
|
|
|
136
136
|
if (sitemapSync) {
|
|
137
137
|
content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
138
138
|
content,
|
|
139
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkPPRAW576_js.SitemapSync, { debug })
|
|
140
140
|
] });
|
|
141
141
|
}
|
|
142
142
|
return /* @__PURE__ */ jsxRuntime.jsx(SiteKitIdentityProvider, { visitorId, sessionId, children: content });
|
|
@@ -154,16 +154,16 @@ async function SiteKitLayout({
|
|
|
154
154
|
managedScripts = true,
|
|
155
155
|
debug = false
|
|
156
156
|
}) {
|
|
157
|
-
const resolvedApiKey = apiKey ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
158
|
-
const resolvedApiUrl = apiUrl ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.
|
|
157
|
+
const resolvedApiKey = apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
158
|
+
const resolvedApiUrl = apiUrl ?? process.env.SONOR_API_URL ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.sonor.io";
|
|
159
159
|
if (!resolvedApiKey && debug) {
|
|
160
160
|
console.warn(
|
|
161
|
-
"[SiteKitLayout] No API key found. Set
|
|
161
|
+
"[SiteKitLayout] No API key found. Set SONOR_API_KEY (or UPTRADE_API_KEY)."
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
164
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
165
|
-
favicon && /* @__PURE__ */ jsxRuntime.jsx(
|
|
166
|
-
managedScripts && /* @__PURE__ */ jsxRuntime.jsx(
|
|
165
|
+
favicon && /* @__PURE__ */ jsxRuntime.jsx(chunkDY4K6X3A_js.ManagedFavicon, { apiKey: resolvedApiKey, apiUrl: resolvedApiUrl }),
|
|
166
|
+
managedScripts && /* @__PURE__ */ jsxRuntime.jsx(chunk2XOW276O_js.ManagedScripts, { position: "head" }),
|
|
167
167
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
168
168
|
SiteKitClientProviders,
|
|
169
169
|
{
|
|
@@ -178,7 +178,7 @@ async function SiteKitLayout({
|
|
|
178
178
|
children
|
|
179
179
|
}
|
|
180
180
|
),
|
|
181
|
-
managedScripts && /* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
managedScripts && /* @__PURE__ */ jsxRuntime.jsx(chunk2XOW276O_js.ManagedScripts, { position: "body-end" })
|
|
182
182
|
] });
|
|
183
183
|
}
|
|
184
184
|
|
package/dist/layout/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shared/identity.tsx","../../src/layout/SiteKitClientProviders.tsx","../../src/layout/SiteKitLayout.tsx"],"names":["createContext","useMemo","jsx","useState","useRef","useCallback","Fragment","SignalBridge","Suspense","AnalyticsProvider","jsxs","EngageWidget","SitemapSync","ManagedFavicon","ManagedScripts"],"mappings":"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","file":"index.js","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","/**\n * @sonordev/site-kit/layout — SiteKitLayout\n *\n * The master layout component. A single RSC that auto-composes every\n * site-kit feature your layout needs:\n *\n * Server-side (RSC):\n * - ManagedFavicon (link tags from Portal logo)\n * - ManagedScripts position=\"head\" (tracking pixels, analytics tags)\n * - ManagedScripts position=\"body-end\"\n *\n * Client-side (island):\n * - AnalyticsProvider (page views, scroll depth, heatmap, web vitals)\n * - EngageWidget (popups, nudges, chat)\n * - SignalBridge (A/B experiments, behavior tracking)\n * - SitemapSync (keeps Portal seo_pages in sync)\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { SiteKitLayout } from '@sonordev/site-kit/layout'\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <SiteKitLayout>\n * <Header />\n * <main>{children}</main>\n * <Footer />\n * </SiteKitLayout>\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example Opt out of specific features:\n * ```tsx\n * <SiteKitLayout engage={false} signal={false}>\n * {children}\n * </SiteKitLayout>\n * ```\n */\n\nimport * as React from 'react'\nimport { ManagedFavicon } from '../images/ManagedFavicon'\nimport { ManagedScripts } from '../seo/ManagedScripts'\nimport { SiteKitClientProviders } from './SiteKitClientProviders'\nimport type { AnalyticsConfig, EngageConfig, SignalConfig } from './types'\n\nexport interface SiteKitLayoutProps {\n children: React.ReactNode\n\n /** Portal API key. Defaults to UPTRADE_API_KEY or NEXT_PUBLIC_UPTRADE_API_KEY env var. */\n apiKey?: string\n /** Portal API URL. Defaults to env or https://api.uptrademedia.com */\n apiUrl?: string\n /** Project ID (for Engage chat room routing). Auto-resolved if not provided. */\n projectId?: string\n\n /** Analytics tracking. true (default) | false | config object */\n analytics?: boolean | AnalyticsConfig\n /** Engage widgets (popups, chat). true (default) | false | config object */\n engage?: boolean | EngageConfig\n /** Signal AI (experiments, behavior). false (default) | true | config object */\n signal?: boolean | SignalConfig\n /** SitemapSync client component. Default: true */\n sitemapSync?: boolean\n /** ManagedFavicon in <head>. Default: true */\n favicon?: boolean\n /** ManagedScripts (head + body-end). Default: true */\n managedScripts?: boolean\n\n /** Debug mode — logs to console. Default: false */\n debug?: boolean\n}\n\nexport async function SiteKitLayout({\n children,\n apiKey,\n apiUrl,\n projectId,\n analytics = true,\n engage = true,\n signal = false,\n sitemapSync = true,\n favicon = true,\n managedScripts = true,\n debug = false,\n}: SiteKitLayoutProps) {\n // Resolve API config from env (server-side, safe)\n const resolvedApiKey =\n apiKey ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const resolvedApiUrl =\n apiUrl ??\n process.env.UPTRADE_API_URL ??\n process.env.NEXT_PUBLIC_UPTRADE_API_URL ??\n 'https://api.uptrademedia.com'\n\n if (!resolvedApiKey && debug) {\n console.warn(\n '[SiteKitLayout] No API key found. Set UPTRADE_API_KEY or NEXT_PUBLIC_UPTRADE_API_KEY.',\n )\n }\n\n return (\n <>\n {/* Server-rendered head components */}\n {favicon && <ManagedFavicon apiKey={resolvedApiKey} apiUrl={resolvedApiUrl} />}\n {managedScripts && <ManagedScripts position=\"head\" />}\n\n {/* Client-side providers island */}\n <SiteKitClientProviders\n apiKey={resolvedApiKey}\n apiUrl={resolvedApiUrl}\n projectId={projectId}\n analytics={analytics}\n engage={engage}\n signal={signal}\n sitemapSync={sitemapSync}\n debug={debug}\n >\n {children}\n </SiteKitClientProviders>\n\n {/* Server-rendered body-end scripts */}\n {managedScripts && <ManagedScripts position=\"body-end\" />}\n </>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/shared/identity.tsx","../../src/layout/SiteKitClientProviders.tsx","../../src/layout/SiteKitLayout.tsx"],"names":["createContext","useMemo","jsx","useState","useRef","useCallback","Fragment","SignalBridge","Suspense","AnalyticsProvider","jsxs","EngageWidget","SitemapSync","ManagedFavicon","ManagedScripts"],"mappings":"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","file":"index.js","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","/**\n * @sonordev/site-kit/layout — SiteKitLayout\n *\n * The master layout component. A single RSC that auto-composes every\n * site-kit feature your layout needs:\n *\n * Server-side (RSC):\n * - ManagedFavicon (link tags from Portal logo)\n * - ManagedScripts position=\"head\" (tracking pixels, analytics tags)\n * - ManagedScripts position=\"body-end\"\n *\n * Client-side (island):\n * - AnalyticsProvider (page views, scroll depth, heatmap, web vitals)\n * - EngageWidget (popups, nudges, chat)\n * - SignalBridge (A/B experiments, behavior tracking)\n * - SitemapSync (keeps Portal seo_pages in sync)\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { SiteKitLayout } from '@sonordev/site-kit/layout'\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <SiteKitLayout>\n * <Header />\n * <main>{children}</main>\n * <Footer />\n * </SiteKitLayout>\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example Opt out of specific features:\n * ```tsx\n * <SiteKitLayout engage={false} signal={false}>\n * {children}\n * </SiteKitLayout>\n * ```\n */\n\nimport * as React from 'react'\nimport { ManagedFavicon } from '../images/ManagedFavicon'\nimport { ManagedScripts } from '../seo/ManagedScripts'\nimport { SiteKitClientProviders } from './SiteKitClientProviders'\nimport type { AnalyticsConfig, EngageConfig, SignalConfig } from './types'\n\nexport interface SiteKitLayoutProps {\n children: React.ReactNode\n\n /** Portal API key. Defaults to SONOR_API_KEY env var. */\n apiKey?: string\n /** Portal API URL. Defaults to env or https://api.sonor.io */\n apiUrl?: string\n /** Project ID (for Engage chat room routing). Auto-resolved if not provided. */\n projectId?: string\n\n /** Analytics tracking. true (default) | false | config object */\n analytics?: boolean | AnalyticsConfig\n /** Engage widgets (popups, chat). true (default) | false | config object */\n engage?: boolean | EngageConfig\n /** Signal AI (experiments, behavior). false (default) | true | config object */\n signal?: boolean | SignalConfig\n /** SitemapSync client component. Default: true */\n sitemapSync?: boolean\n /** ManagedFavicon in <head>. Default: true */\n favicon?: boolean\n /** ManagedScripts (head + body-end). Default: true */\n managedScripts?: boolean\n\n /** Debug mode — logs to console. Default: false */\n debug?: boolean\n}\n\nexport async function SiteKitLayout({\n children,\n apiKey,\n apiUrl,\n projectId,\n analytics = true,\n engage = true,\n signal = false,\n sitemapSync = true,\n favicon = true,\n managedScripts = true,\n debug = false,\n}: SiteKitLayoutProps) {\n // Resolve API config from env (server-side, safe)\n const resolvedApiKey =\n apiKey ??\n process.env.SONOR_API_KEY ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const resolvedApiUrl =\n 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\n if (!resolvedApiKey && debug) {\n console.warn(\n '[SiteKitLayout] No API key found. Set SONOR_API_KEY (or UPTRADE_API_KEY).',\n )\n }\n\n return (\n <>\n {/* Server-rendered head components */}\n {favicon && <ManagedFavicon apiKey={resolvedApiKey} apiUrl={resolvedApiUrl} />}\n {managedScripts && <ManagedScripts position=\"head\" />}\n\n {/* Client-side providers island */}\n <SiteKitClientProviders\n apiKey={resolvedApiKey}\n apiUrl={resolvedApiUrl}\n projectId={projectId}\n analytics={analytics}\n engage={engage}\n signal={signal}\n sitemapSync={sitemapSync}\n debug={debug}\n >\n {children}\n </SiteKitClientProviders>\n\n {/* Server-rendered body-end scripts */}\n {managedScripts && <ManagedScripts position=\"body-end\" />}\n </>\n )\n}\n"]}
|
package/dist/layout/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { SignalBridge } from '../chunk-
|
|
2
|
-
import { ManagedFavicon } from '../chunk-
|
|
3
|
-
import { ManagedScripts } from '../chunk-
|
|
4
|
-
import { SitemapSync } from '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import { AnalyticsProvider } from '../chunk-
|
|
7
|
-
import { EngageWidget } from '../chunk-
|
|
1
|
+
import { SignalBridge } from '../chunk-UPR5FEIO.mjs';
|
|
2
|
+
import { ManagedFavicon } from '../chunk-N24BPFF6.mjs';
|
|
3
|
+
import { ManagedScripts } from '../chunk-5F7FFUPJ.mjs';
|
|
4
|
+
import { SitemapSync } from '../chunk-JIDOXTX2.mjs';
|
|
5
|
+
import '../chunk-SQSBAPWA.mjs';
|
|
6
|
+
import { AnalyticsProvider } from '../chunk-DOSSLBNW.mjs';
|
|
7
|
+
import { EngageWidget } from '../chunk-EISQ7LJG.mjs';
|
|
8
8
|
import '../chunk-4XPGGLVP.mjs';
|
|
9
9
|
import { createContext, useState, useRef, useCallback, Suspense, useMemo } from 'react';
|
|
10
10
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
@@ -152,11 +152,11 @@ async function SiteKitLayout({
|
|
|
152
152
|
managedScripts = true,
|
|
153
153
|
debug = false
|
|
154
154
|
}) {
|
|
155
|
-
const resolvedApiKey = apiKey ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
156
|
-
const resolvedApiUrl = apiUrl ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.
|
|
155
|
+
const resolvedApiKey = apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
156
|
+
const resolvedApiUrl = apiUrl ?? process.env.SONOR_API_URL ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.sonor.io";
|
|
157
157
|
if (!resolvedApiKey && debug) {
|
|
158
158
|
console.warn(
|
|
159
|
-
"[SiteKitLayout] No API key found. Set
|
|
159
|
+
"[SiteKitLayout] No API key found. Set SONOR_API_KEY (or UPTRADE_API_KEY)."
|
|
160
160
|
);
|
|
161
161
|
}
|
|
162
162
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/shared/identity.tsx","../../src/layout/SiteKitClientProviders.tsx","../../src/layout/SiteKitLayout.tsx"],"names":["jsx","jsxs","Fragment"],"mappings":"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","file":"index.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","/**\n * @sonordev/site-kit/layout — SiteKitLayout\n *\n * The master layout component. A single RSC that auto-composes every\n * site-kit feature your layout needs:\n *\n * Server-side (RSC):\n * - ManagedFavicon (link tags from Portal logo)\n * - ManagedScripts position=\"head\" (tracking pixels, analytics tags)\n * - ManagedScripts position=\"body-end\"\n *\n * Client-side (island):\n * - AnalyticsProvider (page views, scroll depth, heatmap, web vitals)\n * - EngageWidget (popups, nudges, chat)\n * - SignalBridge (A/B experiments, behavior tracking)\n * - SitemapSync (keeps Portal seo_pages in sync)\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { SiteKitLayout } from '@sonordev/site-kit/layout'\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <SiteKitLayout>\n * <Header />\n * <main>{children}</main>\n * <Footer />\n * </SiteKitLayout>\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example Opt out of specific features:\n * ```tsx\n * <SiteKitLayout engage={false} signal={false}>\n * {children}\n * </SiteKitLayout>\n * ```\n */\n\nimport * as React from 'react'\nimport { ManagedFavicon } from '../images/ManagedFavicon'\nimport { ManagedScripts } from '../seo/ManagedScripts'\nimport { SiteKitClientProviders } from './SiteKitClientProviders'\nimport type { AnalyticsConfig, EngageConfig, SignalConfig } from './types'\n\nexport interface SiteKitLayoutProps {\n children: React.ReactNode\n\n /** Portal API key. Defaults to UPTRADE_API_KEY or NEXT_PUBLIC_UPTRADE_API_KEY env var. */\n apiKey?: string\n /** Portal API URL. Defaults to env or https://api.uptrademedia.com */\n apiUrl?: string\n /** Project ID (for Engage chat room routing). Auto-resolved if not provided. */\n projectId?: string\n\n /** Analytics tracking. true (default) | false | config object */\n analytics?: boolean | AnalyticsConfig\n /** Engage widgets (popups, chat). true (default) | false | config object */\n engage?: boolean | EngageConfig\n /** Signal AI (experiments, behavior). false (default) | true | config object */\n signal?: boolean | SignalConfig\n /** SitemapSync client component. Default: true */\n sitemapSync?: boolean\n /** ManagedFavicon in <head>. Default: true */\n favicon?: boolean\n /** ManagedScripts (head + body-end). Default: true */\n managedScripts?: boolean\n\n /** Debug mode — logs to console. Default: false */\n debug?: boolean\n}\n\nexport async function SiteKitLayout({\n children,\n apiKey,\n apiUrl,\n projectId,\n analytics = true,\n engage = true,\n signal = false,\n sitemapSync = true,\n favicon = true,\n managedScripts = true,\n debug = false,\n}: SiteKitLayoutProps) {\n // Resolve API config from env (server-side, safe)\n const resolvedApiKey =\n apiKey ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const resolvedApiUrl =\n apiUrl ??\n process.env.UPTRADE_API_URL ??\n process.env.NEXT_PUBLIC_UPTRADE_API_URL ??\n 'https://api.uptrademedia.com'\n\n if (!resolvedApiKey && debug) {\n console.warn(\n '[SiteKitLayout] No API key found. Set UPTRADE_API_KEY or NEXT_PUBLIC_UPTRADE_API_KEY.',\n )\n }\n\n return (\n <>\n {/* Server-rendered head components */}\n {favicon && <ManagedFavicon apiKey={resolvedApiKey} apiUrl={resolvedApiUrl} />}\n {managedScripts && <ManagedScripts position=\"head\" />}\n\n {/* Client-side providers island */}\n <SiteKitClientProviders\n apiKey={resolvedApiKey}\n apiUrl={resolvedApiUrl}\n projectId={projectId}\n analytics={analytics}\n engage={engage}\n signal={signal}\n sitemapSync={sitemapSync}\n debug={debug}\n >\n {children}\n </SiteKitClientProviders>\n\n {/* Server-rendered body-end scripts */}\n {managedScripts && <ManagedScripts position=\"body-end\" />}\n </>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/shared/identity.tsx","../../src/layout/SiteKitClientProviders.tsx","../../src/layout/SiteKitLayout.tsx"],"names":["jsx","jsxs","Fragment"],"mappings":"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","file":"index.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","/**\n * @sonordev/site-kit/layout — SiteKitLayout\n *\n * The master layout component. A single RSC that auto-composes every\n * site-kit feature your layout needs:\n *\n * Server-side (RSC):\n * - ManagedFavicon (link tags from Portal logo)\n * - ManagedScripts position=\"head\" (tracking pixels, analytics tags)\n * - ManagedScripts position=\"body-end\"\n *\n * Client-side (island):\n * - AnalyticsProvider (page views, scroll depth, heatmap, web vitals)\n * - EngageWidget (popups, nudges, chat)\n * - SignalBridge (A/B experiments, behavior tracking)\n * - SitemapSync (keeps Portal seo_pages in sync)\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { SiteKitLayout } from '@sonordev/site-kit/layout'\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html lang=\"en\">\n * <body>\n * <SiteKitLayout>\n * <Header />\n * <main>{children}</main>\n * <Footer />\n * </SiteKitLayout>\n * </body>\n * </html>\n * )\n * }\n * ```\n *\n * @example Opt out of specific features:\n * ```tsx\n * <SiteKitLayout engage={false} signal={false}>\n * {children}\n * </SiteKitLayout>\n * ```\n */\n\nimport * as React from 'react'\nimport { ManagedFavicon } from '../images/ManagedFavicon'\nimport { ManagedScripts } from '../seo/ManagedScripts'\nimport { SiteKitClientProviders } from './SiteKitClientProviders'\nimport type { AnalyticsConfig, EngageConfig, SignalConfig } from './types'\n\nexport interface SiteKitLayoutProps {\n children: React.ReactNode\n\n /** Portal API key. Defaults to SONOR_API_KEY env var. */\n apiKey?: string\n /** Portal API URL. Defaults to env or https://api.sonor.io */\n apiUrl?: string\n /** Project ID (for Engage chat room routing). Auto-resolved if not provided. */\n projectId?: string\n\n /** Analytics tracking. true (default) | false | config object */\n analytics?: boolean | AnalyticsConfig\n /** Engage widgets (popups, chat). true (default) | false | config object */\n engage?: boolean | EngageConfig\n /** Signal AI (experiments, behavior). false (default) | true | config object */\n signal?: boolean | SignalConfig\n /** SitemapSync client component. Default: true */\n sitemapSync?: boolean\n /** ManagedFavicon in <head>. Default: true */\n favicon?: boolean\n /** ManagedScripts (head + body-end). Default: true */\n managedScripts?: boolean\n\n /** Debug mode — logs to console. Default: false */\n debug?: boolean\n}\n\nexport async function SiteKitLayout({\n children,\n apiKey,\n apiUrl,\n projectId,\n analytics = true,\n engage = true,\n signal = false,\n sitemapSync = true,\n favicon = true,\n managedScripts = true,\n debug = false,\n}: SiteKitLayoutProps) {\n // Resolve API config from env (server-side, safe)\n const resolvedApiKey =\n apiKey ??\n process.env.SONOR_API_KEY ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const resolvedApiUrl =\n 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\n if (!resolvedApiKey && debug) {\n console.warn(\n '[SiteKitLayout] No API key found. Set SONOR_API_KEY (or UPTRADE_API_KEY).',\n )\n }\n\n return (\n <>\n {/* Server-rendered head components */}\n {favicon && <ManagedFavicon apiKey={resolvedApiKey} apiUrl={resolvedApiUrl} />}\n {managedScripts && <ManagedScripts position=\"head\" />}\n\n {/* Client-side providers island */}\n <SiteKitClientProviders\n apiKey={resolvedApiKey}\n apiUrl={resolvedApiUrl}\n projectId={projectId}\n analytics={analytics}\n engage={engage}\n signal={signal}\n sitemapSync={sitemapSync}\n debug={debug}\n >\n {children}\n </SiteKitClientProviders>\n\n {/* Server-rendered body-end scripts */}\n {managedScripts && <ManagedScripts position=\"body-end\" />}\n </>\n )\n}\n"]}
|
package/dist/llms/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkBFJDUTXK_js = require('../chunk-BFJDUTXK.js');
|
|
4
4
|
require('../chunk-ZSMWDLMK.js');
|
|
5
5
|
var fs = require('fs');
|
|
6
6
|
var path = require('path');
|
|
@@ -23,7 +23,7 @@ function createLLMsTxtHandler(options = {}) {
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
const { markdown, metadata } = await
|
|
26
|
+
const { markdown, metadata } = await chunkBFJDUTXK_js.generateLLMsTxt(generateOptions);
|
|
27
27
|
return new Response(markdown, {
|
|
28
28
|
status: 200,
|
|
29
29
|
headers: {
|
|
@@ -59,7 +59,7 @@ function createLLMsFullTxtHandler(options = {}) {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
const { markdown, metadata } = await
|
|
62
|
+
const { markdown, metadata } = await chunkBFJDUTXK_js.generateLLMsFullTxt(generateOptions);
|
|
63
63
|
return new Response(markdown, {
|
|
64
64
|
status: 200,
|
|
65
65
|
headers: {
|
|
@@ -527,39 +527,39 @@ function AEOCitedContent({
|
|
|
527
527
|
|
|
528
528
|
Object.defineProperty(exports, "generateLLMsFullTxt", {
|
|
529
529
|
enumerable: true,
|
|
530
|
-
get: function () { return
|
|
530
|
+
get: function () { return chunkBFJDUTXK_js.generateLLMsFullTxt; }
|
|
531
531
|
});
|
|
532
532
|
Object.defineProperty(exports, "generateLLMsTxt", {
|
|
533
533
|
enumerable: true,
|
|
534
|
-
get: function () { return
|
|
534
|
+
get: function () { return chunkBFJDUTXK_js.generateLLMsTxt; }
|
|
535
535
|
});
|
|
536
536
|
Object.defineProperty(exports, "getBusinessInfo", {
|
|
537
537
|
enumerable: true,
|
|
538
|
-
get: function () { return
|
|
538
|
+
get: function () { return chunkBFJDUTXK_js.getBusinessInfo; }
|
|
539
539
|
});
|
|
540
540
|
Object.defineProperty(exports, "getFAQItems", {
|
|
541
541
|
enumerable: true,
|
|
542
|
-
get: function () { return
|
|
542
|
+
get: function () { return chunkBFJDUTXK_js.getFAQItems; }
|
|
543
543
|
});
|
|
544
544
|
Object.defineProperty(exports, "getLLMsData", {
|
|
545
545
|
enumerable: true,
|
|
546
|
-
get: function () { return
|
|
546
|
+
get: function () { return chunkBFJDUTXK_js.getLLMsData; }
|
|
547
547
|
});
|
|
548
548
|
Object.defineProperty(exports, "getOptimizedLLMsTxt", {
|
|
549
549
|
enumerable: true,
|
|
550
|
-
get: function () { return
|
|
550
|
+
get: function () { return chunkBFJDUTXK_js.getOptimizedLLMsTxt; }
|
|
551
551
|
});
|
|
552
552
|
Object.defineProperty(exports, "getPageSummaries", {
|
|
553
553
|
enumerable: true,
|
|
554
|
-
get: function () { return
|
|
554
|
+
get: function () { return chunkBFJDUTXK_js.getPageSummaries; }
|
|
555
555
|
});
|
|
556
556
|
Object.defineProperty(exports, "getServices", {
|
|
557
557
|
enumerable: true,
|
|
558
|
-
get: function () { return
|
|
558
|
+
get: function () { return chunkBFJDUTXK_js.getServices; }
|
|
559
559
|
});
|
|
560
560
|
Object.defineProperty(exports, "writeLLMsTxtToPublic", {
|
|
561
561
|
enumerable: true,
|
|
562
|
-
get: function () { return
|
|
562
|
+
get: function () { return chunkBFJDUTXK_js.writeLLMsTxtToPublic; }
|
|
563
563
|
});
|
|
564
564
|
exports.AEOBlock = AEOBlock;
|
|
565
565
|
exports.AEOCitedContent = AEOCitedContent;
|
package/dist/llms/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { generateLLMsTxt, generateLLMsFullTxt } from '../chunk-
|
|
2
|
-
export { generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, writeLLMsTxtToPublic } from '../chunk-
|
|
1
|
+
import { generateLLMsTxt, generateLLMsFullTxt } from '../chunk-JMNSED4O.mjs';
|
|
2
|
+
export { generateLLMsFullTxt, generateLLMsTxt, getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices, writeLLMsTxtToPublic } from '../chunk-JMNSED4O.mjs';
|
|
3
3
|
import '../chunk-4XPGGLVP.mjs';
|
|
4
4
|
import { existsSync, readFileSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
package/dist/manifest/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkEUNL6GAL_js = require('../chunk-EUNL6GAL.js');
|
|
4
4
|
require('../chunk-ZSMWDLMK.js');
|
|
5
5
|
|
|
6
6
|
// src/manifest/index.ts
|
|
@@ -25,13 +25,13 @@ async function fetchProjectInfo(apiKey, apiUrl) {
|
|
|
25
25
|
}
|
|
26
26
|
function createManifest(config) {
|
|
27
27
|
return async function GET() {
|
|
28
|
-
const apiKey = config?.apiKey ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
29
|
-
const apiUrl = config?.apiUrl ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.
|
|
28
|
+
const apiKey = config?.apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
29
|
+
const apiUrl = config?.apiUrl ?? process.env.SONOR_API_URL ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.sonor.io";
|
|
30
30
|
let project = null;
|
|
31
31
|
if (apiKey) {
|
|
32
32
|
project = await fetchProjectInfo(apiKey, apiUrl);
|
|
33
33
|
}
|
|
34
|
-
apiKey ? await
|
|
34
|
+
apiKey ? await chunkEUNL6GAL_js.getSiteConfig({ apiKey, apiUrl }).catch(() => null) : null;
|
|
35
35
|
const name = config?.name ?? project?.name ?? "My Site";
|
|
36
36
|
const shortName = config?.shortName ?? name.split(/\s+/)[0] ?? name;
|
|
37
37
|
const description = config?.description ?? project?.description ?? "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/manifest/index.ts"],"names":["getSiteConfig"],"mappings":";;;;;;AAoEA,eAAe,gBAAA,CACb,QACA,MAAA,EAC6B;AAC7B,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAsD;AAAA,MAC1D,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,WAAA,EAAa;AAAA;AACf,KACF;AAEC,IAAC,YAAA,CAAqB,IAAA,GAAO,EAAE,UAAA,EAAY,IAAA,EAAK;AACjD,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,MAAM,CAAA,4BAAA,CAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA;AACpB,IAAA,OAAO,MAAM,IAAI,IAAA,EAAK;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMO,SAAS,eACd,MAAA,EACyB;AACzB,EAAA,OAAO,eAAe,GAAA,GAAyB;AAC7C,IAAA,MAAM,MAAA,GACJ,
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/index.ts"],"names":["getSiteConfig"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @sonordev/site-kit/manifest\n *\n * PWA manifest generator. Fetches project name, description, brand colors,\n * and logo from Portal to generate a compliant Web App Manifest.\n *\n * @example\n * ```ts\n * // app/manifest.webmanifest/route.ts\n * import { createManifest } from '@sonordev/site-kit/manifest'\n * export const GET = createManifest()\n * ```\n *\n * @example With overrides:\n * ```ts\n * export const GET = createManifest({\n * display: 'fullscreen',\n * themeColor: '#1a1a2e',\n * categories: ['business', 'productivity'],\n * })\n * ```\n */\n\nimport { getSiteConfig } from '../site-config'\n\nexport interface ManifestConfig {\n /** App name. Defaults to Portal project name. */\n name?: string\n /** Short name for home screen. Defaults to first word of name. */\n shortName?: string\n /** App description. Defaults to Portal project description. */\n description?: string\n /** Theme color for browser chrome. Defaults to Portal brand color or #4bbf39. */\n themeColor?: string\n /** Background color for splash screen. Default: '#ffffff' */\n backgroundColor?: string\n /** Display mode. Default: 'standalone' */\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n /** Orientation preference. Default: 'any' */\n orientation?: 'portrait-primary' | 'landscape-primary' | 'any'\n /** Start URL. Default: '/' */\n startUrl?: string\n /** Scope. Default: '/' */\n scope?: string\n /** App categories */\n categories?: string[]\n /** Custom icons. If not provided, derived from Portal logo. */\n icons?: Array<{\n src: string\n sizes: string\n type: string\n purpose?: string\n }>\n /** Portal API key. Defaults from env. */\n apiKey?: string\n /** Portal API URL. Defaults from env. */\n apiUrl?: string\n}\n\ninterface ProjectInfo {\n site_url?: string\n domain?: string\n name?: string\n description?: string\n logo_url?: string\n brand_primary?: string\n}\n\nasync function fetchProjectInfo(\n apiKey: string,\n apiUrl: string,\n): Promise<ProjectInfo | null> {\n try {\n const fetchOptions: RequestInit & Record<string, unknown> = {\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n }\n // Next.js fetch extension for ISR caching\n ;(fetchOptions as any).next = { revalidate: 3600 }\n const res = await fetch(\n `${apiUrl}/api/public/seo/project-info`,\n fetchOptions,\n )\n if (!res.ok) return null\n return await res.json()\n } catch {\n return null\n }\n}\n\n/**\n * Create a route handler that serves the PWA manifest.\n * Fetches project data from Portal and merges with config overrides.\n */\nexport function createManifest(\n config?: ManifestConfig,\n): () => Promise<Response> {\n return async function GET(): Promise<Response> {\n const apiKey =\n config?.apiKey ??\n process.env.SONOR_API_KEY ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const apiUrl =\n config?.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\n // Fetch project info for defaults\n let project: ProjectInfo | null = null\n if (apiKey) {\n project = await fetchProjectInfo(apiKey, apiUrl)\n }\n\n // Also try getSiteConfig for site_url\n const siteConfig = apiKey\n ? await getSiteConfig({ apiKey, apiUrl }).catch(() => null)\n : null\n\n const name = config?.name ?? project?.name ?? 'My Site'\n const shortName =\n config?.shortName ?? name.split(/\\s+/)[0] ?? name\n const description =\n config?.description ?? project?.description ?? ''\n const themeColor =\n config?.themeColor ?? project?.brand_primary ?? '#4bbf39'\n const backgroundColor = config?.backgroundColor ?? '#ffffff'\n const startUrl = config?.startUrl ?? '/'\n\n // Build icons array\n const logoUrl = project?.logo_url\n const icons =\n config?.icons ??\n (logoUrl\n ? [\n {\n src: logoUrl,\n sizes: '192x192',\n type: 'image/png',\n },\n {\n src: logoUrl,\n sizes: '512x512',\n type: 'image/png',\n },\n {\n src: logoUrl,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ]\n : [])\n\n const manifest = {\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope: config?.scope ?? '/',\n display: config?.display ?? 'standalone',\n orientation: config?.orientation ?? 'any',\n theme_color: themeColor,\n background_color: backgroundColor,\n icons,\n ...(config?.categories?.length\n ? { categories: config.categories }\n : {}),\n }\n\n return new Response(JSON.stringify(manifest, null, 2), {\n status: 200,\n headers: {\n 'Content-Type': 'application/manifest+json',\n 'Cache-Control':\n 'public, max-age=86400, s-maxage=86400',\n },\n })\n }\n}\n"]}
|
package/dist/manifest/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getSiteConfig } from '../chunk-
|
|
1
|
+
import { getSiteConfig } from '../chunk-VZMDH3R4.mjs';
|
|
2
2
|
import '../chunk-4XPGGLVP.mjs';
|
|
3
3
|
|
|
4
4
|
// src/manifest/index.ts
|
|
@@ -23,8 +23,8 @@ async function fetchProjectInfo(apiKey, apiUrl) {
|
|
|
23
23
|
}
|
|
24
24
|
function createManifest(config) {
|
|
25
25
|
return async function GET() {
|
|
26
|
-
const apiKey = config?.apiKey ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
27
|
-
const apiUrl = config?.apiUrl ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.
|
|
26
|
+
const apiKey = config?.apiKey ?? process.env.SONOR_API_KEY ?? process.env.UPTRADE_API_KEY ?? process.env.NEXT_PUBLIC_UPTRADE_API_KEY ?? "";
|
|
27
|
+
const apiUrl = config?.apiUrl ?? process.env.SONOR_API_URL ?? process.env.UPTRADE_API_URL ?? process.env.NEXT_PUBLIC_UPTRADE_API_URL ?? "https://api.sonor.io";
|
|
28
28
|
let project = null;
|
|
29
29
|
if (apiKey) {
|
|
30
30
|
project = await fetchProjectInfo(apiKey, apiUrl);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":";;;;AAoEA,eAAe,gBAAA,CACb,QACA,MAAA,EAC6B;AAC7B,EAAA,IAAI;AACF,IAAA,MAAM,YAAA,GAAsD;AAAA,MAC1D,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,WAAA,EAAa;AAAA;AACf,KACF;AAEC,IAAC,YAAA,CAAqB,IAAA,GAAO,EAAE,UAAA,EAAY,IAAA,EAAK;AACjD,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,MAAM,CAAA,4BAAA,CAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAO,IAAA;AACpB,IAAA,OAAO,MAAM,IAAI,IAAA,EAAK;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMO,SAAS,eACd,MAAA,EACyB;AACzB,EAAA,OAAO,eAAe,GAAA,GAAyB;AAC7C,IAAA,MAAM,MAAA,GACJ,
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @sonordev/site-kit/manifest\n *\n * PWA manifest generator. Fetches project name, description, brand colors,\n * and logo from Portal to generate a compliant Web App Manifest.\n *\n * @example\n * ```ts\n * // app/manifest.webmanifest/route.ts\n * import { createManifest } from '@sonordev/site-kit/manifest'\n * export const GET = createManifest()\n * ```\n *\n * @example With overrides:\n * ```ts\n * export const GET = createManifest({\n * display: 'fullscreen',\n * themeColor: '#1a1a2e',\n * categories: ['business', 'productivity'],\n * })\n * ```\n */\n\nimport { getSiteConfig } from '../site-config'\n\nexport interface ManifestConfig {\n /** App name. Defaults to Portal project name. */\n name?: string\n /** Short name for home screen. Defaults to first word of name. */\n shortName?: string\n /** App description. Defaults to Portal project description. */\n description?: string\n /** Theme color for browser chrome. Defaults to Portal brand color or #4bbf39. */\n themeColor?: string\n /** Background color for splash screen. Default: '#ffffff' */\n backgroundColor?: string\n /** Display mode. Default: 'standalone' */\n display?: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'\n /** Orientation preference. Default: 'any' */\n orientation?: 'portrait-primary' | 'landscape-primary' | 'any'\n /** Start URL. Default: '/' */\n startUrl?: string\n /** Scope. Default: '/' */\n scope?: string\n /** App categories */\n categories?: string[]\n /** Custom icons. If not provided, derived from Portal logo. */\n icons?: Array<{\n src: string\n sizes: string\n type: string\n purpose?: string\n }>\n /** Portal API key. Defaults from env. */\n apiKey?: string\n /** Portal API URL. Defaults from env. */\n apiUrl?: string\n}\n\ninterface ProjectInfo {\n site_url?: string\n domain?: string\n name?: string\n description?: string\n logo_url?: string\n brand_primary?: string\n}\n\nasync function fetchProjectInfo(\n apiKey: string,\n apiUrl: string,\n): Promise<ProjectInfo | null> {\n try {\n const fetchOptions: RequestInit & Record<string, unknown> = {\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n },\n }\n // Next.js fetch extension for ISR caching\n ;(fetchOptions as any).next = { revalidate: 3600 }\n const res = await fetch(\n `${apiUrl}/api/public/seo/project-info`,\n fetchOptions,\n )\n if (!res.ok) return null\n return await res.json()\n } catch {\n return null\n }\n}\n\n/**\n * Create a route handler that serves the PWA manifest.\n * Fetches project data from Portal and merges with config overrides.\n */\nexport function createManifest(\n config?: ManifestConfig,\n): () => Promise<Response> {\n return async function GET(): Promise<Response> {\n const apiKey =\n config?.apiKey ??\n process.env.SONOR_API_KEY ??\n process.env.UPTRADE_API_KEY ??\n process.env.NEXT_PUBLIC_UPTRADE_API_KEY ??\n ''\n const apiUrl =\n config?.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\n // Fetch project info for defaults\n let project: ProjectInfo | null = null\n if (apiKey) {\n project = await fetchProjectInfo(apiKey, apiUrl)\n }\n\n // Also try getSiteConfig for site_url\n const siteConfig = apiKey\n ? await getSiteConfig({ apiKey, apiUrl }).catch(() => null)\n : null\n\n const name = config?.name ?? project?.name ?? 'My Site'\n const shortName =\n config?.shortName ?? name.split(/\\s+/)[0] ?? name\n const description =\n config?.description ?? project?.description ?? ''\n const themeColor =\n config?.themeColor ?? project?.brand_primary ?? '#4bbf39'\n const backgroundColor = config?.backgroundColor ?? '#ffffff'\n const startUrl = config?.startUrl ?? '/'\n\n // Build icons array\n const logoUrl = project?.logo_url\n const icons =\n config?.icons ??\n (logoUrl\n ? [\n {\n src: logoUrl,\n sizes: '192x192',\n type: 'image/png',\n },\n {\n src: logoUrl,\n sizes: '512x512',\n type: 'image/png',\n },\n {\n src: logoUrl,\n sizes: '512x512',\n type: 'image/png',\n purpose: 'maskable',\n },\n ]\n : [])\n\n const manifest = {\n name,\n short_name: shortName,\n description,\n start_url: startUrl,\n scope: config?.scope ?? '/',\n display: config?.display ?? 'standalone',\n orientation: config?.orientation ?? 'any',\n theme_color: themeColor,\n background_color: backgroundColor,\n icons,\n ...(config?.categories?.length\n ? { categories: config.categories }\n : {}),\n }\n\n return new Response(JSON.stringify(manifest, null, 2), {\n status: 200,\n headers: {\n 'Content-Type': 'application/manifest+json',\n 'Cache-Control':\n 'public, max-age=86400, s-maxage=86400',\n },\n })\n }\n}\n"]}
|
package/dist/middleware/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk3MYZS6PD_js = require('../chunk-3MYZS6PD.js');
|
|
4
|
-
var
|
|
5
|
-
require('../chunk-
|
|
4
|
+
var chunkX4J33XQD_js = require('../chunk-X4J33XQD.js');
|
|
5
|
+
require('../chunk-EUNL6GAL.js');
|
|
6
6
|
require('../chunk-ZSMWDLMK.js');
|
|
7
7
|
var server = require('next/server');
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ function createMiddleware(config) {
|
|
|
20
20
|
}
|
|
21
21
|
if (config?.redirects !== false) {
|
|
22
22
|
const redirectConfig = typeof config?.redirects === "object" ? config.redirects : {};
|
|
23
|
-
const redirect = await
|
|
23
|
+
const redirect = await chunkX4J33XQD_js.handleManagedRedirects(
|
|
24
24
|
request,
|
|
25
25
|
redirectConfig
|
|
26
26
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buildSecurityHeaders } from '../chunk-6BIPAKL4.mjs';
|
|
2
|
-
import { handleManagedRedirects } from '../chunk-
|
|
3
|
-
import '../chunk-
|
|
2
|
+
import { handleManagedRedirects } from '../chunk-XFOL6JDF.mjs';
|
|
3
|
+
import '../chunk-VZMDH3R4.mjs';
|
|
4
4
|
import '../chunk-4XPGGLVP.mjs';
|
|
5
5
|
import { NextResponse } from 'next/server';
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { migrateAnalytics, migrateFAQ, migrateFile, migrateFiles, migrateMetadata, migrateSchema, migrateSitemap } from './chunk-
|
|
1
|
+
export { migrateAnalytics, migrateFAQ, migrateFile, migrateFiles, migrateMetadata, migrateSchema, migrateSitemap } from './chunk-HF2FWDBJ.mjs';
|
|
2
2
|
import './chunk-4XPGGLVP.mjs';
|
|
3
|
-
//# sourceMappingURL=migrator-
|
|
4
|
-
//# sourceMappingURL=migrator-
|
|
3
|
+
//# sourceMappingURL=migrator-3WQB3KQ2.mjs.map
|
|
4
|
+
//# sourceMappingURL=migrator-3WQB3KQ2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"migrator-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"migrator-3WQB3KQ2.mjs"}
|