@primestyleai/tryon 5.6.19 → 5.6.21

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.
@@ -325,11 +325,23 @@ function getApiUrl(override) {
325
325
  return override || process.env.NEXT_PUBLIC_PRIMESTYLE_API_URL || "http://localhost:4000";
326
326
  }
327
327
  async function recommendForProduct(input) {
328
+ const log = (...args) => console.log("[ps-sdk:recommend]", ...args);
328
329
  const profile = input.profile ?? getActiveProfile();
329
- if (!profile) return null;
330
+ if (!profile) {
331
+ log("no active profile — returning null");
332
+ return null;
333
+ }
334
+ log("start", {
335
+ productId: input.productId,
336
+ profileId: profile.id,
337
+ profileName: profile.name,
338
+ hasMeasurements: !!profile.measurements && Object.keys(profile.measurements || {}).length,
339
+ measurementsCount: Object.keys(profile.measurements || {}).length
340
+ });
330
341
  if (!input.skipCache) {
331
342
  const cached = getCachedSize(profile, input.productId);
332
343
  if (cached) {
344
+ log("cache HIT", { recommendedSize: cached.recommendedSize, hasSectionsFull: !!cached.sectionsFull });
333
345
  const reconstructedRaw = cached.sectionsFull ? {
334
346
  recommendedSize: cached.recommendedSize,
335
347
  confidence: cached.confidence || "high",
@@ -357,14 +369,19 @@ async function recommendForProduct(input) {
357
369
  };
358
370
  }
359
371
  }
372
+ log("cache MISS — calling backend");
360
373
  let apiKey;
361
374
  try {
362
375
  apiKey = input.apiKey ?? getApiKey();
363
- } catch {
376
+ } catch (e) {
377
+ log("no api key — aborting", e);
364
378
  return null;
365
379
  }
366
380
  const apiUrl = (input.apiUrl ?? getApiUrl()).replace(/\/+$/, "");
367
- if (!apiKey) return null;
381
+ if (!apiKey) {
382
+ log("no api key — aborting");
383
+ return null;
384
+ }
368
385
  let sizeGuide = null;
369
386
  if (input.sizeGuideData != null) {
370
387
  try {
@@ -376,9 +393,17 @@ async function recommendForProduct(input) {
376
393
  sizeGuideRaw: input.sizeGuideData
377
394
  })
378
395
  });
379
- if (sgRes.ok) sizeGuide = await sgRes.json();
380
- } catch {
396
+ if (sgRes.ok) {
397
+ sizeGuide = await sgRes.json();
398
+ log("sizeguide OK", { found: sizeGuide?.found, sectionCount: Object.keys(sizeGuide?.sections || {}).length });
399
+ } else {
400
+ log("sizeguide FAILED", sgRes.status, sgRes.statusText);
401
+ }
402
+ } catch (e) {
403
+ log("sizeguide threw", e);
381
404
  }
405
+ } else {
406
+ log("no sizeGuideData provided");
382
407
  }
