@sdcorejs/angular 19.1.3 → 19.1.4

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 (295) hide show
  1. package/README.md +17 -14
  2. package/components/audit-diff/index.d.ts +2 -0
  3. package/components/audit-diff/src/audit-diff.component.d.ts +30 -0
  4. package/components/audit-diff/src/audit-diff.engine.d.ts +40 -0
  5. package/components/badge/src/badge.component.d.ts +1 -1
  6. package/components/breadcrumb/index.d.ts +1 -0
  7. package/components/breadcrumb/src/breadcrumb.component.d.ts +50 -0
  8. package/components/data-state/index.d.ts +1 -0
  9. package/components/data-state/src/data-state.component.d.ts +40 -0
  10. package/components/document-builder/src/components/header-footer-builder/header-footer-builder.component.d.ts +1 -2
  11. package/components/document-builder/src/document-builder.component.d.ts +4 -4
  12. package/components/form-generic/src/components/form-builder/components/attribute-expression/attribute-expression.component.d.ts +7 -8
  13. package/components/form-generic/src/components/form-builder/components/attribute-input/attribute-input.component.d.ts +4 -5
  14. package/components/form-generic/src/components/form-builder/components/attribute-input-number/attribute-input-number.component.d.ts +1 -2
  15. package/components/form-generic/src/components/form-builder/components/attribute-parameter/attribute-parameter.component.d.ts +6 -5
  16. package/components/form-generic/src/components/form-builder/components/attribute-select/attribute-select.component.d.ts +4 -5
  17. package/components/form-generic/src/components/form-builder/components/attribute-selection/attribute-selection.component.d.ts +9 -9
  18. package/components/form-generic/src/components/form-builder/components/attribute-selection/components/build-queries/build-queries.component.d.ts +8 -7
  19. package/components/form-generic/src/components/form-builder/components/attribute-selection/components/build-variables/build-variables.component.d.ts +8 -7
  20. package/components/form-generic/src/components/form-builder/components/attribute-switch/attribute-switch.component.d.ts +3 -4
  21. package/components/form-generic/src/components/form-builder/components/attribute-table/attribute-table.component.d.ts +5 -6
  22. package/components/form-generic/src/components/form-builder/components/attribute-template/attribute-template.component.d.ts +1 -2
  23. package/components/form-generic/src/components/form-builder/components/attribute-textarea/attribute-textarea.component.d.ts +4 -5
  24. package/components/form-generic/src/components/form-builder/components/checkbox/attribute/checkbox-attribute.component.d.ts +6 -6
  25. package/components/form-generic/src/components/form-builder/components/chip-calendar/attribute/chip-calendar-attribute.component.d.ts +6 -6
  26. package/components/form-generic/src/components/form-builder/components/chip-calendar/control/chip-calendar-control.component.d.ts +3 -3
  27. package/components/form-generic/src/components/form-builder/components/chip-string/attribute/chip-string-attribute.component.d.ts +6 -6
  28. package/components/form-generic/src/components/form-builder/components/chip-string/control/chip-string-control.component.d.ts +3 -3
  29. package/components/form-generic/src/components/form-builder/components/configure-validation/configure-validation.component.d.ts +2 -2
  30. package/components/form-generic/src/components/form-builder/components/datetime/attribute/datetime-attribute.component.d.ts +6 -6
  31. package/components/form-generic/src/components/form-builder/components/datetime/control/datetime-control.component.d.ts +3 -3
  32. package/components/form-generic/src/components/form-builder/components/expression-builder/expression-builder.component.d.ts +6 -5
  33. package/components/form-generic/src/components/form-builder/components/html/attribute/components/build-queries/build-queries.component.d.ts +7 -6
  34. package/components/form-generic/src/components/form-builder/components/html/attribute/html-attribute.component.d.ts +7 -8
  35. package/components/form-generic/src/components/form-builder/components/html/control/html-control.component.d.ts +3 -4
  36. package/components/form-generic/src/components/form-builder/components/number/attribute/number-attribute.component.d.ts +6 -6
  37. package/components/form-generic/src/components/form-builder/components/number/control/number-control.component.d.ts +3 -3
  38. package/components/form-generic/src/components/form-builder/components/radio/attribute/radio-attribute.component.d.ts +6 -6
  39. package/components/form-generic/src/components/form-builder/components/radio/control/radio-control.component.d.ts +3 -3
  40. package/components/form-generic/src/components/form-builder/components/select/attribute/select-attribute.component.d.ts +6 -6
  41. package/components/form-generic/src/components/form-builder/components/select/control/select-control.component.d.ts +3 -3
  42. package/components/form-generic/src/components/form-builder/components/table/attribute/table-attribute.component.d.ts +6 -6
  43. package/components/form-generic/src/components/form-builder/components/table/control/table-control.component.d.ts +3 -3
  44. package/components/form-generic/src/components/form-builder/components/textarea/attribute/textarea-attribute.component.d.ts +6 -6
  45. package/components/form-generic/src/components/form-builder/components/textarea/control/textarea-control.component.d.ts +3 -3
  46. package/components/form-generic/src/components/form-builder/components/textfield/attribute/textfield-attribute.component.d.ts +6 -6
  47. package/components/form-generic/src/components/form-builder/components/textfield/control/textfield-control.component.d.ts +3 -3
  48. package/components/form-generic/src/components/form-builder/components/upload/attribute/upload-attribute.component.d.ts +6 -6
  49. package/components/form-generic/src/components/form-builder/components/upload/control/upload-control.component.d.ts +3 -3
  50. package/components/form-generic/src/components/form-render/components/item/components/chip-calendar/chip-calendar.component.d.ts +7 -6
  51. package/components/form-generic/src/components/form-render/components/item/components/chip-string/chip-string.component.d.ts +7 -6
  52. package/components/form-generic/src/components/form-render/components/item/components/datetime/datetime.component.d.ts +7 -7
  53. package/components/form-generic/src/components/form-render/components/item/components/html/html.component.d.ts +6 -6
  54. package/components/form-generic/src/components/form-render/components/item/components/number/number.component.d.ts +7 -6
  55. package/components/form-generic/src/components/form-render/components/item/components/radio/radio.component.d.ts +6 -7
  56. package/components/form-generic/src/components/form-render/components/item/components/select/select.component.d.ts +6 -7
  57. package/components/form-generic/src/components/form-render/components/item/components/table/table.component.d.ts +8 -8
  58. package/components/form-generic/src/components/form-render/components/item/components/textarea/textarea.component.d.ts +7 -6
  59. package/components/form-generic/src/components/form-render/components/item/components/textfield/textfield.component.d.ts +7 -6
  60. package/components/form-generic/src/components/form-render/components/item/components/upload/upload.component.d.ts +7 -6
  61. package/components/form-generic/src/components/form-render/components/item/item.component.d.ts +4 -4
  62. package/components/form-generic/src/components/sd-feel-expression/sd-feel-expression.component.d.ts +8 -9
  63. package/components/form-generic/src/pipes/component-viewed.pipe.d.ts +2 -3
  64. package/components/form-generic/src/pipes/html.pipe.d.ts +2 -2
  65. package/components/form-generic/src/services/form-render.service.d.ts +2 -2
  66. package/components/import-excel/src/import-excel.component.d.ts +4 -7
  67. package/components/import-excel/src/pipes/column-transform.pipe.d.ts +3 -2
  68. package/components/index.d.ts +4 -0
  69. package/components/job-progress/index.d.ts +1 -0
  70. package/components/job-progress/src/job-progress.component.d.ts +34 -0
  71. package/components/mini-editor/src/mini-editor.component.d.ts +7 -7
  72. package/components/modal/src/modal.component.d.ts +6 -1
  73. package/components/preview/index.d.ts +3 -0
  74. package/components/preview/src/preview-pdf/preview-pdf.browser.d.ts +28 -0
  75. package/components/preview/src/preview-pdf/preview-pdf.component.d.ts +61 -23
  76. package/components/preview/src/preview-pdf/preview-pdf.pdfjs.d.ts +77 -0
  77. package/components/preview/src/preview-pdf/preview-pdf.print.d.ts +10 -0
  78. package/components/preview/src/preview-pdf/preview-pdf.types.d.ts +11 -9
  79. package/components/side-drawer/src/side-drawer.component.d.ts +6 -1
  80. package/components/tab/src/tab-group.component.d.ts +1 -0
  81. package/components/tab/src/tab.component.d.ts +7 -1
  82. package/components/tab-router/src/components/tab-router-item/tab-router-item.component.d.ts +3 -4
  83. package/components/tab-router/src/pipes/tab-info.pipe.d.ts +2 -2
  84. package/components/tab-router/src/services/tab-decorator.service.d.ts +2 -1
  85. package/components/table/src/components/filter/column-filter/column-filter.component.d.ts +1 -1
  86. package/components/table/src/components/popup-export/popup-export.component.d.ts +6 -6
  87. package/components/table/src/models/table-column.model.d.ts +1 -1
  88. package/components/table/src/services/config.service.d.ts +3 -2
  89. package/components/table/src/services/table-filter/table-filter.model.d.ts +1 -1
  90. package/components/table/src/services/table-filter/table-filter.service.d.ts +2 -2
  91. package/components/tree/src/tree.component.d.ts +13 -2
  92. package/components/tree/src/tree.model.d.ts +11 -0
  93. package/components/upload-file/src/components/preview/preview.component.d.ts +4 -4
  94. package/directives/src/sd-hover-copy.directive.d.ts +6 -5
  95. package/directives/src/sd-href.directive.d.ts +2 -2
  96. package/directives/src/sd-scroll.directive.d.ts +3 -2
  97. package/fesm2022/sdcorejs-angular-components-anchor.mjs +14 -14
  98. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  99. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs +332 -0
  100. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs.map +1 -0
  101. package/fesm2022/sdcorejs-angular-components-badge.mjs +1 -0
  102. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  103. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs +121 -0
  104. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs.map +1 -0
  105. package/fesm2022/sdcorejs-angular-components-data-state.mjs +68 -0
  106. package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -0
  107. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +16 -21
  108. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
  109. package/fesm2022/sdcorejs-angular-components-editor.mjs +6 -4
  110. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  111. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +463 -806
  112. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  113. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +23 -33
  114. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  115. package/fesm2022/sdcorejs-angular-components-job-progress.mjs +97 -0
  116. package/fesm2022/sdcorejs-angular-components-job-progress.mjs.map +1 -0
  117. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +9 -19
  118. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
  119. package/fesm2022/sdcorejs-angular-components-modal.mjs +60 -3
  120. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  121. package/fesm2022/sdcorejs-angular-components-preview.mjs +1437 -217
  122. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  123. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +4 -4
  124. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  125. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +1 -1
  126. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  127. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +38 -1
  128. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  129. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +16 -22
  130. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  131. package/fesm2022/sdcorejs-angular-components-tab.mjs +47 -3
  132. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  133. package/fesm2022/sdcorejs-angular-components-table.mjs +94 -61
  134. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  135. package/fesm2022/sdcorejs-angular-components-tree.mjs +185 -16
  136. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  137. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +14 -21
  138. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  139. package/fesm2022/sdcorejs-angular-components.mjs +4 -0
  140. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  141. package/fesm2022/sdcorejs-angular-directives.mjs +29 -41
  142. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  143. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +7 -7
  144. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  145. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +20 -73
  146. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  147. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +6 -3
  148. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  149. package/fesm2022/sdcorejs-angular-forms-chip.mjs +6 -3
  150. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  151. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +16 -13
  152. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  153. package/fesm2022/sdcorejs-angular-forms-date.mjs +42 -65
  154. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  155. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +51 -66
  156. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  157. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +384 -0
  158. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -0
  159. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +1 -1
  160. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  161. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +7 -5
  162. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  163. package/fesm2022/sdcorejs-angular-forms-input.mjs +289 -55
  164. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  165. package/fesm2022/sdcorejs-angular-forms-models.mjs +155 -2
  166. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  167. package/fesm2022/sdcorejs-angular-forms-radio.mjs +44 -68
  168. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  169. package/fesm2022/sdcorejs-angular-forms-select.mjs +6 -20
  170. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  171. package/fesm2022/sdcorejs-angular-forms-switch.mjs +19 -66
  172. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  173. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +6 -5
  174. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  175. package/fesm2022/sdcorejs-angular-forms-time-range.mjs +279 -0
  176. package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -0
  177. package/fesm2022/sdcorejs-angular-forms-time.mjs +309 -0
  178. package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -0
  179. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +210 -0
  180. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -0
  181. package/fesm2022/sdcorejs-angular-forms.mjs +73 -4
  182. package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
  183. package/fesm2022/sdcorejs-angular-i18n.mjs +355 -10
  184. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  185. package/fesm2022/sdcorejs-angular-interceptors.mjs +12 -17
  186. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  187. package/fesm2022/sdcorejs-angular-modules-layout.mjs +859 -78
  188. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  189. package/fesm2022/sdcorejs-angular-pipes.mjs +5 -7
  190. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  191. package/fesm2022/sdcorejs-angular-services-api.mjs +407 -137
  192. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  193. package/fesm2022/sdcorejs-angular-services-cache.mjs +515 -105
  194. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  195. package/fesm2022/sdcorejs-angular-services-confirm.mjs +5 -7
  196. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  197. package/fesm2022/sdcorejs-angular-services-docx.mjs +7 -10
  198. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
  199. package/fesm2022/sdcorejs-angular-services-loading.mjs +339 -74
  200. package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
  201. package/fesm2022/sdcorejs-angular-services-notify.mjs +7 -10
  202. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  203. package/fesm2022/sdcorejs-angular-services-persistence.mjs +899 -0
  204. package/fesm2022/sdcorejs-angular-services-persistence.mjs.map +1 -0
  205. package/fesm2022/sdcorejs-angular-services-storage.mjs +324 -122
  206. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  207. package/fesm2022/sdcorejs-angular-services-task.mjs +389 -0
  208. package/fesm2022/sdcorejs-angular-services-task.mjs.map +1 -0
  209. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs +255 -0
  210. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs.map +1 -0
  211. package/fesm2022/sdcorejs-angular-services-viewport.mjs +76 -0
  212. package/fesm2022/sdcorejs-angular-services-viewport.mjs.map +1 -0
  213. package/fesm2022/sdcorejs-angular-services.mjs +4 -0
  214. package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
  215. package/forms/autocomplete/src/autocomplete.component.d.ts +3 -4
  216. package/forms/checkbox/src/checkbox.component.d.ts +4 -8
  217. package/forms/date/src/date.component.d.ts +3 -2
  218. package/forms/date-range/src/date-range.component.d.ts +5 -8
  219. package/forms/datetime/src/datetime.component.d.ts +3 -2
  220. package/forms/entity-picker/index.d.ts +1 -0
  221. package/forms/entity-picker/src/entity-picker.component.d.ts +123 -0
  222. package/forms/index.d.ts +6 -0
  223. package/forms/input/index.d.ts +1 -0
  224. package/forms/input/src/input-mask.d.ts +43 -0
  225. package/forms/input/src/input.component.d.ts +26 -9
  226. package/forms/input-number/src/input-number.component.d.ts +1 -1
  227. package/forms/models/index.d.ts +1 -0
  228. package/forms/models/src/sd-form-control-connector.d.ts +86 -0
  229. package/forms/radio/src/radio.component.d.ts +12 -8
  230. package/forms/src/forms.module.d.ts +9 -5
  231. package/forms/switch/src/switch.component.d.ts +4 -7
  232. package/forms/time/index.d.ts +3 -0
  233. package/forms/time/src/time-picker.adapter.d.ts +13 -0
  234. package/forms/time/src/time-value.d.ts +19 -0
  235. package/forms/time/src/time.component.d.ts +78 -0
  236. package/forms/time-range/index.d.ts +2 -0
  237. package/forms/time-range/src/time-range-value.d.ts +14 -0
  238. package/forms/time-range/src/time-range.component.d.ts +80 -0
  239. package/forms/tree-select/index.d.ts +1 -0
  240. package/forms/tree-select/src/tree-select.component.d.ts +71 -0
  241. package/i18n/src/en.d.ts +68 -2
  242. package/interceptors/no-internet/no-internet.interceptor.d.ts +2 -3
  243. package/interceptors/unauthorized/unauthorized.interceptor.d.ts +2 -2
  244. package/modules/layout/components/index.d.ts +6 -0
  245. package/modules/layout/components/layout-main/layout-main.component.d.ts +7 -2
  246. package/modules/layout/components/shared/menu-tree/menu-tree.component.d.ts +28 -0
  247. package/modules/layout/components/shared/user-menu/user-menu.component.d.ts +25 -0
  248. package/modules/layout/components/sidebar-mobile-v2/main.component.d.ts +27 -0
  249. package/modules/layout/components/sidebar-mobile-v3/main.component.d.ts +28 -0
  250. package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +3 -4
  251. package/modules/layout/components/sidebar-v1/main.component.d.ts +2 -2
  252. package/modules/layout/components/sidebar-v2/main.component.d.ts +36 -0
  253. package/modules/layout/components/sidebar-v3/main.component.d.ts +29 -0
  254. package/modules/layout/configurations/layout.configuration.d.ts +36 -2
  255. package/modules/layout/index.d.ts +1 -0
  256. package/modules/layout/pipes/menu.pipe.d.ts +2 -2
  257. package/modules/layout/services/index.d.ts +3 -0
  258. package/modules/layout/services/layout.service.d.ts +2 -2
  259. package/modules/layout/services/menu/menu.utils.d.ts +6 -0
  260. package/modules/layout/services/navigation-state/navigation-state.service.d.ts +18 -0
  261. package/modules/layout/services/responsive/responsive.service.d.ts +12 -0
  262. package/modules/layout/services/storage/storage.service.d.ts +21 -8
  263. package/package.json +49 -1
  264. package/pipes/src/safe-html.pipe.d.ts +2 -2
  265. package/services/api/src/api.model.d.ts +54 -15
  266. package/services/api/src/api.service.d.ts +13 -8
  267. package/services/api/src/interceptors/api.interceptor.d.ts +1 -1
  268. package/services/cache/src/cache.model.d.ts +46 -13
  269. package/services/cache/src/cache.service.d.ts +5 -2
  270. package/services/confirm/src/lib/confirm.service.d.ts +2 -2
  271. package/services/docx/src/lib/docx.service.d.ts +2 -3
  272. package/services/index.d.ts +4 -0
  273. package/services/loading/src/loading.service.d.ts +15 -8
  274. package/services/notify/src/components/toast/toast.component.d.ts +2 -3
  275. package/services/persistence/index.d.ts +5 -0
  276. package/services/persistence/src/graph-serializer.d.ts +16 -0
  277. package/services/persistence/src/persistence-envelope.d.ts +28 -0
  278. package/services/persistence/src/persistence-key.d.ts +17 -0
  279. package/services/persistence/src/persistence.model.d.ts +63 -0
  280. package/services/persistence/src/storage-adapter.d.ts +29 -0
  281. package/services/storage/src/storage.model.d.ts +20 -5
  282. package/services/storage/src/storage.service.d.ts +6 -3
  283. package/services/task/index.d.ts +3 -0
  284. package/services/task/src/task.model.d.ts +75 -0
  285. package/services/task/src/task.service.d.ts +14 -0
  286. package/services/task/src/task.tokens.d.ts +12 -0
  287. package/services/unsaved-changes/index.d.ts +4 -0
  288. package/services/unsaved-changes/src/unsaved-changes.adapters.d.ts +15 -0
  289. package/services/unsaved-changes/src/unsaved-changes.model.d.ts +41 -0
  290. package/services/unsaved-changes/src/unsaved-changes.service.d.ts +16 -0
  291. package/services/unsaved-changes/src/unsaved-changes.tokens.d.ts +9 -0
  292. package/services/viewport/index.d.ts +3 -0
  293. package/services/viewport/src/viewport.model.d.ts +12 -0
  294. package/services/viewport/src/viewport.service.d.ts +18 -0
  295. package/services/viewport/src/viewport.tokens.d.ts +6 -0
