@wix/auto-patterns 1.27.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/cjs/dataSourceAdapters/cms/fetchCmsData.js +1 -1
  2. package/dist/cjs/dataSourceAdapters/cms/fetchCmsData.js.map +1 -1
  3. package/dist/cjs/hooks/useAutoPatternsOptimisticActions.js +13 -6
  4. package/dist/cjs/hooks/useAutoPatternsOptimisticActions.js.map +1 -1
  5. package/dist/cjs/hooks/useBaseCollectionParams.js +38 -0
  6. package/dist/cjs/hooks/useBaseCollectionParams.js.map +1 -0
  7. package/dist/cjs/hooks/useCommonCollectionFeatures.js +13 -6
  8. package/dist/cjs/hooks/useCommonCollectionFeatures.js.map +1 -1
  9. package/dist/cjs/hooks/useFetchData.js +4 -5
  10. package/dist/cjs/hooks/useFetchData.js.map +1 -1
  11. package/dist/cjs/hooks/useGridFeatures.js +6 -26
  12. package/dist/cjs/hooks/useGridFeatures.js.map +1 -1
  13. package/dist/cjs/hooks/useTableFeatures.js +6 -26
  14. package/dist/cjs/hooks/useTableFeatures.js.map +1 -1
  15. package/dist/cjs/hooks/useTableGridSwitchFeatures.js +8 -28
  16. package/dist/cjs/hooks/useTableGridSwitchFeatures.js.map +1 -1
  17. package/dist/cjs/providers/PatternsWizardOverridesContext.js +1 -1
  18. package/dist/cjs/providers/PatternsWizardOverridesContext.js.map +1 -1
  19. package/dist/cjs/types/CollectionPageConfig.js.map +1 -1
  20. package/dist/cjs/types/fetchData.js +4 -0
  21. package/dist/cjs/types/fetchData.js.map +1 -0
  22. package/dist/cjs/types/index.js +6 -0
  23. package/dist/cjs/types/index.js.map +1 -1
  24. package/dist/cjs/types/types.js.map +1 -1
  25. package/dist/docs/app_config_structure.md +1 -0
  26. package/dist/docs/auto-patterns-guide.md +151 -18
  27. package/dist/docs/custom_overrides.md +1 -15
  28. package/dist/docs/error_handling.md +135 -0
  29. package/dist/docs/index.md +4 -0
  30. package/dist/docs/schema_config.md +11 -3
  31. package/dist/docs/wix_fqdn_custom_data_source.md +49 -7
  32. package/dist/esm/dataSourceAdapters/cms/fetchCmsData.js +1 -1
  33. package/dist/esm/dataSourceAdapters/cms/fetchCmsData.js.map +1 -1
  34. package/dist/esm/hooks/useAutoPatternsOptimisticActions.js +14 -9
  35. package/dist/esm/hooks/useAutoPatternsOptimisticActions.js.map +1 -1
  36. package/dist/esm/hooks/useBaseCollectionParams.js +37 -0
  37. package/dist/esm/hooks/useBaseCollectionParams.js.map +1 -0
  38. package/dist/esm/hooks/useCommonCollectionFeatures.js +9 -2
  39. package/dist/esm/hooks/useCommonCollectionFeatures.js.map +1 -1
  40. package/dist/esm/hooks/useFetchData.js +2 -2
  41. package/dist/esm/hooks/useFetchData.js.map +1 -1
  42. package/dist/esm/hooks/useGridFeatures.js +6 -29
  43. package/dist/esm/hooks/useGridFeatures.js.map +1 -1
  44. package/dist/esm/hooks/useTableFeatures.js +6 -29
  45. package/dist/esm/hooks/useTableFeatures.js.map +1 -1
  46. package/dist/esm/hooks/useTableGridSwitchFeatures.js +8 -31
  47. package/dist/esm/hooks/useTableGridSwitchFeatures.js.map +1 -1
  48. package/dist/esm/providers/PatternsWizardOverridesContext.js.map +1 -1
  49. package/dist/esm/types/CollectionPageConfig.js.map +1 -1
  50. package/dist/esm/types/fetchData.js +2 -0
  51. package/dist/esm/types/fetchData.js.map +1 -0
  52. package/dist/esm/types/index.js +1 -0
  53. package/dist/esm/types/index.js.map +1 -1
  54. package/dist/esm/types/types.js.map +1 -1
  55. package/dist/types/hooks/useAutoPatternsOptimisticActions.d.ts +7 -1
  56. package/dist/types/hooks/useAutoPatternsOptimisticActions.d.ts.map +1 -1
  57. package/dist/types/hooks/useBaseCollectionParams.d.ts +27 -0
  58. package/dist/types/hooks/useBaseCollectionParams.d.ts.map +1 -0
  59. package/dist/types/hooks/useCommonCollectionFeatures.d.ts +4 -3
  60. package/dist/types/hooks/useCommonCollectionFeatures.d.ts.map +1 -1
  61. package/dist/types/hooks/useFetchData.d.ts +3 -13
  62. package/dist/types/hooks/useFetchData.d.ts.map +1 -1
  63. package/dist/types/hooks/useGridFeatures.d.ts +1 -1
  64. package/dist/types/hooks/useGridFeatures.d.ts.map +1 -1
  65. package/dist/types/hooks/useTableFeatures.d.ts +1 -1
  66. package/dist/types/hooks/useTableFeatures.d.ts.map +1 -1
  67. package/dist/types/hooks/useTableGridSwitchFeatures.d.ts +1 -1
  68. package/dist/types/hooks/useTableGridSwitchFeatures.d.ts.map +1 -1
  69. package/dist/types/providers/PatternsWizardOverridesContext.d.ts +2 -1
  70. package/dist/types/providers/PatternsWizardOverridesContext.d.ts.map +1 -1
  71. package/dist/types/types/CollectionPageConfig.d.ts +4 -0
  72. package/dist/types/types/CollectionPageConfig.d.ts.map +1 -1
  73. package/dist/types/types/fetchData.d.ts +21 -0
  74. package/dist/types/types/fetchData.d.ts.map +1 -0
  75. package/dist/types/types/index.d.ts +1 -0
  76. package/dist/types/types/index.d.ts.map +1 -1
  77. package/dist/types/types/types.d.ts +5 -5
  78. package/dist/types/types/types.d.ts.map +1 -1
  79. package/package.json +9 -9