383
408
  const measurements = {
384
409
  gender: profile.gender,
@@ -407,6 +432,7 @@ async function recommendForProduct(input) {
407
432
  if (sizeGuide && sizeGuide.found) {
408
433
  payload.sizeGuide = sizeGuide;
409
434
  }
435
+ log("calling /sizing/recommend", { measurements: Object.keys(measurements), hasSizeGuide: !!payload.sizeGuide });
410
436
  let result = null;
411
437
  try {
412
438
  const res = await fetch(`${apiUrl}/api/v1/sizing/recommend`, {
@@ -414,12 +440,24 @@ async function recommendForProduct(input) {
414
440
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
415
441
  body: JSON.stringify(payload)
416
442
  });
417
- if (!res.ok) return null;
443
+ if (!res.ok) {
444
+ log("recommend FAILED", res.status, res.statusText);
445
+ return null;
446
+ }
418
447
  result = await res.json();
419
- } catch {
448
+ log("recommend OK", {
449
+ recommendedSize: result?.recommendedSize,
450
+ sectionKeys: result?.sections ? Object.keys(result.sections) : null,
451
+ sections: result?.sections
452
+ });
453
+ } catch (e) {
454
+ log("recommend threw", e);
455
+ return null;
456
+ }
457
+ if (!result || !result.recommendedSize) {
458
+ log("recommend returned no recommendedSize — bailing");
420
459
  return null;
421
460
  }
422
- if (!result || !result.recommendedSize) return null;
423
461
  const sectionsMap = result.sections ? Object.fromEntries(
424
462
  Object.entries(result.sections).map(([name, sec]) => [name, sec.recommendedSize])
425
463
  ) : void 0;
@@ -9399,6 +9437,7 @@ function BodyProfileView({
9399
9437
  onUseActiveProfile,
9400
9438
  activeProfileName,
9401
9439
  onStartFresh,
9440
+ activeProfile,
9402
9441
  onBack,
9403
9442
  t
9404
9443
  }) {
@@ -9407,15 +9446,42 @@ function BodyProfileView({
9407
9446
  step === "photo" ? 0 : steps.indexOf(step);
9408
9447
  const isMobile = useIsMobile();
9409
9448
  const imperial = isImperial(sizingCountry);
9410
- const [height, setHeight] = useState(formRef.current.height || "173");
9411
- const [heightFeet, setHeightFeet] = useState(formRef.current.heightFeet || "5");
9412
- const [heightInches, setHeightInches] = useState(formRef.current.heightInches || "8");
9413
- const [weight, setWeight] = useState(formRef.current.weight || (imperial ? "154" : "70"));
9414
- const [age, setAge] = useState(formRef.current.age || "30");
9449
+ const profileHeight = activeProfile?.height;
9450
+ const profileWeight = activeProfile?.weight;
9451
+ const profileAge = activeProfile?.age;
9452
+ const profileHUnit = activeProfile?.heightUnit === "ft" ? "in" : activeProfile?.heightUnit;
9453
+ const profileWUnit = activeProfile?.weightUnit;
9454
+ const seedHeightCm = (() => {
9455
+ if (profileHeight != null && profileHUnit === "cm") return String(Math.round(profileHeight));
9456
+ if (profileHeight != null && (profileHUnit === "in" || profileHUnit === "ft"))
9457
+ return String(Math.round(profileHeight * 2.54));
9458
+ return formRef.current.height || "173";
9459
+ })();
9460
+ const seedTotalIn = (() => {
9461
+ if (profileHeight != null && (profileHUnit === "in" || profileHUnit === "ft"))
9462
+ return Math.round(profileHeight);
9463
+ if (profileHeight != null && profileHUnit === "cm")
9464
+ return Math.round(profileHeight / 2.54);
9465
+ return null;
9466
+ })();
9467
+ const seedHeightFeet = seedTotalIn != null ? String(Math.floor(seedTotalIn / 12)) : formRef.current.heightFeet || "5";
9468
+ const seedHeightInches = seedTotalIn != null ? String(seedTotalIn % 12) : formRef.current.heightInches || "8";
9469
+ const seedWeight = (() => {
9470
+ if (profileWeight != null) return String(Math.round(profileWeight));
9471
+ return formRef.current.weight || (imperial ? "154" : "70");
9472
+ })();
9473
+ const seedAge = profileAge != null ? String(profileAge) : formRef.current.age || "30";
9474
+ const [height, setHeight] = useState(seedHeightCm);
9475
+ const [heightFeet, setHeightFeet] = useState(seedHeightFeet);
9476
+ const [heightInches, setHeightInches] = useState(seedHeightInches);
9477
+ const [weight, setWeight] = useState(seedWeight);
9478
+ const [age, setAge] = useState(seedAge);
9415
9479
  const [hUnit, setHUnit] = useState(
9416
- heightUnit === "ft" ? "in" : heightUnit || (imperial ? "in" : "cm")
9480
+ profileHUnit || (heightUnit === "ft" ? "in" : heightUnit || (imperial ? "in" : "cm"))
9481
+ );
9482
+ const [wUnit, setWUnit] = useState(
9483
+ profileWUnit || weightUnit || (imperial ? "lbs" : "kg")
9417
9484
  );
9418
- const [wUnit, setWUnit] = useState(weightUnit || (imperial ? "lbs" : "kg"));
9419
9485
  const isImperialMode = hUnit === "in" || wUnit === "lbs";
9420
9486
  const [photoFile, setPhotoFile] = useState(null);
9421
9487
  const [photoPreview, setPhotoPreview] = useState(null);
@@ -11220,6 +11286,7 @@ function PrimeStyleTryonInner({
11220
11286
  const p = profiles.find((x) => x.id === activeProfileId);
11221
11287
  return p?.name || null;
11222
11288
  })(),
11289
+ activeProfile: profiles.find((x) => x.id === activeProfileId) || null,
11223
11290
  onStartFresh: () => {
11224
11291
  setActiveProfileId$1(null);
11225
11292
  formRef.current = {};
@@ -11245,7 +11312,8 @@ function PrimeStyleTryonInner({
11245
11312
  onSnapSubmit: handleSnapSubmit,
11246
11313
  onBack: handleClose,
11247
11314
  t
11248
- }
11315
+ },
11316
+ `bp-${activeProfileId || "anon"}`
11249
11317
  ) }, "v-bodyprofile");
11250
11318
  }
11251
11319
  case "estimation-review":
@@ -11476,15 +11544,19 @@ function usePrimeStyleSize(input) {
11476
11544
  let cancelled = false;
11477
11545
  setLoading(true);
11478
11546
  setNoProfile(false);
11547
+ console.log("[ps-sdk:hook] usePrimeStyleSize start", { productId: input.productId });
11479
11548
  recommendForProduct(input).then((res) => {
11480
11549
  if (cancelled) return;
11481
11550
  if (res === null) {
11551
+ console.log("[ps-sdk:hook] usePrimeStyleSize → null (no profile or recommendation failed)");
11482
11552
  setNoProfile(true);
11483
11553
  setResult(null);
11484
11554
  } else {
11555
+ console.log("[ps-sdk:hook] usePrimeStyleSize → result", { recommendedSize: res.recommendedSize, hasRaw: !!res.raw });
11485
11556
  setResult(res);
11486
11557
  }
11487
- }).catch(() => {
11558
+ }).catch((e) => {
11559
+ console.log("[ps-sdk:hook] usePrimeStyleSize threw", e);
11488
11560
  if (!cancelled) setResult(null);
11489
11561
  }).finally(() => {
11490
11562
  if (!cancelled) setLoading(false);
@@ -48,8 +48,11 @@ interface BodyProfileViewProps {
48
48
  /** Deselect the active profile so the user can run a fresh AI sizing flow
49
49
  * with full body-shape questions. */
50
50
  onStartFresh?: () => void;
51
+ /** Active profile — when set, its height/weight/age/gender seed the basics
52
+ * inputs so the SDK opens with the user's saved values, not the defaults. */
53
+ activeProfile?: import("../types").Profile | null;
51
54
  onBack: () => void;
52
55
  t: TranslateFn;
53
56
  }
54
- export declare function BodyProfileView({ productImage, productTitle, isWomen, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
57
+ export declare function BodyProfileView({ productImage, productTitle, isWomen, formRef, sizingCountry, heightUnit, setHeightUnit, weightUnit, setWeightUnit, sizingUnit, setSizingUnit, onComplete, onSnapSubmit, hasActiveProfileWithMeasurements, onUseActiveProfile, activeProfileName, onStartFresh, activeProfile, onBack, t, }: BodyProfileViewProps): import("react/jsx-runtime").JSX.Element;
55
58
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "5.6.19",
3
+ "version": "5.6.21",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",