medusa-product-helper 0.0.26 → 0.0.28

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.
@@ -149,7 +149,8 @@ const useMetadataConfig = (entity) => {
149
149
  const useProductMetadataConfig = () => useMetadataConfig("product");
150
150
  const useCategoryMetadataConfig = () => useMetadataConfig("category");
151
151
  const useOrderMetadataConfig = () => useMetadataConfig("order");
152
- const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
152
+ const useCollectionMetadataConfig = () => useMetadataConfig("collection");
153
+ const CONFIG_DOCS_URL$3 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
153
154
  const CategoryMetadataTableWidget = ({ data }) => {
154
155
  const { data: descriptors = [], isPending, isError } = useCategoryMetadataConfig();
155
156
  const categoryId = (data == null ? void 0 : data.id) ?? void 0;
@@ -287,6 +288,390 @@ const CategoryMetadataTableWidget = ({ data }) => {
287
288
  setIsSaving(false);
288
289
  }
289
290
  };
291
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex flex-col gap-y-4", children: [
292
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-y-1", children: [
293
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
294
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Metadata" }),
295
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { size: "2xsmall", rounded: "full", children: descriptors.length })
296
+ ] }),
297
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-subtle", children: "Structured metadata mapped to the keys you configured in the plugin options." })
298
+ ] }),
299
+ isPending || !isInitializedRef.current || Object.keys(values).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "error", label: "Configuration unavailable", children: [
300
+ "Unable to load metadata configuration for this plugin. Confirm that the plugin is registered with options in ",
301
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "medusa-config.ts" }),
302
+ "."
303
+ ] }) : !descriptors.length ? /* @__PURE__ */ jsxRuntime.jsxs(ui.InlineTip, { variant: "info", label: "No configured metadata keys", children: [
304
+ "Provide a ",
305
+ /* @__PURE__ */ jsxRuntime.jsx("code", { children: "metadataDescriptors" }),
306
+ " array in the plugin options to control which keys show up here.",
307
+ " ",
308
+ /* @__PURE__ */ jsxRuntime.jsx(
309
+ "a",
310
+ {
311
+ className: "text-ui-fg-interactive underline",
312
+ href: CONFIG_DOCS_URL$3,
313
+ target: "_blank",
314
+ rel: "noreferrer",
315
+ children: "Learn how to configure it."
316
+ }
317
+ )
318
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
319
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-lg border border-ui-border-base", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
320
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
321
+ /* @__PURE__ */ jsxRuntime.jsx(
322
+ "th",
323
+ {
324
+ scope: "col",
325
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
326
+ children: "Label"
327
+ }
328
+ ),
329
+ /* @__PURE__ */ jsxRuntime.jsx(
330
+ "th",
331
+ {
332
+ scope: "col",
333
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
334
+ children: "Value"
335
+ }
336
+ )
337
+ ] }) }),
338
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-ui-border-subtle bg-ui-bg-base", children: descriptors.map((descriptor) => {
339
+ const value = values[descriptor.key];
340
+ const error = errors[descriptor.key];
341
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
342
+ /* @__PURE__ */ jsxRuntime.jsx(
343
+ "th",
344
+ {
345
+ scope: "row",
346
+ className: "txt-compact-medium text-ui-fg-base align-top px-4 py-4",
347
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
348
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: descriptor.label ?? descriptor.key }),
349
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-xsmall-plus text-ui-fg-muted uppercase tracking-wide", children: descriptor.type })
350
+ ] })
351
+ }
352
+ ),
353
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "align-top px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
354
+ /* @__PURE__ */ jsxRuntime.jsx(
355
+ ValueField$3,
356
+ {
357
+ descriptor,
358
+ value,
359
+ onStringChange: handleStringChange,
360
+ onBooleanChange: handleBooleanChange
361
+ }
362
+ ),
363
+ error && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "txt-compact-small text-ui-fg-error", children: error })
364
+ ] }) })
365
+ ] }, descriptor.key);
366
+ }) })
367
+ ] }) }),
368
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-subtle pt-3 md:flex-row md:items-center md:justify-between", children: [
369
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Changes are stored on the category metadata object. Clearing a field removes the corresponding key on save." }),
370
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
371
+ /* @__PURE__ */ jsxRuntime.jsx(
372
+ ui.Button,
373
+ {
374
+ variant: "secondary",
375
+ size: "small",
376
+ disabled: !isDirty || isSaving,
377
+ onClick: handleReset,
378
+ children: "Reset"
379
+ }
380
+ ),
381
+ /* @__PURE__ */ jsxRuntime.jsx(
382
+ ui.Button,
383
+ {
384
+ size: "small",
385
+ onClick: handleSubmit,
386
+ disabled: !isDirty || hasErrors || isSaving,
387
+ isLoading: isSaving,
388
+ children: "Save metadata"
389
+ }
390
+ )
391
+ ] })
392
+ ] })
393
+ ] })
394
+ ] });
395
+ };
396
+ const ValueField$3 = ({
397
+ descriptor,
398
+ value,
399
+ onStringChange,
400
+ onBooleanChange
401
+ }) => {
402
+ const fileInputRef = react.useRef(null);
403
+ const [isUploading, setIsUploading] = react.useState(false);
404
+ const handleFileUpload = async (event) => {
405
+ var _a;
406
+ const file = (_a = event.target.files) == null ? void 0 : _a[0];
407
+ if (!file) {
408
+ return;
409
+ }
410
+ setIsUploading(true);
411
+ try {
412
+ const formData = new FormData();
413
+ formData.append("files", file);
414
+ const response = await fetch("/admin/uploads", {
415
+ method: "POST",
416
+ credentials: "include",
417
+ body: formData
418
+ });
419
+ if (!response.ok) {
420
+ const payload = await response.json().catch(() => null);
421
+ throw new Error((payload == null ? void 0 : payload.message) ?? "File upload failed");
422
+ }
423
+ const result = await response.json();
424
+ if (result.files && result.files.length > 0) {
425
+ const uploadedFile = result.files[0];
426
+ const fileUrl = uploadedFile.url || uploadedFile.key;
427
+ if (fileUrl) {
428
+ onStringChange(descriptor.key, fileUrl);
429
+ ui.toast.success("File uploaded successfully");
430
+ } else {
431
+ throw new Error("File upload succeeded but no URL returned");
432
+ }
433
+ } else {
434
+ throw new Error("File upload failed - no files returned");
435
+ }
436
+ } catch (error) {
437
+ ui.toast.error(
438
+ error instanceof Error ? error.message : "Failed to upload file"
439
+ );
440
+ } finally {
441
+ setIsUploading(false);
442
+ if (fileInputRef.current) {
443
+ fileInputRef.current.value = "";
444
+ }
445
+ }
446
+ };
447
+ if (descriptor.type === "bool") {
448
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
449
+ /* @__PURE__ */ jsxRuntime.jsx(
450
+ ui.Switch,
451
+ {
452
+ checked: Boolean(value),
453
+ onCheckedChange: (checked) => onBooleanChange(descriptor.key, Boolean(checked)),
454
+ "aria-label": `Toggle ${descriptor.label ?? descriptor.key}`
455
+ }
456
+ ),
457
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "txt-compact-small text-ui-fg-muted", children: Boolean(value) ? "True" : "False" })
458
+ ] });
459
+ }
460
+ if (descriptor.type === "text") {
461
+ return /* @__PURE__ */ jsxRuntime.jsx(
462
+ ui.Textarea,
463
+ {
464
+ value: value ?? "",
465
+ placeholder: "Enter text",
466
+ rows: 3,
467
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
468
+ }
469
+ );
470
+ }
471
+ if (descriptor.type === "number") {
472
+ return /* @__PURE__ */ jsxRuntime.jsx(
473
+ ui.Input,
474
+ {
475
+ type: "text",
476
+ inputMode: "decimal",
477
+ placeholder: "0.00",
478
+ value: value ?? "",
479
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
480
+ }
481
+ );
482
+ }
483
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
484
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
485
+ /* @__PURE__ */ jsxRuntime.jsx(
486
+ ui.Input,
487
+ {
488
+ type: "url",
489
+ placeholder: "https://example.com/file",
490
+ value: value ?? "",
491
+ onChange: (event) => onStringChange(descriptor.key, event.target.value),
492
+ className: "flex-1"
493
+ }
494
+ ),
495
+ /* @__PURE__ */ jsxRuntime.jsx(
496
+ "input",
497
+ {
498
+ ref: fileInputRef,
499
+ type: "file",
500
+ className: "hidden",
501
+ onChange: handleFileUpload,
502
+ disabled: isUploading,
503
+ "aria-label": `Upload file for ${descriptor.label ?? descriptor.key}`
504
+ }
505
+ ),
506
+ /* @__PURE__ */ jsxRuntime.jsx(
507
+ ui.Button,
508
+ {
509
+ type: "button",
510
+ variant: "secondary",
511
+ size: "small",
512
+ onClick: () => {
513
+ var _a;
514
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
515
+ },
516
+ disabled: isUploading,
517
+ isLoading: isUploading,
518
+ children: isUploading ? "Uploading..." : "Upload"
519
+ }
520
+ )
521
+ ] }),
522
+ typeof value === "string" && value && /* @__PURE__ */ jsxRuntime.jsx(
523
+ "a",
524
+ {
525
+ className: "txt-compact-small-plus text-ui-fg-interactive underline",
526
+ href: value,
527
+ target: "_blank",
528
+ rel: "noreferrer",
529
+ children: "View file"
530
+ }
531
+ )
532
+ ] });
533
+ };
534
+ adminSdk.defineWidgetConfig({
535
+ zone: "product_category.details.after"
536
+ });
537
+ const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-collection-details";
538
+ const CollectionMetadataTableWidget = ({ data }) => {
539
+ const { data: descriptors = [], isPending, isError } = useCollectionMetadataConfig();
540
+ const collectionId = (data == null ? void 0 : data.id) ?? void 0;
541
+ const [baselineMetadata, setBaselineMetadata] = react.useState(
542
+ (data == null ? void 0 : data.metadata) ?? {}
543
+ );
544
+ const queryClient = reactQuery.useQueryClient();
545
+ const previousCollectionIdRef = react.useRef(collectionId);
546
+ const isInitializedRef = react.useRef(false);
547
+ const dataRef = react.useRef(data);
548
+ const descriptorsRef = react.useRef(descriptors);
549
+ react.useEffect(() => {
550
+ dataRef.current = data;
551
+ descriptorsRef.current = descriptors;
552
+ }, [data, descriptors]);
553
+ react.useEffect(() => {
554
+ var _a;
555
+ if (previousCollectionIdRef.current === collectionId && isInitializedRef.current) {
556
+ return;
557
+ }
558
+ const collectionIdChanged = previousCollectionIdRef.current !== collectionId;
559
+ if (collectionIdChanged || !isInitializedRef.current) {
560
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? ((_a = dataRef.current) == null ? void 0 : _a.metadata) ?? {};
561
+ const currentDescriptors = descriptorsRef.current.length > 0 ? descriptorsRef.current : descriptors;
562
+ if (currentDescriptors.length === 0) {
563
+ return;
564
+ }
565
+ previousCollectionIdRef.current = collectionId;
566
+ setBaselineMetadata(currentMetadata);
567
+ const newInitialState = buildInitialFormState(currentDescriptors, currentMetadata);
568
+ setValues(newInitialState);
569
+ isInitializedRef.current = true;
570
+ }
571
+ }, [collectionId]);
572
+ const metadataStringRef = react.useRef("");
573
+ react.useEffect(() => {
574
+ const hasCollectionData = !!data;
575
+ const descriptorsLoaded = descriptors.length > 0;
576
+ const sameCollection = previousCollectionIdRef.current === collectionId;
577
+ const notInitialized = !isInitializedRef.current;
578
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
579
+ const currentMetadataString = JSON.stringify(currentMetadata);
580
+ const metadataChanged = currentMetadataString !== metadataStringRef.current;
581
+ if (hasCollectionData && descriptorsLoaded && sameCollection && (notInitialized || metadataChanged)) {
582
+ const newInitialState = buildInitialFormState(descriptors, currentMetadata);
583
+ setBaselineMetadata(currentMetadata);
584
+ setValues(newInitialState);
585
+ metadataStringRef.current = currentMetadataString;
586
+ isInitializedRef.current = true;
587
+ }
588
+ }, [data, descriptors.length, collectionId]);
589
+ const initialState = react.useMemo(
590
+ () => buildInitialFormState(descriptors, baselineMetadata),
591
+ [descriptors, baselineMetadata]
592
+ );
593
+ const [values, setValues] = react.useState({});
594
+ const [isSaving, setIsSaving] = react.useState(false);
595
+ const errors = react.useMemo(() => {
596
+ return descriptors.reduce((acc, descriptor) => {
597
+ const error = validateValueForDescriptor(descriptor, values[descriptor.key]);
598
+ if (error) {
599
+ acc[descriptor.key] = error;
600
+ }
601
+ return acc;
602
+ }, {});
603
+ }, [descriptors, values]);
604
+ const hasErrors = Object.keys(errors).length > 0;
605
+ const isDirty = react.useMemo(() => {
606
+ return hasMetadataChanges({
607
+ descriptors,
608
+ values,
609
+ originalMetadata: baselineMetadata
610
+ });
611
+ }, [descriptors, values, baselineMetadata]);
612
+ const handleStringChange = (key, nextValue) => {
613
+ setValues((prev) => ({
614
+ ...prev,
615
+ [key]: nextValue
616
+ }));
617
+ };
618
+ const handleBooleanChange = (key, nextValue) => {
619
+ setValues((prev) => ({
620
+ ...prev,
621
+ [key]: nextValue
622
+ }));
623
+ };
624
+ const handleReset = () => {
625
+ setValues(initialState);
626
+ };
627
+ const handleSubmit = async () => {
628
+ if (!(data == null ? void 0 : data.id) || !descriptors.length) {
629
+ return;
630
+ }
631
+ setIsSaving(true);
632
+ try {
633
+ const metadataPayload = buildMetadataPayload({
634
+ descriptors,
635
+ values,
636
+ originalMetadata: baselineMetadata
637
+ });
638
+ const response = await fetch(`/admin/collections/${data.id}`, {
639
+ method: "POST",
640
+ credentials: "include",
641
+ headers: {
642
+ "Content-Type": "application/json"
643
+ },
644
+ body: JSON.stringify({
645
+ metadata: metadataPayload
646
+ })
647
+ });
648
+ if (!response.ok) {
649
+ const payload = await response.json().catch(() => null);
650
+ throw new Error((payload == null ? void 0 : payload.message) ?? "Unable to save metadata");
651
+ }
652
+ const updated = await response.json();
653
+ const nextMetadata = updated.product_collection.metadata;
654
+ setBaselineMetadata(nextMetadata);
655
+ setValues(buildInitialFormState(descriptors, nextMetadata));
656
+ ui.toast.success("Metadata saved");
657
+ await queryClient.invalidateQueries({
658
+ queryKey: ["collections"]
659
+ });
660
+ await queryClient.invalidateQueries({
661
+ queryKey: ["collection", data.id]
662
+ });
663
+ if (data.id) {
664
+ queryClient.refetchQueries({
665
+ queryKey: ["collection", data.id]
666
+ }).catch(() => {
667
+ });
668
+ }
669
+ } catch (error) {
670
+ ui.toast.error(error instanceof Error ? error.message : "Save failed");
671
+ } finally {
672
+ setIsSaving(false);
673
+ }
674
+ };
290
675
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "flex flex-col gap-y-4", children: [
291
676
  /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-col gap-y-1", children: [
292
677
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-3", children: [
@@ -365,7 +750,7 @@ const CategoryMetadataTableWidget = ({ data }) => {
365
750
  }) })
