@donotdev/crud 0.0.31 → 0.1.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 (248) hide show
  1. package/LICENSE.md +3 -3
  2. package/dist/CrudService.d.ts +4 -4
  3. package/dist/CrudService.js +2 -2
  4. package/dist/CrudStore.d.ts +1 -1
  5. package/dist/CrudStore.js +1 -1
  6. package/dist/FieldRegistry.d.ts +1 -1
  7. package/dist/FieldRegistry.d.ts.map +1 -1
  8. package/dist/FieldRegistry.js +1 -1
  9. package/dist/adapters/FunctionsAdapter.d.ts +3 -3
  10. package/dist/adapters/FunctionsAdapter.d.ts.map +1 -1
  11. package/dist/adapters/FunctionsAdapter.js +1 -1
  12. package/dist/adapters/index.d.ts +1 -1
  13. package/dist/builtinFieldTypes.d.ts +1 -1
  14. package/dist/components/CrudButton.js +1 -1
  15. package/dist/components/DateFilter.js +1 -1
  16. package/dist/components/DisplayFieldRenderer.d.ts +1 -1
  17. package/dist/components/DisplayFieldRenderer.js +1 -1
  18. package/dist/components/DisplayThumbnail.d.ts +1 -1
  19. package/dist/components/DisplayThumbnail.js +1 -1
  20. package/dist/components/EntityFilters.js +1 -1
  21. package/dist/components/FormFieldRenderer.js +1 -1
  22. package/dist/components/FormLayout.d.ts +1 -1
  23. package/dist/components/FormLayout.js +1 -1
  24. package/dist/components/controlled/complex/ControlledAddressField.js +1 -1
  25. package/dist/components/controlled/complex/ControlledDateField.js +1 -1
  26. package/dist/components/controlled/complex/ControlledFieldArrayField.js +1 -1
  27. package/dist/components/controlled/complex/ControlledGeoPointField.js +1 -1
  28. package/dist/components/controlled/complex/ControlledMapField.js +1 -1
  29. package/dist/components/controlled/complex/ControlledMultiInputField.js +1 -1
  30. package/dist/components/controlled/complex/ControlledRichTextField.js +1 -1
  31. package/dist/components/controlled/complex/ControlledTimestampField.js +1 -1
  32. package/dist/components/controlled/complex/index.js +1 -1
  33. package/dist/components/controlled/file/ControlledDocumentField.js +1 -1
  34. package/dist/components/controlled/file/ControlledFileField.js +1 -1
  35. package/dist/components/controlled/file/ControlledImageField.js +1 -1
  36. package/dist/components/controlled/file/ControlledMultiDocumentField.js +1 -1
  37. package/dist/components/controlled/file/ControlledMultiFileField.js +1 -1
  38. package/dist/components/controlled/file/ControlledMultiImageField.js +1 -1
  39. package/dist/components/controlled/file/index.js +1 -1
  40. package/dist/components/controlled/index.js +1 -1
  41. package/dist/components/controlled/input/ControlledCheckboxField.js +1 -1
  42. package/dist/components/controlled/input/ControlledCurrencyField.js +1 -1
  43. package/dist/components/controlled/input/ControlledDurationField.js +1 -1
  44. package/dist/components/controlled/input/ControlledGdprConsentField.js +1 -1
  45. package/dist/components/controlled/input/ControlledNumberField.js +1 -1
  46. package/dist/components/controlled/input/ControlledPasswordField.js +1 -1
  47. package/dist/components/controlled/input/ControlledPhoneField.js +1 -1
  48. package/dist/components/controlled/input/ControlledPriceField.js +1 -1
  49. package/dist/components/controlled/input/ControlledRangeField.js +1 -1
  50. package/dist/components/controlled/input/ControlledRatingField.js +1 -1
  51. package/dist/components/controlled/input/ControlledSwitchField.js +1 -1
  52. package/dist/components/controlled/input/ControlledTextField.js +1 -1
  53. package/dist/components/controlled/input/ControlledTextareaField.js +1 -1
  54. package/dist/components/controlled/input/index.js +1 -1
  55. package/dist/components/controlled/select/ControlledComboboxField.js +1 -1
  56. package/dist/components/controlled/select/ControlledDropdownField.js +1 -1
  57. package/dist/components/controlled/select/ControlledMultiDropdownField.js +1 -1
  58. package/dist/components/controlled/select/ControlledRadioField.js +1 -1
  59. package/dist/components/controlled/select/ControlledReferenceField.js +1 -1
  60. package/dist/components/controlled/select/ControlledYearField.js +1 -1
  61. package/dist/components/controlled/select/index.js +1 -1
  62. package/dist/components/controlled/types.js +1 -1
  63. package/dist/components/fields/display/AvatarFieldDisplay.d.ts +1 -1
  64. package/dist/components/fields/display/AvatarFieldDisplay.js +1 -1
  65. package/dist/components/fields/display/BadgeFieldDisplay.d.ts +1 -1
  66. package/dist/components/fields/display/BadgeFieldDisplay.js +1 -1
  67. package/dist/components/fields/display/ButtonFieldDisplay.d.ts +2 -2
  68. package/dist/components/fields/display/ButtonFieldDisplay.js +1 -1
  69. package/dist/components/fields/display/CheckboxFieldDisplay.d.ts +1 -1
  70. package/dist/components/fields/display/CheckboxFieldDisplay.js +1 -1
  71. package/dist/components/fields/display/DateFieldDisplay.d.ts +1 -1
  72. package/dist/components/fields/display/DateFieldDisplay.js +1 -1
  73. package/dist/components/fields/display/DropdownDisplay.d.ts +1 -1
  74. package/dist/components/fields/display/DropdownDisplay.js +1 -1
  75. package/dist/components/fields/display/FileFieldDisplay.d.ts +1 -1
  76. package/dist/components/fields/display/FileFieldDisplay.js +1 -1
  77. package/dist/components/fields/display/GeoPointFieldDisplay.d.ts +1 -1
  78. package/dist/components/fields/display/GeoPointFieldDisplay.js +1 -1
  79. package/dist/components/fields/display/HiddenFieldDisplay.d.ts +2 -2
  80. package/dist/components/fields/display/HiddenFieldDisplay.js +1 -1
  81. package/dist/components/fields/display/ImageFieldDisplay.d.ts +1 -1
  82. package/dist/components/fields/display/ImageFieldDisplay.js +1 -1
  83. package/dist/components/fields/display/LinkFieldDisplay.d.ts +1 -1
  84. package/dist/components/fields/display/LinkFieldDisplay.js +1 -1
  85. package/dist/components/fields/display/MapFieldDisplay.d.ts +1 -1
  86. package/dist/components/fields/display/MapFieldDisplay.js +1 -1
  87. package/dist/components/fields/display/MultiDropdownDisplay.d.ts +1 -1
  88. package/dist/components/fields/display/MultiDropdownDisplay.js +1 -1
  89. package/dist/components/fields/display/MultiInputTextFieldDisplay.d.ts +1 -1
  90. package/dist/components/fields/display/MultiInputTextFieldDisplay.js +1 -1
  91. package/dist/components/fields/display/NumberFieldDisplay.d.ts +1 -1
  92. package/dist/components/fields/display/NumberFieldDisplay.js +1 -1
  93. package/dist/components/fields/display/PasswordFieldDisplay.d.ts +1 -1
  94. package/dist/components/fields/display/PasswordFieldDisplay.js +1 -1
  95. package/dist/components/fields/display/PhoneNumberDisplay.d.ts +1 -1
  96. package/dist/components/fields/display/PhoneNumberDisplay.js +1 -1
  97. package/dist/components/fields/display/RadioFieldDisplay.d.ts +1 -1
  98. package/dist/components/fields/display/RadioFieldDisplay.js +1 -1
  99. package/dist/components/fields/display/RangeFieldDisplay.d.ts +1 -1
  100. package/dist/components/fields/display/RangeFieldDisplay.js +1 -1
  101. package/dist/components/fields/display/ReferenceFieldDisplay.d.ts +1 -1
  102. package/dist/components/fields/display/ReferenceFieldDisplay.js +1 -1
  103. package/dist/components/fields/display/RichTextDisplay.d.ts +1 -1
  104. package/dist/components/fields/display/RichTextDisplay.js +2 -2
  105. package/dist/components/fields/display/TextAreaDisplay.d.ts +1 -1
  106. package/dist/components/fields/display/TextAreaDisplay.js +1 -1
  107. package/dist/components/fields/display/TextFieldDisplay.d.ts +1 -1
  108. package/dist/components/fields/display/TextFieldDisplay.js +1 -1
  109. package/dist/components/fields/display/TimestampFieldDisplay.d.ts +1 -1
  110. package/dist/components/fields/display/TimestampFieldDisplay.js +1 -1
  111. package/dist/components/fields/display/index.d.ts +1 -1
  112. package/dist/components/fields/display/index.js +1 -1
  113. package/dist/components/form/fields/AddressFieldComponent.js +1 -1
  114. package/dist/components/form/fields/AvatarFieldComponent.d.ts +2 -2
  115. package/dist/components/form/fields/AvatarFieldComponent.js +1 -1
  116. package/dist/components/form/fields/BadgeFieldComponent.d.ts +2 -2
  117. package/dist/components/form/fields/BadgeFieldComponent.js +1 -1
  118. package/dist/components/form/fields/ButtonFieldComponent.js +1 -1
  119. package/dist/components/form/fields/CheckboxFieldComponent.d.ts +1 -1
  120. package/dist/components/form/fields/CheckboxFieldComponent.js +1 -1
  121. package/dist/components/form/fields/ComboboxComponent.d.ts +1 -1
  122. package/dist/components/form/fields/ComboboxComponent.js +1 -1
  123. package/dist/components/form/fields/CurrencyFieldComponent.d.ts +1 -1
  124. package/dist/components/form/fields/CurrencyFieldComponent.js +1 -1
  125. package/dist/components/form/fields/DateFieldComponent.d.ts +1 -1
  126. package/dist/components/form/fields/DateFieldComponent.js +1 -1
  127. package/dist/components/form/fields/DocumentFieldComponent.js +1 -1
  128. package/dist/components/form/fields/DropdownComponent.d.ts +1 -1
  129. package/dist/components/form/fields/DropdownComponent.js +1 -1
  130. package/dist/components/form/fields/DurationFieldComponent.js +1 -1
  131. package/dist/components/form/fields/FileFieldComponent.js +1 -1
  132. package/dist/components/form/fields/GdprConsentFieldComponent.d.ts +1 -1
  133. package/dist/components/form/fields/GdprConsentFieldComponent.js +1 -1
  134. package/dist/components/form/fields/GeoPointFieldComponent.d.ts +1 -1
  135. package/dist/components/form/fields/GeoPointFieldComponent.js +1 -1
  136. package/dist/components/form/fields/HiddenFieldComponent.d.ts +1 -1
  137. package/dist/components/form/fields/HiddenFieldComponent.js +1 -1
  138. package/dist/components/form/fields/ImageFieldComponent.js +1 -1
  139. package/dist/components/form/fields/MapFieldComponent.js +1 -1
  140. package/dist/components/form/fields/MultiDropdownComponent.d.ts +1 -1
  141. package/dist/components/form/fields/MultiDropdownComponent.js +1 -1
  142. package/dist/components/form/fields/MultiInputTextFieldComponent.js +1 -1
  143. package/dist/components/form/fields/NumberFieldComponent.d.ts +1 -1
  144. package/dist/components/form/fields/NumberFieldComponent.js +1 -1
  145. package/dist/components/form/fields/PasswordFieldComponent.d.ts +1 -1
  146. package/dist/components/form/fields/PasswordFieldComponent.js +1 -1
  147. package/dist/components/form/fields/PhoneNumberComponent.d.ts +1 -1
  148. package/dist/components/form/fields/PhoneNumberComponent.js +1 -1
  149. package/dist/components/form/fields/PriceFieldComponent.js +1 -1
  150. package/dist/components/form/fields/RadioFieldComponent.js +1 -1
  151. package/dist/components/form/fields/RangeFieldComponent.d.ts +1 -1
  152. package/dist/components/form/fields/RangeFieldComponent.js +1 -1
  153. package/dist/components/form/fields/RatingFieldComponent.d.ts +1 -1
  154. package/dist/components/form/fields/RatingFieldComponent.js +1 -1
  155. package/dist/components/form/fields/ReferenceFieldComponent.js +1 -1
  156. package/dist/components/form/fields/RichTextComponent.d.ts +1 -1
  157. package/dist/components/form/fields/RichTextComponent.js +1 -1
  158. package/dist/components/form/fields/SwitchFieldComponent.d.ts +1 -1
  159. package/dist/components/form/fields/SwitchFieldComponent.js +1 -1
  160. package/dist/components/form/fields/TextAreaComponent.d.ts +1 -1
  161. package/dist/components/form/fields/TextAreaComponent.js +1 -1
  162. package/dist/components/form/fields/TextFieldComponent.d.ts +2 -2
  163. package/dist/components/form/fields/TextFieldComponent.js +1 -1
  164. package/dist/components/form/fields/TimestampFieldComponent.js +1 -1
  165. package/dist/components/form/fields/index.d.ts +1 -1
  166. package/dist/components/form/fields/index.js +1 -1
  167. package/dist/components/form/fields/internal/TiptapEditor.d.ts +1 -1
  168. package/dist/components/form/fields/internal/TiptapEditor.js +2 -2
  169. package/dist/components/form/fields/types.d.ts +1 -1
  170. package/dist/components/form/index.d.ts +1 -1
  171. package/dist/components/form/internal/ImageViewerDialog.js +1 -1
  172. package/dist/components/index.d.ts +1 -1
  173. package/dist/components/index.js +1 -1
  174. package/dist/contexts/UploadContext.js +1 -1
  175. package/dist/contexts/index.js +1 -1
  176. package/dist/fieldTypeRegistry.d.ts.map +1 -1
  177. package/dist/fieldTypeRegistry.js +1 -1
  178. package/dist/fieldTypeRegistry.store.js +1 -1
  179. package/dist/fieldTypeRegistry.types.d.ts.map +1 -1
  180. package/dist/forms/hooks/index.d.ts +1 -1
  181. package/dist/forms/hooks/index.js +1 -1
  182. package/dist/forms/hooks/useController.js +1 -1
  183. package/dist/forms/hooks/useEntityField.d.ts +1 -1
  184. package/dist/forms/hooks/useEntityField.js +1 -1
  185. package/dist/forms/hooks/useEntityForm.d.ts.map +1 -1
  186. package/dist/forms/hooks/useEntityForm.js +1 -1
  187. package/dist/forms/index.d.ts +1 -1
  188. package/dist/forms/index.js +1 -1
  189. package/dist/forms/types.d.ts +7 -7
  190. package/dist/forms/utils/buildInitialValues.js +1 -1
  191. package/dist/forms/utils/getFieldsForOperation.d.ts +2 -2
  192. package/dist/forms/utils/getFieldsForOperation.js +1 -1
  193. package/dist/forms/utils/index.d.ts +1 -1
  194. package/dist/forms/utils/index.js +1 -1
  195. package/dist/forms/utils/isFieldEditable.d.ts +1 -1
  196. package/dist/forms/utils/isFieldEditable.js +1 -1
  197. package/dist/forms/utils/translateFieldLabel.d.ts +3 -3
  198. package/dist/forms/utils/translateFieldLabel.js +1 -1
  199. package/dist/forms/utils/validateEntity.d.ts +1 -1
  200. package/dist/forms/utils/validateEntity.js +1 -1
  201. package/dist/hooks/index.js +1 -1
  202. package/dist/hooks/useCrudFilters.js +1 -1
  203. package/dist/hooks/useEntityFavorites.js +1 -1
  204. package/dist/hooks/useFieldConditions.js +1 -1
  205. package/dist/hooks/useFileUpload.js +1 -1
  206. package/dist/hooks/useReferenceResolver.js +1 -1
  207. package/dist/hooks/useRelatedItems.js +1 -1
  208. package/dist/hooks/useUnsavedChangesWarning.js +1 -1
  209. package/dist/index.d.ts +1 -1
  210. package/dist/index.js +1 -1
  211. package/dist/registerBuiltinFieldTypes.js +1 -1
  212. package/dist/stores/FormStore.js +1 -1
  213. package/dist/stores/UploadStore.js +1 -1
  214. package/dist/stores/index.d.ts +1 -1
  215. package/dist/stores/index.js +1 -1
  216. package/dist/tsconfig.tsbuildinfo +1 -1
  217. package/dist/types.d.ts +4 -4
  218. package/dist/types.js +1 -1
  219. package/dist/useBaseCrudList.js +1 -1
  220. package/dist/useCrud.js +1 -1
  221. package/dist/useCrudCardList.js +1 -1
  222. package/dist/useCrudList.js +1 -1
  223. package/dist/utils/clientListProcessing.d.ts +1 -1
  224. package/dist/utils/clientListProcessing.js +1 -1
  225. package/dist/utils/collections.d.ts +6 -6
  226. package/dist/utils/collections.js +1 -1
  227. package/dist/utils/fileStorage.js +1 -1
  228. package/dist/utils/imageProcessing.d.ts +1 -1
  229. package/dist/utils/imageProcessing.js +1 -1
  230. package/dist/utils/imageStorage.js +1 -1
  231. package/dist/utils/imageUtils.d.ts +1 -1
  232. package/dist/utils/imageUtils.js +1 -1
  233. package/dist/utils/matchesFilter.d.ts.map +1 -1
  234. package/dist/utils/matchesFilter.js +1 -1
  235. package/dist/utils/mergeWithOptimistic.js +1 -1
  236. package/dist/utils/sanitizeHtml.d.ts +0 -5
  237. package/dist/utils/sanitizeHtml.d.ts.map +1 -1
  238. package/dist/utils/sanitizeHtml.js +1 -1
  239. package/dist/utils/scopeUtils.js +1 -1
  240. package/dist/utils/uploadValidation.d.ts +1 -1
  241. package/dist/utils/uploadValidation.js +1 -1
  242. package/dist/workflows/WorkflowPersistence.d.ts +1 -1
  243. package/dist/workflows/WorkflowPersistence.js +1 -1
  244. package/dist/workflows/defineWorkflow.d.ts +1 -1
  245. package/dist/workflows/index.d.ts +1 -1
  246. package/dist/workflows/index.js +1 -1
  247. package/dist/workflows/useEntityWorkflow.js +1 -1
  248. package/package.json +3 -3
