@decocms/start 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/skills/deco-api-call-dedup/SKILL.md +443 -0
- package/.cursor/skills/deco-apps-architecture/SKILL.md +255 -0
- package/.cursor/skills/deco-apps-architecture/app-pattern.md +288 -0
- package/.cursor/skills/deco-apps-architecture/commerce-types.md +239 -0
- package/.cursor/skills/deco-apps-architecture/new-app-guide.md +268 -0
- package/.cursor/skills/deco-apps-architecture/scripts-codegen.md +148 -0
- package/.cursor/skills/deco-apps-architecture/shared-utils.md +181 -0
- package/.cursor/skills/deco-apps-architecture/vtex-deep-structure.md +253 -0
- package/.cursor/skills/deco-apps-architecture/website-app.md +169 -0
- package/.cursor/skills/deco-apps-vtex-porting/SKILL.md +189 -0
- package/.cursor/skills/deco-apps-vtex-porting/adaptation-patterns.md +335 -0
- package/.cursor/skills/deco-apps-vtex-porting/commerce-porting.md +155 -0
- package/.cursor/skills/deco-apps-vtex-porting/cookie-auth-patterns.md +148 -0
- package/.cursor/skills/deco-apps-vtex-porting/structure-map.md +234 -0
- package/.cursor/skills/deco-apps-vtex-porting/transform-mapping.md +99 -0
- package/.cursor/skills/deco-apps-vtex-porting/website-porting.md +194 -0
- package/.cursor/skills/deco-apps-vtex-review/SKILL.md +234 -0
- package/.cursor/skills/deco-async-rendering-architecture/SKILL.md +270 -0
- package/.cursor/skills/deco-async-rendering-site-guide/SKILL.md +417 -0
- package/.cursor/skills/deco-cms-layout-caching/SKILL.md +293 -0
- package/.cursor/skills/deco-cms-route-config/SKILL.md +388 -0
- package/.cursor/skills/deco-core-architecture/SKILL.md +185 -0
- package/.cursor/skills/deco-core-architecture/blocks.md +196 -0
- package/.cursor/skills/deco-core-architecture/deco-vs-deco-start.md +191 -0
- package/.cursor/skills/deco-core-architecture/engine.md +220 -0
- package/.cursor/skills/deco-core-architecture/hooks-components.md +157 -0
- package/.cursor/skills/deco-core-architecture/plugins-clients.md +136 -0
- package/.cursor/skills/deco-core-architecture/runtime.md +116 -0
- package/.cursor/skills/deco-core-architecture/site-usage.md +165 -0
- package/.cursor/skills/deco-e2e-testing/SKILL.md +372 -0
- package/.cursor/skills/deco-e2e-testing/discovery.md +337 -0
- package/.cursor/skills/deco-e2e-testing/scripts/scaffold.sh +81 -0
- package/.cursor/skills/deco-e2e-testing/selectors.md +175 -0
- package/.cursor/skills/deco-e2e-testing/templates/package.json +18 -0
- package/.cursor/skills/deco-e2e-testing/templates/playwright.config.ts +65 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/baseline.ts +279 -0
- package/.cursor/skills/deco-e2e-testing/templates/scripts/run-e2e.ts +194 -0
- package/.cursor/skills/deco-e2e-testing/templates/specs/ecommerce-flow.spec.ts +612 -0
- package/.cursor/skills/deco-e2e-testing/templates/tsconfig.json +12 -0
- package/.cursor/skills/deco-e2e-testing/templates/utils/metrics-collector.ts +918 -0
- package/.cursor/skills/deco-e2e-testing/troubleshooting.md +602 -0
- package/.cursor/skills/deco-edge-caching/SKILL.md +316 -0
- package/.cursor/skills/deco-full-analysis/SKILL.md +898 -0
- package/.cursor/skills/deco-full-analysis/checklists/asset-optimization.md +251 -0
- package/.cursor/skills/deco-full-analysis/checklists/bug-fix.md +189 -0
- package/.cursor/skills/deco-full-analysis/checklists/cache-strategy.md +144 -0
- package/.cursor/skills/deco-full-analysis/checklists/dependency-update.md +150 -0
- package/.cursor/skills/deco-full-analysis/checklists/hydration-fix.md +191 -0
- package/.cursor/skills/deco-full-analysis/checklists/image-optimization.md +180 -0
- package/.cursor/skills/deco-full-analysis/checklists/loader-optimization.md +165 -0
- package/.cursor/skills/deco-full-analysis/checklists/seo-fix.md +183 -0
- package/.cursor/skills/deco-full-analysis/checklists/site-cleanup.md +281 -0
- package/.cursor/skills/deco-full-analysis/discovery.md +548 -0
- package/.cursor/skills/deco-incident-debugging/SKILL.md +378 -0
- package/.cursor/skills/deco-incident-debugging/headless-mode.md +510 -0
- package/.cursor/skills/deco-incident-debugging/learnings-index.md +227 -0
- package/.cursor/skills/deco-incident-debugging/triage-workflow.md +312 -0
- package/.cursor/skills/deco-islands-migration/SKILL.md +251 -0
- package/.cursor/skills/deco-loader-n-plus-1-detector/SKILL.md +275 -0
- package/.cursor/skills/deco-performance-audit/SKILL.md +530 -0
- package/.cursor/skills/deco-performance-audit/tools-reference.md +428 -0
- package/.cursor/skills/deco-performance-audit/workflow.md +457 -0
- package/.cursor/skills/deco-server-functions-invoke/SKILL.md +92 -0
- package/.cursor/skills/deco-server-functions-invoke/architecture.md +166 -0
- package/.cursor/skills/deco-server-functions-invoke/generator.md +122 -0
- package/.cursor/skills/deco-server-functions-invoke/problem.md +98 -0
- package/.cursor/skills/deco-server-functions-invoke/troubleshooting.md +110 -0
- package/.cursor/skills/deco-site-deployment/SKILL.md +396 -0
- package/.cursor/skills/deco-site-memory-debugging/SKILL.md +121 -0
- package/.cursor/skills/deco-site-memory-debugging/cdp-connection.md +222 -0
- package/.cursor/skills/deco-site-memory-debugging/memory-analysis.md +362 -0
- package/.cursor/skills/deco-site-patterns/SKILL.md +124 -0
- package/.cursor/skills/deco-site-patterns/app-composition.md +337 -0
- package/.cursor/skills/deco-site-patterns/client-patterns.md +341 -0
- package/.cursor/skills/deco-site-patterns/cms-wiring.md +230 -0
- package/.cursor/skills/deco-site-patterns/section-patterns.md +340 -0
- package/.cursor/skills/deco-site-scaling-tuning/SKILL.md +240 -0
- package/.cursor/skills/deco-site-scaling-tuning/analysis-scripts.md +267 -0
- package/.cursor/skills/deco-start-architecture/SKILL.md +218 -0
- package/.cursor/skills/deco-start-architecture/admin-protocol.md +156 -0
- package/.cursor/skills/deco-start-architecture/cms-resolution.md +201 -0
- package/.cursor/skills/deco-start-architecture/code-quality.md +158 -0
- package/.cursor/skills/deco-start-architecture/gap-analysis.md +129 -0
- package/.cursor/skills/deco-start-architecture/sdk-utilities.md +197 -0
- package/.cursor/skills/deco-start-architecture/worker-entry-caching.md +154 -0
- package/.cursor/skills/deco-startup-analysis/SKILL.md +248 -0
- package/.cursor/skills/deco-storefront-test-checklist/SKILL.md +369 -0
- package/.cursor/skills/deco-tanstack-hydration-fixes/SKILL.md +468 -0
- package/.cursor/skills/deco-tanstack-navigation/SKILL.md +681 -0
- package/.cursor/skills/deco-tanstack-search/SKILL.md +411 -0
- package/.cursor/skills/deco-tanstack-storefront-patterns/SKILL.md +1013 -0
- package/.cursor/skills/deco-to-tanstack-migration/SKILL.md +518 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/codemod-commands.md +174 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/commerce/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/deco-framework/README.md +128 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/gotchas.md +719 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/imports/README.md +70 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/platform-hooks/README.md +154 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/signals/README.md +220 -0
- package/.cursor/skills/deco-to-tanstack-migration/references/vite-config/README.md +78 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/package-json.md +55 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/root-route.md +110 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/router.md +96 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/setup-ts.md +167 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/vite-config.md +122 -0
- package/.cursor/skills/deco-to-tanstack-migration/templates/worker-entry.md +67 -0
- package/.cursor/skills/deco-typescript-fixes/SKILL.md +178 -0
- package/.cursor/skills/deco-typescript-fixes/common-fixes.md +330 -0
- package/.cursor/skills/deco-typescript-fixes/strategy.md +148 -0
- package/.cursor/skills/deco-variant-selection-perf/SKILL.md +272 -0
- package/.cursor/skills/deco-vtex-fetch-cache/SKILL.md +225 -0
- package/.cursor/skills/find-skills/SKILL.md +133 -0
- package/.cursor/skills/incident-report/SKILL.md +179 -0
- package/.cursor/skills/incident-report/references/5-whys.md +75 -0
- package/.cursor/skills/incident-report/templates/client-report.md +187 -0
- package/.cursor/skills/incident-report/templates/internal-report.md +206 -0
- package/.cursor/skills/template-skill/SKILL.md +38 -0
- package/.github/workflows/release.yml +32 -0
- package/.releaserc.json +25 -0
- package/CLAUDE.md +135 -0
- package/GAP_ANALYSIS.md +224 -0
- package/GAP_ANALYSIS_V2.md +1013 -0
- package/biome.json +39 -0
- package/knip.json +5 -0
- package/package.json +87 -0
- package/scripts/generate-blocks.ts +69 -0
- package/scripts/generate-invoke.ts +378 -0
- package/scripts/generate-schema.ts +657 -0
- package/src/admin/cors.ts +29 -0
- package/src/admin/decofile.ts +72 -0
- package/src/admin/index.ts +24 -0
- package/src/admin/invoke.ts +163 -0
- package/src/admin/liveControls.ts +29 -0
- package/src/admin/meta.ts +70 -0
- package/src/admin/render.ts +205 -0
- package/src/admin/schema.ts +686 -0
- package/src/admin/setup.ts +44 -0
- package/src/cms/index.ts +59 -0
- package/src/cms/loader.ts +180 -0
- package/src/cms/registry.ts +162 -0
- package/src/cms/resolve.ts +1005 -0
- package/src/cms/sectionLoaders.ts +294 -0
- package/src/hooks/DecoPageRenderer.tsx +444 -0
- package/src/hooks/LazySection.tsx +109 -0
- package/src/hooks/LiveControls.tsx +108 -0
- package/src/hooks/SectionErrorFallback.tsx +85 -0
- package/src/hooks/index.ts +8 -0
- package/src/index.ts +5 -0
- package/src/matchers/builtins.ts +184 -0
- package/src/matchers/posthog.ts +154 -0
- package/src/middleware/decoState.ts +55 -0
- package/src/middleware/healthMetrics.ts +131 -0
- package/src/middleware/index.ts +80 -0
- package/src/middleware/liveness.ts +21 -0
- package/src/middleware/observability.ts +205 -0
- package/src/routes/adminRoutes.ts +83 -0
- package/src/routes/cmsRoute.ts +302 -0
- package/src/routes/components.tsx +34 -0
- package/src/routes/index.ts +15 -0
- package/src/sdk/analytics.ts +72 -0
- package/src/sdk/cacheHeaders.ts +268 -0
- package/src/sdk/cachedLoader.ts +206 -0
- package/src/sdk/clx.ts +3 -0
- package/src/sdk/cookie.ts +39 -0
- package/src/sdk/createInvoke.ts +57 -0
- package/src/sdk/csp.ts +59 -0
- package/src/sdk/env.ts +27 -0
- package/src/sdk/index.ts +63 -0
- package/src/sdk/instrumentedFetch.ts +137 -0
- package/src/sdk/invoke.ts +133 -0
- package/src/sdk/mergeCacheControl.ts +150 -0
- package/src/sdk/redirects.ts +217 -0
- package/src/sdk/requestContext.ts +184 -0
- package/src/sdk/serverTimings.ts +68 -0
- package/src/sdk/signal.ts +41 -0
- package/src/sdk/sitemap.ts +143 -0
- package/src/sdk/urlUtils.ts +117 -0
- package/src/sdk/useDevice.ts +82 -0
- package/src/sdk/useId.ts +7 -0
- package/src/sdk/useScript.ts +101 -0
- package/src/sdk/workerEntry.ts +703 -0
- package/src/sdk/wrapCaughtErrors.ts +107 -0
- package/src/types/index.ts +39 -0
- package/src/types/widgets.ts +13 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL utility functions.
|
|
3
|
+
*
|
|
4
|
+
* Handles UTM parameter stripping for cache-friendly URLs,
|
|
5
|
+
* canonical URL generation, and other URL manipulation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const UTM_PARAMS = new Set([
|
|
9
|
+
"utm_source",
|
|
10
|
+
"utm_medium",
|
|
11
|
+
"utm_campaign",
|
|
12
|
+
"utm_term",
|
|
13
|
+
"utm_content",
|
|
14
|
+
"utmi_campaign",
|
|
15
|
+
"utmi_page",
|
|
16
|
+
"utmi_part",
|
|
17
|
+
"fbclid",
|
|
18
|
+
"gclid",
|
|
19
|
+
"gclsrc",
|
|
20
|
+
"dclid",
|
|
21
|
+
"msclkid",
|
|
22
|
+
"twclid",
|
|
23
|
+
"li_fat_id",
|
|
24
|
+
"mc_cid",
|
|
25
|
+
"mc_eid",
|
|
26
|
+
"ttclid",
|
|
27
|
+
"srsltid",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Strip UTM and tracking parameters from a URL.
|
|
32
|
+
*
|
|
33
|
+
* Used to normalize URLs for caching -- two requests that differ
|
|
34
|
+
* only in UTM params should hit the same cache entry.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* stripTrackingParams("https://example.com/shoes?color=red&utm_source=google")
|
|
39
|
+
* // => "https://example.com/shoes?color=red"
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function stripTrackingParams(urlString: string): string {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(urlString);
|
|
45
|
+
let changed = false;
|
|
46
|
+
|
|
47
|
+
for (const param of [...url.searchParams.keys()]) {
|
|
48
|
+
if (UTM_PARAMS.has(param.toLowerCase())) {
|
|
49
|
+
url.searchParams.delete(param);
|
|
50
|
+
changed = true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return changed ? url.toString() : urlString;
|
|
55
|
+
} catch {
|
|
56
|
+
return urlString;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Strip tracking params from a URL and return just the pathname + non-UTM search.
|
|
62
|
+
* Useful for cache key generation.
|
|
63
|
+
*/
|
|
64
|
+
export function cleanPathForCacheKey(urlString: string): string {
|
|
65
|
+
try {
|
|
66
|
+
const url = new URL(urlString);
|
|
67
|
+
|
|
68
|
+
for (const param of [...url.searchParams.keys()]) {
|
|
69
|
+
if (UTM_PARAMS.has(param.toLowerCase())) {
|
|
70
|
+
url.searchParams.delete(param);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const search = url.searchParams.toString();
|
|
75
|
+
return search ? `${url.pathname}?${search}` : url.pathname;
|
|
76
|
+
} catch {
|
|
77
|
+
return urlString;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Build a canonical URL from a request, stripping tracking params
|
|
83
|
+
* and normalizing the protocol/host.
|
|
84
|
+
*
|
|
85
|
+
* @param request - The incoming request
|
|
86
|
+
* @param baseUrl - Override origin (useful when behind a proxy)
|
|
87
|
+
*/
|
|
88
|
+
export function canonicalUrl(request: Request, baseUrl?: string): string {
|
|
89
|
+
const url = new URL(request.url);
|
|
90
|
+
const origin = baseUrl ?? url.origin;
|
|
91
|
+
|
|
92
|
+
for (const param of [...url.searchParams.keys()]) {
|
|
93
|
+
if (UTM_PARAMS.has(param.toLowerCase())) {
|
|
94
|
+
url.searchParams.delete(param);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const search = url.searchParams.toString();
|
|
99
|
+
const path = search ? `${url.pathname}?${search}` : url.pathname;
|
|
100
|
+
|
|
101
|
+
return `${origin}${path}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if a URL has any tracking/UTM parameters.
|
|
106
|
+
*/
|
|
107
|
+
export function hasTrackingParams(urlString: string): boolean {
|
|
108
|
+
try {
|
|
109
|
+
const url = new URL(urlString);
|
|
110
|
+
for (const param of url.searchParams.keys()) {
|
|
111
|
+
if (UTM_PARAMS.has(param.toLowerCase())) return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side device detection via RequestContext.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* // In a section loader or server function:
|
|
7
|
+
* import { detectDevice } from "@decocms/start/sdk/useDevice";
|
|
8
|
+
*
|
|
9
|
+
* export function loader(props: Props, req: Request) {
|
|
10
|
+
* const device = detectDevice(req.headers.get("user-agent") ?? "");
|
|
11
|
+
* return { ...props, device };
|
|
12
|
+
* }
|
|
13
|
+
*
|
|
14
|
+
* // Or via RequestContext (no request argument needed):
|
|
15
|
+
* import { useDevice } from "@decocms/start/sdk/useDevice";
|
|
16
|
+
*
|
|
17
|
+
* export function loader(props: Props) {
|
|
18
|
+
* const device = useDevice();
|
|
19
|
+
* return { ...props, isMobile: device === "mobile" };
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { RequestContext } from "./requestContext";
|
|
25
|
+
|
|
26
|
+
export type Device = "mobile" | "tablet" | "desktop";
|
|
27
|
+
|
|
28
|
+
// Android phones include "Mobile" in their UA; Android tablets do not.
|
|
29
|
+
// Check TABLET_RE first so `android(?!.*mobile)` captures tablets before
|
|
30
|
+
// the MOBILE_RE `android.*mobile` branch matches phones.
|
|
31
|
+
const MOBILE_RE = /mobile|android.*mobile|iphone|ipod|webos|blackberry|opera mini|iemobile/i;
|
|
32
|
+
const TABLET_RE = /ipad|tablet|kindle|silk|playbook|android(?!.*mobile)/i;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Detect device type from a User-Agent string.
|
|
36
|
+
* Pure function — no side effects, works anywhere.
|
|
37
|
+
*/
|
|
38
|
+
export function detectDevice(userAgent: string): Device {
|
|
39
|
+
if (TABLET_RE.test(userAgent)) return "tablet";
|
|
40
|
+
if (MOBILE_RE.test(userAgent)) return "mobile";
|
|
41
|
+
return "desktop";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the current device type via RequestContext.
|
|
46
|
+
*
|
|
47
|
+
* Must be called within a `RequestContext.run()` scope (i.e., during
|
|
48
|
+
* request handling). Falls back to "desktop" outside request scope.
|
|
49
|
+
*/
|
|
50
|
+
export function useDevice(): Device {
|
|
51
|
+
const ctx = RequestContext.current;
|
|
52
|
+
if (!ctx) return "desktop";
|
|
53
|
+
const ua = ctx.request.headers.get("user-agent") ?? "";
|
|
54
|
+
return detectDevice(ua);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check if the current request is from a mobile device.
|
|
59
|
+
*/
|
|
60
|
+
export function checkMobile(): boolean {
|
|
61
|
+
const ctx = RequestContext.current;
|
|
62
|
+
if (!ctx) return false;
|
|
63
|
+
return detectDevice(ctx.request.headers.get("user-agent") ?? "") === "mobile";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check if the current request is from a tablet device.
|
|
68
|
+
*/
|
|
69
|
+
export function checkTablet(): boolean {
|
|
70
|
+
const ctx = RequestContext.current;
|
|
71
|
+
if (!ctx) return false;
|
|
72
|
+
return detectDevice(ctx.request.headers.get("user-agent") ?? "") === "tablet";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Check if the current request is from a desktop device.
|
|
77
|
+
*/
|
|
78
|
+
export function checkDesktop(): boolean {
|
|
79
|
+
const ctx = RequestContext.current;
|
|
80
|
+
if (!ctx) return true;
|
|
81
|
+
return detectDevice(ctx.request.headers.get("user-agent") ?? "") === "desktop";
|
|
82
|
+
}
|
package/src/sdk/useId.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serializes functions into inline script strings for SSR output.
|
|
3
|
+
*
|
|
4
|
+
* Includes lightweight minification (whitespace + comment removal)
|
|
5
|
+
* with an LRU cache to avoid re-processing the same function bodies.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// LRU cache for minified function bodies
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
const MAX_CACHE_SIZE = 200;
|
|
13
|
+
const minifyCache = new Map<string, string>();
|
|
14
|
+
|
|
15
|
+
function cacheGet(key: string): string | undefined {
|
|
16
|
+
const value = minifyCache.get(key);
|
|
17
|
+
if (value !== undefined) {
|
|
18
|
+
// Move to end (most recently used)
|
|
19
|
+
minifyCache.delete(key);
|
|
20
|
+
minifyCache.set(key, value);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cacheSet(key: string, value: string) {
|
|
26
|
+
if (minifyCache.size >= MAX_CACHE_SIZE) {
|
|
27
|
+
// Delete oldest entry (first key in insertion order)
|
|
28
|
+
const oldest = minifyCache.keys().next().value;
|
|
29
|
+
if (oldest !== undefined) minifyCache.delete(oldest);
|
|
30
|
+
}
|
|
31
|
+
minifyCache.set(key, value);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Lightweight minification (no external deps)
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
function minifyJs(code: string): string {
|
|
39
|
+
return (
|
|
40
|
+
code
|
|
41
|
+
// Remove block comments only — line-comment stripping and operator-spacing
|
|
42
|
+
// collapse are unsafe: they can corrupt string literals containing "//"
|
|
43
|
+
// or operators, and regex literals whose delimiters look like operators.
|
|
44
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
45
|
+
// Collapse runs of whitespace (spaces, tabs, newlines) to a single space.
|
|
46
|
+
// This is safe because whitespace inside string/template literals is
|
|
47
|
+
// preserved as a single space, which is semantically identical.
|
|
48
|
+
.replace(/\s+/g, " ")
|
|
49
|
+
.trim()
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Public API
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Serializes a function and its arguments into a self-executing inline script.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <script dangerouslySetInnerHTML={{ __html: useScript(onLoad, elementId, config) }} />
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export function useScript<T extends (...args: any[]) => void>(
|
|
66
|
+
fn: T,
|
|
67
|
+
...args: Parameters<T>
|
|
68
|
+
): string {
|
|
69
|
+
const fnStr = fn.toString();
|
|
70
|
+
let minified = cacheGet(fnStr);
|
|
71
|
+
if (minified === undefined) {
|
|
72
|
+
minified = minifyJs(fnStr);
|
|
73
|
+
cacheSet(fnStr, minified);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const serializedArgs = args.map((a) => JSON.stringify(a)).join(",");
|
|
77
|
+
return `(${minified})(${serializedArgs})`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Like useScript, but returns a data: URI suitable for `<script src="...">`.
|
|
82
|
+
*/
|
|
83
|
+
export function useScriptAsDataURI<T extends (...args: any[]) => void>(
|
|
84
|
+
fn: T,
|
|
85
|
+
...args: Parameters<T>
|
|
86
|
+
): string {
|
|
87
|
+
const code = useScript(fn, ...args);
|
|
88
|
+
return `data:text/javascript;charset=utf-8,${encodeURIComponent(code)}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Stub -- Deco partial sections don't apply in TanStack Start.
|
|
93
|
+
* Returns the provided props as-is.
|
|
94
|
+
*/
|
|
95
|
+
export function usePartialSection(props?: Record<string, unknown>) {
|
|
96
|
+
return props || {};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function useSection(_props?: Record<string, unknown>) {
|
|
100
|
+
return "";
|
|
101
|
+
}
|