@fluid-app/portal-sdk 0.1.298 → 0.1.300

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.
Files changed (87) hide show
  1. package/dist/{CalendarWidget-DW7jTZf3.mjs → CalendarWidget-BQP9CfCI.mjs} +2 -2
  2. package/dist/{CalendarWidget-DW7jTZf3.mjs.map → CalendarWidget-BQP9CfCI.mjs.map} +1 -1
  3. package/dist/{CalendarWidget-C0F4Tn6V.cjs → CalendarWidget-D-ccEA_l.cjs} +2 -2
  4. package/dist/{CalendarWidget-C0F4Tn6V.cjs.map → CalendarWidget-D-ccEA_l.cjs.map} +1 -1
  5. package/dist/{CardWidget-DHH4OIIs.cjs → CardWidget-CYhmSVgN.cjs} +3 -3
  6. package/dist/{CardWidget-D6CDrYMH.cjs → CardWidget-Ck84gmPU.cjs} +2 -2
  7. package/dist/{CardWidget-D6CDrYMH.cjs.map → CardWidget-Ck84gmPU.cjs.map} +1 -1
  8. package/dist/{CardWidget-B6W_LADC.mjs → CardWidget-DfY3Lrm_.mjs} +2 -2
  9. package/dist/{CardWidget-B6W_LADC.mjs.map → CardWidget-DfY3Lrm_.mjs.map} +1 -1
  10. package/dist/{CatchUpWidget-z6QHlvp8.mjs → CatchUpWidget-BtEH9EHQ.mjs} +2 -2
  11. package/dist/{CatchUpWidget-z6QHlvp8.mjs.map → CatchUpWidget-BtEH9EHQ.mjs.map} +1 -1
  12. package/dist/{CatchUpWidget-CjemRhbH.cjs → CatchUpWidget-DrYyYWHQ.cjs} +2 -2
  13. package/dist/{CatchUpWidget-CjemRhbH.cjs.map → CatchUpWidget-DrYyYWHQ.cjs.map} +1 -1
  14. package/dist/{ContainerWidget-CDwBQfHU.cjs → ContainerWidget-BEHhDggR.cjs} +2 -2
  15. package/dist/{ContainerWidget-CDwBQfHU.cjs.map → ContainerWidget-BEHhDggR.cjs.map} +1 -1
  16. package/dist/ContainerWidget-CPZH6TiA.cjs +8 -0
  17. package/dist/{ContainerWidget-DjhBudsq.mjs → ContainerWidget-DBRBSg15.mjs} +2 -2
  18. package/dist/{ContainerWidget-DjhBudsq.mjs.map → ContainerWidget-DBRBSg15.mjs.map} +1 -1
  19. package/dist/{FluidProvider-DTDhVSLQ.mjs → FluidProvider-BBxURUBq.mjs} +21 -21
  20. package/dist/{FluidProvider-DTDhVSLQ.mjs.map → FluidProvider-BBxURUBq.mjs.map} +1 -1
  21. package/dist/{FluidProvider-0sOzJmJn.cjs → FluidProvider-CBuTpv9I.cjs} +21 -21
  22. package/dist/{FluidProvider-0sOzJmJn.cjs.map → FluidProvider-CBuTpv9I.cjs.map} +1 -1
  23. package/dist/{LayoutWidget-DTgEFTTC.mjs → LayoutWidget-DYekGAi3.mjs} +2 -2
  24. package/dist/{LayoutWidget-DTgEFTTC.mjs.map → LayoutWidget-DYekGAi3.mjs.map} +1 -1
  25. package/dist/{LayoutWidget-CkBCBeVz.cjs → LayoutWidget-LfbpniWh.cjs} +3 -3
  26. package/dist/{LayoutWidget-DvhG2-qb.cjs → LayoutWidget-XlOfo8WQ.cjs} +2 -2
  27. package/dist/{LayoutWidget-DvhG2-qb.cjs.map → LayoutWidget-XlOfo8WQ.cjs.map} +1 -1
  28. package/dist/{MessagingScreen-HRUVbuPI.cjs → MessagingScreen-2M2ETWXp.cjs} +55 -49
  29. package/dist/{MessagingScreen-HRUVbuPI.cjs.map → MessagingScreen-2M2ETWXp.cjs.map} +1 -1
  30. package/dist/{MessagingScreen-aTcZSffe.mjs → MessagingScreen-B4vUvkRg.mjs} +13 -14
  31. package/dist/{MessagingScreen-D6kpqIC2.cjs → MessagingScreen-BI4AufwC.cjs} +13 -13
  32. package/dist/{MessagingScreen-Ja-iZNt3.mjs → MessagingScreen-CwzSY_G8.mjs} +55 -49
  33. package/dist/{MessagingScreen-Ja-iZNt3.mjs.map → MessagingScreen-CwzSY_G8.mjs.map} +1 -1
  34. package/dist/{MySiteWidget-B7sG9bQJ.mjs → MySiteWidget-D8UtttYC.mjs} +2 -2
  35. package/dist/{MySiteWidget-B7sG9bQJ.mjs.map → MySiteWidget-D8UtttYC.mjs.map} +1 -1
  36. package/dist/{MySiteWidget-DnHHWYX3.cjs → MySiteWidget-Pw7jVaF7.cjs} +2 -2
  37. package/dist/{MySiteWidget-DnHHWYX3.cjs.map → MySiteWidget-Pw7jVaF7.cjs.map} +1 -1
  38. package/dist/{OrdersScreen-B-xjxtr6.mjs → OrdersScreen-CFfrQG4i.mjs} +2 -2
  39. package/dist/{OrdersScreen-B-xjxtr6.mjs.map → OrdersScreen-CFfrQG4i.mjs.map} +1 -1
  40. package/dist/{OrdersScreen-ByLEuvca.cjs → OrdersScreen-CS1xA9q5.cjs} +2 -2
  41. package/dist/{OrdersScreen-ByLEuvca.cjs.map → OrdersScreen-CS1xA9q5.cjs.map} +1 -1
  42. package/dist/{OrdersScreen-De0aPrG9.mjs → OrdersScreen-DoopejMR.mjs} +13 -15
  43. package/dist/{OrdersScreen-tlHu0IR3.cjs → OrdersScreen-sLr0z213.cjs} +13 -13
  44. package/dist/{PointsWidget-DGLpUoZw.mjs → PointsWidget-4tTrD6UA.mjs} +2 -2
  45. package/dist/{PointsWidget-DGLpUoZw.mjs.map → PointsWidget-4tTrD6UA.mjs.map} +1 -1
  46. package/dist/{PointsWidget-COBlvYry.cjs → PointsWidget-BeiXr9cO.cjs} +2 -2
  47. package/dist/{PointsWidget-COBlvYry.cjs.map → PointsWidget-BeiXr9cO.cjs.map} +1 -1
  48. package/dist/{ProfileScreen-CHWtLOmi.cjs → ProfileScreen-BCR3FU5g.cjs} +2 -2
  49. package/dist/{ProfileScreen-CHWtLOmi.cjs.map → ProfileScreen-BCR3FU5g.cjs.map} +1 -1
  50. package/dist/{ProfileScreen-BEDzcVzD.mjs → ProfileScreen-CefqZr-Q.mjs} +2 -2
  51. package/dist/{ProfileScreen-BEDzcVzD.mjs.map → ProfileScreen-CefqZr-Q.mjs.map} +1 -1
  52. package/dist/{ProfileScreen-Dzgilark.cjs → ProfileScreen-CwP66ls2.cjs} +13 -13
  53. package/dist/{ProfileScreen-2ox06tSQ.mjs → ProfileScreen-wj0KTaQF.mjs} +13 -14
  54. package/dist/{RecentActivityWidget-C47O-9dM.mjs → RecentActivityWidget-C9fWPsVD.mjs} +2 -2
  55. package/dist/{RecentActivityWidget-C47O-9dM.mjs.map → RecentActivityWidget-C9fWPsVD.mjs.map} +1 -1
  56. package/dist/{RecentActivityWidget-BS9oXu_h.cjs → RecentActivityWidget-CsZPHcY4.cjs} +2 -2
  57. package/dist/{RecentActivityWidget-BS9oXu_h.cjs.map → RecentActivityWidget-CsZPHcY4.cjs.map} +1 -1
  58. package/dist/{ScreenRenderer-6qtnq9PQ.cjs → ScreenRenderer-BQZygrNq.cjs} +141 -33
  59. package/dist/ScreenRenderer-BQZygrNq.cjs.map +1 -0
  60. package/dist/{ScreenRenderer-CuaL4ulD.mjs → ScreenRenderer-wC15Ys7_.mjs} +141 -33
  61. package/dist/ScreenRenderer-wC15Ys7_.mjs.map +1 -0
  62. package/dist/{ShareablesScreen-IOujFj2X.mjs → ShareablesScreen-Cg10X417.mjs} +0 -2
  63. package/dist/{ShopScreen-Dd5EVGCt.mjs → ShopScreen-BKMR1rdM.mjs} +13 -15
  64. package/dist/{ShopScreen-FAgW632j.cjs → ShopScreen-CZdXE7dM.cjs} +2 -2
  65. package/dist/{ShopScreen-FAgW632j.cjs.map → ShopScreen-CZdXE7dM.cjs.map} +1 -1
  66. package/dist/{ShopScreen-BmP7vkuc.mjs → ShopScreen-DdAmK5yn.mjs} +2 -2
  67. package/dist/{ShopScreen-BmP7vkuc.mjs.map → ShopScreen-DdAmK5yn.mjs.map} +1 -1
  68. package/dist/{ShopScreen-DGMPFzcV.cjs → ShopScreen-xfPTLG5b.cjs} +13 -13
  69. package/dist/{ToDoWidget-DJiV9a3T.cjs → ToDoWidget-B_E2o_7m.cjs} +2 -2
  70. package/dist/{ToDoWidget-IKwBkpj3.mjs → ToDoWidget-CXhlO0BY.mjs} +2 -2
  71. package/dist/{ToDoWidget-IKwBkpj3.mjs.map → ToDoWidget-CXhlO0BY.mjs.map} +1 -1
  72. package/dist/{ToDoWidget-boT2GH5o.cjs → ToDoWidget-D6sXCE2R.cjs} +2 -2
  73. package/dist/{ToDoWidget-boT2GH5o.cjs.map → ToDoWidget-D6sXCE2R.cjs.map} +1 -1
  74. package/dist/index.cjs +24 -24
  75. package/dist/index.d.cts.map +1 -1
  76. package/dist/index.d.mts.map +1 -1
  77. package/dist/index.mjs +26 -26
  78. package/dist/{registry-context-DZOQLVi4.cjs → registry-context-D2pft0tu.cjs} +7 -1
  79. package/dist/registry-context-D2pft0tu.cjs.map +1 -0
  80. package/dist/{registry-context-DdfXs3K3.mjs → registry-context-gb8MAG9c.mjs} +2 -2
  81. package/dist/registry-context-gb8MAG9c.mjs.map +1 -0
  82. package/package.json +22 -22
  83. package/dist/ContainerWidget-CBksBaz3.cjs +0 -8
  84. package/dist/ScreenRenderer-6qtnq9PQ.cjs.map +0 -1
  85. package/dist/ScreenRenderer-CuaL4ulD.mjs.map +0 -1
  86. package/dist/registry-context-DZOQLVi4.cjs.map +0 -1
  87. package/dist/registry-context-DdfXs3K3.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScreenRenderer-CuaL4ulD.mjs","names":[],"sources":["../../core/src/data-source-api-context.ts","../../widgets/src/contexts/RegistryContext.tsx","../../widgets/src/contexts/ScreenRendererContext.tsx","../../core/src/types/widget-schema.ts","../../core/src/data-sources/presets.ts","../../react/src/data-sources/use-widget-data.ts","../../react/src/data-sources/ErrorState.tsx","../../react/src/data-sources/DataAwareWidget.tsx","../../widgets/src/core/ScreenRenderer.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { DataSourceApi } from \"./data-source-api\";\n\nconst DataSourceApiContext = createContext<DataSourceApi | null>(null);\n\nexport const DataSourceApiProvider = DataSourceApiContext.Provider;\n\n/**\n * Access the DataSourceApi adapter.\n * Throws if no DataSourceApiProvider ancestor exists.\n */\nexport function useDataSourceApi(): DataSourceApi {\n const api = useContext(DataSourceApiContext);\n if (!api) {\n throw new Error(\n \"useDataSourceApi must be used within a DataSourceApiProvider\",\n );\n }\n return api;\n}\n\n/**\n * Access the DataSourceApi adapter without throwing.\n * Returns null when no DataSourceApiProvider ancestor exists.\n * Use in isolated rendering contexts (Storybook, unit tests) where the\n * full provider stack may not be wired.\n */\nexport function useDataSourceApiOptional(): DataSourceApi | null {\n return useContext(DataSourceApiContext);\n}\n","import React, {\n createContext,\n useContext,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport type { WidgetSchema } from \"@fluid-app/portal-core/types\";\n\n/**\n * Base props interface for widget components.\n * All widgets receive at least these props from the ScreenRenderer.\n */\nexport interface WidgetBaseProps {\n readonly widget: WidgetSchema;\n readonly path?: readonly number[];\n}\n\n/**\n * Generic widget component type.\n * Widgets receive WidgetBaseProps and may have additional props.\n */\nexport type WidgetComponent<P extends WidgetBaseProps = WidgetBaseProps> =\n ComponentType<P>;\n\n/**\n * Registry mapping widget type names to their components.\n * The keys are widget type strings (e.g., \"TextWidget\", \"ButtonWidget\").\n * Using WidgetComponent for the value type provides better type safety than `any`.\n */\nexport type WidgetRegistry = Readonly<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Widget props vary by type\n Record<string, WidgetComponent<any>>\n>;\n\n/**\n * Context for providing the widget registry to all components in the tree.\n * This eliminates prop drilling and makes the registry accessible anywhere.\n *\n * Default to undefined - registry must be provided by a RegistryProvider.\n */\nexport const RegistryContext: React.Context<WidgetRegistry | undefined> =\n createContext<WidgetRegistry | undefined>(undefined);\n\nexport interface RegistryProviderProps {\n registry?: WidgetRegistry;\n children: ReactNode;\n}\n\n/**\n * Provider component that makes the widget registry available to all descendants.\n * A registry must be provided either via props or by nesting within another RegistryProvider.\n */\nexport function RegistryProvider({\n registry,\n children,\n}: RegistryProviderProps): React.JSX.Element {\n // If no registry provided, inherit from parent provider\n const parentRegistry = useContext(RegistryContext);\n const contextValue = registry ?? parentRegistry;\n\n if (!contextValue) {\n throw new Error(\n \"RegistryProvider requires a registry prop or must be nested within another RegistryProvider.\",\n );\n }\n\n return (\n <RegistryContext.Provider value={contextValue}>\n {children}\n </RegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the widget registry from anywhere in the component tree.\n * Must be used within a RegistryProvider that has a registry prop.\n */\nexport function useRegistry(): WidgetRegistry {\n const registry = useContext(RegistryContext);\n\n if (!registry) {\n throw new Error(\n \"useRegistry must be used within a RegistryProvider with a registry prop.\",\n );\n }\n\n return registry;\n}\n","import React, { createContext, useContext, type ComponentType } from \"react\";\nimport type { WidgetSchema } from \"@fluid-app/portal-core/types\";\nimport type { WidgetRegistry } from \"./RegistryContext\";\n\n/**\n * Props that any ScreenRenderer must accept.\n * This is the minimal interface used by container widgets (e.g. LayoutWidget)\n * to render their children.\n */\nexport interface ScreenRendererComponentProps {\n screen: WidgetSchema[];\n registry?: WidgetRegistry;\n className?: string;\n}\n\n/**\n * Context for providing an alternative ScreenRenderer component.\n *\n * This allows packages like portal-builder to inject their own ScreenRenderer\n * (with edit mode, drag-and-drop, etc.) so that container widgets in portal-widgets\n * use the richer renderer instead of the basic view-only one.\n *\n * Default is undefined — container widgets fall back to the local ScreenRenderer import.\n */\nexport const ScreenRendererContext: React.Context<\n ComponentType<ScreenRendererComponentProps> | undefined\n> = createContext<ComponentType<ScreenRendererComponentProps> | undefined>(\n undefined,\n);\n\n/**\n * Hook to get the ScreenRenderer component from context.\n * Returns undefined if no override has been provided.\n */\nexport function useScreenRenderer():\n | ComponentType<ScreenRendererComponentProps>\n | undefined {\n return useContext(ScreenRendererContext);\n}\n","import type { DataSourceConfig } from \"../data-sources/types\";\n\n/**\n * Generic component type — avoids React dependency in core.\n * Accepts both function components and class component constructors.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type AnyComponent = ((props: any) => any) | (new (props: any) => any);\n\n/**\n * Widget type names as a const object.\n * This serves as the single source of truth for widget discriminants.\n * Use `as const` for literal type inference (safety-as-const-deep-readonly rule).\n */\nexport const WIDGET_TYPE_NAMES = {\n Alert: \"AlertWidget\",\n BulletList: \"BulletListWidget\",\n Calendar: \"CalendarWidget\",\n Card: \"CardWidget\",\n Carousel: \"CarouselWidget\",\n CatchUp: \"CatchUpWidget\",\n Chart: \"ChartWidget\",\n Container: \"ContainerWidget\",\n Embed: \"EmbedWidget\",\n Image: \"ImageWidget\",\n Layout: \"LayoutWidget\",\n Link: \"LinkWidget\",\n List: \"ListWidget\",\n MySite: \"MySiteWidget\",\n Nested: \"NestedWidget\",\n Points: \"PointsWidget\",\n QuickLinks: \"QuickLinksWidget\",\n QuickShare: \"QuickShareWidget\",\n RecentActivity: \"RecentActivityWidget\",\n Separator: \"SeparatorWidget\",\n Spacer: \"SpacerWidget\",\n Table: \"TableWidget\",\n Text: \"TextWidget\",\n ToDo: \"ToDoWidget\",\n Video: \"VideoWidget\",\n} as const;\n\n/**\n * Union of all known widget type names.\n * Derived from WIDGET_TYPE_NAMES to avoid duplication (deriving-typeof-for-object-keys rule).\n */\nexport type WidgetTypeName =\n (typeof WIDGET_TYPE_NAMES)[keyof typeof WIDGET_TYPE_NAMES];\n\n/**\n * Legacy alias for backwards compatibility.\n * Prefer using WidgetTypeName for new code when you need the union type.\n */\nexport type WidgetType = string;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type WidgetRegistry = Record<WidgetType, AnyComponent>;\n\n/**\n * Base widget schema with loose typing for runtime data.\n * Use TypedWidgetSchema<T> when you have a known registry for better type safety.\n */\nexport type WidgetSchema = {\n readonly type: WidgetType;\n readonly props: Readonly<Record<string, unknown>>;\n readonly id?: string; // Optional unique identifier for drag-and-drop\n /** Optional data source configuration for data-bound widgets */\n readonly dataSource?: DataSourceConfig | undefined;\n /** Column index for masonry layouts (0-indexed) */\n readonly columnIndex?: number;\n};\n\n/**\n * Type-safe widget schema based on registry.\n * Uses discriminated unions - the `type` field serves as discriminant.\n * When narrowed (e.g., `if (widget.type === \"AlertWidget\")`),\n * TypeScript automatically knows the correct props type.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type TypedWidgetSchema<T extends Record<string, AnyComponent>> = {\n [K in keyof T]: {\n readonly type: K;\n readonly props: Readonly<\n T[K] extends (props: infer P) => any\n ? P\n : T[K] extends new (props: infer P) => any\n ? P\n : never\n >;\n readonly id?: string;\n readonly dataSource?: DataSourceConfig | undefined;\n /** Column index for masonry layouts (0-indexed) */\n readonly columnIndex?: number;\n };\n}[keyof T];\n\n/**\n * Widget path in the tree - array of indices.\n * Readonly tuple to prevent accidental mutation.\n */\nexport type WidgetPath = readonly number[];\n\n// ============================================================================\n// Type Guards and Assertion Functions\n// ============================================================================\n\n/**\n * Type predicate to check if a string is a known widget type name.\n * Use for runtime validation of widget types.\n *\n * @example\n * if (isWidgetTypeName(widget.type)) {\n * // TypeScript knows widget.type is WidgetTypeName\n * }\n */\nexport function isWidgetTypeName(type: string): type is WidgetTypeName {\n // Type assertion required in type guard: Object.values() returns string[], but we\n // need to check against WidgetTypeName values. The assertion is safe because we're\n // checking membership, and the return type predicate ensures correct narrowing.\n return Object.values(WIDGET_TYPE_NAMES).includes(type as WidgetTypeName);\n}\n\n/**\n * Type predicate to check if a widget has a specific type.\n * Enables type-safe widget narrowing without `as` assertions.\n *\n * @example\n * if (isWidgetType(widget, \"LayoutWidget\")) {\n * // TypeScript knows widget.type === \"LayoutWidget\"\n * // and widget.props is LayoutWidget props\n * }\n */\nexport function isWidgetType<T extends WidgetTypeName>(\n widget: WidgetSchema | null | undefined,\n typeName: T,\n): widget is WidgetSchema & { readonly type: T } {\n return widget != null && widget.type === typeName;\n}\n\n/**\n * Helper for exhaustive switch statements on widget types.\n * Use in the default case to ensure all widget types are handled.\n *\n * @example\n * switch (widget.type) {\n * case \"AlertWidget\": return handleAlert();\n * case \"TextWidget\": return handleText();\n * // ... all other widget types\n * default: return assertNever(widget.type, \"widget type\");\n * }\n */\nexport function assertNever(value: never, context?: string): never {\n const message = context\n ? `Unexpected ${context}: ${String(value)}`\n : `Unexpected value: ${String(value)}`;\n throw new Error(message);\n}\n\n/**\n * Assertion function that throws if value is undefined.\n * Narrows the type to exclude undefined.\n *\n * @example\n * const widget = screen[0];\n * assertDefined(widget, \"widget at index 0\");\n * // TypeScript knows widget is defined here\n */\nexport function assertDefined<T>(\n value: T | undefined | null,\n name?: string,\n): asserts value is T {\n if (value == null) {\n throw new Error(name ? `${name} is required` : \"Value is required\");\n }\n}\n","/**\n * Data Source Presets Registry\n *\n * Configurable presets that allow users to select options via sub-menus\n * and fine-tune parameters in a detail panel.\n */\n\nimport type {\n SelectFieldSchema,\n NumberFieldSchema,\n} from \"../registries/property-schema-types\";\nimport type { DataSource } from \"./types\";\n\n/** Widget types that can use data sources */\nexport type DataSourceCompatibleWidget =\n | \"CarouselWidget\"\n | \"ChartWidget\"\n | \"EmbedWidget\"\n | \"ImageWidget\"\n | \"ListWidget\"\n | \"NestedWidget\"\n | \"TableWidget\"\n | \"VideoWidget\";\n\n/** Field types supported in preset config panels */\nexport type PresetConfigField = SelectFieldSchema<string> | NumberFieldSchema;\n\n/** A preset data source configuration */\nexport interface DataSourcePreset {\n /** Unique identifier for the preset */\n id: string;\n /** Human-readable name for display */\n name: string;\n /** Description of what data this endpoint provides */\n description: string;\n /** The API endpoint path (can include {variable} placeholders) */\n endpoint: string;\n /** Transformer name to apply to the data */\n transform?: string;\n /** Optional path to extract data from response (e.g., \"data.items\") */\n resultPath?: string;\n /** Which widgets this preset is compatible with */\n compatibleWidgets: DataSourceCompatibleWidget[];\n /** Optional select field shown as a sub-menu. The field's key becomes a variable in the endpoint URL. */\n menuField?: SelectFieldSchema<string>;\n /** Optional config fields rendered in the detail panel below the popover. Each field's key becomes a variable. */\n configFields?: PresetConfigField[];\n}\n\n/**\n * Pre-configured data source presets\n */\nexport const DATA_SOURCE_PRESETS: DataSourcePreset[] = [\n {\n id: \"rep-most-shared\",\n name: \"Most Shared Visits\",\n description: \"Content with the most share-link click-throughs\",\n endpoint:\n \"/v2025-06/reps/{rep_id}/most_shared?shareable_type={shareable_type}&limit={limit}&period={period}&language_iso={language_iso}\",\n resultPath: \"resources\",\n compatibleWidgets: [\n \"CarouselWidget\",\n \"ListWidget\",\n \"NestedWidget\",\n \"TableWidget\",\n ],\n menuField: {\n key: \"shareable_type\",\n label: \"Content Type\",\n type: \"select\",\n options: [\n { label: \"Products\", value: \"products\" },\n { label: \"Media\", value: \"media\" },\n { label: \"Pages\", value: \"pages\" },\n { label: \"Libraries\", value: \"libraries\" },\n { label: \"Enrollment Packs\", value: \"enrollment_packs\" },\n ],\n defaultValue: \"products\",\n },\n configFields: [\n {\n key: \"limit\",\n label: \"Limit\",\n type: \"number\",\n defaultValue: 10,\n min: 1,\n max: 20,\n description: \"Maximum number of items to show\",\n },\n {\n key: \"period\",\n label: \"Time Range\",\n type: \"select\",\n options: [\n { label: \"7 days\", value: \"7d\" },\n { label: \"30 days\", value: \"30d\" },\n { label: \"90 days\", value: \"90d\" },\n { label: \"1 year\", value: \"1y\" },\n { label: \"All time\", value: \"all\" },\n ],\n defaultValue: \"all\",\n },\n ],\n },\n {\n id: \"rep-most-viewed\",\n name: \"Most Viewed\",\n description: \"Most viewed content\",\n endpoint:\n \"/v2025-06/reps/{rep_id}/most_viewed?shareable_type={shareable_type}&limit={limit}&period={period}&language_iso={language_iso}\",\n resultPath: \"resources\",\n compatibleWidgets: [\n \"CarouselWidget\",\n \"ListWidget\",\n \"NestedWidget\",\n \"TableWidget\",\n ],\n menuField: {\n key: \"shareable_type\",\n label: \"Content Type\",\n type: \"select\",\n options: [\n { label: \"Products\", value: \"products\" },\n { label: \"Media\", value: \"media\" },\n { label: \"Pages\", value: \"pages\" },\n { label: \"Libraries\", value: \"libraries\" },\n { label: \"Enrollment Packs\", value: \"enrollment_packs\" },\n ],\n defaultValue: \"products\",\n },\n configFields: [\n {\n key: \"limit\",\n label: \"Limit\",\n type: \"number\",\n defaultValue: 10,\n min: 1,\n max: 20,\n description: \"Maximum number of items to show\",\n },\n {\n key: \"period\",\n label: \"Time Range\",\n type: \"select\",\n options: [\n { label: \"7 days\", value: \"7d\" },\n { label: \"30 days\", value: \"30d\" },\n { label: \"90 days\", value: \"90d\" },\n { label: \"1 year\", value: \"1y\" },\n { label: \"All time\", value: \"all\" },\n ],\n defaultValue: \"all\",\n },\n ],\n },\n {\n id: \"customer-orders\",\n name: \"Orders\",\n description: \"Customer order history\",\n endpoint:\n \"/v202506/orders?customer_id={customer_id}&page[limit]={limit}&status={status}\",\n resultPath: \"orders\",\n transform: \"toOrderTableProps\",\n compatibleWidgets: [\"TableWidget\"],\n configFields: [\n {\n key: \"limit\",\n label: \"Limit\",\n type: \"number\",\n defaultValue: 10,\n min: 1,\n max: 50,\n description: \"Maximum number of orders to show\",\n },\n {\n key: \"status\",\n label: \"Status\",\n type: \"select\",\n options: [\n { label: \"All\", value: \"all\" },\n { label: \"Paid\", value: \"paid\" },\n { label: \"Unpaid\", value: \"unpaid\" },\n { label: \"Refunded\", value: \"refunded\" },\n ],\n defaultValue: \"all\",\n },\n ],\n },\n {\n id: \"customer-subscriptions\",\n name: \"Subscriptions\",\n description: \"Customer subscriptions\",\n // Subscriptions endpoint is unversioned (legacy API), orders uses v202506\n endpoint:\n \"/subscriptions?customer_id={customer_id}&per_page={limit}&status={status}\",\n resultPath: \"subscriptions\",\n transform: \"toSubscriptionTableProps\",\n compatibleWidgets: [\"TableWidget\"],\n configFields: [\n {\n key: \"limit\",\n label: \"Limit\",\n type: \"number\",\n defaultValue: 10,\n min: 1,\n max: 50,\n description: \"Maximum number of subscriptions to show\",\n },\n {\n key: \"status\",\n label: \"Status\",\n type: \"select\",\n options: [\n { label: \"All\", value: \"all\" },\n { label: \"Active\", value: \"active\" },\n { label: \"Paused\", value: \"paused\" },\n { label: \"Cancelled\", value: \"cancelled\" },\n ],\n defaultValue: \"all\",\n },\n ],\n },\n];\n\n/** Lookup map for O(1) preset resolution */\nconst PRESET_MAP = new Map<string, DataSourcePreset>(\n DATA_SOURCE_PRESETS.map((p) => [p.id, p]),\n);\n\n/**\n * Resolves a preset by ID, returning the current preset definition.\n * Returns undefined if the preset ID is not recognized.\n */\nexport function resolvePreset(presetId: string): DataSourcePreset | undefined {\n return PRESET_MAP.get(presetId);\n}\n\n/**\n * If the source is an API source with a presetId, returns a copy with\n * endpoint, resultPath, and transform resolved from the current preset.\n * Falls back to stored values if the preset is unknown.\n * Non-API sources are returned as-is.\n */\nexport function resolveSource<T extends DataSource>(source: T): T {\n if (source.type !== \"api\" || !source.presetId) return source;\n\n const preset = resolvePreset(source.presetId);\n if (!preset) {\n console.warn(\n `[DataSource] Unknown preset \"${source.presetId}\", falling back to stored values`,\n );\n return source;\n }\n\n return {\n ...source,\n endpoint: preset.endpoint,\n resultPath: preset.resultPath,\n transform: preset.transform ?? source.transform,\n } as T;\n}\n","import { useQueries } from \"@tanstack/react-query\";\nimport { useCallback, useMemo, useRef } from \"react\";\nimport type { WidgetSchema } from \"@fluid-app/portal-core/types\";\nimport type {\n DataSourceRegistry,\n WidgetDataResult,\n DataSourceContext,\n DataSource,\n} from \"@fluid-app/portal-core/data-sources/types\";\nimport { resolveSource } from \"@fluid-app/portal-core/data-sources/presets\";\nimport { useDataSourceApiOptional } from \"@fluid-app/portal-core/data-source-api-context\";\nimport { useDataSourceRegistryConfig } from \"./registry-context\";\n\ninterface UseWidgetDataOptions {\n /** Override the default registry from context */\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n}\n\n/**\n * Generates a cache key for the raw data fetch (endpoint/items identity only).\n * Transforms and targetProps are NOT included — they are applied per-widget\n * after reading from the shared cache.\n */\nfunction getSourceKey(source: DataSource): string {\n if (source.type === \"api\") {\n const varsKey = source.variables\n ? `:${JSON.stringify(source.variables)}`\n : \"\";\n // Use presetId as identity when available — keeps cache key stable across preset endpoint changes\n const identity = source.presetId ?? source.endpoint;\n return `${identity}${varsKey}`;\n }\n if (source.type === \"custom\") {\n const itemKeys =\n source.selectedItems?.map((item) => {\n return `${item.shareableType}:${item.id}`;\n }) ?? [];\n return `custom:${itemKeys.join(\",\")}`;\n }\n if (source.type === \"static\") {\n return `static:${source.staticType}:${source.selectedId}`;\n }\n return \"unknown\";\n}\n\n/**\n * Resolves cached raw data into widget props by applying each widget's own\n * transforms and targetProps mapping.\n */\nfunction resolvePropsFromQueries<T>(\n queryResults: ReadonlyArray<{\n data?: unknown;\n isLoading: boolean;\n error: Error | null;\n }>,\n sources: DataSource[],\n registry: DataSourceRegistry,\n errorConfig?: { fallback?: unknown },\n): T | undefined {\n if (sources.length === 0) return undefined;\n if (queryResults.some((q) => q.isLoading && !q.data)) return undefined;\n\n const failedQuery = queryResults.find((q) => q.error);\n const hasError = !!failedQuery?.error;\n\n if (hasError && errorConfig?.fallback) {\n return errorConfig.fallback as T;\n }\n\n if (hasError) {\n return undefined;\n }\n\n const resolvedProps: Record<string, unknown> = {};\n\n for (let i = 0; i < queryResults.length; i++) {\n const query = queryResults[i];\n const source = sources[i];\n if (!query?.data || !source) continue;\n\n // Sentry fix: FLUID-ADMIN-1DH — source or targetProps can be undefined from malformed widget config\n if (!source.targetProps) continue;\n\n // Apply this widget's transform to the cached raw data\n let result: unknown = query.data;\n if (source.transform) {\n const transformer = registry.transformers[source.transform];\n if (transformer) {\n result = transformer(result, source);\n } else {\n console.warn(`Transform \"${source.transform}\" not found in registry`);\n }\n }\n\n // Map to this widget's targetProps\n if (\n result !== null &&\n typeof result === \"object\" &&\n !Array.isArray(result) &&\n source.targetProps.length > 1\n ) {\n const resultObj = result as Record<string, unknown>;\n for (const prop of source.targetProps) {\n if (prop in resultObj) {\n resolvedProps[prop] = resultObj[prop];\n }\n }\n } else {\n for (const prop of source.targetProps) {\n resolvedProps[prop] = result;\n }\n }\n }\n\n return resolvedProps as T;\n}\n\n/**\n * Hook that fetches and resolves data sources for a widget using React Query.\n *\n * Raw API data is cached and shared across widgets with the same data source.\n * Transforms and targetProps mapping are applied per-widget after cache reads,\n * so multiple widgets can share one fetch but resolve data independently.\n */\nexport function useWidgetData<T = Record<string, unknown>>(\n widget: WidgetSchema,\n options?: UseWidgetDataOptions,\n): WidgetDataResult<T> {\n const config = useDataSourceRegistryConfig();\n const registry = options?.registry ?? config.registry;\n const baseUrl = options?.baseUrl ?? config.baseUrl;\n const getApiHeaders = config.getApiHeaders;\n const variables = config.variables;\n // useDataSourceApiOptional returns null outside a DataSourceApiProvider.\n // This allows widgets with zero data sources to render in isolation\n // (Storybook, unit tests). Fetchers that require api will throw at call\n // time if it's missing — not at render time for every widget.\n const api = useDataSourceApiOptional() ?? undefined;\n\n // Resolve preset-backed sources to their current endpoint/resultPath/transform\n const sources = useMemo(\n () => (widget.dataSource?.sources ?? []).map(resolveSource),\n [widget.dataSource?.sources],\n );\n const errorConfig = widget.dataSource?.error;\n const widgetId = widget.id ?? \"unknown\";\n const widgetType = widget.type;\n\n const queryResultsRef = useRef<Array<{ refetch: () => void }>>([]);\n\n // Cache only raw fetched data — no transforms or source objects stored\n const results = useQueries({\n queries: sources.map((source: DataSource) => ({\n queryKey: [\n \"portal-widget-data\",\n getSourceKey(source),\n baseUrl,\n variables,\n ] as const,\n queryFn: async ({\n signal,\n }: {\n signal: AbortSignal;\n }): Promise<unknown> => {\n const context: DataSourceContext = {\n widgetId,\n widgetType,\n signal,\n baseUrl,\n getApiHeaders,\n variables,\n api,\n };\n\n const fetcher = registry.fetchers[source.type];\n if (!fetcher) {\n throw new Error(\n `No fetcher registered for source type: ${source.type}`,\n );\n }\n\n return fetcher(source, context);\n },\n enabled: sources.length > 0,\n retry: errorConfig?.retryCount ?? 0,\n retryDelay: errorConfig?.retryDelay ?? 1000,\n refetchInterval: source.refreshInterval || false,\n })),\n });\n\n // Update ref for refetch callback\n queryResultsRef.current = results;\n\n // Aggregate loading state\n const isLoading = results.some((q) => q.isLoading);\n\n // Get first error from any failed query\n const failedQuery = results.find((q) => q.error);\n const error =\n failedQuery?.error instanceof Error\n ? failedQuery.error\n : failedQuery?.error\n ? new Error(String(failedQuery.error))\n : null;\n\n // Stable fingerprint that changes only when query data or loading states change\n const queryFingerprint = results\n .map((r) => `${r.dataUpdatedAt}:${r.isLoading}`)\n .join(\",\");\n\n // Resolve data: apply per-widget transforms and map to targetProps\n const resultsRef = useRef(results);\n resultsRef.current = results;\n\n const data = useMemo(() => {\n const querySnapshots = resultsRef.current.map((q) => ({\n data: q.data,\n isLoading: q.isLoading,\n error: q.error instanceof Error ? q.error : null,\n }));\n return resolvePropsFromQueries<T>(\n querySnapshots,\n sources,\n registry,\n errorConfig,\n );\n }, [queryFingerprint, sources, registry, errorConfig]);\n\n // Stable refetch callback using ref\n const refetch = useCallback(() => {\n queryResultsRef.current.forEach((q) => q.refetch());\n }, []);\n\n return {\n data,\n isLoading,\n error,\n refetch,\n };\n}\n","import type React from \"react\";\n\nexport function ErrorState(): React.JSX.Element {\n return (\n <div className=\"flex min-h-[120px] flex-col items-center justify-center p-6 text-center\">\n <p className=\"text-lg font-semibold\">Something Went Wrong</p>\n <p className=\"text-muted-foreground text-sm\">\n Please contact a company admin for help\n </p>\n </div>\n );\n}\n","import type React from \"react\";\nimport { memo, useMemo, type ComponentType, type ReactNode } from \"react\";\nimport type { WidgetSchema } from \"@fluid-app/portal-core/types\";\nimport { useWidgetData } from \"./use-widget-data\";\nimport { ErrorState } from \"./ErrorState\";\n\nexport interface DataAwareWidgetProps {\n widget: WidgetSchema;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Component: ComponentType<any>;\n /** Additional props to pass through (e.g., edit mode callbacks) */\n additionalProps?: Record<string, unknown>;\n /** Custom loading component */\n loadingComponent?: ReactNode;\n /** Custom error component */\n errorComponent?: (error: Error) => ReactNode;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n}\n\n// Empty object constant to avoid creating new references\nconst EMPTY_OBJECT: Record<string, unknown> = {};\n\n/**\n * Wrapper component that resolves data sources before rendering the widget.\n * Merges resolved data with static props.\n */\nfunction DataAwareWidgetImpl({\n widget,\n Component,\n additionalProps,\n loadingComponent,\n errorComponent,\n baseUrl,\n}: DataAwareWidgetProps): React.JSX.Element | null {\n // Use stable empty object if no additionalProps provided\n const stableAdditionalProps = additionalProps ?? EMPTY_OBJECT;\n const { data, isLoading, error } = useWidgetData(widget, { baseUrl });\n\n // Merge static props with resolved data\n // Data takes precedence (allows overriding defaults)\n // Memoized to prevent unnecessary child re-renders\n // Note: Must be called before any early returns to satisfy Rules of Hooks\n const mergedProps = useMemo(\n () => ({\n ...widget.props,\n ...data,\n ...stableAdditionalProps,\n }),\n [widget.props, data, stableAdditionalProps],\n );\n\n // Show loading state\n if (isLoading && widget.dataSource?.loading?.showSkeleton !== false) {\n if (loadingComponent) {\n return <>{loadingComponent}</>;\n }\n // Default skeleton - can be customized\n return (\n <div\n className=\"bg-muted animate-pulse rounded-md\"\n style={{ minHeight: 100 }}\n >\n <span className=\"sr-only\">Loading...</span>\n </div>\n );\n }\n\n // Show error state (if no fallback was applied)\n if (error && !data) {\n if (errorComponent) {\n return <>{errorComponent(error)}</>;\n }\n // Default error display\n return <ErrorState />;\n }\n\n return <Component {...mergedProps} />;\n}\n\n/**\n * Memoized wrapper component that resolves data sources before rendering the widget.\n * Prevents re-renders when parent re-renders but props haven't changed.\n */\nexport const DataAwareWidget: React.NamedExoticComponent<DataAwareWidgetProps> =\n memo(DataAwareWidgetImpl);\n","import type { ComponentType } from \"react\";\nimport { useCallback } from \"react\";\nimport type React from \"react\";\nimport type {\n WidgetSchema,\n TypedWidgetSchema,\n WidgetPath,\n} from \"@fluid-app/portal-core/types\";\nimport { WIDGET_TYPE_NAMES } from \"@fluid-app/portal-core/types\";\nimport { DataAwareWidget } from \"@fluid-app/portal-react/data-sources/DataAwareWidget\";\nimport { RegistryProvider, useRegistry } from \"../contexts/RegistryContext\";\n\nexport interface ScreenRendererProps<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T extends Record<string, ComponentType<any>>,\n> {\n /** Array of widget schemas to render */\n screen: TypedWidgetSchema<T>[] | WidgetSchema[];\n /** Widget registry mapping type names to components */\n registry?: T;\n /** Container widgets (like LayoutWidget) receive these additional props */\n containerWidgetTypes?: string[];\n /** Additional CSS classes for the wrapper div */\n className?: string;\n}\n\ninterface ScreenRendererContentProps {\n screen: WidgetSchema[];\n containerWidgetTypes: string[];\n className?: string | undefined;\n}\n\n/**\n * Internal component that uses the registry from context.\n * This allows us to avoid prop drilling the registry.\n */\nfunction ScreenRendererContent({\n screen,\n containerWidgetTypes,\n className,\n}: ScreenRendererContentProps) {\n const registry = useRegistry();\n\n // Check if a widget type is a container\n const isContainerWidget = useCallback(\n (widgetType: string) => containerWidgetTypes.includes(widgetType),\n [containerWidgetTypes],\n );\n\n // Render widgets recursively with path tracking\n const renderWidget = useCallback(\n (widget: WidgetSchema, index: number, currentPath: WidgetPath) => {\n const Component = registry[widget.type];\n if (!Component) {\n console.warn(\n `Widget type \"${String(widget.type)}\" not found in registry`,\n );\n return null;\n }\n\n const widgetPath = [...currentPath, index];\n\n // Build additional props for container widgets\n const additionalProps = isContainerWidget(widget.type)\n ? {\n widgetId: widget.id,\n widgetPath,\n }\n : {};\n\n const props = {\n ...widget.props,\n ...additionalProps,\n };\n\n // Wrap data-bound widgets with DataAwareWidget to resolve data sources\n if (widget.dataSource) {\n return (\n <div\n key={widget.id || index}\n className=\"h-full w-full overflow-x-hidden\"\n >\n <DataAwareWidget widget={widget} Component={Component} />\n </div>\n );\n }\n\n return (\n <div\n key={widget.id || index}\n className=\"h-full w-full overflow-x-hidden\"\n >\n <Component {...props} />\n </div>\n );\n },\n [registry, isContainerWidget],\n );\n\n return (\n <div className={className || \"h-full w-full\"}>\n {screen?.map((item, index) => {\n // Skip null items (empty grid cells)\n if (!item) return null;\n return renderWidget(item, index, []);\n })}\n </div>\n );\n}\n\n/**\n * ScreenRenderer - View-only component for rendering widget screens.\n *\n * This is a simplified version designed for the SDK that only handles\n * rendering widgets without edit mode or drag-and-drop functionality.\n *\n * Features:\n * - Static rendering of widgets\n * - Registry context: No prop drilling for widget registry\n * - Container widget support with path tracking\n *\n * Usage:\n * ```tsx\n * import { ScreenRenderer } from '@fluid-app/portal-widgets/core';\n * import { WIDGET_REGISTRY } from '@fluid-app/portal-widgets/widgets';\n *\n * <ScreenRenderer\n * screen={widgets}\n * registry={WIDGET_REGISTRY}\n * />\n * ```\n */\nexport function ScreenRenderer<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n T extends Record<string, ComponentType<any>>,\n>(props: ScreenRendererProps<T>): React.JSX.Element {\n const {\n screen,\n registry,\n containerWidgetTypes = [\n WIDGET_TYPE_NAMES.Layout,\n WIDGET_TYPE_NAMES.Container,\n ],\n className,\n } = props;\n\n // Conditionally pass registry prop to satisfy exactOptionalPropertyTypes\n // When registry is undefined, we omit it entirely and let RegistryProvider inherit from parent\n const registryProviderProps = registry !== undefined ? { registry } : {};\n\n return (\n <RegistryProvider {...registryProviderProps}>\n {/* Type assertion required: TypedWidgetSchema<T>[] is a subtype of WidgetSchema[]\n when T's components accept props compatible with WidgetSchema props.\n This enables type-safe widget rendering with custom registries while allowing\n the internal renderer to work with the base WidgetSchema type. */}\n <ScreenRendererContent\n screen={screen as WidgetSchema[]}\n containerWidgetTypes={containerWidgetTypes}\n className={className}\n />\n </RegistryProvider>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-context-DZOQLVi4.cjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchOrders(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchSubscriptions(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. rep_id not yet loaded). Return null — TanStack Query treats undefined\n // as a missing return and throws, so use null for the no-op case.\n if (/\\{\\w+\\}/.test(url)) {\n return null;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo =\n d.kind === \"video\" ||\n d.content_format === \"video\" ||\n d.videoUrl ||\n d.video_url;\n const videoSrc =\n ((d.videoUrl ?? d.video_url) as string) ||\n (isVideo ? (d.url as string) || \"\" : \"\");\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: videoSrc,\n poster: imageUrl,\n caption: title,\n autoplay: false,\n loop: false,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":";;;;;;;;AAOA,eAAe,gBACb,QACA,SACkB;CAClB,MAAM,MAAM,QAAQ;CACpB,MAAM,OAAO;EAAE,GAAG,QAAQ;EAAW,GAAG,OAAO;EAAW;AAE1D,SAAQ,OAAO,UAAf;EACE,KAAK,kBACH,QAAO,IAAI,gBAAgB,MAAM,UAAU,IAAI;GAC7C,eACG,MAAM,kBAA8C;GACvD,OAAO,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAG,KAAA;GAC1C,QAAQ,MAAM;GACd,aAAa,MAAM;GACnB,QAAQ,QAAQ;GACjB,CAAC;EAEJ,KAAK,kBACH,QAAO,IAAI,gBAAgB,MAAM,UAAU,IAAI;GAC7C,eACG,MAAM,kBAA8C;GACvD,OAAO,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAG,KAAA;GAC1C,QAAQ,MAAM;GACd,aAAa,MAAM;GACnB,QAAQ,QAAQ;GACjB,CAAC;EAEJ,KAAK,kBAEH,QAAO,IAAI,YAAY,MAAM,eAAe,IAAI;GAC9C,OAAO,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAG,KAAA;GAC1C,QAAQ,MAAM;GACd,QAAQ,QAAQ;GACjB,CAAC;EAEJ,KAAK,yBAEH,QAAO,IAAI,mBAAmB,MAAM,eAAe,IAAI;GACrD,OAAO,MAAM,QAAQ,OAAO,KAAK,MAAM,GAAG,KAAA;GAC1C,QAAQ,MAAM;GACd,QAAQ,QAAQ;GACjB,CAAC;EAEJ,QACE;;;;;;;AAQN,SAAS,UAAU,KAAc,MAAuB;AACtD,QAAO,KAAK,MAAM,IAAI,CAAC,QAAQ,SAAS,QAAQ;AAC9C,MAAI,WAAW,OAAO,YAAY,YAAY,OAAO,QACnD,QAAQ,QAAoC;IAG7C,IAAI;;;;;;;AAQT,SAAS,qBACP,UACA,WACQ;AACR,KAAI,CAAC,UAAW,QAAO;CACvB,MAAM,WAAW,SAAS,QACxB,eACC,OAAO,QAAgB,UAAU,QAAQ,MAC3C;CACD,MAAM,aAAa,SAAS,MAAM,aAAa;AAC/C,KAAI,WACF,SAAQ,KACN,8DAA8D,WAAW,KAAK,KAAK,CAAC,eACpE,SAAS,0BAA0B,OAAO,KAAK,UAAU,CAAC,KAAK,KAAK,IAAI,WACzF;AAEH,QAAO,oBAAoB,SAAS;;;;;;;;;;;;AAatC,SAAS,oBAAoB,KAAqB;CAChD,MAAM,SAAS,IAAI,QAAQ,IAAI;AAC/B,KAAI,WAAW,GAAI,QAAO;CAE1B,MAAM,OAAO,IAAI,MAAM,GAAG,OAAO;CAEjC,MAAM,OADQ,IAAI,MAAM,SAAS,EAAE,CAEhC,MAAM,IAAI,CACV,QAAQ,SAAS;EAChB,MAAM,UAAU,KAAK,QAAQ,IAAI;AACjC,MAAI,YAAY,GAAI,QAAO;AAC3B,SAAO,KAAK,MAAM,UAAU,EAAE,KAAK;GACnC,CACD,KAAK,IAAI;AAEZ,QAAO,OAAO,GAAG,KAAK,GAAG,SAAS;;;;;;;;AASpC,SAAS,mBACP,UACA,SACA,WACQ;CACR,MAAM,WAAW,qBAAqB,UAAU,UAAU;AAG1D,KAAI,SAAS,WAAW,UAAU,IAAI,SAAS,WAAW,WAAW,CACnE,QAAO;AAIT,KAAI,QAIF,QAAO,GAFM,QAAQ,SAAS,IAAI,GAAG,QAAQ,MAAM,GAAG,GAAG,GAAG,UAC/C,SAAS,WAAW,IAAI,GAAG,WAAW,IAAI;AAKzD,QAAO;;;;;AAMT,eAAsB,WACpB,QACA,SACkB;AAElB,KAAI,QAAQ,OAAO,OAAO,UAAU;EAClC,MAAM,SAAS,MAAM,gBAAgB,QAAQ,QAAQ;AACrD,MAAI,WAAW,KAAA,EAAW,QAAO;;CAInC,MAAM,EAAE,UAAU,SAAS,OAAO,UAAU,EAAE,EAAE,MAAM,eAAe;CAGrE,MAAM,kBAAkB;EAAE,GAAG,QAAQ;EAAW,GAAG,OAAO;EAAW;CAGrE,MAAM,MAAM,mBAAmB,UAAU,QAAQ,SAAS,gBAAgB;AAK1E,KAAI,UAAU,KAAK,IAAI,CACrB,QAAO;CAGT,MAAM,eAA4B;EAChC;EACA,SAAS;GACP,gBAAgB;GAChB,GAAG,QAAQ,iBAAiB;GAC5B,GAAG;GACJ;EACD,QAAQ,QAAQ;EACjB;AAED,KAAI,SAAS,WAAW,UAAU,WAAW,OAC3C,cAAa,OAAO,KAAK,UAAU,KAAK;CAG1C,MAAM,WAAW,MAAM,MAAM,KAAK,aAAa;AAE/C,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MACR,uBAAuB,SAAS,OAAO,GAAG,SAAS,aACpD;CAGH,MAAM,OAAO,MAAM,SAAS,MAAM;AAGlC,KAAI,WACF,QAAO,UAAU,MAAM,WAAW;AAGpC,QAAO;;;;AC1MT,MAAM,6BAA2D;CAC/D,QAAQ;CACR,MAAM;CACN,SAAS;CACT,SAAS;CACT,gBAAgB;CACjB;AAED,eAAe,qBACb,OACA,SACoB;CACpB,MAAM,MAAM,QAAQ;CAKpB,MAAM,UAAU,MAAM,QAAQ,WAC5B,MAAM,IAAI,OAAO,SAAS;EACxB,MAAM,eAAe,2BAA2B,KAAK;AACrD,MAAI,CAAC,aACH,OAAM,IAAI,MACR,2BAA2B,KAAK,cAAc,aAAa,KAAK,KACjE;AAEH,SAAO,IAAI,cAAc,cAAc,KAAK,IAAI,QAAQ,OAAO;GAC/D,CACH;CAED,MAAM,aAAwB,EAAE;CAChC,MAAM,WAAsD,EAAE;AAE9D,SAAQ,SAAS,QAAQ,UAAU;EACjC,MAAM,OAAO,MAAM;AACnB,MAAI,CAAC,KAAM;AACX,MAAI,OAAO,WAAW,YACpB,YAAW,KAAK,OAAO,MAAM;MAE7B,UAAS,KAAK;GAAE;GAAM,QAAQ,OAAO;GAAQ,CAAC;GAEhD;AAEF,KAAI,SAAS,SAAS,EAGpB,SAAQ,MACN,mBAAmB,SAAS,OAAO,GAAG,MAAM,OAAO,0BACnD,SAAS,KAAK,OAAO;EACnB,eAAe,EAAE,KAAK;EACtB,IAAI,EAAE,KAAK;EACX,OAAO,EAAE,kBAAkB,QAAQ,EAAE,OAAO,UAAU,EAAE;EACzD,EAAE,CACJ;AAGH,KAAI,WAAW,WAAW,KAAK,MAAM,SAAS,GAAG;EAC/C,MAAM,WAAW,SAAS,IAAI;AAC9B,QAAM,IAAI,MACR,uBAAuB,MAAM,OAAO,UAAU,oBAAoB,QAAQ,KAAK,SAAS,YAAY,KACrG;;AAGH,QAAO;;;;;;;;;AAUT,eAAsB,cACpB,QACA,SACoB;CACpB,MAAM,EAAE,kBAAkB;AAC1B,KAAI,CAAC,iBAAiB,cAAc,WAAW,EAC7C,QAAO,EAAE;AAGX,KAAI,CAAC,QAAQ,IACX,OAAM,IAAI,MACR,uFACD;AAGH,QAAO,qBAAqB,eAAe,QAAQ;;;;;;;;;;AClFrD,eAAsB,cACpB,QACA,SACoB;CACpB,MAAM,EAAE,YAAY,eAAe;AAEnC,KAAI,CAAC,QAAQ,IACX,OAAM,IAAI,MACR,uFACD;AAMH,KAAI,eAAe,UAAU,OAAO,MAAM,OAAO,WAAW,CAAC,CAC3D,OAAM,IAAI,MACR,mDAAmD,WAAW,GAC/D;AAGH,QAAO,QAAQ,IAAI,sBACjB,YACA,YACA,QAAQ,OACT;;;;;;;;;;;ACbH,SAAS,gBAAgB,GAAoC;AAE3D,KAAI,EAAE,UAAW,QAAO,EAAE;AAC1B,KAAI,EAAE,SAAU,QAAO,EAAE;AACzB,KAAI,EAAE,cAAe,QAAO,EAAE;AAC9B,KAAI,EAAE,IAAK,QAAO,EAAE;CAGpB,MAAM,SAAS,EAAE;AACjB,KAAI,UAAU,OAAO,SAAS,GAAG;EAC/B,MAAM,aAAa,OAAO;AAC1B,MAAI,YAAY,UAAW,QAAO,WAAW;AAC7C,MAAI,YAAY,IAAK,QAAO,WAAW;;CAIzC,MAAM,eAAe,EAAE;AAGvB,KAAI,gBAAgB,aAAa,SAAS,GAAG;EAE3C,MAAM,aADY,aAAa,IACD;AAG9B,MAAI,YAAY,UAAW,QAAO,WAAW;AAC7C,MAAI,YAAY,SAAU,QAAO,WAAW;AAC5C,MAAI,YAAY,cAAe,QAAO,WAAW;;AAGnD,QAAO;;;;;;AAOT,SAAS,mBAAmB,GAAoC;CAE9D,MAAM,OACJ,EAAE,eAAe,EAAE,YAAY,EAAE,wBAAwB,EAAE,QAAQ;AAGrE,KAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU,KACzD,QAAS,KAAiC,QAAmB;AAG/D,QAAO;;;;;AAMT,SAAS,0BACP,GACA,QACyB;AACzB,KAAI,WAAW,KAAA,KAAa,OAAO,SAAS,SAAU,QAAO,EAAE;AAK/D,QAHqB,OAAO,cAAc,MACvC,MAAM,OAAO,EAAE,GAAG,KAAK,OAAO,EAAE,GAAG,CACrC,EACoB,gBAAgB,EAAE;;;;;AAMzC,MAAM,6BAA8C,SAAS;CAC3D,MAAM,OAAO,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;AAC7C,KAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,QAAO;EAAE,KAAK;EAAI,KAAK;EAAS,WAAW;EAAS;CAGtD,MAAM,IAAI;AACV,QAAO;EACL,KAAK,gBAAgB,EAAE;EACvB,KAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO;EACpC,WAAW;EACZ;;;;;AAMH,MAAM,6BAA8C,SAAS;CAC3D,MAAM,OAAO,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;AAC7C,KAAI,CAAC,QAAQ,OAAO,SAAS,SAC3B,QAAO;EAAE,KAAK;EAAI,QAAQ;EAAI,SAAS;EAAI;CAG7C,MAAM,IAAI;AACV,QAAO;EACL,MAAO,EAAE,aAAa,EAAE,YAAY,EAAE,QAAmB;EACzD,QAAQ,gBAAgB,EAAE;EAC1B,SAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW;EAC7C;;;;;;AAOH,MAAM,oBAAqC,MAAM,WAAW;AAC1D,KAAI,CAAC,MAAM,QAAQ,KAAK,CAAE,QAAO,EAAE;CAKnC,MAAM,iBACJ,QAAQ,SAAS,QAAQ,OAAO,WAAW,iBAAiB,KAAA;AAE9D,QAAO,KAAK,KAAK,SAAkB;EACjC,MAAM,IAAI;EAEV,MAAM,eAAe,0BAA0B,GAAG,OAAO;EAGzD,MAAM,gBAAiB,EAAE,QACvB,EAAE,mBACF,EAAE,kBACF,EAAE,iBACF,kBACA;AAEF,SAAO;GACL,GAAG;GACH,IAAI,EAAE;GACN,OAAQ,EAAE,SAAS,EAAE,QAAQ;GAC7B,aAAa,mBAAmB,EAAE;GAClC,UAAU,gBAAgB,EAAE;GAC5B,WAAY,EAAE,aAAa,EAAE,aAAwB;GACrD;GACA,MAAO,EAAE,QAAQ;GACjB,QAAS,EAAE,UAAU;GACrB,gBAAgB,EAAE,2BAA2B,EAAE,mBAAmB;GAClE,mBAAmB,EAAE,sBAAsB;GAC3C,YAAY,EAAE,gBAAgB;GAC9B,YAAY,EAAE,gBAAgB;GAC9B,GAAG;GACJ;GACD;;;;;AAMJ,MAAM,kCAAmD,MAAM,WAAW;AACxE,KAAI,CAAC,MAAM,QAAQ,KAAK,CAAE,QAAO,EAAE;AAEnC,QAAO,KAAK,KAAK,MAAe,UAAkB;EAChD,MAAM,IAAI;EAEV,MAAM,eAAe,0BAA0B,GAAG,OAAO;EAEzD,MAAM,WAAW,gBAAgB,EAAE;EACnC,MAAM,UACJ,EAAE,SAAS,WACX,EAAE,mBAAmB,WACrB,EAAE,YACF,EAAE;EACJ,MAAM,YACF,EAAE,YAAY,EAAE,eACjB,UAAW,EAAE,OAAkB,KAAK;EACvC,MAAM,QAAS,EAAE,SAAS,EAAE,QAAQ;EAEpC,MAAM,UAAU,UACZ;GACE,MAAM;GACN,OAAO;IACL,KAAK;IACL,QAAQ;IACR,SAAS;IACT,UAAU;IACV,MAAM;IACN,OAAO;IACP,UAAU;IACX;GACF,GACD;GACE,MAAM;GACN,OAAO;IACL,KAAK;IACL,KAAK,SAAS;IACd,WAAW;IACZ;GACF;AASL,SAAO;GANL,IAAI,OAAO,EAAE,MAAM,SAAS,QAAQ;GACpC;GACA;GACA,aAAa,mBAAmB,EAAE;GAKlC,GAAG;GACJ;GACD;;;;;;;AAQJ,MAAM,qBAAsC,SAAS;AA6BnD,QAAO;EAAE,OA5BM,MAAM,QAAQ,KAAK,GAAG,OAAO,EAAE,EAS1B,KAAK,SAAkB;GACzC,MAAM,IAAI;GACV,MAAM,YAAY,EAAE;GACpB,MAAM,SAAS,WAAW,OAAO,EAAE,UAAU,IAAI,CAAC,IAAI;AAEtD,UAAO;IACL,GAAG;IACH,IAAI,EAAE,MAAM,EAAE;IACd,eAAe;IACf,UAAW,WAAW,aAAwB;IAC9C,OAAQ,WAAW,SAAoB;IACvC,cAAc,EAAE,gBAAgB;IAChC,OAAO;IACP,eAAgB,EAAE,wBAAmC,EAAE,UAAU;IACjE,QAAS,EAAE,UAAqB;IAChC,YAAY,EAAE;IACf;IACD;EAEmB,SA1BL;GACd;IAAE,KAAK;IAAY,OAAO;IAAS,UAAU;IAAO;GACpD;IAAE,KAAK;IAAgB,OAAO;IAAW,UAAU;IAAM;GACzD;IAAE,KAAK;IAAS,OAAO;IAAS,UAAU;IAAM;GAChD;IAAE,KAAK;IAAU,OAAO;IAAU,UAAU;IAAM;GACnD;EAqB6B;;;;;;AAOhC,MAAM,4BAA6C,SAAS;AA6B1D,QAAO;EAAE,OA5Ba,MAAM,QAAQ,KAAK,GAAG,OAAO,EAAE,EAS1B,KAAK,SAAkB;GAChD,MAAM,IAAI;GAEV,MAAM,UADU,EAAE,SACO;AAEzB,UAAO;IACL,GAAG;IACH,IAAI,EAAE,MAAM,EAAE;IACd,eAAe;IACf,UAAW,SAAS,aAAwB;IAC5C,OAAQ,SAAS,SAAoB;IACrC,OAAO,WAAW,OAAO,EAAE,SAAS,IAAI,CAAC,IAAI;IAC7C,eACG,SAAS,qBAAgC,OAAO,EAAE,SAAS,GAAG;IACjE,QAAS,EAAE,UAAqB;IAChC,gBAAgB,EAAE;IACnB;IACD;EAEmB,SA1BL;GACd;IAAE,KAAK;IAAY,OAAO;IAAS,UAAU;IAAO;GACpD;IAAE,KAAK;IAAS,OAAO;IAAW,UAAU;IAAM;GAClD;IAAE,KAAK;IAAS,OAAO;IAAS,UAAU;IAAM;GAChD;IAAE,KAAK;IAAU,OAAO;IAAU,UAAU;IAAM;GACnD;EAqB6B;;;;;AAMhC,MAAa,sBAAuD;CAClE;CACA;CACA;CACA;CACA;CACA;CACD;;;;;;;AC9RD,SAAgB,yBACd,SACoB;AACpB,QAAO;EACL,UAAU;GACR,KAAK;GACL,QAAQ;GACR,QAAQ;GACR,GAAG,SAAS;GACb;EACD,cAAc;GACZ,GAAG;GACH,GAAG,SAAS;GACb;EACF;;;AAIH,MAAa,+BACX,0BAA0B;;;ACjC5B,MAAM,qBAAA,GAAA,MAAA,eAA0D,EAAE,CAAC;AAQnE,SAAgB,mBAAmB,EACjC,SACA,eACA,YAC6C;CAC7C,MAAM,SAAA,GAAA,MAAA,gBACG;EAAE;EAAS;EAAe,GACjC,CAAC,SAAS,cAAc,CACzB;AAED,QACE,iBAAA,GAAA,kBAAA,KAAC,kBAAkB,UAAnB;EAAmC;EAChC;EAC0B,CAAA;;;;ACdjC,MAAM,6BAAA,GAAA,MAAA,eACJ,EACE,UAAU,8BACX,CACF;;;;;;;;;AAuBD,SAAgB,2BAA2B,EACzC,UACA,SACA,eACA,WACA,YACqD;CACrD,MAAM,SAAA,GAAA,MAAA,gBACG;EACL,UAAU,YAAY;EACtB;EACA;EACA;EACD,GACD;EAAC;EAAU;EAAS;EAAe;EAAU,CAC9C;AAED,QACE,iBAAA,GAAA,kBAAA,KAAC,0BAA0B,UAA3B;EAA2C;YACzC,iBAAA,GAAA,kBAAA,KAAC,oBAAD;GAA6B;GAAwB;GAClD;GACkB,CAAA;EACc,CAAA;;;;;AAczC,SAAgB,8BAA8D;AAC5E,SAAA,GAAA,MAAA,YAAkB,0BAA0B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry-context-DdfXs3K3.mjs","names":[],"sources":["../../core/src/data-sources/fetchers/api.ts","../../core/src/data-sources/fetchers/custom.ts","../../core/src/data-sources/fetchers/static.ts","../../core/src/data-sources/transformers.ts","../../core/src/data-sources/registry.ts","../../react/src/data-sources/context.tsx","../../react/src/data-sources/registry-context.tsx"],"sourcesContent":["import type { DataSourceShareableType } from \"../../data-source-api-types\";\nimport type { ApiDataSource, DataSourceContext } from \"../types\";\n\n/**\n * Delegates a preset API source to the injected DataSourceApi adapter.\n * Returns undefined for unknown presets (caller falls through to raw fetch).\n */\nasync function fetchViaAdapter(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n const api = context.api!;\n const vars = { ...context.variables, ...source.variables };\n\n switch (source.presetId) {\n case \"rep-most-shared\": {\n return api.fetchMostShared(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"rep-most-viewed\": {\n return api.fetchMostViewed(vars?.rep_id ?? \"\", {\n shareableType:\n (vars?.shareable_type as DataSourceShareableType) ?? \"products\",\n limit: vars?.limit ? Number(vars.limit) : undefined,\n period: vars?.period,\n languageIso: vars?.language_iso,\n signal: context.signal,\n });\n }\n case \"customer-orders\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchOrders(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n case \"customer-subscriptions\": {\n // BFF scopes by session — customer_id is informational/optional.\n return api.fetchSubscriptions(vars?.customer_id ?? \"\", {\n limit: vars?.limit ? Number(vars.limit) : undefined,\n status: vars?.status,\n signal: context.signal,\n });\n }\n default:\n return undefined;\n }\n}\n\n/**\n * Extracts a value from an object using dot notation path\n * e.g., getByPath({ data: { items: [1,2,3] } }, 'data.items') => [1,2,3]\n */\nfunction getByPath(obj: unknown, path: string): unknown {\n return path.split(\".\").reduce((current, key) => {\n if (current && typeof current === \"object\" && key in current) {\n return (current as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Replaces {variable} placeholders in an endpoint path with values from the\n * variables map. E.g., \"/reps/{rep_id}/most_shared\" with { rep_id: \"42\" }\n * becomes \"/reps/42/most_shared\".\n */\nfunction interpolateVariables(\n endpoint: string,\n variables?: Record<string, string>,\n): string {\n if (!variables) return endpoint;\n const resolved = endpoint.replace(\n /\\{(\\w+)\\}/g,\n (match, key: string) => variables[key] ?? match,\n );\n const unresolved = resolved.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n console.warn(\n `[DataSource] Unresolved variable placeholders in endpoint: ${unresolved.join(\", \")}. ` +\n `Endpoint: \"${endpoint}\". Available variables: ${Object.keys(variables).join(\", \") || \"(none)\"}`,\n );\n }\n return stripAllQueryParams(resolved);\n}\n\n/**\n * Removes query parameters whose value is \"all\" from a URL.\n *\n * Convention: \"all\" is a reserved no-op value for data source preset\n * config fields. Preset authors should use \"all\" as the default option\n * for \"show everything\" filters. This function strips those params so\n * APIs that don't recognise \"all\" fall back to their default (return\n * everything) behaviour. Do not use \"all\" as a meaningful filter value\n * in preset endpoints.\n */\nfunction stripAllQueryParams(url: string): string {\n const qIndex = url.indexOf(\"?\");\n if (qIndex === -1) return url;\n\n const base = url.slice(0, qIndex);\n const query = url.slice(qIndex + 1);\n const kept = query\n .split(\"&\")\n .filter((pair) => {\n const eqIndex = pair.indexOf(\"=\");\n if (eqIndex === -1) return true;\n return pair.slice(eqIndex + 1) !== \"all\";\n })\n .join(\"&\");\n\n return kept ? `${base}?${kept}` : base;\n}\n\n/**\n * Resolves the full URL for an endpoint.\n * - Substitutes {variable} placeholders from context variables\n * - Absolute URLs (starting with http:// or https://) are used as-is\n * - Relative paths are prefixed with the context's baseUrl\n */\nfunction resolveEndpointUrl(\n endpoint: string,\n baseUrl?: string,\n variables?: Record<string, string>,\n): string {\n const resolved = interpolateVariables(endpoint, variables);\n\n // If endpoint is already absolute, use it directly\n if (resolved.startsWith(\"http://\") || resolved.startsWith(\"https://\")) {\n return resolved;\n }\n\n // If we have a baseUrl, prepend it to the relative endpoint\n if (baseUrl) {\n // Ensure proper joining (no double slashes)\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n const path = resolved.startsWith(\"/\") ? resolved : `/${resolved}`;\n return `${base}${path}`;\n }\n\n // No baseUrl provided, return endpoint as-is (will likely fail for relative paths)\n return resolved;\n}\n\n/**\n * Default API fetcher implementation\n */\nexport async function apiFetcher(\n source: ApiDataSource,\n context: DataSourceContext,\n): Promise<unknown> {\n // Delegate to adapter if available for preset-backed sources\n if (context.api && source.presetId) {\n const result = await fetchViaAdapter(source, context);\n if (result !== undefined) return result;\n // Fall through to legacy fetch for unknown presets\n }\n\n const { endpoint, method = \"GET\", headers = {}, body, resultPath } = source;\n\n // Merge context variables with per-source variables (source overrides context)\n const mergedVariables = { ...context.variables, ...source.variables };\n\n // Resolve the full URL, substituting variables and using baseUrl for relative endpoints\n const url = resolveEndpointUrl(endpoint, context.baseUrl, mergedVariables);\n\n // Skip the fetch if the URL still contains unresolved {variable} placeholders\n // (e.g. rep_id not yet loaded). Return null — TanStack Query treats undefined\n // as a missing return and throws, so use null for the no-op case.\n if (/\\{\\w+\\}/.test(url)) {\n return null;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n \"content-type\": \"application/json\",\n ...context.getApiHeaders?.(),\n ...headers,\n },\n signal: context.signal,\n };\n\n if (body && (method === \"POST\" || method === \"PUT\")) {\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n\n if (!response.ok) {\n throw new Error(\n `API request failed: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n // Extract data at resultPath if specified\n if (resultPath) {\n return getByPath(data, resultPath);\n }\n\n return data;\n}\n","import type { ResourceType } from \"../../data-source-api-types\";\nimport type {\n CustomDataSource,\n DataSourceContext,\n SelectedItem,\n} from \"../types\";\n\nconst SHAREABLE_TO_RESOURCE_TYPE: Record<string, ResourceType> = {\n Medium: \"Medium\",\n Page: \"Page\",\n Library: \"Library\",\n Product: \"Product\",\n EnrollmentPack: \"EnrollmentPack\",\n};\n\nasync function fetchItemsViaAdapter(\n items: SelectedItem[],\n context: DataSourceContext,\n): Promise<unknown[]> {\n const api = context.api!;\n\n // Use Promise.allSettled so individual failures don't blow up the whole\n // batch, but *do* surface the aggregate failure for visibility — a rep who\n // hand-picked 5 items shouldn't silently see 3 without knowing why.\n const settled = await Promise.allSettled(\n items.map(async (item) => {\n const resourceType = SHAREABLE_TO_RESOURCE_TYPE[item.shareableType];\n if (!resourceType) {\n throw new Error(\n `Unknown shareable type: ${item.shareableType} for item #${item.id}`,\n );\n }\n return api.fetchResource(resourceType, item.id, context.signal);\n }),\n );\n\n const successful: unknown[] = [];\n const failures: { item: SelectedItem; reason: unknown }[] = [];\n\n settled.forEach((result, index) => {\n const item = items[index];\n if (!item) return;\n if (result.status === \"fulfilled\") {\n successful.push(result.value);\n } else {\n failures.push({ item, reason: result.reason });\n }\n });\n\n if (failures.length > 0) {\n // Log once with aggregate context so Sentry/logs show the full picture\n // rather than N scattered warnings that are hard to correlate.\n console.error(\n `[CustomFetcher] ${failures.length}/${items.length} items failed to fetch:`,\n failures.map((f) => ({\n shareableType: f.item.shareableType,\n id: f.item.id,\n error: f.reason instanceof Error ? f.reason.message : f.reason,\n })),\n );\n }\n\n if (successful.length === 0 && items.length > 0) {\n const firstErr = failures[0]?.reason;\n throw new Error(\n `Failed to fetch all ${items.length} item(s)${firstErr instanceof Error ? `: ${firstErr.message}` : \"\"}`,\n );\n }\n\n return successful;\n}\n\n/**\n * Custom fetcher that fetches selected items via the injected DataSourceApi adapter.\n *\n * Fetches all items in parallel for performance.\n * Returns an array of successfully fetched items, preserving order.\n * Logs warnings for failed fetches but doesn't throw unless all items fail.\n */\nexport async function customFetcher(\n source: CustomDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { selectedItems } = source;\n if (!selectedItems || selectedItems.length === 0) {\n return [];\n }\n\n if (!context.api) {\n throw new Error(\n \"customFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n return fetchItemsViaAdapter(selectedItems, context);\n}\n","import type {\n StaticDataSource,\n DataSourceContext,\n StaticSourceType,\n} from \"../types\";\n\n/**\n * Static data source fetcher.\n *\n * Delegates to the injected DataSourceApi adapter to fetch products filtered\n * by collection, category, or tag.\n */\nexport async function staticFetcher(\n source: StaticDataSource,\n context: DataSourceContext,\n): Promise<unknown[]> {\n const { staticType, selectedId } = source;\n\n if (!context.api) {\n throw new Error(\n \"staticFetcher requires context.api — ensure a DataSourceApiProvider wraps this tree.\",\n );\n }\n\n // Validate filterId once at the shared delegation point so BFF and legacy\n // adapters behave identically. Tags are a known-unsupported type the\n // adapters throw for separately.\n if (staticType !== \"tags\" && Number.isNaN(Number(selectedId))) {\n throw new Error(\n `staticFetcher: selectedId must be numeric, got \"${selectedId}\"`,\n );\n }\n\n return context.api.fetchProductsByFilter(\n staticType,\n selectedId,\n context.signal,\n );\n}\n\n/**\n * Endpoints for listing static source items (collections, categories, tags).\n * Used by the portal builder UI for populating selection dropdowns.\n */\nexport const LIST_ENDPOINTS: Record<\n StaticSourceType,\n { endpoint: string; resultKey: string }\n> = {\n collections: {\n endpoint: \"/company/v1/collections\",\n resultKey: \"collections\",\n },\n categories: { endpoint: \"/company/v1/categories\", resultKey: \"categories\" },\n tags: { endpoint: \"/company/v1/tags\", resultKey: \"tags\" },\n};\n","/**\n * Widget Transformers\n *\n * Transform functions that map API response data to widget-specific prop shapes.\n * Each widget has one transformer that handles all data structure variants:\n * - Standard: Direct field name match\n * - Legacy: Different field names that need mapping\n * - Minimal: Bare minimum fields that need defaults\n *\n * Usage:\n * 1. Transformers are registered in the DataSourceRegistry\n * 2. Reference by name in ApiDataSource.transform\n * 3. Applied after resultPath extraction, before targetProps assignment\n */\n\nimport type { DataTransformer, DataSource } from \"./types\";\n\n/**\n * Helper to extract image URL from various API response structures.\n * Handles:\n * - Flat fields (Medium, Page, Product): image_url, imageUrl, thumbnail_url, src\n * - Nested images array (EnrollmentPack): images[0].image_url\n * - Nested library_items (Library): library_items[0].relateable.image_url\n */\nfunction extractImageUrl(d: Record<string, unknown>): string {\n // Try flat fields first (Medium, Page, Product)\n if (d.image_url) return d.image_url as string;\n if (d.imageUrl) return d.imageUrl as string;\n if (d.thumbnail_url) return d.thumbnail_url as string;\n if (d.src) return d.src as string;\n\n // Try nested images array (EnrollmentPack)\n const images = d.images as Array<Record<string, unknown>> | undefined;\n if (images && images.length > 0) {\n const firstImage = images[0];\n if (firstImage?.image_url) return firstImage.image_url as string;\n if (firstImage?.url) return firstImage.url as string;\n }\n\n // Try nested library_items (Library/Playlist)\n const libraryItems = d.library_items as\n | Array<Record<string, unknown>>\n | undefined;\n if (libraryItems && libraryItems.length > 0) {\n const firstItem = libraryItems[0];\n const relateable = firstItem?.relateable as\n | Record<string, unknown>\n | undefined;\n if (relateable?.image_url) return relateable.image_url as string;\n if (relateable?.imageUrl) return relateable.imageUrl as string;\n if (relateable?.thumbnail_url) return relateable.thumbnail_url as string;\n }\n\n return \"\";\n}\n\n/**\n * Helper to extract description from various API response structures.\n * Handles different field names across endpoints.\n */\nfunction extractDescription(d: Record<string, unknown>): string {\n // Try various description field names\n const desc =\n d.description ?? d.stripped ?? d.stripped_description ?? d.body ?? \"\";\n\n // Handle nested description object (some APIs return { body: \"...\" })\n if (typeof desc === \"object\" && desc !== null && \"body\" in desc) {\n return ((desc as Record<string, unknown>).body as string) ?? \"\";\n }\n\n return desc as string;\n}\n\n/**\n * Helper to extract custom widget config from a selected item.\n */\nfunction extractCustomWidgetConfig(\n d: Record<string, unknown>,\n source: DataSource | undefined,\n): Record<string, unknown> {\n if (source === undefined || source.type !== \"custom\") return {};\n\n const selectedItem = source.selectedItems.find(\n (s) => String(s.id) === String(d.id),\n );\n return selectedItem?.widgetConfig ?? {};\n}\n\n/**\n * ImageWidget transformer from shareable data\n */\nconst toImagePropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", alt: \"Image\", objectFit: \"cover\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: extractImageUrl(d),\n alt: (d.title ?? d.name ?? d.alt ?? \"Image\") as string,\n objectFit: \"cover\" as const,\n };\n};\n\n/**\n * VideoWidget transformer from shareable data\n */\nconst toVideoPropsFromShareable: DataTransformer = (data) => {\n const item = Array.isArray(data) ? data[0] : data;\n if (!item || typeof item !== \"object\") {\n return { src: \"\", poster: \"\", caption: \"\" };\n }\n\n const d = item as Record<string, unknown>;\n return {\n src: ((d.video_url ?? d.videoUrl ?? d.src) as string) || \"\",\n poster: extractImageUrl(d),\n caption: (d.title ?? d.name ?? d.caption ?? \"\") as string,\n };\n};\n\n/**\n * Shareable content transformer\n * Normalizes shareable API responses to a consistent format\n */\nconst toShareableProps: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n // Derive a fallback shareable type from the data source configuration.\n // API presets pass shareable_type in their variables (e.g., \"products\").\n // Custom sources store it per-item (handled below).\n const sourceTypeHint =\n source?.type === \"api\" ? source.variables?.shareable_type : undefined;\n\n return data.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n // Resolve shareable type from the item itself, then fall back to source hint\n const shareableType = (d.type ??\n d.relateable_type ??\n d.shareable_type ??\n d.shareableType ??\n sourceTypeHint ??\n \"\") as string;\n\n return {\n ...d,\n id: d.id,\n title: (d.title ?? d.name ?? \"\") as string,\n description: extractDescription(d),\n imageUrl: extractImageUrl(d),\n videoUrl: ((d.video_url ?? d.videoUrl) as string) || null,\n shareableType,\n kind: (d.kind ?? \"image\") as string,\n status: (d.status ?? \"active\") as string,\n wholesalePrice: d.display_wholesale_price ?? d.wholesale_price ?? null,\n subscriptionPrice: d.subscription_price ?? null,\n outOfStock: d.out_of_stock ?? false,\n lowInStock: d.low_in_stock ?? false,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Carousel slides from shareables transformer\n */\nconst toCarouselSlidesFromShareables: DataTransformer = (data, source) => {\n if (!Array.isArray(data)) return [];\n\n return data.map((item: unknown, index: number) => {\n const d = item as Record<string, unknown>;\n\n const widgetConfig = extractCustomWidgetConfig(d, source);\n\n const imageUrl = extractImageUrl(d);\n const isVideo =\n d.kind === \"video\" ||\n d.content_format === \"video\" ||\n d.videoUrl ||\n d.video_url;\n const videoSrc =\n ((d.videoUrl ?? d.video_url) as string) ||\n (isVideo ? (d.url as string) || \"\" : \"\");\n const title = (d.title ?? d.name ?? \"\") as string;\n\n const content = isVideo\n ? {\n type: \"VideoWidget\",\n props: {\n src: videoSrc,\n poster: imageUrl,\n caption: title,\n autoplay: false,\n loop: false,\n muted: true,\n controls: true,\n },\n }\n : {\n type: \"ImageWidget\",\n props: {\n src: imageUrl,\n alt: title || \"Slide image\",\n objectFit: \"cover\",\n },\n };\n\n const baseSlide = {\n id: String(d.id ?? `slide-${index}`),\n content,\n title,\n description: extractDescription(d),\n };\n\n return {\n ...baseSlide,\n ...widgetConfig,\n };\n });\n};\n\n/**\n * Orders table transformer\n * Normalizes order list data into ShareableItem rows + column definitions.\n * Returns { data, columns } so multi-targetProp mapping sends each to the widget.\n */\nconst toOrderTableProps: DataTransformer = (data) => {\n const orders = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"order_number\", label: \"Order #\", sortable: true },\n { key: \"price\", label: \"Total\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = orders.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const firstItem = d.first_item as Record<string, unknown> | undefined;\n const amount = parseFloat(String(d.amount ?? \"0\")) || 0;\n\n return {\n ...d,\n id: d.id ?? d.token,\n shareableType: \"Order\",\n imageUrl: (firstItem?.image_url as string) || \"\",\n title: (firstItem?.title as string) || \"\",\n order_number: d.order_number ?? \"\",\n price: amount,\n display_price: (d.total_display_amount as string) ?? d.amount ?? \"\",\n status: (d.status as string) ?? \"unknown\",\n created_at: d.created_at,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * Subscriptions table transformer\n * Normalizes subscription list data into ShareableItem rows + column definitions.\n */\nconst toSubscriptionTableProps: DataTransformer = (data) => {\n const subscriptions = Array.isArray(data) ? data : [];\n\n const columns = [\n { key: \"imageUrl\", label: \"Image\", sortable: false },\n { key: \"title\", label: \"Product\", sortable: true },\n { key: \"price\", label: \"Price\", sortable: true },\n { key: \"status\", label: \"Status\", sortable: true },\n ];\n\n const rows = subscriptions.map((item: unknown) => {\n const d = item as Record<string, unknown>;\n const variant = d.variant as Record<string, unknown> | undefined;\n const product = variant?.product as Record<string, unknown> | undefined;\n\n return {\n ...d,\n id: d.id ?? d.subscription_token,\n shareableType: \"Subscription\",\n imageUrl: (product?.image_url as string) || \"\",\n title: (product?.title as string) || \"\",\n price: parseFloat(String(d.price ?? \"0\")) || 0,\n display_price:\n (product?.price_in_currency as string) ?? String(d.price ?? \"\"),\n status: (d.status as string) ?? \"unknown\",\n next_bill_date: d.next_bill_date,\n };\n });\n\n return { data: rows, columns };\n};\n\n/**\n * All widget transformers bundled for registration\n */\nexport const WIDGET_TRANSFORMERS: Record<string, DataTransformer> = {\n toShareableProps,\n toCarouselSlidesFromShareables,\n toImagePropsFromShareable,\n toVideoPropsFromShareable,\n toOrderTableProps,\n toSubscriptionTableProps,\n};\n","import type {\n DataSourceRegistry,\n DataFetcher,\n DataTransformer,\n DataSourceType,\n} from \"./types\";\nimport { apiFetcher } from \"./fetchers/api\";\nimport { customFetcher } from \"./fetchers/custom\";\nimport { staticFetcher } from \"./fetchers/static\";\nimport { WIDGET_TRANSFORMERS } from \"./transformers\";\n\nexport interface CreateDataSourceRegistryOptions {\n /** Custom fetchers to add or override */\n fetchers?: Partial<Record<DataSourceType, DataFetcher>>;\n /** Custom transform functions */\n transformers?: Record<string, DataTransformer>;\n}\n\n/**\n * Creates a data source registry with default fetchers.\n * Users can extend this with custom fetchers and transformers.\n */\nexport function createDataSourceRegistry(\n options?: CreateDataSourceRegistryOptions,\n): DataSourceRegistry {\n return {\n fetchers: {\n api: apiFetcher,\n custom: customFetcher,\n static: staticFetcher,\n ...options?.fetchers,\n } as Record<DataSourceType, DataFetcher>,\n transformers: {\n ...WIDGET_TRANSFORMERS,\n ...options?.transformers,\n },\n };\n}\n\n/** Default registry instance */\nexport const DEFAULT_DATA_SOURCE_REGISTRY: DataSourceRegistry =\n createDataSourceRegistry();\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\n\nexport interface DataSourceContextValue {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n}\n\nconst DataSourceContext = createContext<DataSourceContextValue>({});\n\nexport interface DataSourceProviderProps {\n baseUrl?: string | undefined;\n getApiHeaders?: (() => Record<string, string>) | undefined;\n children: ReactNode;\n}\n\nexport function DataSourceProvider({\n baseUrl,\n getApiHeaders,\n children,\n}: DataSourceProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({ baseUrl, getApiHeaders }),\n [baseUrl, getApiHeaders],\n );\n\n return (\n <DataSourceContext.Provider value={value}>\n {children}\n </DataSourceContext.Provider>\n );\n}\n\nexport function useDataSourceConfig(): DataSourceContextValue {\n return useContext(DataSourceContext);\n}\n","import type React from \"react\";\nimport { createContext, useContext, useMemo, type ReactNode } from \"react\";\nimport type { DataSourceRegistry } from \"@fluid-app/portal-core/data-sources/types\";\nimport { DEFAULT_DATA_SOURCE_REGISTRY } from \"@fluid-app/portal-core/data-sources/registry\";\nimport { DataSourceProvider } from \"./context\";\n\ninterface DataSourceRegistryContextValue {\n registry: DataSourceRegistry;\n baseUrl?: string | undefined;\n /** Get API headers function */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n}\n\nconst DataSourceRegistryContext = createContext<DataSourceRegistryContextValue>(\n {\n registry: DEFAULT_DATA_SOURCE_REGISTRY,\n },\n);\n\nexport interface DataSourceRegistryProviderProps {\n registry?: DataSourceRegistry | undefined;\n /** Base URL for API calls (e.g., \"https://api.fluid.app/api\") */\n baseUrl?: string | undefined;\n /**\n * Get API headers function\n */\n getApiHeaders?: (() => Record<string, string>) | undefined;\n /** Dynamic variables for endpoint path substitution (e.g., { rep_id: \"123\" }) */\n variables?: Record<string, string> | undefined;\n children: ReactNode;\n}\n\n/**\n * Provides data source registry and configuration to all descendants.\n * If no registry is provided, uses the default.\n * Also provides the shared DataSourceProvider from portal-core so that\n * portal-widgets hooks can access baseUrl and getApiHeaders.\n *\n * The DataSourceApi adapter is provided separately via DataSourceApiProvider.\n */\nexport function DataSourceRegistryProvider({\n registry,\n baseUrl,\n getApiHeaders,\n variables,\n children,\n}: DataSourceRegistryProviderProps): React.JSX.Element {\n const value = useMemo(\n () => ({\n registry: registry ?? DEFAULT_DATA_SOURCE_REGISTRY,\n baseUrl,\n getApiHeaders,\n variables,\n }),\n [registry, baseUrl, getApiHeaders, variables],\n );\n\n return (\n <DataSourceRegistryContext.Provider value={value}>\n <DataSourceProvider baseUrl={baseUrl} getApiHeaders={getApiHeaders}>\n {children}\n </DataSourceProvider>\n </DataSourceRegistryContext.Provider>\n );\n}\n\n/**\n * Hook to access the data source registry.\n */\nexport function useDataSourceRegistry(): DataSourceRegistry {\n return useContext(DataSourceRegistryContext).registry;\n}\n\n/**\n * Hook to access the full data source registry context (registry + config).\n */\nexport function useDataSourceRegistryConfig(): DataSourceRegistryContextValue {\n return useContext(DataSourceRegistryContext);\n}\n"],"mappings":"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"}