@@ -1,155 +1,565 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, InjectionToken } from '@angular/core';
3
- import { DateUtilities } from '@sdcorejs/angular/utilities/extensions';
2
+ import { InjectionToken, inject, DestroyRef, Injectable } from '@angular/core';
3
+ import { SD_PERSISTENCE_STORAGE_ADAPTER, SdGraphSerializer, SdGraphIdentityCanonicalizer, canonicalizeSdPersistenceValue, buildSdPersistenceKey, digestSdPersistenceKey, readSdPersistenceStorageItem, parseSdPersistenceEnvelope, stringifySdPersistenceValueEnvelope, stringifySdPersistenceTombstoneEnvelope } from '@sdcorejs/angular/services/persistence';
4
4
  import { Utilities } from '@sdcorejs/utils/fns';
5
5
  import { BehaviorSubject } from 'rxjs';
6
- import { map } from 'rxjs/operators';
6
+
7
+ const SD_CACHE_CONFIG = new InjectionToken('sd-cache.configuration');
8
+ /** @deprecated Prefer globally safe unknown callbacks on `ISdCacheConfiguration`. */
9
+ function adaptLegacySdCacheCallbacks(callbacks) {
10
+ return {
11
+ set: callbacks.set
12
+ ? (key, value, option) => {
13
+ if (!callbacks.matches(key, option))
14
+ return;
15
+ if (!callbacks.isValue(value.data))
16
+ throw new TypeError(`Legacy cache value did not match key ${key}`);
17
+ return callbacks.set?.(key, { data: value.data, createdOn: new Date(value.createdOn) }, option);
18
+ }
19
+ : undefined,
20
+ get: callbacks.get
21
+ ? async (key, option) => {
22
+ if (!callbacks.matches(key, option))
23
+ return undefined;
24
+ const value = await callbacks.get?.(key, option);
25
+ if (!value)
26
+ return undefined;
27
+ if (!callbacks.isValue(value.data))
28
+ throw new TypeError(`Legacy cache value did not match key ${key}`);
29
+ return { data: value.data, createdOn: new Date(value.createdOn) };
30
+ }
31
+ : undefined,
32
+ remove: callbacks.remove
33
+ ? (key, option) => {
34
+ if (!callbacks.matches(key, option))
35
+ return;
36
+ return callbacks.remove?.(key, option);
37
+ }
38
+ : undefined,
39
+ };
40
+ }
7
41
 