366
751
  ] }) }),
367
752
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-subtle pt-3 md:flex-row md:items-center md:justify-between", children: [
368
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Changes are stored on the category metadata object. Clearing a field removes the corresponding key on save." }),
753
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Changes are stored on the collection metadata object. Clearing a field removes the corresponding key on save." }),
369
754
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
370
755
  /* @__PURE__ */ jsxRuntime.jsx(
371
756
  ui.Button,
@@ -531,7 +916,7 @@ const ValueField$2 = ({
531
916
  ] });
532
917
  };
533
918
  adminSdk.defineWidgetConfig({
534
- zone: "product_category.details.after"
919
+ zone: "product_collection.details.after"
535
920
  });
536
921
  const HideCategoryDefaultMetadataWidget = () => {
537
922
  react.useEffect(() => {
@@ -680,14 +1065,14 @@ const OrderMetadataTableWidget = ({ data }) => {
680
1065
  }, [orderId]);
681
1066
  const metadataStringRef = react.useRef("");
682
1067
  react.useEffect(() => {
683
- const hasMetadata = (data == null ? void 0 : data.metadata) && Object.keys(data.metadata).length > 0;
1068
+ const hasOrderData = !!data;
684
1069
  const descriptorsLoaded = descriptors.length > 0;
685
1070
  const sameOrder = previousOrderIdRef.current === orderId;
686
1071
  const notInitialized = !isInitializedRef.current;
687
- const currentMetadataString = hasMetadata ? JSON.stringify(data.metadata) : "";
1072
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
1073
+ const currentMetadataString = JSON.stringify(currentMetadata);
688
1074
  const metadataChanged = currentMetadataString !== metadataStringRef.current;
689
- if (hasMetadata && descriptorsLoaded && sameOrder && (notInitialized || metadataChanged)) {
690
- const currentMetadata = data.metadata ?? {};
1075
+ if (hasOrderData && descriptorsLoaded && sameOrder && (notInitialized || metadataChanged)) {
691
1076
  const newInitialState = buildInitialFormState(descriptors, currentMetadata);
692
1077
  setBaselineMetadata(currentMetadata);
693
1078
  setValues(newInitialState);
@@ -1540,6 +1925,10 @@ const widgetModule = { widgets: [
1540
1925
  Component: CategoryMetadataTableWidget,
1541
1926
  zone: ["product_category.details.after"]
1542
1927
  },
1928
+ {
1929
+ Component: CollectionMetadataTableWidget,
1930
+ zone: ["product_collection.details.after"]
1931
+ },
1543
1932
  {
1544
1933
  Component: HideCategoryDefaultMetadataWidget,
1545
1934
  zone: ["product_category.details.side.before"]
@@ -148,7 +148,8 @@ const useMetadataConfig = (entity) => {
148
148
  const useProductMetadataConfig = () => useMetadataConfig("product");
149
149
  const useCategoryMetadataConfig = () => useMetadataConfig("category");
150
150
  const useOrderMetadataConfig = () => useMetadataConfig("order");
151
- const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
151
+ const useCollectionMetadataConfig = () => useMetadataConfig("collection");
152
+ const CONFIG_DOCS_URL$3 = "https://docs.medusajs.com/admin/extension-points/widgets#product-category-details";
152
153
  const CategoryMetadataTableWidget = ({ data }) => {
153
154
  const { data: descriptors = [], isPending, isError } = useCategoryMetadataConfig();
154
155
  const categoryId = (data == null ? void 0 : data.id) ?? void 0;
@@ -286,6 +287,390 @@ const CategoryMetadataTableWidget = ({ data }) => {
286
287
  setIsSaving(false);
287
288
  }
288
289
  };
290
+ return /* @__PURE__ */ jsxs(Container, { className: "flex flex-col gap-y-4", children: [
291
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-y-1", children: [
292
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
293
+ /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Metadata" }),
294
+ /* @__PURE__ */ jsx(Badge, { size: "2xsmall", rounded: "full", children: descriptors.length })
295
+ ] }),
296
+ /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "Structured metadata mapped to the keys you configured in the plugin options." })
297
+ ] }),
298
+ isPending || !isInitializedRef.current || Object.keys(values).length === 0 ? /* @__PURE__ */ jsx(Skeleton, { className: "h-[160px] w-full" }) : isError ? /* @__PURE__ */ jsxs(InlineTip, { variant: "error", label: "Configuration unavailable", children: [
299
+ "Unable to load metadata configuration for this plugin. Confirm that the plugin is registered with options in ",
300
+ /* @__PURE__ */ jsx("code", { children: "medusa-config.ts" }),
301
+ "."
302
+ ] }) : !descriptors.length ? /* @__PURE__ */ jsxs(InlineTip, { variant: "info", label: "No configured metadata keys", children: [
303
+ "Provide a ",
304
+ /* @__PURE__ */ jsx("code", { children: "metadataDescriptors" }),
305
+ " array in the plugin options to control which keys show up here.",
306
+ " ",
307
+ /* @__PURE__ */ jsx(
308
+ "a",
309
+ {
310
+ className: "text-ui-fg-interactive underline",
311
+ href: CONFIG_DOCS_URL$3,
312
+ target: "_blank",
313
+ rel: "noreferrer",
314
+ children: "Learn how to configure it."
315
+ }
316
+ )
317
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
318
+ /* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-lg border border-ui-border-base", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-ui-border-base", children: [
319
+ /* @__PURE__ */ jsx("thead", { className: "bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("tr", { children: [
320
+ /* @__PURE__ */ jsx(
321
+ "th",
322
+ {
323
+ scope: "col",
324
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
325
+ children: "Label"
326
+ }
327
+ ),
328
+ /* @__PURE__ */ jsx(
329
+ "th",
330
+ {
331
+ scope: "col",
332
+ className: "txt-compact-xsmall-plus text-left uppercase tracking-wide text-ui-fg-muted px-4 py-3",
333
+ children: "Value"
334
+ }
335
+ )
336
+ ] }) }),
337
+ /* @__PURE__ */ jsx("tbody", { className: "divide-y divide-ui-border-subtle bg-ui-bg-base", children: descriptors.map((descriptor) => {
338
+ const value = values[descriptor.key];
339
+ const error = errors[descriptor.key];
340
+ return /* @__PURE__ */ jsxs("tr", { children: [
341
+ /* @__PURE__ */ jsx(
342
+ "th",
343
+ {
344
+ scope: "row",
345
+ className: "txt-compact-medium text-ui-fg-base align-top px-4 py-4",
346
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
347
+ /* @__PURE__ */ jsx("span", { children: descriptor.label ?? descriptor.key }),
348
+ /* @__PURE__ */ jsx("span", { className: "txt-compact-xsmall-plus text-ui-fg-muted uppercase tracking-wide", children: descriptor.type })
349
+ ] })
350
+ }
351
+ ),
352
+ /* @__PURE__ */ jsx("td", { className: "align-top px-4 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
353
+ /* @__PURE__ */ jsx(
354
+ ValueField$3,
355
+ {
356
+ descriptor,
357
+ value,
358
+ onStringChange: handleStringChange,
359
+ onBooleanChange: handleBooleanChange
360
+ }
361
+ ),
362
+ error && /* @__PURE__ */ jsx(Text, { className: "txt-compact-small text-ui-fg-error", children: error })
363
+ ] }) })
364
+ ] }, descriptor.key);
365
+ }) })
366
+ ] }) }),
367
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-subtle pt-3 md:flex-row md:items-center md:justify-between", children: [
368
+ /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-muted", children: "Changes are stored on the category metadata object. Clearing a field removes the corresponding key on save." }),
369
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
370
+ /* @__PURE__ */ jsx(
371
+ Button,
372
+ {
373
+ variant: "secondary",
374
+ size: "small",
375
+ disabled: !isDirty || isSaving,
376
+ onClick: handleReset,
377
+ children: "Reset"
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsx(
381
+ Button,
382
+ {
383
+ size: "small",
384
+ onClick: handleSubmit,
385
+ disabled: !isDirty || hasErrors || isSaving,
386
+ isLoading: isSaving,
387
+ children: "Save metadata"
388
+ }
389
+ )
390
+ ] })
391
+ ] })
392
+ ] })
393
+ ] });
394
+ };
395
+ const ValueField$3 = ({
396
+ descriptor,
397
+ value,
398
+ onStringChange,
399
+ onBooleanChange
400
+ }) => {
401
+ const fileInputRef = useRef(null);
402
+ const [isUploading, setIsUploading] = useState(false);
403
+ const handleFileUpload = async (event) => {
404
+ var _a;
405
+ const file = (_a = event.target.files) == null ? void 0 : _a[0];
406
+ if (!file) {
407
+ return;
408
+ }
409
+ setIsUploading(true);
410
+ try {
411
+ const formData = new FormData();
412
+ formData.append("files", file);
413
+ const response = await fetch("/admin/uploads", {
414
+ method: "POST",
415
+ credentials: "include",
416
+ body: formData
417
+ });
418
+ if (!response.ok) {
419
+ const payload = await response.json().catch(() => null);
420
+ throw new Error((payload == null ? void 0 : payload.message) ?? "File upload failed");
421
+ }
422
+ const result = await response.json();
423
+ if (result.files && result.files.length > 0) {
424
+ const uploadedFile = result.files[0];
425
+ const fileUrl = uploadedFile.url || uploadedFile.key;
426
+ if (fileUrl) {
427
+ onStringChange(descriptor.key, fileUrl);
428
+ toast.success("File uploaded successfully");
429
+ } else {
430
+ throw new Error("File upload succeeded but no URL returned");
431
+ }
432
+ } else {
433
+ throw new Error("File upload failed - no files returned");
434
+ }
435
+ } catch (error) {
436
+ toast.error(
437
+ error instanceof Error ? error.message : "Failed to upload file"
438
+ );
439
+ } finally {
440
+ setIsUploading(false);
441
+ if (fileInputRef.current) {
442
+ fileInputRef.current.value = "";
443
+ }
444
+ }
445
+ };
446
+ if (descriptor.type === "bool") {
447
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
448
+ /* @__PURE__ */ jsx(
449
+ Switch,
450
+ {
451
+ checked: Boolean(value),
452
+ onCheckedChange: (checked) => onBooleanChange(descriptor.key, Boolean(checked)),
453
+ "aria-label": `Toggle ${descriptor.label ?? descriptor.key}`
454
+ }
455
+ ),
456
+ /* @__PURE__ */ jsx(Text, { className: "txt-compact-small text-ui-fg-muted", children: Boolean(value) ? "True" : "False" })
457
+ ] });
458
+ }
459
+ if (descriptor.type === "text") {
460
+ return /* @__PURE__ */ jsx(
461
+ Textarea,
462
+ {
463
+ value: value ?? "",
464
+ placeholder: "Enter text",
465
+ rows: 3,
466
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
467
+ }
468
+ );
469
+ }
470
+ if (descriptor.type === "number") {
471
+ return /* @__PURE__ */ jsx(
472
+ Input,
473
+ {
474
+ type: "text",
475
+ inputMode: "decimal",
476
+ placeholder: "0.00",
477
+ value: value ?? "",
478
+ onChange: (event) => onStringChange(descriptor.key, event.target.value)
479
+ }
480
+ );
481
+ }
482
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-2", children: [
483
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
484
+ /* @__PURE__ */ jsx(
485
+ Input,
486
+ {
487
+ type: "url",
488
+ placeholder: "https://example.com/file",
489
+ value: value ?? "",
490
+ onChange: (event) => onStringChange(descriptor.key, event.target.value),
491
+ className: "flex-1"
492
+ }
493
+ ),
494
+ /* @__PURE__ */ jsx(
495
+ "input",
496
+ {
497
+ ref: fileInputRef,
498
+ type: "file",
499
+ className: "hidden",
500
+ onChange: handleFileUpload,
501
+ disabled: isUploading,
502
+ "aria-label": `Upload file for ${descriptor.label ?? descriptor.key}`
503
+ }
504
+ ),
505
+ /* @__PURE__ */ jsx(
506
+ Button,
507
+ {
508
+ type: "button",
509
+ variant: "secondary",
510
+ size: "small",
511
+ onClick: () => {
512
+ var _a;
513
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
514
+ },
515
+ disabled: isUploading,
516
+ isLoading: isUploading,
517
+ children: isUploading ? "Uploading..." : "Upload"
518
+ }
519
+ )
520
+ ] }),
521
+ typeof value === "string" && value && /* @__PURE__ */ jsx(
522
+ "a",
523
+ {
524
+ className: "txt-compact-small-plus text-ui-fg-interactive underline",
525
+ href: value,
526
+ target: "_blank",
527
+ rel: "noreferrer",
528
+ children: "View file"
529
+ }
530
+ )
531
+ ] });
532
+ };
533
+ defineWidgetConfig({
534
+ zone: "product_category.details.after"
535
+ });
536
+ const CONFIG_DOCS_URL$2 = "https://docs.medusajs.com/admin/extension-points/widgets#product-collection-details";
537
+ const CollectionMetadataTableWidget = ({ data }) => {
538
+ const { data: descriptors = [], isPending, isError } = useCollectionMetadataConfig();
539
+ const collectionId = (data == null ? void 0 : data.id) ?? void 0;
540
+ const [baselineMetadata, setBaselineMetadata] = useState(
541
+ (data == null ? void 0 : data.metadata) ?? {}
542
+ );
543
+ const queryClient = useQueryClient();
544
+ const previousCollectionIdRef = useRef(collectionId);
545
+ const isInitializedRef = useRef(false);
546
+ const dataRef = useRef(data);
547
+ const descriptorsRef = useRef(descriptors);
548
+ useEffect(() => {
549
+ dataRef.current = data;
550
+ descriptorsRef.current = descriptors;
551
+ }, [data, descriptors]);
552
+ useEffect(() => {
553
+ var _a;
554
+ if (previousCollectionIdRef.current === collectionId && isInitializedRef.current) {
555
+ return;
556
+ }
557
+ const collectionIdChanged = previousCollectionIdRef.current !== collectionId;
558
+ if (collectionIdChanged || !isInitializedRef.current) {
559
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? ((_a = dataRef.current) == null ? void 0 : _a.metadata) ?? {};
560
+ const currentDescriptors = descriptorsRef.current.length > 0 ? descriptorsRef.current : descriptors;
561
+ if (currentDescriptors.length === 0) {
562
+ return;
563
+ }
564
+ previousCollectionIdRef.current = collectionId;
565
+ setBaselineMetadata(currentMetadata);
566
+ const newInitialState = buildInitialFormState(currentDescriptors, currentMetadata);
567
+ setValues(newInitialState);
568
+ isInitializedRef.current = true;
569
+ }
570
+ }, [collectionId]);
571
+ const metadataStringRef = useRef("");
572
+ useEffect(() => {
573
+ const hasCollectionData = !!data;
574
+ const descriptorsLoaded = descriptors.length > 0;
575
+ const sameCollection = previousCollectionIdRef.current === collectionId;
576
+ const notInitialized = !isInitializedRef.current;
577
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
578
+ const currentMetadataString = JSON.stringify(currentMetadata);
579
+ const metadataChanged = currentMetadataString !== metadataStringRef.current;
580
+ if (hasCollectionData && descriptorsLoaded && sameCollection && (notInitialized || metadataChanged)) {
581
+ const newInitialState = buildInitialFormState(descriptors, currentMetadata);
582
+ setBaselineMetadata(currentMetadata);
583
+ setValues(newInitialState);
584
+ metadataStringRef.current = currentMetadataString;
585
+ isInitializedRef.current = true;
586
+ }
587
+ }, [data, descriptors.length, collectionId]);
588
+ const initialState = useMemo(
589
+ () => buildInitialFormState(descriptors, baselineMetadata),
590
+ [descriptors, baselineMetadata]
591
+ );
592
+ const [values, setValues] = useState({});
593
+ const [isSaving, setIsSaving] = useState(false);
594
+ const errors = useMemo(() => {
595
+ return descriptors.reduce((acc, descriptor) => {
596
+ const error = validateValueForDescriptor(descriptor, values[descriptor.key]);
597
+ if (error) {
598
+ acc[descriptor.key] = error;
599
+ }
600
+ return acc;
601
+ }, {});
602
+ }, [descriptors, values]);
603
+ const hasErrors = Object.keys(errors).length > 0;
604
+ const isDirty = useMemo(() => {
605
+ return hasMetadataChanges({
606
+ descriptors,
607
+ values,
608
+ originalMetadata: baselineMetadata
609
+ });
610
+ }, [descriptors, values, baselineMetadata]);
611
+ const handleStringChange = (key, nextValue) => {
612
+ setValues((prev) => ({
613
+ ...prev,
614
+ [key]: nextValue
615
+ }));
616
+ };
617
+ const handleBooleanChange = (key, nextValue) => {
618
+ setValues((prev) => ({
619
+ ...prev,
620
+ [key]: nextValue
621
+ }));
622
+ };
623
+ const handleReset = () => {
624
+ setValues(initialState);
625
+ };
626
+ const handleSubmit = async () => {
627
+ if (!(data == null ? void 0 : data.id) || !descriptors.length) {
628
+ return;
629
+ }
630
+ setIsSaving(true);
631
+ try {
632
+ const metadataPayload = buildMetadataPayload({
633
+ descriptors,
634
+ values,
635
+ originalMetadata: baselineMetadata
636
+ });
637
+ const response = await fetch(`/admin/collections/${data.id}`, {
638
+ method: "POST",
639
+ credentials: "include",
640
+ headers: {
641
+ "Content-Type": "application/json"
642
+ },
643
+ body: JSON.stringify({
644
+ metadata: metadataPayload
645
+ })
646
+ });
647
+ if (!response.ok) {
648
+ const payload = await response.json().catch(() => null);
649
+ throw new Error((payload == null ? void 0 : payload.message) ?? "Unable to save metadata");
650
+ }
651
+ const updated = await response.json();
652
+ const nextMetadata = updated.product_collection.metadata;
653
+ setBaselineMetadata(nextMetadata);
654
+ setValues(buildInitialFormState(descriptors, nextMetadata));
655
+ toast.success("Metadata saved");
656
+ await queryClient.invalidateQueries({
657
+ queryKey: ["collections"]
658
+ });
659
+ await queryClient.invalidateQueries({
660
+ queryKey: ["collection", data.id]
661
+ });
662
+ if (data.id) {
663
+ queryClient.refetchQueries({
664
+ queryKey: ["collection", data.id]
665
+ }).catch(() => {
666
+ });
667
+ }
668
+ } catch (error) {
669
+ toast.error(error instanceof Error ? error.message : "Save failed");
670
+ } finally {
671
+ setIsSaving(false);
672
+ }
673
+ };
289
674
  return /* @__PURE__ */ jsxs(Container, { className: "flex flex-col gap-y-4", children: [
290
675
  /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-y-1", children: [
291
676
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
@@ -364,7 +749,7 @@ const CategoryMetadataTableWidget = ({ data }) => {
364
749
  }) })
365
750
  ] }) }),