@@ -1 +1 @@
1
- {"version":3,"names":["ComponentTypeEnum","exports"],"sources":["../../../src/types/CollectionPageConfig.ts"],"sourcesContent":["import { CollectionToolbarFiltersProps } from '@wix/patterns';\nimport { DateRangeFilterMode, DateRangeOptions } from '@wix/patterns/core';\nimport { BaseCollectionConfig } from './types';\nimport {\n ActionCellConfig,\n BulkActionsConfig,\n CollectionPageOnRowClickActionConfig,\n CollectionPagePrimaryActions,\n CollectionPageSecondaryActions,\n} from './actions';\n\nexport interface CollectionPageTitle {\n text: string;\n hideTotal?: boolean;\n}\n\nexport interface CollectionPageSubtitle {\n text: string;\n learnMore?: {\n url: string;\n label?: string;\n };\n}\n\nexport interface CollectionPageConfig {\n route: {\n path: string;\n };\n title: CollectionPageTitle;\n subtitle?: CollectionPageSubtitle;\n actions?: {\n primaryActions?: CollectionPagePrimaryActions;\n secondaryActions?: CollectionPageSecondaryActions;\n };\n components: ComponentConfig[];\n}\n\nexport interface CollectionComponentConfig\n extends BaseCollectionComponentConfig {\n type: 'collection';\n layout: LayoutItemConfig[];\n}\n\nexport interface CustomComponentConfig {\n type: 'custom';\n id: string;\n}\n\nexport type ComponentConfig = CollectionComponentConfig | CustomComponentConfig;\n\nexport interface LayoutItemConfig {\n type: 'Table' | 'Grid';\n table?: TableSpecificConfig;\n grid?: GridSpecificConfig;\n}\n\nexport type ColumnsConfig = Column[];\n\nexport interface TableSpecificConfig {\n columns: ColumnsConfig;\n customColumns?: {\n enabled: boolean;\n };\n stickyColumns?: number;\n onRowClick?: CollectionPageOnRowClickActionConfig;\n showTitleBar?: boolean;\n sections?: {\n id: string;\n };\n}\n\nexport interface GridSpecificConfig {\n item: GridItem;\n}\n\nexport interface TableConfig\n extends BaseCollectionComponentConfig,\n TableSpecificConfig {}\nexport interface GridConfig\n extends BaseCollectionComponentConfig,\n GridSpecificConfig {}\nexport interface TableGridSwitchConfig\n extends BaseCollectionComponentConfig,\n TableSpecificConfig,\n GridSpecificConfig {}\n\nexport type CollectionConfig = BaseCollectionConfig & {\n limit?: number;\n reflectQueryInUrl?: boolean;\n selectAllScope?: 'page' | 'all';\n selectionUpdateMode?: 'preserve' | 'clear';\n};\n\nexport interface BaseCollectionComponentConfig {\n collection: CollectionConfig;\n entityPageId?: string;\n search?: { shown?: boolean };\n toolbarTitle?: ToolbarTitle;\n actionCell?: ActionCellConfig;\n emptyState?: EmptyState;\n filters?: FiltersConfig;\n bulkActionToolbar?: BulkActionsConfig;\n}\n\nexport interface ToolbarTitle {\n title: string;\n subtitle?: {\n text: string;\n info?: {\n content: {\n text: string;\n link?: {\n url: string;\n label: string;\n };\n };\n };\n learnMore?: {\n url: string;\n label?: string;\n };\n };\n showTotal?: boolean;\n itemsLimit?: number;\n}\n\nexport interface Column {\n id: string;\n name: string;\n width: string;\n sortable?: boolean;\n defaultSortOrder?: 'asc' | 'desc';\n sortMode?: 'asc' | 'desc';\n defaultHidden?: boolean;\n hiddenFromCustomColumnsSelection?: boolean;\n hideable?: boolean;\n reorderDisabled?: boolean;\n}\n\nexport interface GridItem {\n titleFieldId: string;\n subtitleFieldId?: string;\n imageFieldId?: string;\n cardContentMode?: 'full' | 'title' | 'empty'; // Footer is not supported in auto-patterns\n imagePlacement?: 'top' | 'side';\n}\n\nexport interface EmptyState {\n title?: string;\n subtitle?: string;\n image?: {\n id: string;\n };\n addNewCta?: {\n id?: string;\n text?: string;\n };\n customCta?: {\n id?: string;\n };\n}\n\nexport interface FilterOption {\n value: string;\n label: string;\n}\n\nexport type FilterSelectionMode = 'single' | 'multiple';\nexport type FilterOptionType =\n | 'checkbox'\n | 'inlineCheckbox'\n | 'radio'\n | 'select';\n\nexport enum ComponentTypeEnum {\n SINGLE = 'single',\n MULTI_SELECT = 'multi-select',\n RADIO_GROUP = 'radio-group',\n NUMBER = 'number',\n DATE_RANGE = 'date-range',\n}\n\nexport type FilterItems = Filter[];\nexport interface FiltersConfig {\n items: FilterItems;\n maxInlineFilters?: CollectionToolbarFiltersProps['inline'];\n panelTitle?: string;\n}\n\nexport interface BaseOptionsFilterConfig {\n selectionMode: FilterSelectionMode;\n}\n\nexport interface DateFilterConfig {\n mode?: DateRangeFilterMode;\n presets?: DateRangeOptions;\n includeTime?: boolean;\n}\n\nexport interface NumberFilterConfig {\n min?: number;\n max?: number;\n allowedDecimals?: boolean;\n}\n\nexport interface BooleanFilterConfig {\n trueLabel?: string;\n falseLabel?: string;\n}\n\nexport interface EnumFilterConfig extends BaseOptionsFilterConfig {\n options: FilterOption[];\n optionType?: FilterOptionType;\n}\n\nexport interface DynamicOptionsFilterConfig extends BaseOptionsFilterConfig {}\n\nexport interface Filter {\n id: string;\n fieldId: string;\n displayName?: string;\n sectionTitle?: string;\n openByDefault?: boolean;\n tagLabel?: string;\n numberConfig?: NumberFilterConfig;\n dateConfig?: DateFilterConfig;\n booleanConfig?: BooleanFilterConfig;\n enumConfig?: EnumFilterConfig;\n dynamicOptionsConfig?: DynamicOptionsFilterConfig;\n}\n"],"mappings":";;;;IA8KYA,iBAAiB,GAAAC,OAAA,CAAAD,iBAAA,0BAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAA,OAAjBA,iBAAiB;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["ComponentTypeEnum","exports"],"sources":["../../../src/types/CollectionPageConfig.ts"],"sourcesContent":["import { CollectionToolbarFiltersProps } from '@wix/patterns';\nimport { DateRangeFilterMode, DateRangeOptions } from '@wix/patterns/core';\nimport { BaseCollectionConfig } from './types';\nimport {\n ActionCellConfig,\n BulkActionsConfig,\n CollectionPageOnRowClickActionConfig,\n CollectionPagePrimaryActions,\n CollectionPageSecondaryActions,\n} from './actions';\n\nexport interface CollectionPageTitle {\n text: string;\n hideTotal?: boolean;\n}\n\nexport interface CollectionPageSubtitle {\n text: string;\n learnMore?: {\n url: string;\n label?: string;\n };\n}\n\nexport interface CollectionPageConfig {\n route: {\n path: string;\n };\n title: CollectionPageTitle;\n subtitle?: CollectionPageSubtitle;\n actions?: {\n primaryActions?: CollectionPagePrimaryActions;\n secondaryActions?: CollectionPageSecondaryActions;\n };\n components: ComponentConfig[];\n}\n\nexport interface CollectionComponentConfig\n extends BaseCollectionComponentConfig {\n type: 'collection';\n layout: LayoutItemConfig[];\n}\n\nexport interface CustomComponentConfig {\n type: 'custom';\n id: string;\n}\n\nexport type ComponentConfig = CollectionComponentConfig | CustomComponentConfig;\n\nexport interface LayoutItemConfig {\n type: 'Table' | 'Grid';\n table?: TableSpecificConfig;\n grid?: GridSpecificConfig;\n}\n\nexport type ColumnsConfig = Column[];\n\nexport interface TableSpecificConfig {\n columns: ColumnsConfig;\n customColumns?: {\n enabled: boolean;\n };\n stickyColumns?: number;\n onRowClick?: CollectionPageOnRowClickActionConfig;\n showTitleBar?: boolean;\n sections?: {\n id: string;\n };\n}\n\nexport interface GridSpecificConfig {\n item: GridItem;\n}\n\nexport interface TableConfig\n extends BaseCollectionComponentConfig,\n TableSpecificConfig {}\nexport interface GridConfig\n extends BaseCollectionComponentConfig,\n GridSpecificConfig {}\nexport interface TableGridSwitchConfig\n extends BaseCollectionComponentConfig,\n TableSpecificConfig,\n GridSpecificConfig {}\n\nexport type CollectionConfig = BaseCollectionConfig & {\n limit?: number;\n reflectQueryInUrl?: boolean;\n selectAllScope?: 'page' | 'all';\n selectionUpdateMode?: 'preserve' | 'clear';\n optimisticActions?: {\n id: string;\n };\n paginationMode?: 'cursor' | 'offset';\n};\n\nexport interface BaseCollectionComponentConfig {\n collection: CollectionConfig;\n entityPageId?: string;\n search?: { shown?: boolean };\n toolbarTitle?: ToolbarTitle;\n actionCell?: ActionCellConfig;\n emptyState?: EmptyState;\n filters?: FiltersConfig;\n bulkActionToolbar?: BulkActionsConfig;\n}\n\nexport interface ToolbarTitle {\n title: string;\n subtitle?: {\n text: string;\n info?: {\n content: {\n text: string;\n link?: {\n url: string;\n label: string;\n };\n };\n };\n learnMore?: {\n url: string;\n label?: string;\n };\n };\n showTotal?: boolean;\n itemsLimit?: number;\n}\n\nexport interface Column {\n id: string;\n name: string;\n width: string;\n sortable?: boolean;\n defaultSortOrder?: 'asc' | 'desc';\n sortMode?: 'asc' | 'desc';\n defaultHidden?: boolean;\n hiddenFromCustomColumnsSelection?: boolean;\n hideable?: boolean;\n reorderDisabled?: boolean;\n}\n\nexport interface GridItem {\n titleFieldId: string;\n subtitleFieldId?: string;\n imageFieldId?: string;\n cardContentMode?: 'full' | 'title' | 'empty'; // Footer is not supported in auto-patterns\n imagePlacement?: 'top' | 'side';\n}\n\nexport interface EmptyState {\n title?: string;\n subtitle?: string;\n image?: {\n id: string;\n };\n addNewCta?: {\n id?: string;\n text?: string;\n };\n customCta?: {\n id?: string;\n };\n}\n\nexport interface FilterOption {\n value: string;\n label: string;\n}\n\nexport type FilterSelectionMode = 'single' | 'multiple';\nexport type FilterOptionType =\n | 'checkbox'\n | 'inlineCheckbox'\n | 'radio'\n | 'select';\n\nexport enum ComponentTypeEnum {\n SINGLE = 'single',\n MULTI_SELECT = 'multi-select',\n RADIO_GROUP = 'radio-group',\n NUMBER = 'number',\n DATE_RANGE = 'date-range',\n}\n\nexport type FilterItems = Filter[];\nexport interface FiltersConfig {\n items: FilterItems;\n maxInlineFilters?: CollectionToolbarFiltersProps['inline'];\n panelTitle?: string;\n}\n\nexport interface BaseOptionsFilterConfig {\n selectionMode: FilterSelectionMode;\n}\n\nexport interface DateFilterConfig {\n mode?: DateRangeFilterMode;\n presets?: DateRangeOptions;\n includeTime?: boolean;\n}\n\nexport interface NumberFilterConfig {\n min?: number;\n max?: number;\n allowedDecimals?: boolean;\n}\n\nexport interface BooleanFilterConfig {\n trueLabel?: string;\n falseLabel?: string;\n}\n\nexport interface EnumFilterConfig extends BaseOptionsFilterConfig {\n options: FilterOption[];\n optionType?: FilterOptionType;\n}\n\nexport interface DynamicOptionsFilterConfig extends BaseOptionsFilterConfig {}\n\nexport interface Filter {\n id: string;\n fieldId: string;\n displayName?: string;\n sectionTitle?: string;\n openByDefault?: boolean;\n tagLabel?: string;\n numberConfig?: NumberFilterConfig;\n dateConfig?: DateFilterConfig;\n booleanConfig?: BooleanFilterConfig;\n enumConfig?: EnumFilterConfig;\n dynamicOptionsConfig?: DynamicOptionsFilterConfig;\n}\n"],"mappings":";;;;IAkLYA,iBAAiB,GAAAC,OAAA,CAAAD,iBAAA,0BAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAjBA,iBAAiB;EAAA,OAAjBA,iBAAiB;AAAA","ignoreList":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ //# sourceMappingURL=fetchData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["../../../src/types/fetchData.ts"],"sourcesContent":["import { CursorQuery, OffsetQuery } from '@wix/patterns';\n\nexport type Mode = 'cursor' | 'offset';\n\nexport type UseFetchDataProps<M extends Mode> = {\n searchableFieldIds?: string[];\n filterFieldMapping?: Record<string, { fieldId: string }>;\n paginationMode?: M;\n};\n\nexport interface CursorQueryResult {\n items: any[];\n cursor?: string | undefined | null;\n total?: number | null;\n}\n\nexport interface OffsetQueryResult {\n items: any[];\n total?: number | null;\n hasNext?: boolean;\n}\n\nexport type FetchDataFn<M extends Mode> = M extends 'cursor'\n ? (q: CursorQuery<any>) => Promise<CursorQueryResult>\n : (q: OffsetQuery<any>) => Promise<OffsetQueryResult>;\n"],"mappings":"","ignoreList":[]}
@@ -43,4 +43,10 @@ Object.keys(_BaseSDK).forEach(function (key) {
43
43
  if (key in exports && exports[key] === _BaseSDK[key]) return;
44
44
  exports[key] = _BaseSDK[key];
45
45
  });
46
+ var _fetchData = require("./fetchData");
47
+ Object.keys(_fetchData).forEach(function (key) {
48
+ if (key === "default" || key === "__esModule") return;
49
+ if (key in exports && exports[key] === _fetchData[key]) return;
50
+ exports[key] = _fetchData[key];
51
+ });
46
52
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_types","require","Object","keys","forEach","key","exports","_CollectionPageConfig","_EntityPageConfig","_providers","_actions","_types2","_BaseSDK"],"sources":["../../../src/types/index.ts"],"sourcesContent":["export * from './types';\nexport * from './CollectionPageConfig';\nexport * from './EntityPageConfig';\nexport * from './providers';\nexport * from './actions';\nexport * from '../utils/actions/types';\nexport * from './BaseSDK';\n"],"mappings":";;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,MAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,qBAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,qBAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,qBAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,qBAAA,CAAAF,GAAA;AAAA;AACA,IAAAG,iBAAA,GAAAP,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAK,iBAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAG,iBAAA,CAAAH,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAG,iBAAA,CAAAH,GAAA;AAAA;AACA,IAAAI,UAAA,GAAAR,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAM,UAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAI,UAAA,CAAAJ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAI,UAAA,CAAAJ,GAAA;AAAA;AACA,IAAAK,QAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,QAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,QAAA,CAAAL,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAK,QAAA,CAAAL,GAAA;AAAA;AACA,IAAAM,OAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,OAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,OAAA,CAAAN,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAM,OAAA,CAAAN,GAAA;AAAA;AACA,IAAAO,QAAA,GAAAX,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAS,QAAA,EAAAR,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,QAAA,CAAAP,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAO,QAAA,CAAAP,GAAA;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["_types","require","Object","keys","forEach","key","exports","_CollectionPageConfig","_EntityPageConfig","_providers","_actions","_types2","_BaseSDK","_fetchData"],"sources":["../../../src/types/index.ts"],"sourcesContent":["export * from './types';\nexport * from './CollectionPageConfig';\nexport * from './EntityPageConfig';\nexport * from './providers';\nexport * from './actions';\nexport * from '../utils/actions/types';\nexport * from './BaseSDK';\nexport * from './fetchData';\n"],"mappings":";;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAH,MAAA,EAAAI,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAL,MAAA,CAAAK,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAL,MAAA,CAAAK,GAAA;AAAA;AACA,IAAAE,qBAAA,GAAAN,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAI,qBAAA,EAAAH,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAE,qBAAA,CAAAF,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAE,qBAAA,CAAAF,GAAA;AAAA;AACA,IAAAG,iBAAA,GAAAP,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAK,iBAAA,EAAAJ,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAG,iBAAA,CAAAH,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAG,iBAAA,CAAAH,GAAA;AAAA;AACA,IAAAI,UAAA,GAAAR,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAM,UAAA,EAAAL,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAI,UAAA,CAAAJ,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAI,UAAA,CAAAJ,GAAA;AAAA;AACA,IAAAK,QAAA,GAAAT,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAO,QAAA,EAAAN,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,QAAA,CAAAL,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAK,QAAA,CAAAL,GAAA;AAAA;AACA,IAAAM,OAAA,GAAAV,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAQ,OAAA,EAAAP,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,OAAA,CAAAN,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAM,OAAA,CAAAN,GAAA;AAAA;AACA,IAAAO,QAAA,GAAAX,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAS,QAAA,EAAAR,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,QAAA,CAAAP,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAO,QAAA,CAAAP,GAAA;AAAA;AACA,IAAAQ,UAAA,GAAAZ,OAAA;AAAAC,MAAA,CAAAC,IAAA,CAAAU,UAAA,EAAAT,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAQ,UAAA,CAAAR,GAAA;EAAAC,OAAA,CAAAD,GAAA,IAAAQ,UAAA,CAAAR,GAAA;AAAA","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["../../../src/types/types.ts"],"sourcesContent":["import { EntityPageConfig } from './EntityPageConfig';\nimport { CollectionPageConfig } from './CollectionPageConfig';\n\ninterface BaseCollectionConfigCommon {\n collectionId: string;\n}\n\ninterface CMSCollectionConfig extends BaseCollectionConfigCommon {\n entityTypeSource: 'cms';\n custom?: never;\n}\n\ninterface CustomCollectionConfig extends BaseCollectionConfigCommon {\n entityTypeSource: 'custom';\n custom: {\n id: string;\n };\n}\n\nexport type BaseCollectionConfig = CMSCollectionConfig | CustomCollectionConfig;\n\nexport type PatternsFieldType =\n | 'SHORT_TEXT'\n | 'LONG_TEXT'\n | 'NUMBER'\n | 'BOOLEAN'\n | 'DATE'\n | 'DATETIME'\n | 'URL'\n | 'ARRAY'\n | 'REFERENCE'\n | 'IMAGE';\n\nexport interface AppConfig {\n pages: PageConfig[];\n layout?: 'panel';\n}\n\nexport interface BasePageConfig {\n id: string;\n appMainPage?: boolean;\n}\n\nexport interface CollectionPageConfigType extends BasePageConfig {\n type: 'collectionPage';\n collectionPage: CollectionPageConfig;\n entityPage?: never;\n}\n\nexport interface EntityPageConfigType extends BasePageConfig {\n type: 'entityPage';\n entityPage: EntityPageConfig;\n collectionPage?: never;\n}\n\nexport type PageConfig = CollectionPageConfigType | EntityPageConfigType;\n\nexport type EntityProps = { [key: string]: any };\n\nexport interface IMenuItem<T extends EntityProps = any> {\n item: T;\n}\nexport interface IColumnValue<T> {\n value: T;\n row: Record<string, any>;\n}\n\nexport type QueryOperator =\n | 'CONTAINS'\n | 'ENDS_WITH'\n | 'EQ'\n | 'EXISTS'\n | 'GT'\n | 'GTE'\n | 'HAS_ALL'\n | 'HAS_SOME'\n | 'LT'\n | 'LTE'\n | 'NE'\n | 'STARTS_WITH'\n | 'URLIZED';\n\ninterface BaseField {\n id: string;\n displayName: string;\n validation?: {\n numberRange?: NumberRange;\n stringLengthRange?: StringLengthRange;\n required: boolean;\n };\n capabilities: {\n supportedQueryOperators: QueryOperator[];\n sortable: boolean;\n };\n}\n\nexport interface ReferenceField extends BaseField {\n type: 'REFERENCE';\n referenceMetadata: {\n referencedCollectionId: string;\n };\n}\n\nexport interface NonReferenceField extends BaseField {\n type: Exclude<PatternsFieldType, 'REFERENCE'>;\n}\n\nexport type Field = ReferenceField | NonReferenceField;\n\nexport interface NumberRange {\n min?: number;\n max?: number;\n}\nexport interface StringLengthRange {\n minLength?: number;\n maxLength?: number;\n}\n\nexport interface Query {\n limit: number;\n offset: number;\n page: number;\n search?: string;\n cursor?: string | null;\n filters: Record<string, any>;\n sort?: {\n fieldName: string;\n order: 'asc' | 'desc';\n }[];\n}\n\nexport interface SchemaConfig {\n id: string;\n fields: Record<string, Field | undefined>;\n displayField: string;\n idField: string;\n actions: {\n get: (entityId: string) => Promise<any>;\n create: (newEntity: Partial<any>) => Promise<any>;\n update: (updatedEntity: any) => Promise<any>;\n delete: (entityId: string) => Promise<any>;\n bulkDelete: (entityIds: string[]) => Promise<any>;\n find: (\n query: Query,\n options?: {\n searchableFieldIds?: string[];\n filterFieldMapping?: Record<string, { fieldId: string }>;\n },\n ) => Promise<{ items: any[]; total: number }>;\n };\n}\n"],"mappings":"","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["../../../src/types/types.ts"],"sourcesContent":["import { EntityPageConfig } from './EntityPageConfig';\nimport { CollectionPageConfig } from './CollectionPageConfig';\nimport { useOptimisticActions } from '@wix/patterns';\nimport { CursorQueryResult, OffsetQueryResult } from './fetchData';\n\ninterface BaseCollectionConfigCommon {\n collectionId: string;\n}\n\ninterface CMSCollectionConfig extends BaseCollectionConfigCommon {\n entityTypeSource: 'cms';\n custom?: never;\n}\n\ninterface CustomCollectionConfig extends BaseCollectionConfigCommon {\n entityTypeSource: 'custom';\n custom: {\n id: string;\n };\n}\n\nexport type BaseCollectionConfig = CMSCollectionConfig | CustomCollectionConfig;\n\nexport type PatternsFieldType =\n | 'SHORT_TEXT'\n | 'LONG_TEXT'\n | 'NUMBER'\n | 'BOOLEAN'\n | 'DATE'\n | 'DATETIME'\n | 'URL'\n | 'ARRAY'\n | 'REFERENCE'\n | 'IMAGE';\n\nexport interface AppConfig {\n pages: PageConfig[];\n layout?: 'panel';\n}\n\nexport interface BasePageConfig {\n id: string;\n appMainPage?: boolean;\n}\n\nexport interface CollectionPageConfigType extends BasePageConfig {\n type: 'collectionPage';\n collectionPage: CollectionPageConfig;\n entityPage?: never;\n}\n\nexport interface EntityPageConfigType extends BasePageConfig {\n type: 'entityPage';\n entityPage: EntityPageConfig;\n collectionPage?: never;\n}\n\nexport type PageConfig = CollectionPageConfigType | EntityPageConfigType;\n\nexport type EntityProps = { [key: string]: any };\n\nexport interface IMenuItem<T extends EntityProps = any> {\n item: T;\n}\nexport interface IColumnValue<T> {\n value: T;\n row: Record<string, any>;\n}\n\nexport type QueryOperator =\n | 'CONTAINS'\n | 'ENDS_WITH'\n | 'EQ'\n | 'EXISTS'\n | 'GT'\n | 'GTE'\n | 'HAS_ALL'\n | 'HAS_SOME'\n | 'LT'\n | 'LTE'\n | 'NE'\n | 'STARTS_WITH'\n | 'URLIZED';\n\ninterface BaseField {\n id: string;\n displayName: string;\n validation?: {\n numberRange?: NumberRange;\n stringLengthRange?: StringLengthRange;\n required: boolean;\n };\n capabilities: {\n supportedQueryOperators: QueryOperator[];\n sortable: boolean;\n };\n}\n\nexport interface ReferenceField extends BaseField {\n type: 'REFERENCE';\n referenceMetadata: {\n referencedCollectionId: string;\n };\n}\n\nexport interface NonReferenceField extends BaseField {\n type: Exclude<PatternsFieldType, 'REFERENCE'>;\n}\n\nexport type Field = ReferenceField | NonReferenceField;\n\nexport interface NumberRange {\n min?: number;\n max?: number;\n}\nexport interface StringLengthRange {\n minLength?: number;\n maxLength?: number;\n}\n\nexport interface Query {\n limit: number;\n offset?: number;\n page: number;\n search?: string;\n cursor?: string | null;\n filters: Record<string, any>;\n sort?: {\n fieldName: string;\n order: 'asc' | 'desc';\n }[];\n}\nexport interface SchemaConfig {\n id: string;\n fields: Record<string, Field | undefined>;\n displayField: string;\n idField: string;\n actions: {\n get: (entityId: string) => Promise<any>;\n create: (newEntity: Partial<any>) => Promise<any>;\n update: (updatedEntity: any) => Promise<any>;\n delete: (entityId: string) => Promise<any>;\n bulkDelete: (entityIds: string[]) => Promise<any>;\n find: (\n query: Query,\n options?: {\n searchableFieldIds?: string[];\n filterFieldMapping?: Record<string, { fieldId: string }>;\n },\n ) => Promise<CursorQueryResult | OffsetQueryResult>;\n };\n}\n\nexport type OptimisticActionsParams = Parameters<\n typeof useOptimisticActions\n>[1];\n"],"mappings":"","ignoreList":[]}
@@ -89,6 +89,7 @@ export interface AppConfig {
89
89
  reflectQueryInUrl?: boolean; // Reflects query state (search, filters, sorting) in the browser URL. Default: false
90
90
  selectAllScope?: 'page' | 'all'; // Controls "Select All" scope. 'all' selects entire collection, 'page' selects only visible items. Default: 'all'
91
91
  selectionUpdateMode?: 'preserve' | 'clear'; // Controls selection behavior when data changes. 'preserve' maintains selections, 'clear' clears them. Default: 'clear'
92
+ paginationMode?: 'cursor' | 'offset'; // Controls pagination strategy and expected find() return shape. 'cursor' => { items, cursor, total? }, 'offset' (default) => { items, hasNext, total? }
92
93
  };
93
94
  filters?: {
94
95
  panelTitle?: string; // Title of the filters panel
@@ -167,6 +167,7 @@ export interface AppConfig {
167
167
  reflectQueryInUrl?: boolean; // Reflects query state (search, filters, sorting) in the browser URL. Default: false
168
168
  selectAllScope?: 'page' | 'all'; // Controls "Select All" scope. 'all' selects entire collection, 'page' selects only visible items. Default: 'all'
169
169
  selectionUpdateMode?: 'preserve' | 'clear'; // Controls selection behavior when data changes. 'preserve' maintains selections, 'clear' clears them. Default: 'clear'
170
+ paginationMode?: 'cursor' | 'offset'; // Controls pagination strategy and expected find() return shape. 'cursor' => { items, cursor, total? }, 'offset' (default) => { items, hasNext, total? }
170
171
  };
171
172
  filters?: {
172
173
  panelTitle?: string; // Title of the filters panel
@@ -1235,19 +1236,25 @@ export interface SchemaConfig {
1235
1236
  update: (updatedEntity: any) => Promise<any>;
1236
1237
  delete: (entityId: string) => Promise<any>;
1237
1238
  bulkDelete: (entityIds: string[]) => Promise<any>;
1239
+ // The return shape depends on pagination mode (see AppConfig.collection.paginationMode)
1240
+ // - Cursor mode: { items, cursor, total? }
1241
+ // - Offset mode (default): { items, hasNext, total? }
1238
1242
  find: (
1239
1243
  query: Query,
1240
1244
  options?: {
1241
1245
  searchableFieldIds?: string[];
1242
1246
  filterFieldMapping?: Record<string, { fieldId: string }>;
1243
1247
  },
1244
- ) => Promise<{ items: any[]; total: number }>;
1248
+ ) => Promise<
1249
+ | { items: any[]; cursor?: string | null; total?: number | null }
1250
+ | { items: any[]; hasNext?: boolean; total?: number | null }
1251
+ >;
1245
1252
  };
1246
1253
  }
1247
1254
 
1248
1255
  export interface Query {
1249
1256
  limit: number; // Maximum number of items to return per request (controls page size)
1250
- offset: number; // Number of items to skip from the beginning (for pagination)
1257
+ offset?: number; // Number of items to skip from the beginning (for pagination)
1251
1258
  page: number; // Current page number (1-based, works with limit for pagination)
1252
1259
  search?: string; // Text search query applied to searchable fields
1253
1260
  cursor?: string | null; // Cursor-based pagination token (alternative to offset-based pagination)
@@ -1346,7 +1353,9 @@ export type Field = ReferenceField | NonReferenceField;
1346
1353
  - `query`: Query object with pagination, filtering, sorting, and search criteria (see Query Interface section)
1347
1354
  - `options.searchableFieldIds`: Array of field IDs that support text search
1348
1355
  - `options.filterFieldMapping`: Maps filter IDs to actual field IDs for complex filtering
1349
- - Returns: `{ items: any[], total: number }`
1356
+ - Returns (depends on pagination mode):
1357
+ - Cursor mode: `{ items: any[]; cursor?: string | null; total?: number | null }`
1358
+ - Offset mode (default): `{ items: any[]; hasNext?: boolean; total?: number | null }`
1350
1359
 
1351
1360
  ### Field Type Information
1352
1361
 
@@ -2833,6 +2842,7 @@ export default withDashboard(Index);
2833
2842
 
2834
2843
  - **Custom overrides are restricted to the defined areas only** - attempting to override or modify any other aspect of `AutoPatternsApp` is prohibited and can cause unexpected behavior
2835
2844
  - **Always verify override implementation** - when implementing custom overrides, you MUST ensure they are correctly imported and passed to the `PatternsWizardOverridesProvider`
2845
+ - **CRITICAL: Error handling for custom actions** - Custom actions that make external API calls (using `fetch()`, `axios`, etc.) should NOT use `errorHandler.withErrorHandler`. Only Wix HTTP requests (httpClient from @wix/essentials, Wix APIs like wix/data and wix/stores, and httpClient.fetchWithAuth()) require errorHandler wrapping. See the "Error Handling for HTTP Requests" section for details.
2836
2846
 
2837
2847
  The `PatternsWizardOverridesProvider` allows you to inject custom code to override default behaviors or add additional functionality. Below are the areas where overrides can be applied:
2838
2848
 
@@ -3639,22 +3649,7 @@ When implementing custom data sources, you need to map your data source field ty
3639
3649
  - **Reference fields** → `'REFERENCE'`
3640
3650
  - **URL fields** → `'URL'`
3641
3651
 
3642
- ### Error Handling
3643
3652
 
3644
- Custom data sources should include proper error handling:
3645
-
3646
- ```tsx
3647
- actions: {
3648
- get: async (entityId: string) => {
3649
- try {
3650
- const result = await yourDataSourceCall(entityId);
3651
- return result;
3652
- } catch (error) {
3653
- throw new Error(`Failed to fetch entity: ${error.message}`);
3654
- }
3655
- }
3656
- }
3657
- ```
3658
3653
 
3659
3654
  ### Validation Requirements
3660
3655
 
@@ -4001,3 +3996,141 @@ export default function YourPage() {
4001
3996
  Slots provide a powerful way to enhance collection pages with custom functionality while maintaining the structure and features of the AutoPatterns system.
4002
3997
 
4003
3998
  ---
3999
+
4000
+ # Error Handling for HTTP Requests
4001
+
4002
+ **⚠️ CRITICAL**: When implementing custom data sources that make HTTP requests, you **MUST** wrap specific HTTP calls with proper error handling. This ensures consistent error management, prevents unhandled promise rejections, and provides better user experience.
4003
+
4004
+ ## What Requires Error Handling
4005
+
4006
+ **ONLY the following HTTP requests** in your custom data source actions must be wrapped with `errorHandler`:
4007
+
4008
+ - **httpClient from @wix/essentials** (e.g., `httpClient.request(getDummyEntity(...))`)
4009
+ - **Wix APIs** (e.g., `wix/data`, `wix/stores`, `items.get()`, `items.insert()`, `collections.getDataCollection()`)
4010
+ - **httpClient.fetchWithAuth()** calls
4011
+
4012
+ **DO NOT use errorHandler with:**
4013
+
4014
+ - **External API calls** using `fetch()`, `axios.get()`, or other HTTP libraries
4015
+ - **Custom HTTP clients** (e.g., any non-Wix HTTP request library)
4016
+ - **Third-party API calls** using non-Wix HTTP methods
4017
+
4018
+ **EXCEPTION**: SDK actions that you get from the AutoPatterns SDK (e.g., `sdk.getOptimisticActions()`, `sdk.getSchema()`) do NOT need error handling as they are already handled internally.
4019
+
4020
+ ## Why Error Handling is Required
4021
+
4022
+ Custom data sources often make HTTP requests to Wix APIs and services. Without proper error handling:
4023
+
4024
+ - **Unhandled Promise Rejections**: HTTP failures can crash your application
4025
+ - **Poor User Experience**: Users don't get meaningful error messages
4026
+ - **Inconsistent Error Management**: Different parts of your app handle errors differently
4027
+ - **Debugging Difficulties**: Hard to trace and diagnose API failures
4028
+
4029
+ ## Using @wix/essentials errorHandler
4030
+
4031
+ The recommended approach is to use the `errorHandler` from `@wix/essentials` package, which provides consistent error handling patterns across Wix applications.
4032
+
4033
+ ### Installation
4034
+
4035
+ First, ensure `@wix/essentials` is installed in your project:
4036
+
4037
+ ```bash
4038
+ npm install @wix/essentials
4039
+ ```
4040
+
4041
+ ### Basic Error Handling Pattern
4042
+
4043
+ Wrap Wix HTTP requests in your custom data source actions with `errorHandler.withErrorHandler`:
4044
+
4045
+ ```typescript
4046
+ import { errorHandler } from '@wix/essentials';
4047
+
4048
+ // In your custom data source actions
4049
+ actions: {
4050
+ get: async (entityId: string) => {
4051
+ return errorHandler.withErrorHandler(
4052
+ async () => {
4053
+ const response = await httpClient.request(
4054
+ getDummyEntity({ dummyEntityId: entityId })
4055
+ );
4056
+ return response.data.dummyEntity;
4057
+ },
4058
+ {}
4059
+ );
4060
+ },
4061
+ }
4062
+ ```
4063
+
4064
+ ### Examples of HTTP Requests That Need Error Handling
4065
+
4066
+ **httpClient from @wix/essentials:**
4067
+
4068
+ ```typescript
4069
+ return errorHandler.withErrorHandler(async () => {
4070
+ const response = await httpClient.request(
4071
+ getDummyEntity({ dummyEntityId: entityId })
4072
+ );
4073
+ return response.data.dummyEntity;
4074
+ }, {});
4075
+ ```
4076
+
4077
+ **Wix APIs (wix/data, wix/stores):**
4078
+
4079
+ ```typescript
4080
+ return errorHandler.withErrorHandler(async () => {
4081
+ return await items.get(collectionId, entityId);
4082
+ }, {});
4083
+ ```
4084
+
4085
+ **httpClient.fetchWithAuth() calls:**
4086
+
4087
+ ```typescript
4088
+ return errorHandler.withErrorHandler(async () => {
4089
+ const response = await httpClient.fetchWithAuth("/api/data");
4090
+ return await response.json();
4091
+ }, {});
4092
+ ```
4093
+
4094
+ ### Examples of HTTP Requests That Do NOT Need Error Handling
4095
+
4096
+ **External API calls (using fetch, axios, etc.):**
4097
+
4098
+ ```typescript
4099
+ // ✅ CORRECT - No error handling needed for external APIs
4100
+ const response = await fetch("https://api.example.com/data");
4101
+ return await response.json();
4102
+
4103
+ // ✅ CORRECT - No error handling needed for axios
4104
+ const response = await axios.get("https://api.example.com/data");
4105
+ return response.data;
4106
+ ```
4107
+
4108
+ **Third-party HTTP libraries:**
4109
+
4110
+ ```typescript
4111
+ // ✅ CORRECT - No error handling needed for third-party HTTP clients
4112
+ const response = await someThirdPartyHttpClient.get("/data");
4113
+ return response.data;
4114
+ ```
4115
+
4116
+ ## Integration with AutoPatterns Error Handling
4117
+
4118
+ The error handling in your custom data source integrates seamlessly with AutoPatterns' built-in error handling:
4119
+
4120
+ 1. **User-Friendly Messages**: Errors are displayed to users in a consistent format
4121
+ 2. **Retry Mechanisms**: Users can retry failed operations
4122
+ 3. **Loading States**: Proper loading states during HTTP requests
4123
+ 4. **Error Boundaries**: Errors are caught and handled gracefully
4124
+
4125
+ ## Validation Checklist
4126
+
4127
+ Before deploying your custom data source, ensure:
4128
+
4129
+ ✅ **httpClient from @wix/essentials** is wrapped with `errorHandler.withErrorHandler`
4130
+ ✅ **Wix APIs (wix/data, wix/stores, etc)** are wrapped with `errorHandler.withErrorHandler`
4131
+ ✅ **httpClient.fetchWithAuth()** calls are wrapped with `errorHandler.withErrorHandler`
4132
+ ✅ **External API calls are NOT wrapped** with errorHandler (e.g., fetch(), axios, third-party HTTP clients)
4133
+ ✅ **SDK actions are used directly** without error handling (e.g., `sdk.getOptimisticActions()`, `sdk.getSchema()`)
4134
+ ✅ **@wix/essentials** is installed as a dependency
4135
+
4136
+ ---
@@ -4,6 +4,7 @@
4
4
 
5
5
  - **Custom overrides are restricted to the defined areas only** - attempting to override or modify any other aspect of `AutoPatternsApp` is prohibited and can cause unexpected behavior
6
6
  - **Always verify override implementation** - when implementing custom overrides, you MUST ensure they are correctly imported and passed to the `PatternsWizardOverridesProvider`
7
+ - **CRITICAL: Error handling for custom actions** - Custom actions that make external API calls (using `fetch()`, `axios`, etc.) should NOT use `errorHandler.withErrorHandler`. Only Wix HTTP requests (httpClient from @wix/essentials, Wix APIs like wix/data and wix/stores, and httpClient.fetchWithAuth()) require errorHandler wrapping. See the "Error Handling for HTTP Requests" section for details.
7
8
 
8
9
  The `PatternsWizardOverridesProvider` allows you to inject custom code to override default behaviors or add additional functionality. Below are the areas where overrides can be applied:
9
10
 
@@ -810,22 +811,7 @@ When implementing custom data sources, you need to map your data source field ty
810
811
  - **Reference fields** → `'REFERENCE'`
811
812
  - **URL fields** → `'URL'`
812
813
 
813
- ### Error Handling
814
814
 
815
- Custom data sources should include proper error handling:
816
-
817
- ```tsx
818
- actions: {
819
- get: async (entityId: string) => {
820
- try {
821
- const result = await yourDataSourceCall(entityId);
822
- return result;
823
- } catch (error) {
824
- throw new Error(`Failed to fetch entity: ${error.message}`);
825
- }
826
- }
827
- }
828
- ```
829
815
 
830
816
  ### Validation Requirements
831
817
 
@@ -0,0 +1,135 @@
1
+ # Error Handling for HTTP Requests
2
+
3
+ **⚠️ CRITICAL**: When implementing custom data sources that make HTTP requests, you **MUST** wrap specific HTTP calls with proper error handling. This ensures consistent error management, prevents unhandled promise rejections, and provides better user experience.
4
+
5
+ ## What Requires Error Handling
6
+
7
+ **ONLY the following HTTP requests** in your custom data source actions must be wrapped with `errorHandler`:
8
+
9
+ - **httpClient from @wix/essentials** (e.g., `httpClient.request(getDummyEntity(...))`)
10
+ - **Wix APIs** (e.g., `wix/data`, `wix/stores`, `items.get()`, `items.insert()`, `collections.getDataCollection()`)
11
+ - **httpClient.fetchWithAuth()** calls
12
+
13
+ **DO NOT use errorHandler with:**
14
+
15
+ - **External API calls** using `fetch()`, `axios.get()`, or other HTTP libraries
16
+ - **Custom HTTP clients** (e.g., any non-Wix HTTP request library)
17
+ - **Third-party API calls** using non-Wix HTTP methods
18
+
19
+ **EXCEPTION**: SDK actions that you get from the AutoPatterns SDK (e.g., `sdk.getOptimisticActions()`, `sdk.getSchema()`) do NOT need error handling as they are already handled internally.
20
+
21
+ ## Why Error Handling is Required
22
+
23
+ Custom data sources often make HTTP requests to Wix APIs and services. Without proper error handling:
24
+
25
+ - **Unhandled Promise Rejections**: HTTP failures can crash your application
26
+ - **Poor User Experience**: Users don't get meaningful error messages
27
+ - **Inconsistent Error Management**: Different parts of your app handle errors differently
28
+ - **Debugging Difficulties**: Hard to trace and diagnose API failures
29
+
30
+ ## Using @wix/essentials errorHandler
31
+
32
+ The recommended approach is to use the `errorHandler` from `@wix/essentials` package, which provides consistent error handling patterns across Wix applications.
33
+
34
+ ### Installation
35
+
36
+ First, ensure `@wix/essentials` is installed in your project:
37
+
38
+ ```bash
39
+ npm install @wix/essentials
40
+ ```
41
+
42
+ ### Basic Error Handling Pattern
43
+
44
+ Wrap Wix HTTP requests in your custom data source actions with `errorHandler.withErrorHandler`:
45
+
46
+ ```typescript
47
+ import { errorHandler } from '@wix/essentials';
48
+
49
+ // In your custom data source actions
50
+ actions: {
51
+ get: async (entityId: string) => {
52
+ return errorHandler.withErrorHandler(
53
+ async () => {
54
+ const response = await httpClient.request(
55
+ getDummyEntity({ dummyEntityId: entityId })
56
+ );
57
+ return response.data.dummyEntity;
58
+ },
59
+ {}
60
+ );
61
+ },
62
+ }
63
+ ```
64
+
65
+ ### Examples of HTTP Requests That Need Error Handling
66
+
67
+ **httpClient from @wix/essentials:**
68
+
69
+ ```typescript
70
+ return errorHandler.withErrorHandler(async () => {
71
+ const response = await httpClient.request(
72
+ getDummyEntity({ dummyEntityId: entityId })
73
+ );
74
+ return response.data.dummyEntity;
75
+ }, {});
76
+ ```
77
+
78
+ **Wix APIs (wix/data, wix/stores):**
79
+
80
+ ```typescript
81
+ return errorHandler.withErrorHandler(async () => {
82
+ return await items.get(collectionId, entityId);
83
+ }, {});
84
+ ```
85
+
86
+ **httpClient.fetchWithAuth() calls:**
87
+
88
+ ```typescript
89
+ return errorHandler.withErrorHandler(async () => {
90
+ const response = await httpClient.fetchWithAuth("/api/data");
91
+ return await response.json();
92
+ }, {});
93
+ ```
94
+
95
+ ### Examples of HTTP Requests That Do NOT Need Error Handling
96
+
97
+ **External API calls (using fetch, axios, etc.):**
98
+
99
+ ```typescript
100
+ // ✅ CORRECT - No error handling needed for external APIs
101
+ const response = await fetch("https://api.example.com/data");
102
+ return await response.json();
103
+
104
+ // ✅ CORRECT - No error handling needed for axios
105
+ const response = await axios.get("https://api.example.com/data");
106
+ return response.data;
107
+ ```
108
+
109
+ **Third-party HTTP libraries:**
110
+
111
+ ```typescript
112
+ // ✅ CORRECT - No error handling needed for third-party HTTP clients
113
+ const response = await someThirdPartyHttpClient.get("/data");
114
+ return response.data;
115
+ ```
116
+
117
+ ## Integration with AutoPatterns Error Handling
118
+
119
+ The error handling in your custom data source integrates seamlessly with AutoPatterns' built-in error handling:
120
+
121
+ 1. **User-Friendly Messages**: Errors are displayed to users in a consistent format
122
+ 2. **Retry Mechanisms**: Users can retry failed operations
123
+ 3. **Loading States**: Proper loading states during HTTP requests
124
+ 4. **Error Boundaries**: Errors are caught and handled gracefully
125
+
126
+ ## Validation Checklist
127
+
128
+ Before deploying your custom data source, ensure:
129
+
130
+ ✅ **httpClient from @wix/essentials** is wrapped with `errorHandler.withErrorHandler`
131
+ ✅ **Wix APIs (wix/data, wix/stores, etc)** are wrapped with `errorHandler.withErrorHandler`
132
+ ✅ **httpClient.fetchWithAuth()** calls are wrapped with `errorHandler.withErrorHandler`
133
+ ✅ **External API calls are NOT wrapped** with errorHandler (e.g., fetch(), axios, third-party HTTP clients)
134
+ ✅ **SDK actions are used directly** without error handling (e.g., `sdk.getOptimisticActions()`, `sdk.getSchema()`)
135
+ ✅ **@wix/essentials** is installed as a dependency
@@ -74,6 +74,10 @@ This index maps user requests to the appropriate section IDs for fetching releva
74
74
  **Topics**: FQDN-based custom data sources, Wix Business API integration, schema mapping, custom data source implementation
75
75
  **Keywords**: FQDN, Wix Business API, custom data source, schema mapping, client library, field type mapping, custom implementation, entityTypeSource custom, Business API integration, schema extraction
76
76
 
77
+ ### ID: `error_handling`
78
+ **Topics**: HTTP request error handling, errorHandler usage, custom data source error management, API error handling
79
+ **Keywords**: error handling, HTTP errors, API errors, errorHandler, @wix/essentials, custom data source errors, error management, promise rejections, user experience, error messages
80
+
77
81
  ---
78
82
 
79
83
  ## Recipe Section IDs (Step-by-Step Guides)
@@ -16,19 +16,25 @@ export interface SchemaConfig {
16
16
  update: (updatedEntity: any) => Promise<any>;
17
17
  delete: (entityId: string) => Promise<any>;
18
18
  bulkDelete: (entityIds: string[]) => Promise<any>;
19
+ // The return shape depends on pagination mode (see AppConfig.collection.paginationMode)
20
+ // - Cursor mode: { items, cursor, total? }
21
+ // - Offset mode (default): { items, hasNext, total? }
19
22
  find: (
20
23
  query: Query,
21
24
  options?: {
22
25
  searchableFieldIds?: string[];
23
26
  filterFieldMapping?: Record<string, { fieldId: string }>;
24
27
  },
25
- ) => Promise<{ items: any[]; total: number }>;
28
+ ) => Promise<
29
+ | { items: any[]; cursor?: string | null; total?: number | null }
30
+ | { items: any[]; hasNext?: boolean; total?: number | null }
31
+ >;
26
32
  };
27
33
  }
28
34
 
29
35
  export interface Query {
30
36
  limit: number; // Maximum number of items to return per request (controls page size)
31
- offset: number; // Number of items to skip from the beginning (for pagination)
37
+ offset?: number; // Number of items to skip from the beginning (for pagination)
32
38
  page: number; // Current page number (1-based, works with limit for pagination)
33
39
  search?: string; // Text search query applied to searchable fields
34
40
  cursor?: string | null; // Cursor-based pagination token (alternative to offset-based pagination)
@@ -127,7 +133,9 @@ export type Field = ReferenceField | NonReferenceField;
127
133
  - `query`: Query object with pagination, filtering, sorting, and search criteria (see Query Interface section)
128
134
  - `options.searchableFieldIds`: Array of field IDs that support text search
129
135
  - `options.filterFieldMapping`: Maps filter IDs to actual field IDs for complex filtering
130
- - Returns: `{ items: any[], total: number }`
136
+ - Returns (depends on pagination mode):
137
+ - Cursor mode: `{ items: any[]; cursor?: string | null; total?: number | null }`
138
+ - Offset mode (default): `{ items: any[]; hasNext?: boolean; total?: number | null }`
131
139
 
132
140
  ### Field Type Information
133
141
 
@@ -114,6 +114,7 @@ Follow the complete custom data source implementation guide in the "Custom Overr
114
114
  1. **Import the client library** identified in Step 2
115
115
  2. **Use the field mappings** from Step 3 in your SchemaConfig
116
116
  3. **⚠️ CRITICAL: DO NOT IMPLEMENT THE ACTIONS** - Instead, add guidance comments explaining how to use the imported client library for each CRUD operation, then throw an "unimplemented exception" error
117
+ 4. **⚠️ CRITICAL: Add Error Handling** - When implementing the actions, you MUST wrap all HTTP requests with proper error handling using `errorHandler` from `@wix/essentials` (see "Error Handling for HTTP Requests" section)
117
118
 
118
119
  **Important**: The schema actions should contain helpful comments but NOT actual implementations. Each action should throw an error indicating it's unimplemented and needs to be implemented by the user.
119
120
 
@@ -123,6 +124,8 @@ Create your custom data source with the hook pattern:
123
124
 
124
125
  In `components/customDataSources/myCustomDataSource.ts`:
125
126
  ```typescript
127
+ import { errorHandler } from '@wix/essentials';
128
+
126
129
  export const myCustomDataSource = async (collectionId: string, context: any) => {
127
130
  return {
128
131
  id: 'myCustomCollection',
@@ -134,37 +137,76 @@ export const myCustomDataSource = async (collectionId: string, context: any) =>
134
137
  actions: {
135
138
  get: async (entityId: string) => {
136
139
  // TODO: Implement using your FQDN client library
137
- // Example: const result = await yourFQDNClient.getEntity(entityId);
140
+ // Example:
141
+ // return errorHandler.withErrorHandler(
142
+ // async () => {
143
+ // return yourFQDNClient.getEntity(entityId);
144
+ // },
145
+ // {}
146
+ // );
138
147
  // Remember to map the response fields from snake_case to camelCase
139
148
  throw new Error('get action not implemented - user must implement this method');
140
149
  },
141
150
  create: async (newEntity: any) => {
142
151
  // TODO: Implement using your FQDN client library
143
- // Example: const result = await yourFQDNClient.createEntity(newEntity);
152
+ // Example:
153
+ // return errorHandler.withErrorHandler(
154
+ // async () => {
155
+ // return yourFQDNClient.createEntity(newEntity);
156
+ // },
157
+ // {}
158
+ // );
144
159
  // Remember to map the request fields from camelCase to snake_case
145
160
  throw new Error('create action not implemented - user must implement this method');
146
161
  },
147
162
  update: async (updatedEntity: any) => {
148
163
  // TODO: Implement using your FQDN client library
149
- // Example: const result = await yourFQDNClient.updateEntity(updatedEntity);
164
+ // Example:
165
+ // return errorHandler.withErrorHandler(
166
+ // async () => {
167
+ // return yourFQDNClient.updateEntity(updatedEntity);
168
+ // },
169
+ // {}
170
+ // );
150
171
  // Remember to map the request fields from camelCase to snake_case
151
172
  throw new Error('update action not implemented - user must implement this method');
152
173
  },
153
174
  delete: async (entityId: string) => {
154
175
  // TODO: Implement using your FQDN client library
155
- // Example: await yourFQDNClient.deleteEntity(entityId);
176
+ // Example:
177
+ // return errorHandler.withErrorHandler(
178
+ // async () => {
179
+ // return yourFQDNClient.deleteEntity(entityId);
180
+ // },
181
+ // {}
182
+ // );
156
183
  throw new Error('delete action not implemented - user must implement this method');
157
184
  },
158
185
  bulkDelete: async (entityIds: string[]) => {
159
186
  // TODO: Implement using your FQDN client library
160
- // Example: await yourFQDNClient.bulkDeleteEntities(entityIds);
187
+ // Example:
188
+ // return errorHandler.withErrorHandler(
189
+ // async () => {
190
+ // return yourFQDNClient.bulkDeleteEntities(entityIds);
191
+ // },
192
+ // {}
193
+ // );
161
194
  throw new Error('bulkDelete action not implemented - user must implement this method');
162
195
  },
163
196
  find: async (query: Query, options?: any) => {
164
197
  // TODO: Implement using your FQDN client library
165
- // Example: const result = await yourFQDNClient.queryEntities(query, options);
198
+ // Example:
199
+ // return errorHandler.withErrorHandler(
200
+ // async () => {
201
+ // return yourFQDNClient.queryEntities(query, options);
202
+ // },
203
+ // {}
204
+ // );
166
205
  // Remember to map the response fields from snake_case to camelCase
167
- // Must return: { items: any[], total: number }
206
+ // IMPORTANT: Return shape depends on pagination mode.
207
+ // Detect by presence of query.cursor (cursor mode) vs. query.offset/page (offset mode):
208
+ // - Cursor mode: return { items, cursor, total? }
209
+ // - Offset mode (default): return { items, hasNext, total? }
168
210
  throw new Error('find action not implemented - user must implement this method');
169
211
  }
170
212
  }
@@ -31,7 +31,7 @@ export async function fetchCmsData(collectionId, query, fields, options) {
31
31
  if (referenceFieldIds.length > 0) {
32
32
  dataQuery = dataQuery.include(...referenceFieldIds);
33
33
  }
34
- const res = await dataQuery.skip(query.offset).limit(query.limit).find({
34
+ const res = await dataQuery.skip(query.offset ?? 0).limit(query.limit).find({
35
35
  returnTotalCount: true
36
36
  });
37
37
  return {