8
42
  class SdCacheService {
9
- #memoryCache = new Map();
10
- #subjects = new Map();
11
- constructor() { }
12
- create(key, option) {
43
+ #configuration = inject(SD_CACHE_CONFIG, { optional: true });
44
+ #adapter = inject(SD_PERSISTENCE_STORAGE_ADAPTER);
45
+ #destroyRef = inject(DestroyRef);
46
+ #defaultSerializer = new SdGraphSerializer();
47
+ #defaultIdentityCanonicalizer = new SdGraphIdentityCanonicalizer();
48
+ #states = new Map();
49
+ #remoteQueues = new Map();
50
+ #memoryEntries = new Map();
51
+ #failedOwners = new Map();
52
+ #maxFailedOwners = 256;
53
+ #destroyed = false;
54
+ constructor() {
55
+ this.#destroyRef.onDestroy(() => {
56
+ this.#destroyed = true;
57
+ for (const state of this.#states.values()) {
58
+ state.disposed = true;
59
+ state.generation += 1;
60
+ state.entry = undefined;
61
+ state.inFlight = undefined;
62
+ for (const handle of state.handles)
63
+ handle.complete();
64
+ state.handles.clear();
65
+ }
66
+ this.#states.clear();
67
+ this.#remoteQueues.clear();
68
+ this.#memoryEntries.clear();
69
+ this.#failedOwners.clear();
70
+ });
71
+ }
72
+ create(key, option = {}) {
73
+ if (this.#destroyed)
74
+ throw new Error('Cache service has been destroyed');
13
75
  if (!key)
14
76
  throw new Error('Key is required');
15
- const hashKey = Utilities.hash({ key });
16
- // 1. Init Subject: Load data có sẵn nếu có
17
- if (!this.#subjects.has(hashKey)) {
18
- const existingData = this.#internalGet(hashKey, option);
19
- this.#subjects.set(hashKey, new BehaviorSubject(existingData ?? option?.default));
20
- }
21
- const subject = this.#subjects.get(hashKey);
22
- // 2. Define helpers
77
+ const normalized = this.#normalize(key, option);
78
+ const state = this.#getOrCreateState(normalized);
79
+ if (Object.prototype.hasOwnProperty.call(option, 'default')) {
80
+ return this.#createDefaultHandle(state, normalized, this.#cloneAs(normalized.serializer, option.default));
81
+ }
82
+ return this.#createOptionalHandle(state, normalized);
83
+ }
84
+ #getOrCreateState(normalized) {
85
+ const existing = this.#states.get(normalized.ownerDigest);
86
+ if (existing)
87
+ return existing;
88
+ const state = {
89
+ hydrated: false,
90
+ handles: new Set(),
91
+ generation: 0,
92
+ disposed: false,
93
+ };
94
+ this.#states.set(normalized.ownerDigest, state);
95
+ this.#hydrateState(state, normalized);
96
+ return state;
97
+ }
98
+ #createOptionalHandle(state, normalized) {
99
+ const initial = this.#readOptional(state, normalized);
100
+ const subject = new BehaviorSubject(initial);
101
+ const facade = {
102
+ emit: (present, value) => subject.next(present ? this.#cloneAs(normalized.serializer, value) : undefined),
103
+ complete: () => subject.complete(),
104
+ };
105
+ const operations = this.#attachHandle(state, normalized, facade, () => this.#readOptional(state, normalized));
106
+ return { ...operations, observer: subject.asObservable() };
107
+ }
108
+ #createDefaultHandle(state, normalized, defaultSnapshot) {
109
+ const read = () => this.#readWithDefault(state, normalized, defaultSnapshot);
110
+ const subject = new BehaviorSubject(read());
111
+ const facade = {
112
+ emit: (present, value) => subject.next(present ? this.#cloneAs(normalized.serializer, value) : this.#cloneAs(normalized.serializer, defaultSnapshot)),
113
+ complete: () => subject.complete(),
114
+ };
115
+ const operations = this.#attachHandle(state, normalized, facade, read);
116
+ return { ...operations, get: read, observer: subject.asObservable() };
117
+ }
118
+ #attachHandle(state, normalized, facade, read) {
119
+ state.handles.add(facade);
120
+ let active = true;
121
+ const assertActive = () => {
122
+ if (!active || state.disposed || this.#destroyed)
123
+ throw new Error('Cache handle has been destroyed');
124
+ };
23
125
  const get = () => {
24
- const val = this.#internalGet(hashKey, option);
25
- // Fix strict type: Ép kiểu về T (chấp nhận rủi ro undefined nếu user không check)
26
- return (val ?? option?.default);
126
+ assertActive();
127
+ return read();
128
+ };
129
+ const snapshot = () => {
130
+ assertActive();
131
+ const entry = this.#getValidEntry(state, normalized);
132
+ return entry === undefined ? { present: false } : { present: true, value: this.#cloneAs(normalized.serializer, entry.data) };
27
133
  };
28
134
  const set = (data) => {
29
- this.#internalSet(hashKey, data, option);
30
- subject.next(data);
135
+ assertActive();
136
+ this.#setEntry(state, normalized, data, true);
137
+ this.#broadcast(state);
31
138
  };
32
139
  const has = () => {
33
- return this.#internalGet(hashKey, option) !== undefined;
140
+ assertActive();
141
+ return this.#getValidEntry(state, normalized) !== undefined;
34
142
  };
35
143
  const remove = () => {
36
- this.#internalRemove(hashKey, option);
37
- subject.next(undefined);
144
+ assertActive();
145
+ this.#removeEntry(state, normalized, true);
146
+ this.#broadcast(state);
147
+ };
148
+ const releaseFacade = () => {
149
+ if (!active)
150
+ return;
151
+ active = false;
152
+ state.handles.delete(facade);
153
+ facade.complete();
154
+ if (state.handles.size > 0)
155
+ return;
156
+ state.disposed = true;
157
+ state.generation += 1;
158
+ state.entry = undefined;
159
+ state.inFlight = undefined;
160
+ this.#states.delete(normalized.ownerDigest);
38
161
  };
162
+ const release = () => releaseFacade();
39
163
  const destroy = () => {
40
- subject.complete();
41
- this.#subjects.delete(hashKey);
42
- this.#memoryCache.delete(hashKey);
164
+ if (!active)
165
+ return;
166
+ releaseFacade();
167
+ if (normalized.area !== 'memory')
168
+ return;
169
+ this.#memoryEntries.delete(normalized.ownerDigest);
170
+ if (state.disposed)
171
+ return;
172
+ state.entry = undefined;
173
+ state.hydrated = true;
174
+ this.#broadcast(state);
43
175
  };
44
- // 3. IMPLEMENT LOAD (Get-Or-Set Pattern)
45
- const load = async (callback) => {
46
- // Check cache trước
47
- if (has()) {
48
- return get();
176
+ const load = (callback) => {
177
+ try {
178
+ assertActive();
49
179
  }
50
- // Cache miss -> Gọi API
51
- const result = await callback();
52
- // Chỉ lưu nếu kết quả hợp lệ (khác undefined/null)
53
- if (result !== undefined && result !== null) {
54
- set(result);
180
+ catch (error) {
181
+ return Promise.reject(error);
55
182
  }
56
- return result;
183
+ const entry = this.#getValidEntry(state, normalized);
184
+ if (entry)
185
+ return Promise.resolve(this.#cloneAs(normalized.serializer, entry.data));
186
+ const generation = state.generation;
187
+ if (state.inFlight?.generation === generation) {
188
+ return state.inFlight.promise.then(value => this.#cloneAs(normalized.serializer, value));
189
+ }
190
+ const promise = this.#loadMiss(state, normalized, callback, generation);
191
+ state.inFlight = { generation, promise };
192
+ void promise
193
+ .finally(() => {
194
+ if (state.inFlight?.promise === promise)
195
+ state.inFlight = undefined;
196
+ })
197
+ .catch(() => undefined);
198
+ return promise;
57
199
  };
200
+ return { get, snapshot, set, has, remove, release, destroy, load };
201
+ }
202
+ async #loadMiss(state, normalized, callback, generation) {
203
+ const remote = await this.#readRemote(normalized);
204
+ if (remote) {
205
+ if (!state.disposed && state.generation === generation) {
206
+ state.entry = this.#cloneEntry(remote, normalized.serializer);
207
+ state.hydrated = true;
208
+ state.generation += 1;
209
+ this.#writePersistent(normalized, state.entry);
210
+ this.#broadcast(state);
211
+ }
212
+ return this.#cloneAs(normalized.serializer, remote.data);
213
+ }
214
+ const result = await callback();
215
+ if (result !== null && result !== undefined && !state.disposed && state.generation === generation) {
216
+ this.#setEntry(state, normalized, result, true);
217
+ this.#broadcast(state);
218
+ }
219
+ if (result === null || result === undefined)
220
+ return result;
221
+ return this.#cloneAs(normalized.serializer, result);
222
+ }
223
+ #normalize(key, option) {
224
+ const serializer = option.serializer ?? this.#configuration?.serializer ?? this.#defaultSerializer;
225
+ const identityCanonicalizer = option.identityCanonicalizer ?? this.#configuration?.identityCanonicalizer ?? this.#defaultIdentityCanonicalizer;
226
+ const canonicalKey = canonicalizeSdPersistenceValue(identityCanonicalizer, key, 'cache key');
227
+ const legacyStorageKey = this.#legacyStorageKey(key);
228
+ const namespace = option.namespace ?? this.#configuration?.namespace;
229
+ const version = option.version ?? this.#configuration?.version;
230
+ const area = option.type ?? 'memory';
231
+ const ttlMs = this.#normalizeTtl(option);
232
+ const serializerFormat = this.#serializerFormat(serializer);
233
+ const hasArgs = Object.prototype.hasOwnProperty.call(option, 'args');
234
+ const hasDefault = Object.prototype.hasOwnProperty.call(option, 'default');
235
+ const fields = [
236
+ { tag: 'area', value: canonicalizeSdPersistenceValue(identityCanonicalizer, area, 'cache area') },
237
+ { tag: 'namespace', value: this.#optionalIdentity(identityCanonicalizer, namespace !== undefined, namespace, 'cache namespace') },
238
+ { tag: 'version', value: this.#optionalIdentity(identityCanonicalizer, version !== undefined, version, 'cache version') },
239
+ { tag: 'ttlMs', value: this.#optionalIdentity(identityCanonicalizer, ttlMs !== undefined, ttlMs, 'cache TTL') },
240
+ { tag: 'args', value: this.#optionalIdentity(identityCanonicalizer, hasArgs, option.args, 'cache args') },
241
+ { tag: 'default', value: this.#optionalIdentity(identityCanonicalizer, hasDefault, option.default, 'cache default') },
242
+ { tag: 'serializer', value: serializerFormat },
243
+ { tag: 'identityCanonicalizer', value: this.#identityCanonicalizerFormat(identityCanonicalizer) },
244
+ ];
245
+ const identity = buildSdPersistenceKey(canonicalKey, fields);
246
+ const identityDigest = digestSdPersistenceKey(identity);
247
+ const storageKey = this.#convertKey(`sdcorejs.cache@1:${identityDigest}`);
248
+ const ownerDigest = digestSdPersistenceKey(buildSdPersistenceKey(storageKey, [{ tag: 'area', value: area }]));
58
249
  return {
59
- get,
60
- set,
61
- has,
62
- remove,
63
- destroy,
64
- load,
65
- observer: subject.asObservable().pipe(map(() => get())),
250
+ publicOption: option,
251
+ area,
252
+ storageKey,
253
+ legacyStorageKey,
254
+ ownerDigest,
255
+ identityDigest,
256
+ ttlMs,
257
+ serializer,
66
258
  };
67
259
  }
68
- // --- PRIVATE HELPERS ---
69
- #getStorage(option) {
70
- if (option?.type === 'local')
71
- return localStorage;
72
- if (option?.type === 'session')
73
- return sessionStorage;
74
- return null;
75
- }
76
- #internalGet(key, option) {
77
- let entry = this.#memoryCache.get(key);
78
- if (!entry) {
79
- const storage = this.#getStorage(option);
80
- if (storage) {
81
- const raw = storage.getItem(key);
82
- if (raw) {
83
- try {
84
- const parsed = JSON.parse(raw);
85
- entry = {
86
- data: parsed.data,
87
- createdOn: new Date(parsed.createdOn),
88
- };
89
- this.#memoryCache.set(key, entry);
90
- }
91
- catch (e) {
92
- this.#internalRemove(key, option);
93
- }
94
- }
95
- }
260
+ #convertKey(baseKey) {
261
+ try {
262
+ return this.#configuration?.convertKey?.(baseKey) ?? baseKey;
263
+ }
264
+ catch {
265
+ return baseKey;
266
+ }
267
+ }
268
+ #legacyStorageKey(key) {
269
+ try {
270
+ return this.#convertKey(Utilities.hash({ key }));
96
271
  }
97
- if (!entry)
272
+ catch {
273
+ return undefined;
274
+ }
275
+ }
276
+ #normalizeTtl(option) {
277
+ const candidate = option.ttlMs ?? (option.hours === undefined ? undefined : option.hours * 3_600_000);
278
+ if (candidate === undefined || !Number.isFinite(candidate) || candidate <= 0)
279
+ return undefined;
280
+ return Math.min(candidate, Number.MAX_SAFE_INTEGER);
281
+ }
282
+ #optionalIdentity(canonicalizer, present, value, label) {
283
+ return present ? `1${canonicalizeSdPersistenceValue(canonicalizer, value, label)}` : '0';
284
+ }
285
+ #identityCanonicalizerFormat(canonicalizer) {
286
+ if (typeof canonicalizer.format !== 'string' || canonicalizer.format.length === 0) {
287
+ throw new Error('Persistence identity canonicalizer format must be a non-empty string');
288
+ }
289
+ return canonicalizer.format;
290
+ }
291
+ #serializerFormat(serializer) {
292
+ if (typeof serializer.format !== 'string' || serializer.format.length === 0) {
293
+ throw new Error('Persistence serializer format must be a non-empty string');
294
+ }
295
+ return serializer.format;
296
+ }
297
+ #readOptional(state, normalized) {
298
+ const entry = this.#getValidEntry(state, normalized);
299
+ return entry ? this.#cloneAs(normalized.serializer, entry.data) : undefined;
300
+ }
301
+ #readWithDefault(state, normalized, defaultSnapshot) {
302
+ const entry = this.#getValidEntry(state, normalized);
303
+ return entry ? this.#cloneAs(normalized.serializer, entry.data) : this.#cloneAs(normalized.serializer, defaultSnapshot);
304
+ }
305
+ #getValidEntry(state, normalized) {
306
+ if (!state.hydrated) {
307
+ this.#hydrateState(state, normalized);
308
+ }
309
+ if (!state.entry)
310
+ return undefined;
311
+ if (this.#isExpired(state.entry, normalized.ttlMs)) {
312
+ this.#removeEntry(state, normalized, true);
313
+ this.#broadcast(state);
98
314
  return undefined;
99
- if (option?.hours && entry.createdOn) {
100
- const expiredOn = DateUtilities.addHours(entry.createdOn, option.hours);
101
- if (expiredOn && expiredOn < new Date()) {
102
- this.#internalRemove(key, option);
103
- return undefined;
104
- }
105
315
  }
106
- return this.#deepClone(entry.data);
316
+ return state.entry;
317
+ }
318
+ #isExpired(entry, ttlMs) {
319
+ return ttlMs !== undefined && entry.createdOn.getTime() + ttlMs <= Date.now();
107
320
  }
108
- #internalSet(key, data, option) {
109
- // FIX LỖI TẠI ĐÂY: Bỏ "?? null" để giữ nguyên kiểu T
110
- const clonedData = this.#deepClone(data);
321
+ #hydrateState(state, normalized) {
322
+ const read = this.#readEntry(normalized);
323
+ state.entry = read.status === 'found' ? read.entry : undefined;
324
+ state.hydrated = read.status !== 'unavailable';
325
+ }
326
+ #setEntry(state, normalized, data, notifyRemote) {
111
327
  const entry = {
112
- data: clonedData,
328
+ data: normalized.serializer.clone(data),
113
329
  createdOn: new Date(),
114
330
  };
