@jmp-technologies/analytics 0.1.20 → 0.1.22
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 +7 -7
- package/dist/astro/client.cjs +93 -108
- package/dist/astro/client.cjs.map +1 -1
- package/dist/astro/client.d.cts +3 -12
- package/dist/astro/client.d.ts +3 -12
- package/dist/astro/client.js +4 -2
- package/dist/astro/client.js.map +1 -1
- package/dist/astro/content.cjs +106 -98
- package/dist/astro/content.cjs.map +1 -1
- package/dist/astro/content.d.cts +2 -2
- package/dist/astro/content.d.ts +2 -2
- package/dist/astro/content.js +3 -2
- package/dist/astro/integration.cjs +68 -60
- package/dist/astro/integration.cjs.map +1 -1
- package/dist/astro/integration.js +3 -2
- package/dist/astro/integration.js.map +1 -1
- package/dist/astro/middleware.cjs +66 -63
- package/dist/astro/middleware.cjs.map +1 -1
- package/dist/astro/middleware.d.cts +2 -2
- package/dist/astro/middleware.d.ts +2 -2
- package/dist/astro/middleware.js +2 -2
- package/dist/astro/register.cjs +68 -60
- package/dist/astro/register.cjs.map +1 -1
- package/dist/astro/register.js +3 -2
- package/dist/{chunk-UDNKWFBM.js → chunk-3U2BSIYX.js} +5 -3
- package/dist/{chunk-UDNKWFBM.js.map → chunk-3U2BSIYX.js.map} +1 -1
- package/dist/chunk-4OOWA55U.js +215 -0
- package/dist/chunk-4OOWA55U.js.map +1 -0
- package/dist/{chunk-GFCBZN6S.js → chunk-AHRVNEFV.js} +80 -276
- package/dist/chunk-AHRVNEFV.js.map +1 -0
- package/dist/{chunk-ALTSW5DB.js → chunk-DQ6A6HTY.js} +12 -8
- package/dist/chunk-DQ6A6HTY.js.map +1 -0
- package/dist/{chunk-QIWGUF7V.js → chunk-IYFVJ2EY.js} +6 -4
- package/dist/{chunk-QIWGUF7V.js.map → chunk-IYFVJ2EY.js.map} +1 -1
- package/dist/{chunk-NZS4M3V3.js → chunk-TEFKM3GW.js} +2 -2
- package/dist/chunk-TEFKM3GW.js.map +1 -0
- package/dist/create-jmp-analytics-BdGOgPxl.d.ts +70 -0
- package/dist/create-jmp-analytics-DxhHOmtR.d.cts +70 -0
- package/dist/env-public-B6Y0DG68.d.cts +14 -0
- package/dist/env-public-B6Y0DG68.d.ts +14 -0
- package/dist/index.cjs +203 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -340
- package/dist/index.d.ts +16 -340
- package/dist/index.js +9 -5
- package/dist/landing-capture-C8pyZWuF.d.cts +4 -0
- package/dist/landing-capture-C8pyZWuF.d.ts +4 -0
- package/dist/next/content.cjs +106 -98
- package/dist/next/content.cjs.map +1 -1
- package/dist/next/content.d.cts +2 -1
- package/dist/next/content.d.ts +2 -1
- package/dist/next/content.js +3 -2
- package/dist/next/content.js.map +1 -1
- package/dist/next/instrumentation.cjs +68 -60
- package/dist/next/instrumentation.cjs.map +1 -1
- package/dist/next/instrumentation.js +4 -2
- package/dist/next/instrumentation.js.map +1 -1
- package/dist/next/middleware.cjs +66 -63
- package/dist/next/middleware.cjs.map +1 -1
- package/dist/next/middleware.d.cts +2 -2
- package/dist/next/middleware.d.ts +2 -2
- package/dist/next/middleware.js +2 -2
- package/dist/next.cjs +152 -123
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +15 -3
- package/dist/next.d.ts +15 -3
- package/dist/next.js +45 -7
- package/dist/next.js.map +1 -1
- package/dist/react.cjs +115 -118
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -1
- package/dist/react.d.ts +2 -1
- package/dist/react.js +3 -2
- package/dist/site-config-BRuZWGSW.d.cts +46 -0
- package/dist/site-config-hkGMSeT7.d.ts +46 -0
- package/dist/{track-page-view-CoYo96n0.d.cts → track-page-view-BLS0YfL-.d.ts} +1 -1
- package/dist/{track-page-view-DAy0I0Vb.d.ts → track-page-view-DfCyWHqe.d.cts} +1 -1
- package/dist/types-BtiK_Acj.d.cts +224 -0
- package/dist/types-BtiK_Acj.d.ts +224 -0
- package/package.json +2 -4
- package/dist/chunk-ALTSW5DB.js.map +0 -1
- package/dist/chunk-GFCBZN6S.js.map +0 -1
- package/dist/chunk-NZS4M3V3.js.map +0 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// src/http.ts
|
|
2
|
+
function responseLooksLikeHtml(body) {
|
|
3
|
+
const s = body.trimStart();
|
|
4
|
+
return s.startsWith("<!") || s.toLowerCase().startsWith("<html") || s.startsWith("<") && /<html[\s>]/i.test(s.slice(0, 500));
|
|
5
|
+
}
|
|
6
|
+
function normalizeBaseUrl(baseUrl) {
|
|
7
|
+
return baseUrl.replace(/\/$/, "");
|
|
8
|
+
}
|
|
9
|
+
function getHeader(headers, key) {
|
|
10
|
+
if (!headers) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
if (typeof headers.get === "function") {
|
|
14
|
+
return headers.get(key);
|
|
15
|
+
}
|
|
16
|
+
const record = headers;
|
|
17
|
+
const direct = record[key] ?? record[key.toLowerCase()];
|
|
18
|
+
if (Array.isArray(direct)) {
|
|
19
|
+
return direct[0] ?? null;
|
|
20
|
+
}
|
|
21
|
+
return direct ?? null;
|
|
22
|
+
}
|
|
23
|
+
function pathFromRequestUrl(url) {
|
|
24
|
+
if (!url) {
|
|
25
|
+
return "/";
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const u = new URL(url);
|
|
29
|
+
return `${u.pathname}${u.search}`;
|
|
30
|
+
} catch {
|
|
31
|
+
return url.startsWith("/") ? url : "/";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function resolveFetch(fetchImpl, context) {
|
|
35
|
+
const resolved = fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
36
|
+
if (!resolved) {
|
|
37
|
+
throw new Error(`${context}: fetch is not available; pass fetchImpl in config`);
|
|
38
|
+
}
|
|
39
|
+
return resolved;
|
|
40
|
+
}
|
|
41
|
+
function formatApiErrorMessage(status, text, prefix) {
|
|
42
|
+
if (responseLooksLikeHtml(text)) {
|
|
43
|
+
return `${prefix} HTTP ${status} \u2014 response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`;
|
|
44
|
+
}
|
|
45
|
+
let parsed = {};
|
|
46
|
+
try {
|
|
47
|
+
parsed = JSON.parse(text);
|
|
48
|
+
} catch {
|
|
49
|
+
parsed = { error: text };
|
|
50
|
+
}
|
|
51
|
+
const detail = parsed.error ?? text;
|
|
52
|
+
return [
|
|
53
|
+
`${prefix} HTTP ${status}`,
|
|
54
|
+
parsed.code ? `[${parsed.code}]` : null,
|
|
55
|
+
detail,
|
|
56
|
+
parsed.hint ? `Hint: ${parsed.hint}` : null,
|
|
57
|
+
parsed.expectedDomain ? `Domain in JMP admin: ${parsed.expectedDomain}` : null
|
|
58
|
+
].filter(Boolean).join(" \u2014 ");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/server/page-view.ts
|
|
62
|
+
async function trackJmpServerPageView(config, options = {}) {
|
|
63
|
+
const baseUrl = normalizeBaseUrl(config.baseUrl);
|
|
64
|
+
const resolvedFetch = config.fetchImpl ?? (typeof globalThis !== "undefined" && globalThis.fetch ? globalThis.fetch.bind(globalThis) : void 0);
|
|
65
|
+
if (!resolvedFetch) {
|
|
66
|
+
throw new Error("JMP server analytics: fetch is not available; pass fetchImpl in config");
|
|
67
|
+
}
|
|
68
|
+
const visitorUserAgent = options.userAgent ?? getHeader(options.request?.headers, "user-agent");
|
|
69
|
+
const visitorReferer = options.referer ?? getHeader(options.request?.headers, "referer");
|
|
70
|
+
const path = options.path ?? pathFromRequestUrl(options.request?.url);
|
|
71
|
+
const headers = {
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"X-JMP-Tracking-Key": config.trackingKey
|
|
74
|
+
};
|
|
75
|
+
if (visitorUserAgent) {
|
|
76
|
+
headers["X-JMP-Visitor-User-Agent"] = visitorUserAgent;
|
|
77
|
+
}
|
|
78
|
+
if (visitorReferer) {
|
|
79
|
+
headers["X-JMP-Visitor-Referer"] = visitorReferer;
|
|
80
|
+
}
|
|
81
|
+
const payload = {
|
|
82
|
+
type: "page_view",
|
|
83
|
+
path: path || "/",
|
|
84
|
+
metadata: options.metadata && typeof options.metadata === "object" ? options.metadata : {}
|
|
85
|
+
};
|
|
86
|
+
if (options.sessionId) {
|
|
87
|
+
payload.sessionId = options.sessionId;
|
|
88
|
+
}
|
|
89
|
+
const url = `${baseUrl}/api/events`;
|
|
90
|
+
if (config.debug) {
|
|
91
|
+
console.debug("[@jmp-technologies/analytics]", "POST", url, payload);
|
|
92
|
+
}
|
|
93
|
+
const res = await resolvedFetch(url, {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers,
|
|
96
|
+
body: JSON.stringify(payload)
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
const text = await res.text();
|
|
100
|
+
throw new Error(`JMP server analytics HTTP ${res.status} \u2014 ${text}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/env-public.ts
|
|
105
|
+
function firstDefined(...values) {
|
|
106
|
+
for (const v of values) {
|
|
107
|
+
if (v) return v;
|
|
108
|
+
}
|
|
109
|
+
return void 0;
|
|
110
|
+
}
|
|
111
|
+
function readJmpPublicEnvFromProcessEnv() {
|
|
112
|
+
if (typeof process === "undefined" || !process.env) {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
const { env } = process;
|
|
116
|
+
const analyticsUrl = firstDefined(
|
|
117
|
+
env.NEXT_PUBLIC_JMP_ANALYTICS_URL,
|
|
118
|
+
env.PUBLIC_JMP_ANALYTICS_URL
|
|
119
|
+
);
|
|
120
|
+
const trackingKey = firstDefined(
|
|
121
|
+
env.NEXT_PUBLIC_JMP_TRACKING_KEY,
|
|
122
|
+
env.PUBLIC_JMP_TRACKING_KEY
|
|
123
|
+
);
|
|
124
|
+
const requireConsentRaw = firstDefined(
|
|
125
|
+
env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,
|
|
126
|
+
env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT
|
|
127
|
+
);
|
|
128
|
+
const autoContactRaw = firstDefined(
|
|
129
|
+
env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,
|
|
130
|
+
env.PUBLIC_JMP_AUTO_CONTACT_LINKS
|
|
131
|
+
);
|
|
132
|
+
return {
|
|
133
|
+
analyticsUrl,
|
|
134
|
+
trackingKey,
|
|
135
|
+
requireConsent: requireConsentRaw === "true",
|
|
136
|
+
autoContactLinks: autoContactRaw === "true"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function readJmpPublicEnvFromProcess(overrides) {
|
|
140
|
+
const fromEnv = readJmpPublicEnvFromProcessEnv();
|
|
141
|
+
return {
|
|
142
|
+
analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),
|
|
143
|
+
trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),
|
|
144
|
+
requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,
|
|
145
|
+
autoContactLinks: overrides?.autoContactLinks ?? fromEnv.autoContactLinks
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function readJmpPublicEnvFromImportMeta(meta, overrides) {
|
|
149
|
+
const get = (key) => {
|
|
150
|
+
const v = meta?.[key];
|
|
151
|
+
return typeof v === "string" && v.length > 0 ? v : void 0;
|
|
152
|
+
};
|
|
153
|
+
const analyticsUrl = firstDefined(
|
|
154
|
+
overrides?.analyticsUrl,
|
|
155
|
+
get("PUBLIC_JMP_ANALYTICS_URL"),
|
|
156
|
+
get("NEXT_PUBLIC_JMP_ANALYTICS_URL")
|
|
157
|
+
);
|
|
158
|
+
const trackingKey = firstDefined(
|
|
159
|
+
overrides?.trackingKey,
|
|
160
|
+
get("PUBLIC_JMP_TRACKING_KEY"),
|
|
161
|
+
get("NEXT_PUBLIC_JMP_TRACKING_KEY")
|
|
162
|
+
);
|
|
163
|
+
const requireConsentRaw = firstDefined(
|
|
164
|
+
overrides?.requireConsent !== void 0 ? String(overrides.requireConsent) : void 0,
|
|
165
|
+
get("PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT"),
|
|
166
|
+
get("NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT")
|
|
167
|
+
);
|
|
168
|
+
const autoContactRaw = firstDefined(
|
|
169
|
+
overrides?.autoContactLinks !== void 0 ? String(overrides.autoContactLinks) : void 0,
|
|
170
|
+
get("PUBLIC_JMP_AUTO_CONTACT_LINKS"),
|
|
171
|
+
get("NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS")
|
|
172
|
+
);
|
|
173
|
+
return {
|
|
174
|
+
analyticsUrl,
|
|
175
|
+
trackingKey,
|
|
176
|
+
requireConsent: requireConsentRaw === "true",
|
|
177
|
+
autoContactLinks: autoContactRaw === "true"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/site-config.ts
|
|
182
|
+
var registeredSite = null;
|
|
183
|
+
function defineJmpSite(definition) {
|
|
184
|
+
registeredSite = definition;
|
|
185
|
+
return definition;
|
|
186
|
+
}
|
|
187
|
+
function getJmpSiteDefinition() {
|
|
188
|
+
return registeredSite;
|
|
189
|
+
}
|
|
190
|
+
function getJmpContentConfig() {
|
|
191
|
+
const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess();
|
|
192
|
+
if (!analyticsUrl || !trackingKey) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const site = getJmpSiteDefinition();
|
|
196
|
+
return {
|
|
197
|
+
baseUrl: analyticsUrl,
|
|
198
|
+
trackingKey,
|
|
199
|
+
contentWrappers: site?.contentWrappers ?? void 0
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export {
|
|
204
|
+
responseLooksLikeHtml,
|
|
205
|
+
normalizeBaseUrl,
|
|
206
|
+
resolveFetch,
|
|
207
|
+
formatApiErrorMessage,
|
|
208
|
+
trackJmpServerPageView,
|
|
209
|
+
readJmpPublicEnvFromProcess,
|
|
210
|
+
readJmpPublicEnvFromImportMeta,
|
|
211
|
+
defineJmpSite,
|
|
212
|
+
getJmpSiteDefinition,
|
|
213
|
+
getJmpContentConfig
|
|
214
|
+
};
|
|
215
|
+
//# sourceMappingURL=chunk-4OOWA55U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/http.ts","../src/server/page-view.ts","../src/env-public.ts","../src/site-config.ts"],"sourcesContent":["import type { JmpServerRequestLike } from \"./types\"\n\n/** CDN / Next.js often return HTML error pages; API errors are JSON */\nexport function responseLooksLikeHtml(body: string): boolean {\n const s = body.trimStart()\n return (\n s.startsWith(\"<!\") ||\n s.toLowerCase().startsWith(\"<html\") ||\n (s.startsWith(\"<\") && /<html[\\s>]/i.test(s.slice(0, 500)))\n )\n}\n\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/$/, \"\")\n}\n\nexport function getHeader(\n headers: JmpServerRequestLike[\"headers\"] | undefined,\n key: string\n): string | null {\n if (!headers) {\n return null\n }\n if (typeof (headers as Pick<Headers, \"get\">).get === \"function\") {\n return (headers as Pick<Headers, \"get\">).get(key)\n }\n const record = headers as Record<string, string | string[] | undefined | null>\n const direct = record[key] ?? record[key.toLowerCase()]\n if (Array.isArray(direct)) {\n return direct[0] ?? null\n }\n return direct ?? null\n}\n\nexport function pathFromRequestUrl(url: string | undefined): string {\n if (!url) {\n return \"/\"\n }\n try {\n const u = new URL(url)\n return `${u.pathname}${u.search}`\n } catch {\n return url.startsWith(\"/\") ? url : \"/\"\n }\n}\n\nexport function resolveFetch(\n fetchImpl: typeof fetch | undefined,\n context: string\n): typeof fetch {\n const resolved =\n fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n if (!resolved) {\n throw new Error(`${context}: fetch is not available; pass fetchImpl in config`)\n }\n return resolved\n}\n\ntype ApiErrorJson = {\n error?: string\n code?: string\n hint?: string\n expectedDomain?: string\n}\n\nexport function formatApiErrorMessage(\n status: number,\n text: string,\n prefix: string\n): string {\n if (responseLooksLikeHtml(text)) {\n return `${prefix} HTTP ${status} — response was HTML (not the JSON API). Check baseUrl points at the JMP Analytics dashboard.`\n }\n let parsed: ApiErrorJson = {}\n try {\n parsed = JSON.parse(text) as ApiErrorJson\n } catch {\n parsed = { error: text }\n }\n const detail = parsed.error ?? text\n return [\n `${prefix} HTTP ${status}`,\n parsed.code ? `[${parsed.code}]` : null,\n detail,\n parsed.hint ? `Hint: ${parsed.hint}` : null,\n parsed.expectedDomain\n ? `Domain in JMP admin: ${parsed.expectedDomain}`\n : null,\n ]\n .filter(Boolean)\n .join(\" — \")\n}\n","import {\n getHeader,\n normalizeBaseUrl,\n pathFromRequestUrl,\n resolveFetch,\n} from \"../http\"\nimport type { JmpContentConfig, TrackServerPageViewOptions } from \"../types\"\n\nexport async function trackJmpServerPageView(\n config: JmpContentConfig,\n options: TrackServerPageViewOptions = {}\n): Promise<void> {\n const baseUrl = normalizeBaseUrl(config.baseUrl)\n const resolvedFetch =\n config.fetchImpl ??\n (typeof globalThis !== \"undefined\" && globalThis.fetch\n ? globalThis.fetch.bind(globalThis)\n : undefined)\n\n if (!resolvedFetch) {\n throw new Error(\"JMP server analytics: fetch is not available; pass fetchImpl in config\")\n }\n\n const visitorUserAgent =\n options.userAgent ?? getHeader(options.request?.headers, \"user-agent\")\n const visitorReferer =\n options.referer ?? getHeader(options.request?.headers, \"referer\")\n const path = options.path ?? pathFromRequestUrl(options.request?.url)\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"X-JMP-Tracking-Key\": config.trackingKey,\n }\n if (visitorUserAgent) {\n headers[\"X-JMP-Visitor-User-Agent\"] = visitorUserAgent\n }\n if (visitorReferer) {\n headers[\"X-JMP-Visitor-Referer\"] = visitorReferer\n }\n\n const payload: Record<string, unknown> = {\n type: \"page_view\",\n path: path || \"/\",\n metadata:\n options.metadata && typeof options.metadata === \"object\"\n ? options.metadata\n : {},\n }\n if (options.sessionId) {\n payload.sessionId = options.sessionId\n }\n\n const url = `${baseUrl}/api/events`\n if (config.debug) {\n console.debug(\"[@jmp-technologies/analytics]\", \"POST\", url, payload)\n }\n\n const res = await resolvedFetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n })\n\n if (!res.ok) {\n const text = await res.text()\n throw new Error(`JMP server analytics HTTP ${res.status} — ${text}`)\n }\n}\n","/**\n * Public env vars for JMP — supports Next.js (`NEXT_PUBLIC_*`) and Astro (`PUBLIC_*`).\n * Server/build: `process.env`. Astro client bundles: pass overrides from `import.meta.env`.\n */\n\nexport type JmpPublicEnv = {\n analyticsUrl?: string\n trackingKey?: string\n requireConsent?: boolean\n autoContactLinks?: boolean\n}\n\nfunction firstDefined(...values: (string | undefined)[]): string | undefined {\n for (const v of values) {\n if (v) return v\n }\n return undefined\n}\n\n/** Static reads so Next.js / Vite inline `NEXT_PUBLIC_*` into client bundles. */\nfunction readJmpPublicEnvFromProcessEnv(): Omit<JmpPublicEnv, never> {\n if (typeof process === \"undefined\" || !process.env) {\n return {}\n }\n const { env } = process\n const analyticsUrl = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_URL,\n env.PUBLIC_JMP_ANALYTICS_URL,\n )\n const trackingKey = firstDefined(\n env.NEXT_PUBLIC_JMP_TRACKING_KEY,\n env.PUBLIC_JMP_TRACKING_KEY,\n )\n const requireConsentRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n env.PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT,\n )\n const autoContactRaw = firstDefined(\n env.NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS,\n env.PUBLIC_JMP_AUTO_CONTACT_LINKS,\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n\n/** Read dashboard URL + tracking key from Node / build-time env. */\nexport function readJmpPublicEnvFromProcess(\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const fromEnv = readJmpPublicEnvFromProcessEnv()\n\n return {\n analyticsUrl: firstDefined(overrides?.analyticsUrl, fromEnv.analyticsUrl),\n trackingKey: firstDefined(overrides?.trackingKey, fromEnv.trackingKey),\n requireConsent: overrides?.requireConsent ?? fromEnv.requireConsent,\n autoContactLinks:\n overrides?.autoContactLinks ?? fromEnv.autoContactLinks,\n }\n}\n\n/** Read from Astro/Vite `import.meta.env` in client scripts. */\nexport function readJmpPublicEnvFromImportMeta(\n meta: Record<string, unknown> | undefined,\n overrides?: Partial<JmpPublicEnv>,\n): JmpPublicEnv {\n const get = (key: string): string | undefined => {\n const v = meta?.[key]\n return typeof v === \"string\" && v.length > 0 ? v : undefined\n }\n\n const analyticsUrl = firstDefined(\n overrides?.analyticsUrl,\n get(\"PUBLIC_JMP_ANALYTICS_URL\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_URL\"),\n )\n const trackingKey = firstDefined(\n overrides?.trackingKey,\n get(\"PUBLIC_JMP_TRACKING_KEY\"),\n get(\"NEXT_PUBLIC_JMP_TRACKING_KEY\"),\n )\n const requireConsentRaw = firstDefined(\n overrides?.requireConsent !== undefined\n ? String(overrides.requireConsent)\n : undefined,\n get(\"PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n get(\"NEXT_PUBLIC_JMP_ANALYTICS_REQUIRE_CONSENT\"),\n )\n const autoContactRaw = firstDefined(\n overrides?.autoContactLinks !== undefined\n ? String(overrides.autoContactLinks)\n : undefined,\n get(\"PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n get(\"NEXT_PUBLIC_JMP_AUTO_CONTACT_LINKS\"),\n )\n\n return {\n analyticsUrl,\n trackingKey,\n requireConsent: requireConsentRaw === \"true\",\n autoContactLinks: autoContactRaw === \"true\",\n }\n}\n","import type { JmpContentConfig, JmpContentWrapper } from \"./types\"\nimport { readJmpPublicEnvFromProcess } from \"./env-public\"\n\n/** Per-site values used when the dashboard profile is missing or fields are empty. */\nexport type JmpSiteContactFallback = {\n displayName?: string\n founderName?: string\n email?: string\n phone?: string | null\n linkedin?: string | null\n hours?: string | null\n serviceArea?: string | null\n dashboardDemoUrl?: string\n profilePhotoSrc?: string\n privacyUrl?: string\n termsUrl?: string\n}\n\nexport type JmpSiteDefinition = {\n /** Content tabs this site uses — reported via instrumentation capabilities. */\n contentWrappers: JmpContentWrapper[]\n /**\n * Public site origin (no trailing slash), e.g. `https://example.com`.\n * Used to resolve relative profile image paths in structured data.\n */\n siteUrl?: string\n contactFallback?: JmpSiteContactFallback\n /**\n * `extras` keys to read from the dashboard site profile (hyphenated keys from admin).\n */\n contactExtraKeys?: {\n founderName?: readonly string[]\n dashboardDemoUrl?: readonly string[]\n profilePhotoSrc?: readonly string[]\n hours?: readonly string[]\n serviceArea?: readonly string[]\n }\n}\n\nlet registeredSite: JmpSiteDefinition | null = null\n\n/**\n * Register site-specific JMP integration options once (typically from `jmp.config.ts`).\n * Call at module load time before server content or instrumentation runs.\n */\nexport function defineJmpSite(definition: JmpSiteDefinition): JmpSiteDefinition {\n registeredSite = definition\n return definition\n}\n\nexport function getJmpSiteDefinition(): JmpSiteDefinition | null {\n return registeredSite\n}\n\n/** Server content + lead config: env vars + wrappers from {@link defineJmpSite}. */\nexport function getJmpContentConfig(): JmpContentConfig | null {\n const { analyticsUrl, trackingKey } = readJmpPublicEnvFromProcess()\n if (!analyticsUrl || !trackingKey) {\n return null\n }\n const site = getJmpSiteDefinition()\n return {\n baseUrl: analyticsUrl,\n trackingKey,\n contentWrappers: site?.contentWrappers ?? undefined,\n }\n}\n"],"mappings":"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","names":[]}
|