366
751
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3 border-t border-ui-border-subtle pt-3 md:flex-row md:items-center md:justify-between", children: [
367
- /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-muted", children: "Changes are stored on the category metadata object. Clearing a field removes the corresponding key on save." }),
752
+ /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-muted", children: "Changes are stored on the collection metadata object. Clearing a field removes the corresponding key on save." }),
368
753
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
369
754
  /* @__PURE__ */ jsx(
370
755
  Button,
@@ -530,7 +915,7 @@ const ValueField$2 = ({
530
915
  ] });
531
916
  };
532
917
  defineWidgetConfig({
533
- zone: "product_category.details.after"
918
+ zone: "product_collection.details.after"
534
919
  });
535
920
  const HideCategoryDefaultMetadataWidget = () => {
536
921
  useEffect(() => {
@@ -679,14 +1064,14 @@ const OrderMetadataTableWidget = ({ data }) => {
679
1064
  }, [orderId]);
680
1065
  const metadataStringRef = useRef("");
681
1066
  useEffect(() => {
682
- const hasMetadata = (data == null ? void 0 : data.metadata) && Object.keys(data.metadata).length > 0;
1067
+ const hasOrderData = !!data;
683
1068
  const descriptorsLoaded = descriptors.length > 0;
684
1069
  const sameOrder = previousOrderIdRef.current === orderId;
685
1070
  const notInitialized = !isInitializedRef.current;
686
- const currentMetadataString = hasMetadata ? JSON.stringify(data.metadata) : "";
1071
+ const currentMetadata = (data == null ? void 0 : data.metadata) ?? {};
1072
+ const currentMetadataString = JSON.stringify(currentMetadata);
687
1073
  const metadataChanged = currentMetadataString !== metadataStringRef.current;
688
- if (hasMetadata && descriptorsLoaded && sameOrder && (notInitialized || metadataChanged)) {
689
- const currentMetadata = data.metadata ?? {};
1074
+ if (hasOrderData && descriptorsLoaded && sameOrder && (notInitialized || metadataChanged)) {
690
1075
  const newInitialState = buildInitialFormState(descriptors, currentMetadata);
691
1076
  setBaselineMetadata(currentMetadata);
692
1077
  setValues(newInitialState);
@@ -1539,6 +1924,10 @@ const widgetModule = { widgets: [
1539
1924
  Component: CategoryMetadataTableWidget,
1540
1925
  zone: ["product_category.details.after"]
1541
1926
  },
1927
+ {
1928
+ Component: CollectionMetadataTableWidget,
1929
+ zone: ["product_collection.details.after"]
1930
+ },
1542
1931
  {
1543
1932
  Component: HideCategoryDefaultMetadataWidget,
1544
1933
  zone: ["product_category.details.side.before"]
@@ -7,6 +7,7 @@ const ENTITY_PARAM = {
7
7
  PRODUCT: "product",
8
8
  CATEGORY: "category",
9
9
  ORDER: "order",
10
+ COLLECTION: "collection",
10
11
  };
11
12
  async function GET(req, res) {
12
13
  const configModule = req.scope.resolve(utils_1.ContainerRegistrationKeys.CONFIG_MODULE);
@@ -16,9 +17,11 @@ async function GET(req, res) {
16
17
  ? options.metadata.categories.descriptors
17
18
  : entity === ENTITY_PARAM.ORDER
18
19
  ? options.metadata.orders.descriptors
19
- : options.metadata.products.descriptors;
20
+ : entity === ENTITY_PARAM.COLLECTION
21
+ ? options.metadata.collections.descriptors
22
+ : options.metadata.products.descriptors;
20
23
  res.json({
21
24
  metadataDescriptors,
22
25
  });
23
26
  }
24
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Byb2R1Y3QtbWV0YWRhdGEtY29uZmlnL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBYUEsa0JBa0JDO0FBOUJELHFEQUFxRTtBQUVyRSxtRkFBb0Y7QUFFcEYsTUFBTSxZQUFZLEdBQUc7SUFDbkIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsUUFBUSxFQUFFLFVBQVU7SUFDcEIsS0FBSyxFQUFFLE9BQU87Q0FDTixDQUFBO0FBSUgsS0FBSyxVQUFVLEdBQUcsQ0FBQyxHQUFrQixFQUFFLEdBQW1CO0lBQy9ELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUNwQyxpQ0FBeUIsQ0FBQyxhQUFhLENBQ3hDLENBQUE7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFBLG9EQUEyQixFQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ3pELE1BQU0sTUFBTSxHQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBeUIsSUFBSSxZQUFZLENBQUMsT0FBTyxDQUFBO0lBRTVFLE1BQU0sbUJBQW1CLEdBQ3ZCLE1BQU0sS0FBSyxZQUFZLENBQUMsUUFBUTtRQUM5QixDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsV0FBVztRQUN6QyxDQUFDLENBQUMsTUFBTSxLQUFLLFlBQVksQ0FBQyxLQUFLO1lBQy9CLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxXQUFXO1lBQ3JDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUE7SUFFM0MsR0FBRyxDQUFDLElBQUksQ0FBQztRQUNQLG1CQUFtQjtLQUNwQixDQUFDLENBQUE7QUFDSixDQUFDIn0=
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3Byb2R1Y3QtbWV0YWRhdGEtY29uZmlnL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBY0Esa0JBb0JDO0FBakNELHFEQUFxRTtBQUVyRSxtRkFBb0Y7QUFFcEYsTUFBTSxZQUFZLEdBQUc7SUFDbkIsT0FBTyxFQUFFLFNBQVM7SUFDbEIsUUFBUSxFQUFFLFVBQVU7SUFDcEIsS0FBSyxFQUFFLE9BQU87SUFDZCxVQUFVLEVBQUUsWUFBWTtDQUNoQixDQUFBO0FBSUgsS0FBSyxVQUFVLEdBQUcsQ0FBQyxHQUFrQixFQUFFLEdBQW1CO0lBQy9ELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUNwQyxpQ0FBeUIsQ0FBQyxhQUFhLENBQ3hDLENBQUE7SUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFBLG9EQUEyQixFQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ3pELE1BQU0sTUFBTSxHQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBeUIsSUFBSSxZQUFZLENBQUMsT0FBTyxDQUFBO0lBRTVFLE1BQU0sbUJBQW1CLEdBQ3ZCLE1BQU0sS0FBSyxZQUFZLENBQUMsUUFBUTtRQUM5QixDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsV0FBVztRQUN6QyxDQUFDLENBQUMsTUFBTSxLQUFLLFlBQVksQ0FBQyxLQUFLO1lBQy9CLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxXQUFXO1lBQ3JDLENBQUMsQ0FBQyxNQUFNLEtBQUssWUFBWSxDQUFDLFVBQVU7Z0JBQ3BDLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxXQUFXO2dCQUMxQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFBO0lBRTNDLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFDUCxtQkFBbUI7S0FDcEIsQ0FBQyxDQUFBO0FBQ0osQ0FBQyJ9
@@ -66,6 +66,9 @@ const MetadataSchema = zod_1.z.object({
66
66
  orders: MetadataCollectionSchema.default({
67
67
  descriptors: [],
68
68
  }),
69
+ collections: MetadataCollectionSchema.default({
70
+ descriptors: [],
71
+ }),
69
72
  });
70
73
  const PromotionWindowSchema = zod_1.z.object({
71
74
  start_metadata_key: zod_1.z.string().min(1).default("promotion_start"),
@@ -109,6 +112,9 @@ const ProductHelperOptionsSchema = zod_1.z.object({
109
112
  orders: {
110
113
  descriptors: [],
111
114
  },
115
+ collections: {
116
+ descriptors: [],
117
+ },
112
118
  }),
113
119
  default_price_range: PriceRangeSchema.default({
114
120
  label: "custom",
@@ -162,6 +168,10 @@ function normalizeProductHelperOptions(input) {
162
168
  ...parsed.metadata.orders,
163
169
  descriptors: (0, utils_2.normalizeMetadataDescriptors)(parsed.metadata.orders.descriptors),
164
170
  },
171
+ collections: {
172
+ ...parsed.metadata.collections,
173
+ descriptors: (0, utils_2.normalizeMetadataDescriptors)(parsed.metadata.collections.descriptors),
174
+ },
165
175
  },
166
176
  filterProviders: parsed.filterProviders ?? [],
167
177
  disableBuiltInProviders: parsed.disableBuiltInProviders ?? [],
@@ -182,4 +192,4 @@ function resolveProductHelperOptions(configModule) {
182
192
  }
183
193
  return exports.DEFAULT_PRODUCT_HELPER_OPTIONS;
184
194
  }
185
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1oZWxwZXItb3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb25maWcvcHJvZHVjdC1oZWxwZXItb3B0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUEwTUEsc0VBOEJDO0FBRUQsa0VBbUJDO0FBN1BELHFEQUFvRDtBQUNwRCw2QkFBdUI7QUFFdkIsNERBR3lDO0FBQ3pDLDREQUErRTtBQUUvRSxNQUFNLGdCQUFnQixHQUFHLE9BQUM7S0FDdkIsTUFBTSxDQUFDO0lBQ04sS0FBSyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFDbEQsYUFBYSxFQUFFLE9BQUM7U0FDYixNQUFNLEVBQUU7U0FDUixJQUFJLEVBQUU7U0FDTixNQUFNLENBQUMsQ0FBQyxFQUFFLG1DQUFtQyxDQUFDO1NBQzlDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3pDLFFBQVEsRUFBRTtJQUNiLEdBQUcsRUFBRSxPQUFDO1NBQ0gsTUFBTSxDQUFDO1FBQ04sTUFBTSxFQUFFLElBQUk7UUFDWixrQkFBa0IsRUFBRSw0QkFBNEI7S0FDakQsQ0FBQztTQUNELFdBQVcsRUFBRTtTQUNiLFFBQVEsRUFBRTtTQUNWLE9BQU8sQ0FBQyxJQUFJLENBQUM7SUFDaEIsR0FBRyxFQUFFLE9BQUM7U0FDSCxNQUFNLENBQUM7UUFDTixNQUFNLEVBQUUsSUFBSTtRQUNaLGtCQUFrQixFQUFFLDRCQUE0QjtLQUNqRCxDQUFDO1NBQ0QsV0FBVyxFQUFFO1NBQ2IsUUFBUSxFQUFFO1NBQ1YsT0FBTyxDQUFDLElBQUksQ0FBQztDQUNqQixDQUFDO0tBQ0QsTUFBTSxDQUNMLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDUixLQUFL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
195
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1oZWxwZXItb3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb25maWcvcHJvZHVjdC1oZWxwZXItb3B0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFtTkEsc0VBb0NDO0FBRUQsa0VBbUJDO0FBNVFELHFEQUFvRDtBQUNwRCw2QkFBdUI7QUFFdkIsNERBR3lDO0FBQ3pDLDREQUErRTtBQUUvRSxNQUFNLGdCQUFnQixHQUFHLE9BQUM7S0FDdkIsTUFBTSxDQUFDO0lBQ04sS0FBSyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFDbEQsYUFBYSxFQUFFLE9BQUM7U0FDYixNQUFNLEVBQUU7U0FDUixJQUFJLEVBQUU7U0FDTixNQUFNLENBQUMsQ0FBQyxFQUFFLG1DQUFtQyxDQUFDO1NBQzlDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3pDLFFBQVEsRUFBRTtJQUNiLEdBQUcsRUFBRSxPQUFDO1NBQ0gsTUFBTSxDQUFDO1FBQ04sTUFBTSxFQUFFLElBQUk7UUFDWixrQkFBa0IsRUFBRSw0QkFBNEI7S0FDakQsQ0FBQztTQUNELFdBQVcsRUFBRTtTQUNiLFFBQVEsRUFBRTtTQUNWLE9BQU8sQ0FBQyxJQUFJLENBQUM7SUFDaEIsR0FBRyxFQUFFLE9BQUM7U0FDSCxNQUFNLENBQUM7UUFDTixNQUFNLEVBQUUsSUFBSTtRQUNaLGtCQUFrQixFQUFFLDRCQUE0QjtLQUNqRCxDQUFDO1NBQ0QsV0FBVyxFQUFFO1NBQ2IsUUFBUSxFQUFFO1NBQ1YsT0FBTyxDQUFDLElBQUksQ0FBQztDQUNqQixDQUFDO0tBQ0QsTUFBTSxDQUNMLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDUixLQUFL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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusa-product-helper",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "description": "A starter for Medusa plugins.",
5
5
  "author": "Medusa (https://medusajs.com)",
6
6
  "license": "MIT",