@keak/sdk 2.2.1 โ†’ 2.2.3

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/dist/index.js CHANGED
@@ -2357,6 +2357,117 @@ function detectVariantElements(children) {
2357
2357
  // Cache for memoized snapshot objects to prevent infinite re-renders
2358
2358
  // Key format: "ready-isDesktopProject" โ†’ e.g., "true-false"
2359
2359
  const snapshotCache = new Map();
2360
+ // KeakLoader Component - Page-level middleware that waits for embedded script
2361
+ // Wrap your app/page with this to prevent rendering until variant assignments are ready
2362
+ const KeakLoader = ({ children }) => {
2363
+ console.log(`[Keak SDK] ๐Ÿ”ต KeakLoader rendering started`);
2364
+ const embeddedScriptStatus = useSyncExternalStore(
2365
+ // subscribe - called when component mounts
2366
+ (callback) => {
2367
+ console.log(`[Keak SDK] ๐Ÿ“ก KeakLoader subscribe called`);
2368
+ if (typeof window === 'undefined') {
2369
+ return () => { };
2370
+ }
2371
+ // Check if already ready
2372
+ const embeddedData = window.KEAK_EMBEDDED_DATA;
2373
+ const isDesktopProject = !!(embeddedData && embeddedData.projectUuid);
2374
+ const hasComputeFunction = typeof window.KeakAssign?.computeAssignments === 'function';
2375
+ // If not a desktop project AND embedded data exists, no need to wait
2376
+ if (embeddedData && !isDesktopProject) {
2377
+ console.log(`[Keak SDK] โœ… KeakLoader: Not a desktop project - no waiting needed`);
2378
+ return () => { };
2379
+ }
2380
+ // If desktop project and already has compute function, ready immediately
2381
+ if (isDesktopProject && hasComputeFunction) {
2382
+ console.log(`[Keak SDK] โœ… KeakLoader: Embedded script already ready`);
2383
+ return () => { };
2384
+ }
2385
+ // Poll for embedded script to load with shorter timeout (300ms max)
2386
+ console.log(`[Keak SDK] โณ KeakLoader: Starting polling...`);
2387
+ let attempts = 0;
2388
+ const maxAttempts = 10; // 10 * 30ms = 300ms max
2389
+ const pollInterval = setInterval(() => {
2390
+ attempts++;
2391
+ console.log(`[Keak SDK] ๐Ÿ”„ KeakLoader poll attempt ${attempts}/${maxAttempts}`);
2392
+ const currentData = window.KEAK_EMBEDDED_DATA;
2393
+ const currentIsDesktop = !!(currentData && currentData.projectUuid);
2394
+ const currentHasFunc = typeof window.KeakAssign?.computeAssignments === 'function';
2395
+ // If embedded data appears with projectUuid AND compute function is ready
2396
+ if (currentIsDesktop && currentHasFunc) {
2397
+ console.log(`[Keak SDK] โœ… KeakLoader: Desktop project script ready after ${attempts} attempts`);
2398
+ clearInterval(pollInterval);
2399
+ callback(); // Notify React of change
2400
+ }
2401
+ // If embedded data appears but has NO projectUuid (confirmed not a desktop project)
2402
+ else if (currentData && !currentIsDesktop) {
2403
+ console.log(`[Keak SDK] โœ… KeakLoader: Confirmed not a desktop project after ${attempts} attempts`);
2404
+ clearInterval(pollInterval);
2405
+ callback(); // Notify React of change
2406
+ }
2407
+ // Timeout - proceed anyway
2408
+ else if (attempts >= maxAttempts) {
2409
+ console.warn(`[Keak SDK] โฐ KeakLoader: Timeout after 300ms - proceeding anyway`);
2410
+ clearInterval(pollInterval);
2411
+ callback(); // Notify React of change
2412
+ }
2413
+ }, 30); // 30ms interval for faster checks
2414
+ return () => {
2415
+ console.log(`[Keak SDK] ๐Ÿงน KeakLoader cleanup interval`);
2416
+ clearInterval(pollInterval);
2417
+ };
2418
+ },
2419
+ // getSnapshot - called synchronously during render
2420
+ () => {
2421
+ if (typeof window === 'undefined') {
2422
+ const cacheKey = 'true-false';
2423
+ if (!snapshotCache.has(cacheKey)) {
2424
+ snapshotCache.set(cacheKey, { ready: true, isDesktopProject: false });
2425
+ }
2426
+ return snapshotCache.get(cacheKey);
2427
+ }
2428
+ const embeddedData = window.KEAK_EMBEDDED_DATA;
2429
+ const isDesktopProject = !!(embeddedData && embeddedData.projectUuid);
2430
+ const hasComputeFunction = typeof window.KeakAssign?.computeAssignments === 'function';
2431
+ const ready = !isDesktopProject || hasComputeFunction;
2432
+ // Create cache key from the actual values
2433
+ const cacheKey = `${ready}-${isDesktopProject}`;
2434
+ // Return cached snapshot if it exists
2435
+ if (!snapshotCache.has(cacheKey)) {
2436
+ console.log(`[Keak SDK] ๐Ÿ“ธ KeakLoader getSnapshot - Creating new cached snapshot:`, { ready, isDesktopProject });
2437
+ snapshotCache.set(cacheKey, { ready, isDesktopProject });
2438
+ }
2439
+ return snapshotCache.get(cacheKey);
2440
+ },
2441
+ // getServerSnapshot - for SSR
2442
+ () => {
2443
+ if (typeof window === 'undefined') {
2444
+ const cacheKey = 'true-false';
2445
+ if (!snapshotCache.has(cacheKey)) {
2446
+ snapshotCache.set(cacheKey, { ready: true, isDesktopProject: false });
2447
+ }
2448
+ return snapshotCache.get(cacheKey);
2449
+ }
2450
+ // Browser environment - check for embedded data
2451
+ const embeddedData = window.KEAK_EMBEDDED_DATA;
2452
+ const isDesktopProject = !!(embeddedData && embeddedData.projectUuid);
2453
+ const hasComputeFunction = typeof window.KeakAssign?.computeAssignments === 'function';
2454
+ const ready = !isDesktopProject || hasComputeFunction;
2455
+ const cacheKey = `${ready}-${isDesktopProject}`;
2456
+ if (!snapshotCache.has(cacheKey)) {
2457
+ console.log(`[Keak SDK] ๐ŸŒ KeakLoader getServerSnapshot - Creating new cached snapshot:`, { ready, isDesktopProject });
2458
+ snapshotCache.set(cacheKey, { ready, isDesktopProject });
2459
+ }
2460
+ return snapshotCache.get(cacheKey);
2461
+ });
2462
+ console.log(`[Keak SDK] ๐Ÿ” KeakLoader status:`, embeddedScriptStatus);
2463
+ // BLOCKING: Don't render anything until embedded data is ready (for desktop projects)
2464
+ if (embeddedScriptStatus.isDesktopProject && !embeddedScriptStatus.ready) {
2465
+ console.log(`[Keak SDK] ๐Ÿšซ KeakLoader blocking page render - waiting for embedded script`);
2466
+ return null;
2467
+ }
2468
+ console.log(`[Keak SDK] โœ… KeakLoader proceeding with render`);
2469
+ return jsx(Fragment, { children: children });
2470
+ };
2360
2471
  // Experiment Component
2361
2472
  const Experiment = ({ name, children, active = true }) => {
2362
2473
  // CRITICAL: For Keak Code desktop projects, wait for embedded script to load
@@ -2369,19 +2480,21 @@ const Experiment = ({ name, children, active = true }) => {
2369
2480
  if (typeof window === 'undefined') {
2370
2481
  return () => { };
2371
2482
  }
2372
- // If already ready, no need to poll
2483
+ // Check if already ready
2373
2484
  const embeddedData = window.KEAK_EMBEDDED_DATA;
2374
- if (!embeddedData || !embeddedData.projectUuid) {
2375
- // Not a desktop project - no waiting needed
2485
+ const isDesktopProject = !!(embeddedData && embeddedData.projectUuid);
2486
+ const hasComputeFunction = typeof window.KeakAssign?.computeAssignments === 'function';
2487
+ // If not a desktop project AND embedded data exists, no need to wait
2488
+ if (embeddedData && !isDesktopProject) {
2376
2489
  console.log(`[Keak SDK] โœ… Not a desktop project for "${name}" - no waiting needed`);
2377
2490
  return () => { };
2378
2491
  }
2379
- if (typeof window.KeakAssign?.computeAssignments === 'function') {
2380
- // Already ready
2492
+ // If desktop project and already has compute function, ready immediately
2493
+ if (isDesktopProject && hasComputeFunction) {
2381
2494
  console.log(`[Keak SDK] โœ… Embedded script already ready for "${name}"`);
2382
2495
  return () => { };
2383
2496
  }
2384
- // Desktop project but script not ready - poll with timeout
2497
+ // Poll for embedded script to load (either waiting for KEAK_EMBEDDED_DATA or computeAssignments)
2385
2498
  console.log(`[Keak SDK] โณ Starting polling for "${name}"...`);
2386
2499
  let attempts = 0;
2387
2500
  const maxAttempts = 10; // 500ms max
@@ -2389,12 +2502,21 @@ const Experiment = ({ name, children, active = true }) => {
2389
2502
  attempts++;
2390
2503
  console.log(`[Keak SDK] ๐Ÿ”„ Poll attempt ${attempts}/${maxAttempts} for "${name}"`);
2391
2504
  const currentData = window.KEAK_EMBEDDED_DATA;
2392
- const hasFunc = typeof window.KeakAssign?.computeAssignments === 'function';
2393
- if (currentData && hasFunc) {
2394
- console.log(`[Keak SDK] โœ… Script ready after ${attempts} attempts for "${name}"`);
2505
+ const currentIsDesktop = !!(currentData && currentData.projectUuid);
2506
+ const currentHasFunc = typeof window.KeakAssign?.computeAssignments === 'function';
2507
+ // If embedded data appears with projectUuid AND compute function is ready
2508
+ if (currentIsDesktop && currentHasFunc) {
2509
+ console.log(`[Keak SDK] โœ… Desktop project script ready after ${attempts} attempts for "${name}"`);
2510
+ clearInterval(pollInterval);
2511
+ callback(); // Notify React of change
2512
+ }
2513
+ // If embedded data appears but has NO projectUuid (confirmed not a desktop project)
2514
+ else if (currentData && !currentIsDesktop) {
2515
+ console.log(`[Keak SDK] โœ… Confirmed not a desktop project after ${attempts} attempts for "${name}"`);
2395
2516
  clearInterval(pollInterval);
2396
2517
  callback(); // Notify React of change
2397
2518
  }
2519
+ // Timeout - proceed anyway
2398
2520
  else if (attempts >= maxAttempts) {
2399
2521
  console.warn(`[Keak SDK] โฐ Timeout after ${maxAttempts} attempts for "${name}" - proceeding anyway`);
2400
2522
  clearInterval(pollInterval);
@@ -2772,5 +2894,5 @@ function initializeToolbar(config) {
2772
2894
  });
2773
2895
  }
2774
2896
 
2775
- export { Conversion, Experiment, KeakToolbar, Variant, buildSourcePathInjection, initializeToolbar, keak, useKeak };
2897
+ export { Conversion, Experiment, KeakLoader, KeakToolbar, Variant, buildSourcePathInjection, initializeToolbar, keak, useKeak };
2776
2898
  //# sourceMappingURL=index.js.map