115
- this.#memoryCache.set(key, entry);
116
- const storage = this.#getStorage(option);
117
- if (storage) {
331
+ state.entry = entry;
332
+ state.hydrated = true;
333
+ state.generation += 1;
334
+ this.#writePersistent(normalized, entry);
335
+ if (notifyRemote)
336
+ this.#safeRemoteSet(normalized, entry);
337
+ }
338
+ #removeEntry(state, normalized, notifyRemote) {
339
+ state.entry = undefined;
340
+ state.hydrated = true;
341
+ state.generation += 1;
342
+ if (normalized.area !== 'memory')
343
+ this.#writeTombstone(normalized);
344
+ if (notifyRemote)
345
+ void this.#safeRemoteRemove(normalized);
346
+ }
347
+ #broadcast(state) {
348
+ const present = state.entry !== undefined;
349
+ const value = state.entry?.data;
350
+ for (const handle of state.handles)
351
+ handle.emit(present, value);
352
+ }
353
+ #readEntry(normalized) {
354
+ if (normalized.area === 'memory') {
355
+ const entry = this.#memoryEntries.get(normalized.ownerDigest);
356
+ return entry ? { status: 'found', entry: this.#cloneEntry(entry, normalized.serializer) } : { status: 'absent' };
357
+ }
358
+ if (this.#failedOwners.has(normalized.ownerDigest))
359
+ return { status: 'unavailable' };
360
+ const primary = readSdPersistenceStorageItem(this.#adapter, normalized.area, normalized.storageKey);
361
+ if (primary.status === 'found') {
362
+ let envelope;
363
+ try {
364
+ envelope = parseSdPersistenceEnvelope(primary.value, normalized.identityDigest, normalized.serializer.format);
365
+ }
366
+ catch {
367
+ this.#writeTombstone(normalized);
368
+ return { status: 'absent' };
369
+ }
370
+ if (envelope?.kind === 'tombstone')
371
+ return { status: 'absent' };
372
+ const entry = envelope?.kind === 'value' ? this.#parseCurrentEntry(envelope.payload, normalized.serializer) : undefined;
373
+ if (entry)
374
+ return { status: 'found', entry };
375
+ this.#writeTombstone(normalized);
376
+ return { status: 'absent' };
377
+ }
378
+ if (primary.status === 'unavailable')
379
+ return { status: 'unavailable' };
380
+ if (normalized.legacyStorageKey === undefined)
381
+ return { status: 'absent' };
382
+ const legacyRead = readSdPersistenceStorageItem(this.#adapter, normalized.area, normalized.legacyStorageKey);
383
+ if (legacyRead.status === 'unavailable')
384
+ return { status: 'unavailable' };
385
+ if (legacyRead.status === 'absent')
386
+ return { status: 'absent' };
387
+ const legacy = this.#parseLegacy(legacyRead.value);
388
+ if (!legacy) {
389
+ this.#writeTombstone(normalized);
390
+ return { status: 'absent' };
391
+ }
392
+ this.#writePersistent(normalized, legacy);
393
+ return { status: 'found', entry: legacy };
394
+ }
395
+ #parseCurrentEntry(payload, serializer) {
396
+ try {
397
+ return this.#validateEntry(serializer.parse(payload));
398
+ }
399
+ catch {
400
+ return undefined;
401
+ }
402
+ }
403
+ #parseLegacy(raw) {
404
+ try {
405
+ const parsed = JSON.parse(raw);
406
+ if (!this.#hasExactEntryKeys(parsed))
407
+ return undefined;
408
+ const createdOn = this.#toValidDate(parsed['createdOn']);
409
+ return createdOn ? { data: parsed['data'], createdOn } : undefined;
410
+ }
411
+ catch {
412
+ return undefined;
413
+ }
414
+ }
415
+ #validateEntry(value) {
416
+ if (!this.#hasExactEntryKeys(value))
417
+ return undefined;
418
+ const createdOn = this.#toValidDate(value['createdOn']);
419
+ return createdOn ? { data: value['data'], createdOn } : undefined;
420
+ }
421
+ #toValidDate(value) {
422
+ const date = value instanceof Date ? value : typeof value === 'string' || typeof value === 'number' ? new Date(value) : undefined;
423
+ return date && Number.isFinite(date.getTime()) ? date : undefined;
424
+ }
425
+ #writePersistent(normalized, entry) {
426
+ if (normalized.area === 'memory') {
427
+ this.#memoryEntries.set(normalized.ownerDigest, this.#cloneEntry(entry, normalized.serializer));
428
+ return true;
429
+ }
430
+ try {
431
+ const payload = normalized.serializer.stringify(entry);
432
+ if (this.#adapter.setItem(normalized.area, normalized.storageKey, stringifySdPersistenceValueEnvelope(normalized.identityDigest, normalized.serializer.format, payload))) {
433
+ this.#clearFailedOwner(normalized.ownerDigest);
434
+ return true;
435
+ }
436
+ }
437
+ catch {
438
+ // Fall through to canonical quarantine.
439
+ }
440
+ this.#safeAdapterRemove(normalized.area, normalized.storageKey);
441
+ if (this.#tryPersistTombstone(normalized)) {
442
+ this.#clearFailedOwner(normalized.ownerDigest);
443
+ return false;
444
+ }
445
+ this.#recordFailedOwner(normalized.ownerDigest);
446
+ return false;
447
+ }
448
+ #readRemote(normalized) {
449
+ return this.#enqueueRemote(normalized, async () => {
450
+ const get = this.#configuration?.get;
451
+ if (!get)
452
+ return undefined;
453
+ const entry = this.#validateEntry(await get(normalized.storageKey, normalized.publicOption));
454
+ if (!entry || !this.#isExpired(entry, normalized.ttlMs))
455
+ return entry;
456
+ const remove = this.#configuration?.remove;
457
+ if (remove)
458
+ await remove(normalized.storageKey, normalized.publicOption);
459
+ return undefined;
460
+ });
461
+ }
462
+ #safeRemoteSet(normalized, entry) {
463
+ const set = this.#configuration?.set;
464
+ if (!set)
465
+ return;
466
+ void this.#enqueueRemote(normalized, () => set(normalized.storageKey, this.#cloneEntry(entry, normalized.serializer), normalized.publicOption));
467
+ }
468
+ #safeRemoteRemove(normalized) {
469
+ const remove = this.#configuration?.remove;
470
+ if (!remove)
471
+ return Promise.resolve();
472
+ return this.#enqueueRemote(normalized, () => remove(normalized.storageKey, normalized.publicOption));
473
+ }
474
+ #enqueueRemote(normalized, operation) {
475
+ const previous = this.#remoteQueues.get(normalized.ownerDigest) ?? Promise.resolve();
476
+ const result = previous.then(async () => {
118
477
  try {
119
- storage.setItem(key, JSON.stringify(entry));
478
+ return await operation();
120
479
  }
121
- catch (e) {
122
- console.error('Storage quota exceeded', e);
480
+ catch {
481
+ // A failed remote operation cannot poison later work for this identity.
482
+ return undefined;
123
483
  }
484
+ });
485
+ const tail = result.then(() => undefined);
486
+ this.#remoteQueues.set(normalized.ownerDigest, tail);
487
+ void tail.then(() => {
488
+ if (this.#remoteQueues.get(normalized.ownerDigest) === tail)
489
+ this.#remoteQueues.delete(normalized.ownerDigest);
490
+ });
491
+ return result;
492
+ }
493
+ #safeAdapterRemove(area, key) {
494
+ try {
495
+ return this.#adapter.removeItem(area, key);
124
496
  }
497
+ catch {
498
+ return false;
499
+ }
500
+ }
501
+ #writeTombstone(normalized) {
502
+ if (normalized.area === 'memory') {
503
+ this.#memoryEntries.delete(normalized.ownerDigest);
504
+ return true;
505
+ }
506
+ if (this.#tryPersistTombstone(normalized)) {
507
+ this.#clearFailedOwner(normalized.ownerDigest);
508
+ return true;
509
+ }
510
+ this.#safeAdapterRemove(normalized.area, normalized.storageKey);
511
+ this.#recordFailedOwner(normalized.ownerDigest);
512
+ return false;
125
513
  }