package/dist/types.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * - CrudStore = only tracks optimistic metadata (optimisticData + originalData)
8
8
  * - mergeWithOptimistic merges TanStack cache with optimistic data for display
9
9
  *
10
- * @version 0.0.1
10
+ * @version 0.1.0
11
11
  * @since 0.0.1
12
12
  * @author AMBROISE PARK Consulting
13
13
  */
@@ -65,7 +65,7 @@ export interface CollectionUIState {
65
65
  * CRUD store state interface
66
66
  * Note: No data field - TanStack Query owns data, CrudStore only tracks optimistic ops
67
67
  *
68
- * @version 0.0.3
68
+ * @version 0.1.0
69
69
  * @since 0.0.1
70
70
  * @author AMBROISE PARK Consulting
71
71
  */
@@ -87,7 +87,7 @@ export interface CrudState {
87
87
  * CRUD store actions interface
88
88
  * Note: No setData/getData - TanStack Query owns data, CrudStore only tracks optimistic ops
89
89
  *
90
- * @version 0.0.3
90
+ * @version 0.1.0
91
91
  * @since 0.0.1
92
92
  * @author AMBROISE PARK Consulting
93
93
  */
@@ -162,7 +162,7 @@ export interface MutationOptions {
162
162
  * CRUD Service Interface
163
163
  * Complete interface for CRUD operations with caching and optimistic updates
164
164
  *
165
- * @version 0.0.4
165
+ * @version 0.1.0
166
166
  * @since 0.0.1
167
167
  * @author AMBROISE PARK Consulting
168
168
  */
package/dist/types.js CHANGED
@@ -1 +1 @@
1
- const E={PENDING:"pending",CONFIRMED:"confirmed",FAILED:"failed"},e={ADD:"add",UPDATE:"update",SET:"set",DELETE:"delete"};export{e as CRUD_OPERATION,E as OPTIMISTIC_STATUSES};
1
+ const e={PENDING:"pending",CONFIRMED:"confirmed",FAILED:"failed"},E={ADD:"add",UPDATE:"update",SET:"set",DELETE:"delete"};export{E as CRUD_OPERATION,e as OPTIMISTIC_STATUSES};
@@ -1 +1 @@
1
- import{useMemo as P,useCallback as X,useRef as Q,useState as Z,useEffect as $}from"react";import{useQuery as ee}from"@donotdev/core";import{useCrudStore as te}from"./CrudStore";import{CRUD_OPERATION as R}from"./types";import{useCrud as V,getCrudServiceInstance as se,EMPTY_OPTIMISTIC as re}from"./useCrud";import{mergeWithOptimistic as ie}from"./utils/mergeWithOptimistic";import{injectScopeFilter as ae,getCurrentScopeValue as oe}from"./utils/scopeUtils";const ne=1e3;function le(j,f,t,g={}){const K=g.enabled??!0,b=V("status"),c=b==="ready",k=V(j,g),{error:L,invalidate:_,_collection:p,_schemas:v,_cacheOptions:y,_scope:M}=k,T=te(e=>e.collections[p]?.optimistic||re),q=Q(new Map([[1,null]])),S=Q(0),[E,x]=Z(!1),o=t?.mode==="auto"?E?"server":"client":t?.mode??"client",B=oe(M),O=P(()=>{if(!c||!v)return null;const e=se();if(!e)return null;const h=f==="listCard"?v.listCard:v.list,n=ae(g.queryOptions,M);if(!t)return e.getListQueryOptions(p,n,h,y,f);if(o==="client"){const l=t.mode==="auto"&&!n?.limit?{...n,limit:ne}:n;return e.getListQueryOptions(p,l,h,y,f)}const u=q.current,m=S.current,{page:d,pageSize:s}=t;let i,r;if(u.has(d))i=u.get(d)??void 0,r=s;else if(d>m&&u.has(m)){const l=d-m;i=u.get(m)??void 0,r=l*s}else i=void 0,r=d*s;return e.getListQueryOptions(p,{...n,limit:r,startAfter:i},h,y,f)},[c,p,y,v?"hasSchema":"noSchema",f,o,t?.page,t?.pageSize,g.queryOptions,M?.provider,B]),{data:a,isLoading:N,isFetching:U,error:W,refetch:w}=ee({queryKey:O?.queryKey??["crud",p,"disabled"],queryFn:O?.queryFn??(()=>Promise.resolve({items:[]})),staleTime:O?.staleTime,enabled:K&&!!O});$(()=>{t?.mode==="auto"&&!E&&a&&a.total!=null&&a.total>a.items.length&&x(!0)},[a,t?.mode,E]);const A=P(()=>{if(!a||!c)return{items:[],total:void 0};let e=a.items;if(o==="server"&&t&&e.length>0){const s=q.current,i=S.current,{page:r,pageSize:l}=t,G=e.length;if(Math.ceil(G/l)>1||r>i){const D=s.has(r)?r:i+1;for(let C=D;C<=r;C++){const F=(C-D+1)*l-1;if(F<e.length){const J=e[F];s.set(C+1,J.id)}}}a.lastVisible&&s.set(r+1,a.lastVisible),S.current=Math.max(i,r);const z=s.has(r)?0:(r-i-1)*l,H=z+l;e=e.slice(z,H)}const h=ie(e,T),n=new Set(e.map(s=>s.id));let u=0,m=0;for(const[s,i]of Object.entries(T))i.operation===R.ADD&&!n.has(s)?u++:i.operation===R.DELETE&&n.has(s)&&m++;const d=(a.total??e.length)+u-m;return{items:h,total:d}},[a,T,c,o,t?.page,t?.pageSize]),I=X(async()=>{c&&(o==="server"&&(q.current=new Map([[1,null]]),S.current=0),await _(),await w())},[_,w,c,o]);if(!c){const e=async()=>{};return{status:b,data:{items:[],total:void 0},items:[],loading:!0,fetching:!1,error:L,mutate:e,refresh:e,isAvailable:!1,effectiveMode:o}}const Y=A?.items??[];return{status:b,data:A,items:Y,loading:N,fetching:U,error:W??L,mutate:I,refresh:I,isAvailable:!0,effectiveMode:o}}export{le as useBaseCrudList};
1
+ import{useMemo as Q,useCallback as Z,useRef as R,useState as $,useEffect as ee}from"react";import{useQuery as te}from"@donotdev/core";import{useCrudStore as se}from"./CrudStore";import{CRUD_OPERATION as z}from"./types";import{useCrud as V,getCrudServiceInstance as re,EMPTY_OPTIMISTIC as oe}from"./useCrud";import{mergeWithOptimistic as ce}from"./utils/mergeWithOptimistic";import{injectScopeFilter as ie,getCurrentScopeValue as ne}from"./utils/scopeUtils";const ae=1e3;function Oe(j,f,s,g={}){const K=g.enabled??!0,b=V("status"),a=b==="ready",N=V(j,g),{error:E,invalidate:L,_collection:d,_schemas:O,_cacheOptions:S,_scope:T}=N,F=se(e=>e.collections[d]?.optimistic||oe),q=R(new Map([[1,null]])),y=R(0),[A,U]=$(!1),i=s?.mode==="auto"?A?"server":"client":s?.mode??"client",k=ne(T),I=Q(()=>{if(!a||!O)return null;const e=re();if(!e)return null;const h=f==="listCard"?O.listCard:O.list,n=ie(g.queryOptions,T);if(!s)return e.getListQueryOptions(d,n,h,S,f);if(i==="client"){const o=s.mode==="auto"&&!n?.limit?{...n,limit:ae}:n;return e.getListQueryOptions(d,o,h,S,f)}const l=q.current,u=y.current,{page:m,pageSize:p}=s;let t,r;if(l.has(m))t=l.get(m)??void 0,r=p;else if(m>u&&l.has(u)){const o=m-u;t=l.get(u)??void 0,r=o*p}else t=void 0,r=m*p;return e.getListQueryOptions(d,{...n,limit:r,startAfter:t},h,S,f)},[a,d,S,O?"hasSchema":"noSchema",f,i,s?.page,s?.pageSize,g.queryOptions,T?.provider,k]),{data:c,isLoading:B,isFetching:W,error:Y,refetch:M}=te({queryKey:I?.queryKey??["crud",d,"disabled"],queryFn:I?.queryFn??(()=>Promise.resolve({items:[]})),staleTime:I?.staleTime,enabled:K&&!!I});ee(()=>{s?.mode==="auto"&&!A&&c&&c.total!=null&&c.total>c.items.length&&U(!0)},[c,s?.mode,A]);const P=Q(()=>{if(!c||!a)return{items:[],total:void 0};let e=c.items;if(i==="server"&&s&&e.length>0){const t=q.current,r=y.current,{page:o,pageSize:v}=s,H=e.length;if(Math.ceil(H/v)>1||o>r){const w=t.has(o)?o:r+1;for(let C=w;C<=o;C++){const x=(C-w+1)*v-1;if(x<e.length){const X=e[x];t.set(C+1,X.id)}}}c.lastVisible&&t.set(o+1,c.lastVisible),y.current=Math.max(r,o);const _=t.has(o)?0:(o-r-1)*v,J=_+v;e=e.slice(_,J)}const h=ce(e,F),n=new Set(e.map(t=>t.id));let l=0,u=0;for(const[t,r]of Object.entries(F))r.operation===z.ADD&&!n.has(t)?l++:r.operation===z.DELETE&&n.has(t)&&u++;const p=(c.total??e.length)+l-u;return{items:h,total:p}},[c,F,a,i,s?.page,s?.pageSize]),D=Z(async()=>{a&&(i==="server"&&(q.current=new Map([[1,null]]),y.current=0),await L(),await M())},[L,M,a,i]);if(!a){const e=async()=>{};return{status:b,data:{items:[],total:void 0},items:[],loading:!0,fetching:!1,error:E,mutate:e,refresh:e,isAvailable:!1,effectiveMode:i}}const G=P?.items??[];return{status:b,data:P,items:G,loading:B,fetching:W,error:Y??E,mutate:D,refresh:D,isAvailable:!0,effectiveMode:i}}export{Oe as useBaseCrudList};
package/dist/useCrud.js CHANGED
@@ -1 +1 @@
1
- "use client";import{useEffect as K,useMemo as F,useCallback as n}from"react";import{useFeatureConsent as L,FRAMEWORK_FEATURES as W,FEATURE_STATUS as m,handleError as Z,isClient as B,createSchemas as H,DEGRADED_CRUD_API as J}from"@donotdev/core";import{getCrudService as Q}from"./CrudService";import{useCrudStore as u}from"./CrudStore";import{injectScope as M,injectScopeFilter as V}from"./utils/scopeUtils";const X={},$={};let _=null,E=null,b=!1;function r(){return _}function ee(l,d={}){const f=L(W.CRUD),U=u(e=>e.crudService),g=f&&!U,y=f?g?m.INITIALIZING:m.READY:m.DEGRADED,S=l==="status",p=!S&&typeof l=="object"?l:d.entity,a=S?"__status__":typeof l=="string"?l:l.collection,o=p?.scope,v=d.noCache??!1,T=d.staleTime,h=F(()=>({noCache:v,staleTime:T}),[v,T]),t=F(()=>{if(!S){if(d.schema){const e=d.schema;return{create:e,draft:e,update:e,get:e,list:e,listCard:e,delete:e}}if(p)return H(p)}},[S,d.schema,p?.name,a]),Y=u(e=>e.collections[a]?.loading||!1),A=u(e=>e.collections[a]?.error||null),O=null;K(()=>{if(!B()||!f||!t)return;const{crudService:e}=u.getState();e||_||E||(E=(async()=>{try{if(_||u.getState().crudService)return;const s=Q();_=s,s.setStore(u),await s.initialize(),b=!1,u.getState().setCrudService(s)}catch(s){b||(Z(s,{userMessage:"Failed to initialize CRUD service.",context:{collection:a},severity:"error"}),b=!0)}finally{E=null}})())},[f,a,t?"hasSchema":"noSchema"]);const D=g||Y,P=y===m.READY,j=n(async e=>{const s=r();return!s||!t?null:s.get(a,e,t.get,h)},[a,t?"hasSchema":"noSchema",h]),G=n(async(e,s,c)=>{const i=r();if(!i||!t)return;const C=M(s,o),k=C?.status==="draft"?t.draft:t.create;await i.set(a,e,C,k,c)},[a,t?"hasSchema":"noSchema",o?.provider]),q=n(async(e,s,c)=>{const i=r();i&&await i.update(a,e,s,t?.update,c)},[a,t]),x=n(async(e,s)=>{const c=r();c&&await c.delete(a,e,s)},[a]),z=n(async(e,s)=>{const c=r();if(!c||!t)return"";const i=M(e,o),C=i?.status==="draft"?t.draft:t.create;return c.add(a,i,C,s)},[a,t?"hasSchema":"noSchema",o?.provider]),N=n(async e=>{const s=r();if(!s||!t)return[];const c=V(e,o);return(await s.query(a,c,t.list,h)).items},[a,t?"hasSchema":"noSchema",h,o?.provider]),R=n((e,s)=>{const c=r();return!c||!t?()=>{}:c.subscribe(a,e,s,t.get)},[a,t?"hasSchema":"noSchema"]),I=n((e,s)=>{const c=r();return!c||!t?()=>{}:c.subscribeToCollection(a,e,s,t.list)},[a,t?"hasSchema":"noSchema"]),w=n(async()=>{const e=r();e&&await e.invalidateCollection(a)},[a]);return S?y:P?{status:m.READY,data:O,loading:D,error:A,get:j,set:G,update:q,delete:x,add:z,query:N,subscribe:R,subscribeToCollection:I,invalidate:w,isAvailable:!0,_collection:a,_schemas:t,_cacheOptions:h,_scope:o}:{...J,status:y,loading:D,error:A,subscribe:R,subscribeToCollection:I,invalidate:w,_collection:a,_schemas:t,_cacheOptions:h,_scope:o}}export{X as EMPTY_DATA,$ as EMPTY_OPTIMISTIC,r as getCrudServiceInstance,ee as useCrud};
1
+ "use client";import{useEffect as V,useMemo as F,useCallback as a}from"react";import{useFeatureConsent as W,FRAMEWORK_FEATURES as Z,FEATURE_STATUS as h,handleError as $,isClient as B,createSchemas as H,DEGRADED_CRUD_API as J}from"@donotdev/core";import{getCrudService as X}from"./CrudService";import{useCrudStore as u}from"./CrudStore";import{injectScope as P,injectScopeFilter as O}from"./utils/scopeUtils";const re={},ne={};let v=null,_=null,g=!1;function i(){return v}function ae(l,d={}){const S=W(Z.CRUD),x=u(e=>e.crudService),C=S&&!x,D=S?C?h.INITIALIZING:h.READY:h.DEGRADED,m=l==="status",p=!m&&typeof l=="object"?l:d.entity,s=m?"__status__":typeof l=="string"?l:l.collection,o=p?.scope,T=d.noCache??!1,A=d.staleTime,f=F(()=>({noCache:T,staleTime:A}),[T,A]),t=F(()=>{if(!m){if(d.schema){const e=d.schema;return{create:e,draft:e,update:e,get:e,list:e,listCard:e,delete:e}}if(p)return H(p)}},[m,d.schema,p?.name,s]),M=u(e=>e.collections[s]?.loading||!1),b=u(e=>e.collections[s]?.error||null),N=null;V(()=>{if(!B()||!S||!t)return;const{crudService:e}=u.getState();e||v||_||(_=(async()=>{try{if(v||u.getState().crudService)return;const c=X();v=c,c.setStore(u),await c.initialize(),g=!1,u.getState().setCrudService(c)}catch(c){g||($(c,{userMessage:"Failed to initialize CRUD service.",context:{collection:s},severity:"error"}),g=!0)}finally{_=null}})())},[S,s,t?"hasSchema":"noSchema"]);const I=C||M,z=D===h.READY,Y=a(async e=>{const c=i();return!c||!t?null:c.get(s,e,t.get,f)},[s,t?"hasSchema":"noSchema",f]),j=a(async(e,c,r)=>{const n=i();if(!n||!t)return;const E=P(c,o),Q=E?.status==="draft"?t.draft:t.create;await n.set(s,e,E,Q,r)},[s,t?"hasSchema":"noSchema",o?.provider]),k=a(async(e,c,r)=>{const n=i();n&&await n.update(s,e,c,t?.update,r)},[s,t]),q=a(async(e,c)=>{const r=i();r&&await r.delete(s,e,c)},[s]),G=a(async(e,c)=>{const r=i();if(!r||!t)return"";const n=P(e,o),w=n?.status==="draft"?t.draft:t.create;return r.add(s,n,w,c)},[s,t?"hasSchema":"noSchema",o?.provider]),L=a(async e=>{const c=i();if(!c||!t)return[];const r=O(e,o);return(await c.query(s,r,t.list,f)).items},[s,t?"hasSchema":"noSchema",f,o?.provider]),R=a((e,c)=>{const r=i();return!r||!t?()=>{}:r.subscribe(s,e,c,t.get)},[s,t?"hasSchema":"noSchema"]),y=a((e,c)=>{const r=i();return!r||!t?()=>{}:r.subscribeToCollection(s,e,c,t.list)},[s,t?"hasSchema":"noSchema"]),U=a(async()=>{const e=i();e&&await e.invalidateCollection(s)},[s]);return m?D:z?{status:h.READY,data:N,loading:I,error:b,get:Y,set:j,update:k,delete:q,add:G,query:L,subscribe:R,subscribeToCollection:y,invalidate:U,isAvailable:!0,_collection:s,_schemas:t,_cacheOptions:f,_scope:o}:{...J,status:D,loading:I,error:b,subscribe:R,subscribeToCollection:y,invalidate:U,_collection:s,_schemas:t,_cacheOptions:f,_scope:o}}export{re as EMPTY_DATA,ne as EMPTY_OPTIMISTIC,i as getCrudServiceInstance,ae as useCrud};
@@ -1 +1 @@
1
- import{useMemo as d}from"react";import{useCrudFilters as p}from"./hooks/useCrudFilters";import{useBaseCrudList as f}from"./useBaseCrudList";import{applyFilters as h,applySearch as y,applySort as g}from"./utils/clientListProcessing";function C(l,t={}){const o={enabled:t.enabled,queryOptions:t.queryOptions,schema:t.schema,entity:t.entity,staleTime:t.staleTime,noCache:t.noCache},e=f(l,"listCard",null,o),s=typeof l=="string"?null:l,n=s?.collection??l,{filters:a}=p({collection:n}),i=t.clientSort===null?null:t.clientSort??s?.defaultSort??null,{processed:u,filteredTotal:c}=d(()=>{let r=e.items;s&&Object.keys(a).length>0&&(r=h(r,a,s)),s&&t.searchQuery&&(r=y(r,t.searchQuery,s));const m=r.length;return i&&(r=g(r,i)),{processed:r,filteredTotal:m}},[e.items,a,t.searchQuery,i,s]);return{status:e.status,data:e.data?{items:e.data.items}:null,items:e.items,processed:u,filteredTotal:c,loading:e.loading,fetching:e.fetching,error:e.error,mutate:e.mutate,refresh:e.refresh,isAvailable:e.isAvailable}}export{C as useCrudCardList};
1
+ import{useMemo as o}from"react";import{useCrudFilters as f}from"./hooks/useCrudFilters";import{useBaseCrudList as h}from"./useBaseCrudList";import{applyFilters as y,applySearch as g,applySort as p}from"./utils/clientListProcessing";function v(l,t={}){const u={enabled:t.enabled,queryOptions:t.queryOptions,schema:t.schema,entity:t.entity,staleTime:t.staleTime,noCache:t.noCache},e=h(l,"listCard",null,u),s=typeof l=="string"?null:l,c=s?.collection??l,{filters:a}=f({collection:c}),i=t.clientSort===null?null:t.clientSort??s?.defaultSort??null,{processed:n,filteredTotal:m}=o(()=>{let r=e.items;s&&Object.keys(a).length>0&&(r=y(r,a,s)),s&&t.searchQuery&&(r=g(r,t.searchQuery,s));const d=r.length;return i&&(r=p(r,i)),{processed:r,filteredTotal:d}},[e.items,a,t.searchQuery,i,s]);return{status:e.status,data:e.data?{items:e.data.items}:null,items:e.items,processed:n,filteredTotal:m,loading:e.loading,fetching:e.fetching,error:e.error,mutate:e.mutate,refresh:e.refresh,isAvailable:e.isAvailable}}export{v as useCrudCardList};
@@ -1 +1 @@
1
- import{useMemo as h}from"react";import{useCrudFilters as g}from"./hooks/useCrudFilters";import{useBaseCrudList as S}from"./useBaseCrudList";import{applyFilters as C,applySearch as T,applySort as b}from"./utils/clientListProcessing";function Q(l,e={}){const i=e.pagination??"auto",n=e.page??1,p=e.pageSize??10,c={mode:i,page:n,pageSize:p},u={enabled:e.enabled,queryOptions:e.queryOptions,schema:e.schema,entity:e.entity,staleTime:e.staleTime,noCache:e.noCache},o=S(l,"list",c,u),r=typeof l=="string"?null:l,m=r?.collection??l,{filters:s}=g({collection:m}),a=e.clientSort===null?null:e.clientSort??r?.defaultSort??null,{processed:d,filteredTotal:y}=h(()=>{let t=o.items;r&&Object.keys(s).length>0&&(t=C(t,s,r)),r&&e.searchQuery&&(t=T(t,e.searchQuery,r));const f=t.length;return a&&(t=b(t,a)),{processed:t,filteredTotal:f}},[o.items,s,e.searchQuery,a,r]);return{...o,processed:d,filteredTotal:y}}export{Q as useCrudList};
1
+ import{useMemo as h}from"react";import{useCrudFilters as y}from"./hooks/useCrudFilters";import{useBaseCrudList as S}from"./useBaseCrudList";import{applyFilters as b,applySearch as T,applySort as Q}from"./utils/clientListProcessing";function L(a,e={}){const n=e.pagination??"auto",u=e.page??1,i=e.pageSize??10,o={mode:n,page:u,pageSize:i},m={enabled:e.enabled,queryOptions:e.queryOptions,schema:e.schema,entity:e.entity,staleTime:e.staleTime,noCache:e.noCache},s=S(a,"list",o,m),r=typeof a=="string"?null:a,d=r?.collection??a,{filters:l}=y({collection:d}),c=e.clientSort===null?null:e.clientSort??r?.defaultSort??null,{processed:f,filteredTotal:p}=h(()=>{let t=s.items;r&&Object.keys(l).length>0&&(t=b(t,l,r)),r&&e.searchQuery&&(t=T(t,e.searchQuery,r));const g=t.length;return c&&(t=Q(t,c)),{processed:t,filteredTotal:g}},[s.items,l,e.searchQuery,c,r]);return{...s,processed:f,filteredTotal:p}}export{L as useCrudList};
@@ -3,7 +3,7 @@
3
3
  * @description Pure functions for filtering, searching, and sorting entity items.
4
4
  * Used by useCrudList/useCrudCardList hooks and UI components.
5
5
  *
6
- * @version 0.0.1
6
+ * @version 0.1.0
7
7
  * @since 0.0.1
8
8
  * @author AMBROISE PARK Consulting
9
9
  */
@@ -1 +1 @@
1
- import{matchesFilter as u}from"./matchesFilter";import{getValueType as f}from"../fieldTypeRegistry.store";function d(t,i,a){const o=Object.entries(i);return o.length===0?t:t.filter(n=>o.every(([r,l])=>{const e=a.fields[r]?.type||"text";return u(n[r],l,e)}))}function c(t){if(t.search?.fields&&t.search.fields.length>0)return t.search.fields;const i=new Set(["string"]),a=[];for(const[o,n]of Object.entries(t.fields)){if(n.visibility==="hidden"||n.visibility==="technical")continue;const r=f(n.type);r&&i.has(r)&&a.push(o)}return a}function m(t,i,a){if(!i||i.trim()==="")return t;const o=i.toLowerCase(),n=c(a);return n.length===0?t.filter(r=>Object.values(r).some(l=>l==null?!1:String(l).toLowerCase().includes(o))):t.filter(r=>n.some(l=>{const e=r[l];return e==null?!1:typeof e=="object"&&"formatted_address"in e?String(e.formatted_address).toLowerCase().includes(o):String(e).toLowerCase().includes(o)}))}function p(t,i){const{field:a,direction:o="asc"}=i,n=o==="desc"?-1:1;return[...t].sort((r,l)=>{const e=r[a],s=l[a];return e==null&&s==null?0:e==null?1:s==null?-1:typeof e=="number"&&typeof s=="number"?(e-s)*n:typeof e=="object"&&"amount"in e&&typeof s=="object"&&"amount"in s?(e.amount-s.amount)*n:e instanceof Date&&s instanceof Date?(e.getTime()-s.getTime())*n:String(e).localeCompare(String(s))*n})}export{d as applyFilters,m as applySearch,p as applySort,c as getSearchableFields};
1
+ import{matchesFilter as u}from"./matchesFilter";import{getValueType as c}from"../fieldTypeRegistry.store";function g(t,l,s){const o=Object.entries(l);return o.length===0?t:t.filter(r=>o.every(([i,f])=>{const n=s.fields[i]?.type||"text";return u(r[i],f,n)}))}function a(t){if(t.search?.fields&&t.search.fields.length>0)return t.search.fields;const l=new Set(["string"]),s=[];for(const[o,r]of Object.entries(t.fields)){if(r.visibility==="hidden"||r.visibility==="technical")continue;const i=c(r.type);i&&l.has(i)&&s.push(o)}return s}function h(t,l,s){if(!l||l.trim()==="")return t;const o=l.toLowerCase(),r=a(s);return r.length===0?t.filter(i=>Object.values(i).some(f=>f==null?!1:String(f).toLowerCase().includes(o))):t.filter(i=>r.some(f=>{const e=i[f];return e==null?!1:typeof e=="object"&&"formatted_address"in e?String(e.formatted_address).toLowerCase().includes(o):String(e).toLowerCase().includes(o)}))}function b(t,l){const{field:s,direction:o="asc"}=l,r=o==="desc"?-1:1;return[...t].sort((i,f)=>{const e=i[s],n=f[s];return e==null&&n==null?0:e==null?1:n==null?-1:typeof e=="number"&&typeof n=="number"?(e-n)*r:typeof e=="object"&&"amount"in e&&typeof n=="object"&&"amount"in n?(e.amount-n.amount)*r:e instanceof Date&&n instanceof Date?(e.getTime()-n.getTime())*r:String(e).localeCompare(String(n))*r})}export{g as applyFilters,h as applySearch,b as applySort,a as getSearchableFields};
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Collection utilities
3
3
  * @description Utilities for working with collections and subcollections
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -10,7 +10,7 @@ import type { dndevSchema } from '@donotdev/core';
10
10
  /**
11
11
  * Deterministic subcollection configuration
12
12
  *
13
- * @version 0.0.1
13
+ * @version 0.1.0
14
14
  * @since 0.0.1
15
15
  * @author AMBROISE PARK Consulting
16
16
  */
@@ -26,7 +26,7 @@ export interface DeterministicSubcollectionConfig<T> {
26
26
  /**
27
27
  * Append subcollection configuration
28
28
  *
29
- * @version 0.0.1
29
+ * @version 0.1.0
30
30
  * @since 0.0.1
31
31
  * @author AMBROISE PARK Consulting
32
32
  */
@@ -38,7 +38,7 @@ export interface AppendSubcollectionConfig<T> {
38
38
  /**
39
39
  * Load a deterministic range of items from a subcollection
40
40
  *
41
- * @version 0.0.1
41
+ * @version 0.1.0
42
42
  * @since 0.0.1
43
43
  * @author AMBROISE PARK Consulting
44
44
  */
@@ -46,7 +46,7 @@ export declare function loadDeterministicRange<T>(userId: string, config: Determ
46
46
  /**
47
47
  * Upsert a deterministic range of items in a subcollection
48
48
  *
49
- * @version 0.0.1
49
+ * @version 0.1.0
50
50
  * @since 0.0.1
51
51
  * @author AMBROISE PARK Consulting
52
52
  */
@@ -54,7 +54,7 @@ export declare function upsertDeterministic<T>(userId: string, config: Determini
54
54
  /**
55
55
  * Append an item to a subcollection
56
56
  *
57
- * @version 0.0.1
57
+ * @version 0.1.0
58
58
  * @since 0.0.1
59
59
  * @author AMBROISE PARK Consulting
60
60
  */
@@ -1 +1 @@
1
- import{getCrudService as i}from"../CrudService";async function p(a,t){const e=i(),s=[],o=t.range?.start??1,c=t.range?.end??28;for(let r=o;r<=c;r++){const m=String(r),n=await e.get(t.path(a),m,t.schema);n&&s.push(n)}return s}async function d(a,t,e){const s=i();for(const o of e){const c=t.idOf(o);await s.set(t.path(a),c,o,t.schema)}}async function h(a,t,e){const s=i();if(t.idFrom){const o=t.idFrom(e);return s.set(t.path(a),o,e,t.schema)}return s.add(t.path(a),e,t.schema)}export{h as appendToCollection,p as loadDeterministicRange,d as upsertDeterministic};
1
+ import{getCrudService as o}from"../CrudService";async function u(s,t){const e=o(),r=[],a=t.range?.start??1,n=t.range?.end??28;for(let c=a;c<=n;c++){const i=String(c),d=await e.get(t.path(s),i,t.schema);d&&r.push(d)}return r}async function m(s,t,e){const r=o();for(const a of e){const n=t.idOf(a);await r.set(t.path(s),n,a,t.schema)}}async function h(s,t,e){const r=o();if(t.idFrom){const a=t.idFrom(e);return r.set(t.path(s),a,e,t.schema)}return r.add(t.path(s),e,t.schema)}export{h as appendToCollection,u as loadDeterministicRange,m as upsertDeterministic};
@@ -1 +1 @@
1
- "use client";import{handleError as p,getProvider as d}from"@donotdev/core";function x(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function u(e,t={}){const{storagePath:r="uploads/files",filename:s,onProgress:o}=t,n=Date.now(),i=x(e.name),c=s||`${n}_${i}`,l=`${r}/${c}`;try{return{url:(await d("storage").upload(e,{storagePath:r,filename:c,onProgress:o?a=>o({bytesTransferred:0,totalBytes:0,progress:a}):void 0})).url,filename:e.name,size:e.size,mimeType:e.type,uploadedAt:new Date().toISOString()}}catch(a){throw p(a,{userMessage:"Failed to upload file",severity:"error",context:{filename:e.name,fileSize:e.size}})}}async function h(e,t={}){const r=[],s=e.reduce((n,i)=>n+i.size,0);let o=0;for(const n of e){const i=t.onProgress?l=>{const a=l.bytesTransferred/l.totalBytes*n.size;t.onProgress({bytesTransferred:o+a,totalBytes:s,progress:(o+a)/s*100})}:void 0,c=await u(n,{...t,onProgress:i});r.push(c),o+=n.size}return r}async function w(e){try{await d("storage").delete(e.url)}catch(t){throw p(t,{userMessage:"Failed to delete file",severity:"error",context:{url:e.url,filename:e.filename}}),t}}function v(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}function f(e){const t=e.split(".");return t.length>1?t.pop().toLowerCase():""}function y(e,t){const r=t?f(t):"";if(e){if(e.startsWith("image/"))return"image";if(e.startsWith("video/"))return"video";if(e.startsWith("audio/"))return"audio";if(e==="application/pdf")return"pdf";if(e.includes("word")||e.includes("document"))return"doc";if(e.includes("excel")||e.includes("spreadsheet"))return"xls";if(e.includes("powerpoint")||e.includes("presentation"))return"ppt"}switch(r){case"pdf":return"pdf";case"doc":case"docx":return"doc";case"xls":case"xlsx":case"csv":return"xls";case"ppt":case"pptx":return"ppt";case"md":case"txt":return"text";case"html":case"htm":return"html";case"zip":case"rar":case"7z":return"archive";default:return"file"}}function M(e){if(e===0)return"0 B";const t=1024,r=["B","KB","MB","GB"],s=Math.floor(Math.log(e)/Math.log(t));return`${parseFloat((e/Math.pow(t,s)).toFixed(1))} ${r[s]}`}const m=["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","text/plain","text/markdown","text/html","text/csv"],g=[".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".txt",".md",".html",".csv"];function F(){return[...m,...g].join(",")}export{g as DOCUMENT_EXTENSIONS,m as DOCUMENT_MIME_TYPES,w as deleteFile,M as formatFileSize,v as generateFileId,F as getDocumentAcceptString,f as getFileExtension,y as getFileIcon,u as uploadFile,h as uploadFiles};
1
+ "use client";import{handleError as u,getProvider as d}from"@donotdev/core";function f(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function x(e,t={}){const{storagePath:r="uploads/files",filename:n,onProgress:s}=t,o=Date.now(),a=f(e.name),c=n||`${o}_${a}`,l=`${r}/${c}`;try{return{url:(await d("storage").upload(e,{storagePath:r,filename:c,onProgress:s?p=>s({bytesTransferred:0,totalBytes:0,progress:p}):void 0})).url,filename:e.name,size:e.size,mimeType:e.type,uploadedAt:new Date().toISOString()}}catch(i){throw u(i,{userMessage:"Failed to upload file",severity:"error",context:{filename:e.name,fileSize:e.size}})}}async function v(e,t={}){const r=[],n=e.reduce((o,a)=>o+a.size,0);let s=0;for(const o of e){const a=t.onProgress?l=>{const i=l.bytesTransferred/l.totalBytes*o.size;t.onProgress({bytesTransferred:s+i,totalBytes:n,progress:(s+i)/n*100})}:void 0,c=await x(o,{...t,onProgress:a});r.push(c),s+=o.size}return r}async function F(e){try{await d("storage").delete(e.url)}catch(t){throw u(t,{userMessage:"Failed to delete file",severity:"error",context:{url:e.url,filename:e.filename}}),t}}function M(){return`${Date.now()}-${Math.random().toString(36).slice(2,9)}`}function g(e){const t=e.split(".");return t.length>1?t.pop().toLowerCase():""}function P(e,t){const r=t?g(t):"";if(e){if(e.startsWith("image/"))return"image";if(e.startsWith("video/"))return"video";if(e.startsWith("audio/"))return"audio";if(e==="application/pdf")return"pdf";if(e.includes("word")||e.includes("document"))return"doc";if(e.includes("excel")||e.includes("spreadsheet"))return"xls";if(e.includes("powerpoint")||e.includes("presentation"))return"ppt"}switch(r){case"pdf":return"pdf";case"doc":case"docx":return"doc";case"xls":case"xlsx":case"csv":return"xls";case"ppt":case"pptx":return"ppt";case"md":case"txt":return"text";case"html":case"htm":return"html";case"zip":case"rar":case"7z":return"archive";default:return"file"}}function S(e){if(e===0)return"0 B";const t=1024,r=["B","KB","MB","GB"],n=Math.floor(Math.log(e)/Math.log(t));return`${parseFloat((e/Math.pow(t,n)).toFixed(1))} ${r[n]}`}const h=["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","application/vnd.ms-powerpoint","application/vnd.openxmlformats-officedocument.presentationml.presentation","text/plain","text/markdown","text/html","text/csv"],m=[".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".txt",".md",".html",".csv"];function B(){return[...h,...m].join(",")}export{m as DOCUMENT_EXTENSIONS,h as DOCUMENT_MIME_TYPES,F as deleteFile,S as formatFileSize,M as generateFileId,B as getDocumentAcceptString,g as getFileExtension,P as getFileIcon,x as uploadFile,v as uploadFiles};
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Image Processing Utilities
3
3
  * @description Client-side image processing for WebP conversion, resizing, and thumbnail generation
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -1 +1 @@
1
- async function f(i,a={}){const{maxWidth:n=1920,maxHeight:h=1440,thumbWidth:s=300,thumbHeight:t=225,aspectRatio:e=4/3,quality:d=.85,crop:o}=a;return new Promise((w,l)=>{const r=new Image,c=new FileReader;c.onload=g=>{r.src=g.target?.result},c.onerror=()=>l(new Error("Failed to read file")),r.onload=async()=>{try{const{width:g,height:m}=v(o?o.width:r.width,o?o.height:r.height,n,h,e),F=await u(r,g,m,e,d,o),b=await u(r,s,t,e,.65,o);w({fullBlob:F,thumbBlob:b,width:g,height:m})}catch(g){l(g)}},r.onerror=()=>l(new Error("Failed to load image")),c.readAsDataURL(i)})}function v(i,a,n,h,s){let t=i,e=a;t>n&&(e=n/t*e,t=n),e>h&&(t=h/e*t,e=h);const d=t/e;return Math.abs(d-s)>.01&&(d>s?e=t/s:t=e*s),{width:Math.round(t),height:Math.round(e)}}async function u(i,a,n,h,s,t){const e=document.createElement("canvas"),d=e.getContext("2d");if(!d)throw new Error("Failed to get canvas context");e.width=a,e.height=n,d.fillStyle="#FFFFFF",d.fillRect(0,0,a,n);let o,w,l,r;if(t)o=t.x,w=t.y,l=t.width,r=t.height;else{const c=i.width/i.height;l=i.width,r=i.height,o=0,w=0,c>h?(l=i.height*h,o=(i.width-l)/2):c<h&&(r=i.width/h,w=(i.height-r)/2)}return d.drawImage(i,o,w,l,r,0,0,a,n),new Promise((c,g)=>{e.toBlob(m=>{m?c(m):g(new Error("Failed to convert canvas to blob"))},"image/webp",s)})}function x(i,a){return i.type.startsWith("image/")?a&&i.size>a?{valid:!1,error:`File size exceeds ${(a/1048576).toFixed(1)}MB limit`}:{valid:!0}:{valid:!1,error:"File must be an image"}}export{f as processImage,x as validateImageFile};
1
+ async function v(i,r={}){const{maxWidth:h=1920,maxHeight:l=1440,thumbWidth:d=300,thumbHeight:t=225,aspectRatio:e=4/3,quality:a=.85,crop:o}=r;return new Promise((w,s)=>{const n=new Image,c=new FileReader;c.onload=u=>{n.src=u.target?.result},c.onerror=()=>s(new Error("Failed to read file")),n.onload=async()=>{try{const{width:u,height:f}=m(o?o.width:n.width,o?o.height:n.height,h,l,e),b=await F(n,u,f,e,a,o),g=await F(n,d,t,e,.65,o);w({fullBlob:b,thumbBlob:g,width:u,height:f})}catch(u){s(u)}},n.onerror=()=>s(new Error("Failed to load image")),c.readAsDataURL(i)})}function m(i,r,h,l,d){let t=i,e=r;t>h&&(e=h/t*e,t=h),e>l&&(t=l/e*t,e=l);const a=t/e;return Math.abs(a-d)>.01&&(a>d?e=t/d:t=e*d),{width:Math.round(t),height:Math.round(e)}}async function F(i,r,h,l,d,t){const e=document.createElement("canvas"),a=e.getContext("2d");if(!a)throw new Error("Failed to get canvas context");e.width=r,e.height=h,a.fillStyle="#FFFFFF",a.fillRect(0,0,r,h);let o,w,s,n;if(t)o=t.x,w=t.y,s=t.width,n=t.height;else{const c=i.width/i.height;s=i.width,n=i.height,o=0,w=0,c>l?(s=i.height*l,o=(i.width-s)/2):c<l&&(n=i.width/l,w=(i.height-n)/2)}return a.drawImage(i,o,w,s,n,0,0,r,h),new Promise((c,u)=>{e.toBlob(f=>{f?c(f):u(new Error("Failed to convert canvas to blob"))},"image/webp",d)})}function x(i,r){return i.type.startsWith("image/")?r&&i.size>r?{valid:!1,error:`File size exceeds ${(r/1048576).toFixed(1)}MB limit`}:{valid:!0}:{valid:!1,error:"File must be an image"}}export{v as processImage,x as validateImageFile};
@@ -1 +1 @@
1
- import{handleError as f,getProvider as c}from"@donotdev/core";function y(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function $(e,t,a,h={}){const{storagePath:l="uploads/images",filename:m,onProgress:o}=h,w=Date.now(),r=(m||`${w}_${y(a)}`).replace(/\.[^/.]+$/,""),b=`${l}/${r}_full.webp`,d=`${l}/${r}_thumb.webp`;try{const n=new File([e],`${r}_full.webp`,{type:"image/webp"}),s=new File([t],`${r}_thumb.webp`,{type:"image/webp"});let i,p;const g=c("storage");return i=(await g.upload(n,{storagePath:l,filename:`${r}_full.webp`,onProgress:o?u=>o({bytesTransferred:0,totalBytes:0,progress:u*.5}):void 0})).url,p=(await g.upload(s,{storagePath:l,filename:`${r}_thumb.webp`,onProgress:o?u=>o({bytesTransferred:0,totalBytes:0,progress:50+u*.5}):void 0})).url,{fullUrl:i,thumbUrl:p}}catch(n){try{const s=c("storage");await s.delete(b).catch(()=>{}),await s.delete(d).catch(()=>{})}catch{}throw n}}async function _(e){try{const t=c("storage"),a=[t.delete(e.fullUrl)];e.thumbUrl&&a.push(t.delete(e.thumbUrl)),await Promise.all(a)}catch(t){throw f(t,{userMessage:"Failed to delete image",severity:"error",context:{fullUrl:e.fullUrl,thumbUrl:e.thumbUrl}}),t}}export{_ as deleteImage,$ as uploadImage};
1
+ import{handleError as w,getProvider as m}from"@donotdev/core";function y(e){return e.replace(/[^a-zA-Z0-9.-]/g,"_").replace(/_{2,}/g,"_").toLowerCase()}async function F(e,t,r,h={}){const{storagePath:a="uploads/images",filename:f,onProgress:s}=h,g=Date.now(),l=(f||`${g}_${y(r)}`).replace(/\.[^/.]+$/,""),d=`${a}/${l}_full.webp`,p=`${a}/${l}_thumb.webp`;try{const n=new File([e],`${l}_full.webp`,{type:"image/webp"}),o=new File([t],`${l}_thumb.webp`,{type:"image/webp"});let c,i;const b=m("storage");return c=(await b.upload(n,{storagePath:a,filename:`${l}_full.webp`,onProgress:s?u=>s({bytesTransferred:0,totalBytes:0,progress:u*.5}):void 0})).url,i=(await b.upload(o,{storagePath:a,filename:`${l}_thumb.webp`,onProgress:s?u=>s({bytesTransferred:0,totalBytes:0,progress:50+u*.5}):void 0})).url,{fullUrl:c,thumbUrl:i}}catch(n){try{const o=m("storage");await o.delete(d).catch(()=>{}),await o.delete(p).catch(()=>{})}catch{}throw n}}async function x(e){try{const t=m("storage"),r=[t.delete(e.fullUrl)];e.thumbUrl&&r.push(t.delete(e.thumbUrl)),await Promise.all(r)}catch(t){throw w(t,{userMessage:"Failed to delete image",severity:"error",context:{fullUrl:e.fullUrl,thumbUrl:e.thumbUrl}}),t}}export{x as deleteImage,F as uploadImage};
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Image Utility Functions
3
3
  * @description Hash generation, FLIP rotation, deduplication, and local preview management
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -1 +1 @@
1
- async function d(e){const t=await e.arrayBuffer(),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(a=>a.toString(16).padStart(2,"0")).join("")}function h(e){return URL.createObjectURL(e)}function u(e){e.startsWith("blob:")&&URL.revokeObjectURL(e)}async function l(e){return new Promise((t,r)=>{const a=new Image,i=new FileReader;i.onload=n=>{if(!n.target?.result){r(new Error("Failed to read file"));return}a.src=n.target.result},i.onerror=()=>r(new Error("Failed to read file")),a.onload=()=>{const n=document.createElement("canvas"),o=n.getContext("2d");if(!o){r(new Error("Failed to get canvas context"));return}n.width=a.height,n.height=a.width,o.translate(n.width/2,n.height/2),o.rotate(Math.PI/2),o.drawImage(a,-a.width/2,-a.height/2),n.toBlob(s=>{if(s){const c=new File([s],e.name,{type:e.type,lastModified:Date.now()});t(c)}else r(new Error("Failed to create blob from canvas"))},e.type,.95)},a.onerror=()=>r(new Error("Failed to load image")),i.readAsDataURL(e)})}class g{undoStack=[];redoStack=[];maxStackSize=50;push(t){this.undoStack.push(t),this.undoStack.length>this.maxStackSize&&this.undoStack.shift(),this.redoStack=[]}undo(){const t=this.undoStack.pop();return t?(this.redoStack.push(t),t):null}redo(){const t=this.redoStack.pop();return t?(this.undoStack.push(t),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}function S(e,t){return e.filter(r=>r.hash===t)}function w(){return`img_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}export{g as UndoRedoManager,h as createPreviewURL,S as findDuplicatesByHash,d as generateFileHash,w as generateImageId,u as revokePreviewURL,l as rotateImage90};
1
+ async function d(e){const t=await e.arrayBuffer(),r=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(r)).map(o=>o.toString(16).padStart(2,"0")).join("")}function h(e){return URL.createObjectURL(e)}function u(e){e.startsWith("blob:")&&URL.revokeObjectURL(e)}async function l(e){return new Promise((t,r)=>{const a=new Image,o=new FileReader;o.onload=n=>{if(!n.target?.result){r(new Error("Failed to read file"));return}a.src=n.target.result},o.onerror=()=>r(new Error("Failed to read file")),a.onload=()=>{const n=document.createElement("canvas"),i=n.getContext("2d");if(!i){r(new Error("Failed to get canvas context"));return}n.width=a.height,n.height=a.width,i.translate(n.width/2,n.height/2),i.rotate(Math.PI/2),i.drawImage(a,-a.width/2,-a.height/2),n.toBlob(s=>{if(s){const c=new File([s],e.name,{type:e.type,lastModified:Date.now()});t(c)}else r(new Error("Failed to create blob from canvas"))},e.type,.95)},a.onerror=()=>r(new Error("Failed to load image")),o.readAsDataURL(e)})}class f{undoStack=[];redoStack=[];maxStackSize=50;push(t){this.undoStack.push(t),this.undoStack.length>this.maxStackSize&&this.undoStack.shift(),this.redoStack=[]}undo(){const t=this.undoStack.pop();return t?(this.redoStack.push(t),t):null}redo(){const t=this.redoStack.pop();return t?(this.undoStack.push(t),t):null}canUndo(){return this.undoStack.length>0}canRedo(){return this.redoStack.length>0}clear(){this.undoStack=[],this.redoStack=[]}}function g(e,t){return e.filter(r=>r.hash===t)}function p(){return`img_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}export{f as UndoRedoManager,h as createPreviewURL,g as findDuplicatesByHash,d as generateFileHash,p as generateImageId,u as revokePreviewURL,l as rotateImage90};
@@ -1 +1 @@
1
- {"version":3,"file":"matchesFilter.d.ts","sourceRoot":"","sources":["../../src/utils/matchesFilter.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EAEd,WAAW,EACP,MAAM,GACN;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,MAAM,EAAE,GACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IACE,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EAErC,SAAS,EAAE,MAAM,GAChB,OAAO,CA+VT"}
1
+ {"version":3,"file":"matchesFilter.d.ts","sourceRoot":"","sources":["../../src/utils/matchesFilter.ts"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,GAAG,EAEd,WAAW,EACP,MAAM,GACN;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9B,MAAM,EAAE,GACR;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B;IACE,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC,GACD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EAErC,SAAS,EAAE,MAAM,GAChB,OAAO,CA8VT"}
@@ -1 +1 @@
1
- import{getFilterType as N}from"../fieldTypeRegistry.store";function S(t,n,e){if(!n)return!0;if(Array.isArray(n)){if(n.length===0)return!0;if(!(N(e)==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp")))return n.some(a=>{if(typeof a=="object"&&"date"in a){const D=a.date;if(t==null)return!1;const m=t instanceof Date?t:new Date(t);return isNaN(m.getTime())?!1:m.toISOString().split("T")[0]===D}return String(t)===String(a)});if(t==null)return!1;const i=t instanceof Date?t:new Date(t);if(isNaN(i.getTime()))return!1;const o=i.toISOString().split("T")[0];return n.some(a=>typeof a=="string"?o===a:typeof a=="object"&&"date"in a?o===a.date:!1)}if(typeof n=="object"&&"date"in n&&!("min"in n)&&!Array.isArray(n)){if(!(N(e)==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp")))return!1;const i=n.date;if(!i)return!0;if(t==null)return!1;const o=t instanceof Date?t.toISOString().split("T")[0]:new Date(t).toISOString().split("T")[0];if((e==="datetime-local"||e==="timestamp")&&n.time){const a=t instanceof Date?t.toISOString().slice(11,16):new Date(t).toISOString().slice(11,16);return o===i&&a===n.time}return o===i}if(typeof n=="object"&&"min"in n){const i=N(e);if(!i)return!0;const o=i==="range"&&(e==="date"||e==="datetime-local"||e==="timestamp"),a=i==="range"&&!o,D=e==="price",m=D&&t!=null&&typeof t=="object"?Number(t.amount):a&&t!=null?typeof t=="number"?t:Number(t):NaN;if(a||D){if(typeof n.min=="object"&&n.min!==null&&"date"in n.min)return!1;const r=n,c=typeof r.min=="string"&&r.min!=="",g=typeof r.max=="string"&&r.max!=="";return c&&!g?t==null||isNaN(m)?!1:m>=Number(r.min):!c&&g?t==null?!0:isNaN(m)?!1:m<=Number(r.max):c&&g?t==null||isNaN(m)?!1:m>=Number(r.min)&&m<=Number(r.max):!0}if(o){if(typeof n.min=="object"&&n.min!==null&&"date"in n.min&&!("min"in n.min)){const s=n,l=s.min,u=s.max,w=l?.date&&l.date!=="",y=u?.date&&u.date!=="";if(w&&!y){if(t==null)return!1;const f=t instanceof Date?t:new Date(t);if(isNaN(f.getTime()))return!1;const d=new Date(l.date+(l.time?`T${l.time}:00`:"T00:00:00"));return f>=d}if(!w&&y&&u){if(t==null)return!0;const f=t instanceof Date?t:new Date(t);if(isNaN(f.getTime()))return!1;const d=new Date(u.date+(u.time?`T${u.time}:00`:"T23:59:59"));return f<=d}if(w&&y&&u){if(t==null)return!1;const f=t instanceof Date?t:new Date(t);if(isNaN(f.getTime()))return!1;const d=new Date(l.date+(l.time?`T${l.time}:00`:"T00:00:00")),T=new Date(u.date+(u.time?`T${u.time}:00`:"T23:59:59"));return f>=d&&f<=T}return!0}const r=n,c=typeof r.min=="string"&&r.min!=="",g=typeof r.max=="string"&&r.max!=="";if(c&&!g){if(t==null)return!1;const s=t instanceof Date?t:new Date(t);return isNaN(s.getTime())?!1:s>=new Date(r.min)}if(!c&&g){if(t==null)return!0;const s=t instanceof Date?t:new Date(t);return isNaN(s.getTime())?!1:s<=new Date(r.max)}if(c&&g){if(t==null)return!1;const s=t instanceof Date?t:new Date(t);return isNaN(s.getTime())?!1:s>=new Date(r.min)&&s<=new Date(r.max)}return!0}}if(typeof n=="string"&&N(e)==="rating"){if(t==null)return!1;const i=Number(n),o=typeof t=="number"?t:Number(t);return isNaN(i)||isNaN(o)?!1:o>=i}const p=N(e);if(!p)return!0;if(p==="address")return t==null?!1:typeof t=="object"&&"formatted_address"in t?String(t.formatted_address).toLowerCase().includes(String(n).toLowerCase()):!1;if(p==="multiselect"){if(!Array.isArray(t)||t.length===0)return!1;const i=String(n).toLowerCase();return t.some(o=>String(o).toLowerCase().includes(i))}return t==null?!1:String(t).toLowerCase().includes(String(n).toLowerCase())}export{S as matchesFilter};
1
+ import{getFilterType as w}from"../fieldTypeRegistry.store";function T(n,t,s){if(!t)return!0;if(Array.isArray(t)){if(t.length===0)return!0;if(!(w(s)==="range"&&(s==="date"||s==="datetime-local"||s==="timestamp")))return t.some(r=>{if(typeof r=="object"&&"date"in r){const e=r.date;if(n==null)return!1;const f=n instanceof Date?n:new Date(n);return isNaN(f.getTime())?!1:f.toISOString().split("T")[0]===e}return String(n)===String(r)});if(n==null)return!1;const d=n instanceof Date?n:new Date(n);if(isNaN(d.getTime()))return!1;const D=d.toISOString().split("T")[0];return t.some(r=>typeof r=="string"?D===r:typeof r=="object"&&"date"in r?D===r.date:!1)}if(typeof t=="object"&&"date"in t&&!("min"in t)&&!Array.isArray(t)){if(!(w(s)==="range"&&(s==="date"||s==="datetime-local"||s==="timestamp")))return!1;const d=t.date;if(!d)return!0;if(n==null)return!1;const D=n instanceof Date?n.toISOString().split("T")[0]:new Date(n).toISOString().split("T")[0];if((s==="datetime-local"||s==="timestamp")&&t.time){const r=n instanceof Date?n.toISOString().slice(11,16):new Date(n).toISOString().slice(11,16);return D===d&&r===t.time}return D===d}if(typeof t=="object"&&"min"in t){const i=w(s);if(!i)return!0;const c=i==="range"&&(s==="date"||s==="datetime-local"||s==="timestamp"),d=i==="range"&&!c,D=s==="price",r=D&&n!=null&&typeof n=="object"?Number(n.amount):d&&n!=null?typeof n=="number"?n:Number(n):NaN;if(d||D){if(typeof t.min=="object"&&t.min!==null&&"date"in t.min)return!1;const e=t,f=typeof e.min=="string"&&e.min!=="",p=typeof e.max=="string"&&e.max!=="";return f&&!p?n==null||isNaN(r)?!1:r>=Number(e.min):!f&&p?n==null?!0:isNaN(r)?!1:r<=Number(e.max):f&&p?n==null||isNaN(r)?!1:r>=Number(e.min)&&r<=Number(e.max):!0}if(c){if(typeof t.min=="object"&&t.min!==null&&"date"in t.min&&!("min"in t.min)){const o=t,N=o.min,a=o.max,m=N?.date&&N.date!=="",b=a?.date&&a.date!=="";if(m&&!b){if(n==null)return!1;const g=n instanceof Date?n:new Date(n);if(isNaN(g.getTime()))return!1;const u=new Date(N.date+(N.time?`T${N.time}:00`:"T00:00:00"));return g>=u}if(!m&&b&&a){if(n==null)return!0;const g=n instanceof Date?n:new Date(n);if(isNaN(g.getTime()))return!1;const u=new Date(a.date+(a.time?`T${a.time}:00`:"T23:59:59"));return g<=u}if(m&&b&&a){if(n==null)return!1;const g=n instanceof Date?n:new Date(n);if(isNaN(g.getTime()))return!1;const u=new Date(N.date+(N.time?`T${N.time}:00`:"T00:00:00")),y=new Date(a.date+(a.time?`T${a.time}:00`:"T23:59:59"));return g>=u&&g<=y}return!0}const e=t,f=typeof e.min=="string"&&e.min!=="",p=typeof e.max=="string"&&e.max!=="";if(f&&!p){if(n==null)return!1;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o>=new Date(e.min)}if(!f&&p){if(n==null)return!0;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o<=new Date(e.max)}if(f&&p){if(n==null)return!1;const o=n instanceof Date?n:new Date(n);return isNaN(o.getTime())?!1:o>=new Date(e.min)&&o<=new Date(e.max)}return!0}}if(typeof t=="string"&&w(s)==="rating"){if(n==null)return!1;const i=Number(t),c=typeof n=="number"?n:Number(n);return isNaN(i)||isNaN(c)?!1:c>=i}const S=w(s);if(!S)return!0;if(S==="address")return n==null?!1:typeof n=="object"&&"formatted_address"in n?String(n.formatted_address).toLowerCase().includes(String(t).toLowerCase()):!1;if(S==="multiselect"){if(!Array.isArray(n)||n.length===0)return!1;const i=String(t).toLowerCase();return n.some(c=>String(c).toLowerCase().includes(i))}return n==null?!1:String(n).toLowerCase().includes(String(t).toLowerCase())}export{T as matchesFilter};
@@ -1 +1 @@
1
- import{CRUD_OPERATION as a}from"../types";function n(e,s){const o=[],p=new Set;for(const i of e){const t=s[i.id];t?.operation!==a.DELETE&&(t?.operation===a.UPDATE&&t.optimisticData?o.push(t.optimisticData):o.push(i),p.add(i.id))}for(const[i,t]of Object.entries(s))t.operation===a.ADD&&!p.has(i)&&t.optimisticData&&o.push(t.optimisticData);return o}export{n as mergeWithOptimistic};
1
+ import{CRUD_OPERATION as e}from"../types";function r(a,s){const o=[],n=new Set;for(const i of a){const t=s[i.id];t?.operation!==e.DELETE&&(t?.operation===e.UPDATE&&t.optimisticData?o.push(t.optimisticData):o.push(i),n.add(i.id))}for(const[i,t]of Object.entries(s))t.operation===e.ADD&&!n.has(i)&&t.optimisticData&&o.push(t.optimisticData);return o}export{r as mergeWithOptimistic};
@@ -1,7 +1,2 @@
1
- /**
2
- * Sanitize HTML using DOMPurify — handles all known XSS vectors including
3
- * malformed tags, event handlers, javascript: URIs, data: URIs, SVG payloads,
4
- * CSS injection, and HTML entity encoding bypasses.
5
- */
6
1
  export declare function sanitizeHtml(html: string): string;
7
2
  //# sourceMappingURL=sanitizeHtml.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sanitizeHtml.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizeHtml.ts"],"names":[],"mappings":"AAaA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
1
+ {"version":3,"file":"sanitizeHtml.d.ts","sourceRoot":"","sources":["../../src/utils/sanitizeHtml.ts"],"names":[],"mappings":"AA6DA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGjD"}
@@ -1 +1 @@
1
- import t from"dompurify";function n(i){return t.sanitize(i)}export{n as sanitizeHtml};
1
+ import e from"dompurify";const r=["p","h1","h2","h3","h4","h5","h6","blockquote","pre","hr","ul","ol","li","a","strong","b","em","i","u","s","code","br","span","sub","sup","mark","table","thead","tbody","tr","th","td","img","div","figure","figcaption","details","summary"],i=["href","target","rel","src","alt","width","height","class","colspan","rowspan"],a=/<\/?(?:embed|source|track|area|wbr)[^>]*>/gi;function n(t){return e.sanitize(t,{ALLOWED_TAGS:r,ALLOWED_ATTR:i}).replace(a,"")}export{n as sanitizeHtml};
@@ -1 +1 @@
1
- import{getScopeValue as t,CRUD_OPERATORS as c}from"@donotdev/core";function s(r,e){if(!e)return r;const o=t(e.provider);if(!o)throw new Error(`[CRUD] Scope provider "${e.provider}" returned null. Cannot write scoped entity without a scope value. Ensure a scope is selected before creating scoped entities.`);return{...r,[e.field]:o}}function p(r,e){const o=r??{};if(!e||typeof e.field!="string")return o;const n=t(e.provider);if(!n)throw new Error(`[CRUD] Scope provider "${e.provider}" returned null. Cannot query scoped entity without a scope value. Ensure a scope is selected before querying scoped entities.`);const i={field:e.field,operator:c.EQ,value:n};return{...o,where:o.where?[...o.where,i]:[i]}}function u(r){return r?t(r.provider):null}export{u as getCurrentScopeValue,s as injectScope,p as injectScopeFilter};
1
+ import{getScopeValue as o,CRUD_OPERATORS as p}from"@donotdev/core";function c(t,e){if(!e)return t;const r=o(e.provider);if(!r)throw new Error(`[CRUD] Scope provider "${e.provider}" returned null. Cannot write scoped entity without a scope value. Ensure a scope is selected before creating scoped entities.`);return{...t,[e.field]:r}}function l(t,e){const r=t??{};if(!e||typeof e.field!="string")return r;const i=o(e.provider);if(!i)throw new Error(`[CRUD] Scope provider "${e.provider}" returned null. Cannot query scoped entity without a scope value. Ensure a scope is selected before querying scoped entities.`);const n={field:e.field,operator:p.EQ,value:i};return{...r,where:r.where?[...r.where,n]:[n]}}function s(t){return t?o(t.provider):null}export{s as getCurrentScopeValue,c as injectScope,l as injectScopeFilter};
@@ -3,7 +3,7 @@
3
3
  * @description Type-safe validation utilities to ensure no blob URLs reach the database.
4
4
  * Provides security checks for Picture objects and form data validation.
5
5
  *
6
- * @version 0.0.1
6
+ * @version 0.1.0
7
7
  * @since 0.0.1
8
8
  * @author AMBROISE PARK Consulting
9
9
  */
@@ -1 +1 @@
1
- "use client";function o(r){return!r||typeof r!="string"?!1:r.startsWith("https://")&&!r.startsWith("blob:")}function h(r){return!(!r||typeof r!="object"||!o(r.fullUrl)||r.thumbUrl&&!o(r.thumbUrl))}function i(r,l=""){const t=[];if(r==null)return t;if(typeof r=="string")return r.startsWith("blob:")&&t.push(l||"root"),t;if(typeof r!="object")return t;if(Array.isArray(r))r.forEach((e,s)=>{const n=l?`${l}[${s}]`:`[${s}]`;t.push(...i(e,n))});else{const e=r;if(e.fullUrl!==void 0&&e.thumbUrl!==void 0){const s=e.fullUrl,n=e.thumbUrl,u=typeof s=="string"&&!o(s),c=n&&typeof n=="string"&&!o(n);if(u||c){const f=l||"root";t.push(`${f}.fullUrl or ${f}.thumbUrl contains blob URL`)}}else Object.entries(e).forEach(([s,n])=>{const u=l?`${l}.${s}`:s;t.push(...i(n,u))})}return t}function b(r){return i(r).length>0}export{i as checkForBlobUrls,b as hasBlobUrls,o as isStorageUrl,h as validatePicture};
1
+ "use client";function s(r){return!r||typeof r!="string"?!1:r.startsWith("https://")&&!r.startsWith("blob:")}function c(r){return!(!r||typeof r!="object"||!s(r.fullUrl)||r.thumbUrl&&!s(r.thumbUrl))}function u(r,o=""){const t=[];if(r==null)return t;if(typeof r=="string")return r.startsWith("blob:")&&t.push(o||"root"),t;if(typeof r!="object")return t;if(Array.isArray(r))r.forEach((e,n)=>{const l=o?`${o}[${n}]`:`[${n}]`;t.push(...u(e,l))});else{const e=r;if(e.fullUrl!==void 0&&e.thumbUrl!==void 0){const n=e.fullUrl,l=e.thumbUrl,f=typeof n=="string"&&!s(n),b=l&&typeof l=="string"&&!s(l);if(f||b){const i=o||"root";t.push(`${i}.fullUrl or ${i}.thumbUrl contains blob URL`)}}else Object.entries(e).forEach(([n,l])=>{const f=o?`${o}.${n}`:n;t.push(...u(l,f))})}return t}function h(r){return u(r).length>0}export{u as checkForBlobUrls,h as hasBlobUrls,s as isStorageUrl,c as validatePicture};
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Workflow persistence adapter
3
3
  * @description Saves and restores workflow progress to/from localStorage.
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -1 +1 @@
1
- const a="dndev-workflow-";function r(t,o){try{const e=`${a}${t}`;localStorage.setItem(e,JSON.stringify(o))}catch{}}function c(t){try{const o=`${a}${t}`,e=localStorage.getItem(o);return e?JSON.parse(e):null}catch{return null}}function n(t){try{const o=`${a}${t}`;localStorage.removeItem(o)}catch{}}export{n as clearWorkflowState,c as loadWorkflowState,r as saveWorkflowState};
1
+ const r="dndev-workflow-";function c(t,o){try{const e=`${r}${t}`;localStorage.setItem(e,JSON.stringify(o))}catch{}}function n(t){try{const o=`${r}${t}`,e=localStorage.getItem(o);return e?JSON.parse(e):null}catch{return null}}function a(t){try{const o=`${r}${t}`;localStorage.removeItem(o)}catch{}}export{a as clearWorkflowState,n as loadWorkflowState,c as saveWorkflowState};
@@ -18,7 +18,7 @@
18
18
  * });
19
19
  * ```
20
20
  *
21
- * @version 0.0.1
21
+ * @version 0.1.0
22
22
  * @since 0.0.1
23
23
  * @author AMBROISE PARK Consulting
24
24
  */
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Workflow engine exports
3
3
  * @description Multi-step entity workflow: defineWorkflow, useEntityWorkflow, persistence.
4
4
  *
5
- * @version 0.0.1
5
+ * @version 0.1.0
6
6
  * @since 0.0.1
7
7
  * @author AMBROISE PARK Consulting
8
8
  */
@@ -1 +1 @@
1
- import{defineWorkflow as o}from"./defineWorkflow";import{useEntityWorkflow as a}from"./useEntityWorkflow";import{saveWorkflowState as t,loadWorkflowState as r,clearWorkflowState as e}from"./WorkflowPersistence";export{e as clearWorkflowState,o as defineWorkflow,r as loadWorkflowState,t as saveWorkflowState,a as useEntityWorkflow};
1
+ import{defineWorkflow as e}from"./defineWorkflow";import{useEntityWorkflow as f}from"./useEntityWorkflow";import{saveWorkflowState as a,loadWorkflowState as k,clearWorkflowState as w}from"./WorkflowPersistence";export{w as clearWorkflowState,e as defineWorkflow,k as loadWorkflowState,a as saveWorkflowState,f as useEntityWorkflow};
@@ -1 +1 @@
1
- "use client";import{useState as g,useCallback as p,useMemo as h,useEffect as L,useRef as M}from"react";import{evaluateCondition as R}from"@donotdev/core";import{saveWorkflowState as K,loadWorkflowState as j,clearWorkflowState as C}from"./WorkflowPersistence";function V(e,I={}){const{onComplete:m,onStepChange:f,defaultValues:y}=I,w=M(m);w.current=m;const[a,v]=g(()=>{if(e.persist){const t=j(e.persistKey??e.id);if(t)return t.stepData}if(y){const t={};for(const r of e.steps)if(r.entity&&r.fields){const o={};for(const i of r.fields)i in y&&(o[i]=y[i]);Object.keys(o).length>0&&(t[r.id]=o)}return t}return{}}),[s,S]=g(()=>{if(e.persist){const t=j(e.persistKey??e.id);if(t)return t.currentStepIndex}return 0}),[k,x]=g(!1),l=h(()=>{const t={};for(const[r,o]of Object.entries(a))for(const[i,c]of Object.entries(o))t[i]=c,t[`${r}.${i}`]=c;return t},[a]),n=h(()=>e.steps.filter(t=>t.conditions?.visible?R(t.conditions.visible,l):!0),[e.steps,l]),O=n[s]??n[0],b=s===0,d=s===n.length-1;L(()=>{e.persist&&K(e.persistKey??e.id,{currentStepIndex:s,stepData:a,savedAt:Date.now()})},[e.persist,e.persistKey,e.id,s,a]);const W=p(async t=>{const r=n[s];if(!r)return!1;if(t&&v(i=>({...i,[r.id]:{...i[r.id],...t}})),r.validation?.validate){const i={...l,...t??{}};if(r.validation.validate(i)!==!0)return!1}if(r.after){const i={};await r.after({data:t??a[r.id]??{},allData:{...l,...t??{}},next:{prefill:c=>{const u=n[s+1];u&&(i[u.id]=c)}}}),Object.keys(i).length>0&&v(c=>{const u={...c};for(const[D,G]of Object.entries(i))u[D]={...u[D],...G};return u})}if(d){x(!0);try{const i={...l,...t??{}},c=w.current??e.onComplete;return c&&await c(i),e.persist&&C(e.persistKey??e.id),!0}catch{return!1}finally{x(!1)}}const o=s+1;return S(o),f?.(s,o),!0},[n,s,l,a,d,e,f]),N=p(()=>{if(b)return;const t=s-1;S(t),f?.(s,t)},[s,b,f]),A=p(()=>{if(!n[s]?.allowSkip||d)return;const t=s+1;S(t),f?.(s,t)},[n,s,d,f]),E=p(t=>{t>=0&&t<n.length&&(f?.(s,t),S(t))},[n.length,s,f]),P=p(()=>{e.persist&&K(e.persistKey??e.id,{currentStepIndex:s,stepData:a,savedAt:Date.now()})},[e,s,a]),$=p(()=>{C(e.persistKey??e.id)},[e]),F=p((t,r)=>{v(o=>({...o,[t]:{...o[t],...r}}))},[]);return{currentStep:O,currentStepIndex:s,visibleSteps:n,stepData:a,allData:l,goNext:W,goPrevious:N,skipStep:A,goToStep:E,isFirst:b,isLast:d,isSubmitting:k,canGoNext:!k,persistNow:P,clearPersisted:$,prefillStep:F}}export{V as useEntityWorkflow};
1
+ "use client";import{useState as b,useCallback as p,useMemo as I,useEffect as G,useRef as L}from"react";import{evaluateCondition as M}from"@donotdev/core";import{saveWorkflowState as K,loadWorkflowState as j,clearWorkflowState as O}from"./WorkflowPersistence";function B(e,D={}){const{onComplete:k,onStepChange:u,defaultValues:y}=D,w=L(k);w.current=k;const[l,v]=b(()=>{if(e.persist){const t=j(e.persistKey??e.id);if(t)return t.stepData}if(y){const t={};for(const r of e.steps)if(r.entity&&r.fields){const o={};for(const i of r.fields)i in y&&(o[i]=y[i]);Object.keys(o).length>0&&(t[r.id]=o)}return t}return{}}),[s,m]=b(()=>{if(e.persist){const t=j(e.persistKey??e.id);if(t)return t.currentStepIndex}return 0}),[x,h]=b(!1),d=I(()=>{const t={};for(const[r,o]of Object.entries(l))for(const[i,a]of Object.entries(o))t[i]=a,t[`${r}.${i}`]=a;return t},[l]),n=I(()=>e.steps.filter(t=>t.conditions?.visible?M(t.conditions.visible,d):!0),[e.steps,d]),W=n[s]??n[0],S=s===0,c=s===n.length-1;G(()=>{e.persist&&K(e.persistKey??e.id,{currentStepIndex:s,stepData:l,savedAt:Date.now()})},[e.persist,e.persistKey,e.id,s,l]);const F=p(async t=>{const r=n[s];if(!r)return!1;if(t&&v(i=>({...i,[r.id]:{...i[r.id],...t}})),r.validation?.validate){const i={...d,...t??{}};if(r.validation.validate(i)!==!0)return!1}if(r.after){const i={};await r.after({data:t??l[r.id]??{},allData:{...d,...t??{}},next:{prefill:a=>{const f=n[s+1];f&&(i[f.id]=a)}}}),Object.keys(i).length>0&&v(a=>{const f={...a};for(const[C,$]of Object.entries(i))f[C]={...f[C],...$};return f})}if(c){h(!0);try{const i={...d,...t??{}},a=w.current??e.onComplete;return a&&await a(i),e.persist&&O(e.persistKey??e.id),!0}catch{return!1}finally{h(!1)}}const o=s+1;return m(o),u?.(s,o),!0},[n,s,d,l,c,e,u]),N=p(()=>{if(S)return;const t=s-1;m(t),u?.(s,t)},[s,S,u]),A=p(()=>{if(!n[s]?.allowSkip||c)return;const r=s+1;m(r),u?.(s,r)},[n,s,c,u]),E=p(t=>{t>=0&&t<n.length&&(u?.(s,t),m(t))},[n.length,s,u]),P=p(()=>{e.persist&&K(e.persistKey??e.id,{currentStepIndex:s,stepData:l,savedAt:Date.now()})},[e,s,l]),R=p(()=>{O(e.persistKey??e.id)},[e]),V=p((t,r)=>{v(o=>({...o,[t]:{...o[t],...r}}))},[]);return{currentStep:W,currentStepIndex:s,visibleSteps:n,stepData:l,allData:d,goNext:F,goPrevious:N,skipStep:A,goToStep:E,isFirst:S,isLast:c,isSubmitting:x,canGoNext:!x,persistNow:P,clearPersisted:R,prefillStep:V}}export{B as useEntityWorkflow};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donotdev/crud",
3
- "version": "0.0.31",
3
+ "version": "0.1.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -53,8 +53,8 @@
53
53
  "@dnd-kit/core": "^6.3.1",
54
54
  "@dnd-kit/sortable": "^10.0.0",
55
55
  "@dnd-kit/utilities": "^3.2.2",
56
- "@donotdev/components": "^0.0.33",
57
- "@donotdev/core": "^0.0.46",
56
+ "@donotdev/components": "^0.1.0",
57
+ "@donotdev/core": "^0.1.0",
58
58
  "@hookform/resolvers": "^5.2.2",
59
59
  "dompurify": "^3.3.2",
60
60
  "react-easy-crop": "^5.5.6"