126
- #internalRemove(key, option) {
127
- this.#memoryCache.delete(key);
128
- const storage = this.#getStorage(option);
129
- if (storage) {
130
- storage.removeItem(key);
514
+ #tryPersistTombstone(normalized) {
515
+ if (normalized.area === 'memory')
516
+ return false;
517
+ try {
518
+ return this.#adapter.setItem(normalized.area, normalized.storageKey, stringifySdPersistenceTombstoneEnvelope(normalized.identityDigest, normalized.serializer.format));
519
+ }
520
+ catch {
521
+ return false;
131
522
  }
132
523
  }
133
- #deepClone(val) {
134
- if (val === undefined || val === null)
135
- return val;
136
- return JSON.parse(JSON.stringify(val));
524
+ #clearFailedOwner(ownerDigest) {
525
+ this.#failedOwners.delete(ownerDigest);
526
+ }
527
+ #recordFailedOwner(ownerDigest) {
528
+ this.#failedOwners.delete(ownerDigest);
529
+ this.#failedOwners.set(ownerDigest, true);
530
+ if (this.#failedOwners.size <= this.#maxFailedOwners)
531
+ return;
532
+ const oldest = this.#failedOwners.keys().next().value;
533
+ if (oldest !== undefined)
534
+ this.#failedOwners.delete(oldest);
535
+ }
536
+ #cloneEntry(entry, serializer) {
537
+ return { data: serializer.clone(entry.data), createdOn: new Date(entry.createdOn) };
538
+ }
539
+ #cloneAs(serializer, value) {
540
+ const entry = serializer.parse(serializer.stringify({ data: value, createdOn: new Date(0) }));
541
+ return entry.data;
542
+ }
543
+ #isRecord(value) {
544
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
545
+ }
546
+ #hasExactEntryKeys(value) {
547
+ return (this.#isRecord(value) &&
548
+ Reflect.ownKeys(value).length === 2 &&
549
+ Object.prototype.hasOwnProperty.call(value, 'data') &&
550
+ Object.prototype.hasOwnProperty.call(value, 'createdOn'));
137
551
  }
138
552
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
139
553
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdCacheService, providedIn: 'root' });
140
554
  }
141
555
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdCacheService, decorators: [{
142
556
  type: Injectable,
143
- args: [{
144
- providedIn: 'root',
145
- }]
557
+ args: [{ providedIn: 'root' }]
146
558
  }], ctorParameters: () => [] });
147
559
 
148
- const SD_CACHE_CONFIG = new InjectionToken('sd-cache.configuration');
149
-
150
560
  /**
151
561
  * Generated bundle index. Do not edit.
152
562
  */
153
563
 
154
- export { SD_CACHE_CONFIG, SdCacheService };
564
+ export { SD_CACHE_CONFIG, SdCacheService, adaptLegacySdCacheCallbacks };
155
565
  //# sourceMappingURL=sdcorejs-angular-services-cache.mjs.map