@tinya-code/gas-admin-ui 0.2.0-alpha.12 → 0.2.0-alpha.15

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 (369) hide show
  1. package/README.md +222 -0
  2. package/ng-package.json +7 -0
  3. package/package.json +3 -15
  4. package/src/lib/actions/action-registry.spec.ts +52 -0
  5. package/src/lib/actions/action-registry.ts +126 -0
  6. package/src/lib/actions/action-service.spec.ts +215 -0
  7. package/src/lib/actions/action-service.ts +87 -0
  8. package/src/lib/actions/descriptors.spec.ts +155 -0
  9. package/src/lib/actions/descriptors.ts +154 -0
  10. package/src/lib/columns/column-cell.ts +33 -0
  11. package/src/lib/columns/column-defaults.spec.ts +99 -0
  12. package/src/lib/columns/column-defaults.ts +84 -0
  13. package/src/lib/columns/column-format.spec.ts +274 -0
  14. package/src/lib/columns/descriptors.ts +113 -0
  15. package/src/lib/columns/format-badge.ts +51 -0
  16. package/src/lib/columns/format-boolean.ts +58 -0
  17. package/src/lib/columns/format-currency.ts +30 -0
  18. package/src/lib/columns/format-date.ts +35 -0
  19. package/src/lib/columns/format-number.ts +32 -0
  20. package/src/lib/columns/format-text.ts +23 -0
  21. package/src/lib/columns/format-thumbnail.ts +63 -0
  22. package/src/lib/core/adapters/firebase-auth.adapter.ts +6 -0
  23. package/src/lib/core/guards/auth.guard.spec.ts +88 -0
  24. package/src/lib/core/guards/auth.guard.ts +48 -0
  25. package/src/lib/core/guards/unsaved-changes.guard.ts +16 -0
  26. package/src/lib/core/interceptors/api-error.interceptor.spec.ts +182 -0
  27. package/src/lib/core/interceptors/api-error.interceptor.ts +87 -0
  28. package/src/lib/core/models/api.model.ts +104 -0
  29. package/src/lib/core/models/schema-descriptions.ts +118 -0
  30. package/src/lib/core/models/schema.model.ts +1097 -0
  31. package/src/lib/core/registry/composition-validator.spec.ts +358 -0
  32. package/src/lib/core/registry/composition-validator.ts +270 -0
  33. package/src/lib/core/registry/field-validators.spec.ts +199 -0
  34. package/src/lib/core/registry/field-validators.ts +440 -0
  35. package/src/lib/core/registry/render-host.spec.ts +208 -0
  36. package/src/lib/core/registry/render-host.ts +646 -0
  37. package/src/lib/core/registry/render-registry.spec.ts +96 -0
  38. package/src/lib/core/registry/render-registry.ts +312 -0
  39. package/src/lib/core/registry/schema-catalog.ts +156 -0
  40. package/src/lib/core/services/api.service.spec.ts +1142 -0
  41. package/src/lib/core/services/api.service.ts +371 -0
  42. package/src/lib/core/services/auth.service.spec.ts +653 -0
  43. package/src/lib/core/services/auth.service.ts +503 -0
  44. package/src/lib/core/services/config.service.spec.ts +121 -0
  45. package/src/lib/core/services/config.service.ts +119 -0
  46. package/src/lib/core/services/data-source.service.spec.ts +179 -0
  47. package/src/lib/core/services/data-source.service.ts +142 -0
  48. package/src/lib/core/services/error-mapper.service.spec.ts +50 -0
  49. package/src/lib/core/services/error-mapper.service.ts +49 -0
  50. package/src/lib/core/services/notification.service.ts +73 -0
  51. package/src/lib/core/services/relation-drawer.service.ts +41 -0
  52. package/src/lib/core/services/theme.service.spec.ts +106 -0
  53. package/src/lib/core/services/theme.service.ts +86 -0
  54. package/src/lib/core/services/transport.spec.ts +198 -0
  55. package/src/lib/core/services/transport.ts +164 -0
  56. package/src/lib/core/services/upload.service.ts +81 -0
  57. package/src/lib/core/testing/categories.schema.ts +125 -0
  58. package/src/lib/core/testing/orders.schema.ts +372 -0
  59. package/src/lib/core/testing/products.schema.ts +258 -0
  60. package/src/lib/core/testing/site.schema.ts +195 -0
  61. package/src/lib/core/testing/test-catalog.ts +21 -0
  62. package/src/lib/core/tokens.ts +112 -0
  63. package/src/lib/core/utils/clipboard.spec.ts +55 -0
  64. package/src/lib/core/utils/clipboard.ts +90 -0
  65. package/src/lib/core/utils/context-resolver.spec.ts +95 -0
  66. package/src/lib/core/utils/context-resolver.ts +101 -0
  67. package/src/lib/core/utils/response-unwrapper.spec.ts +70 -0
  68. package/src/lib/core/utils/response-unwrapper.ts +103 -0
  69. package/src/lib/core/utils/source-options.spec.ts +96 -0
  70. package/src/lib/core/utils/source-options.ts +54 -0
  71. package/src/lib/core/utils/template-interpolator.spec.ts +59 -0
  72. package/src/lib/core/utils/template-interpolator.ts +56 -0
  73. package/src/lib/core/view-navigation/view-navigation.service.spec.ts +207 -0
  74. package/src/lib/core/view-navigation/view-navigation.service.ts +132 -0
  75. package/src/lib/fields/boolean/boolean.descriptor.ts +11 -0
  76. package/src/lib/fields/boolean/boolean.ts +40 -0
  77. package/src/lib/fields/color/color.descriptor.ts +12 -0
  78. package/src/lib/fields/color/color.ts +34 -0
  79. package/src/lib/fields/currency/currency.descriptor.ts +12 -0
  80. package/src/lib/fields/currency/currency.ts +67 -0
  81. package/src/lib/fields/date/date.descriptor.ts +12 -0
  82. package/src/lib/fields/date/date.ts +36 -0
  83. package/src/lib/fields/descriptors.ts +122 -0
  84. package/src/lib/fields/display/display-badge.ts +65 -0
  85. package/src/lib/fields/display/display-date.ts +39 -0
  86. package/src/lib/fields/display/display-defaults.ts +84 -0
  87. package/src/lib/fields/display/display-file.ts +41 -0
  88. package/src/lib/fields/display/display-image.ts +54 -0
  89. package/src/lib/fields/display/display-list.ts +107 -0
  90. package/src/lib/fields/display/display-number.ts +41 -0
  91. package/src/lib/fields/display/display-text.ts +42 -0
  92. package/src/lib/fields/display/display.spec.ts +242 -0
  93. package/src/lib/fields/dropdown/dropdown.descriptor.ts +12 -0
  94. package/src/lib/fields/dropdown/dropdown.ts +45 -0
  95. package/src/lib/fields/email/email.descriptor.ts +12 -0
  96. package/src/lib/fields/email/email.ts +28 -0
  97. package/src/lib/fields/field-aria.ts +60 -0
  98. package/src/lib/fields/field-host/field-host.spec.ts +118 -0
  99. package/src/lib/fields/field-host/field-host.ts +47 -0
  100. package/src/lib/fields/field-node.ts +88 -0
  101. package/src/lib/fields/file/file.descriptor.ts +14 -0
  102. package/src/lib/fields/file/file.spec.ts +134 -0
  103. package/src/lib/fields/file/file.ts +281 -0
  104. package/src/lib/fields/group/group.descriptor.ts +21 -0
  105. package/src/lib/fields/group/group.ts +110 -0
  106. package/src/lib/fields/image/image.descriptor.ts +12 -0
  107. package/src/lib/fields/image/image.spec.ts +117 -0
  108. package/src/lib/fields/image/image.ts +281 -0
  109. package/src/lib/fields/key-value/key-value.descriptor.ts +11 -0
  110. package/src/lib/fields/key-value/key-value.ts +283 -0
  111. package/src/lib/fields/list/list.descriptor.ts +21 -0
  112. package/src/lib/fields/list/list.ts +376 -0
  113. package/src/lib/fields/multiselect/multiselect.descriptor.ts +11 -0
  114. package/src/lib/fields/multiselect/multiselect.spec.ts +142 -0
  115. package/src/lib/fields/multiselect/multiselect.ts +152 -0
  116. package/src/lib/fields/number/number.descriptor.ts +12 -0
  117. package/src/lib/fields/number/number.ts +40 -0
  118. package/src/lib/fields/phone/phone.descriptor.ts +12 -0
  119. package/src/lib/fields/phone/phone.ts +46 -0
  120. package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +12 -0
  121. package/src/lib/fields/readonly-text/readonly-text.ts +58 -0
  122. package/src/lib/fields/relation/relation.descriptor.ts +12 -0
  123. package/src/lib/fields/relation/relation.spec.ts +193 -0
  124. package/src/lib/fields/relation/relation.ts +224 -0
  125. package/src/lib/fields/rich-select/rich-select.descriptor.ts +12 -0
  126. package/src/lib/fields/rich-select/rich-select.ts +175 -0
  127. package/src/lib/fields/select/radio-mode.ts +25 -0
  128. package/src/lib/fields/select/select.descriptor.ts +12 -0
  129. package/src/lib/fields/select/select.spec.ts +162 -0
  130. package/src/lib/fields/select/select.ts +210 -0
  131. package/src/lib/fields/slug/slug.descriptor.ts +19 -0
  132. package/src/lib/fields/slug/slug.ts +67 -0
  133. package/src/lib/fields/string-list/string-list.descriptor.ts +11 -0
  134. package/src/lib/fields/string-list/string-list.ts +222 -0
  135. package/src/lib/fields/text/text.descriptor.ts +12 -0
  136. package/src/lib/fields/text/text.ts +35 -0
  137. package/src/lib/fields/textarea/textarea.descriptor.ts +12 -0
  138. package/src/lib/fields/textarea/textarea.spec.ts +117 -0
  139. package/src/lib/fields/textarea/textarea.ts +126 -0
  140. package/src/lib/fields/time/time.descriptor.ts +12 -0
  141. package/src/lib/fields/time/time.ts +28 -0
  142. package/src/lib/fields/unknown-render/unknown-render.ts +49 -0
  143. package/src/lib/fields/url/url.descriptor.ts +12 -0
  144. package/src/lib/fields/url/url.ts +53 -0
  145. package/src/lib/gas-admin-ui.spec.ts +21 -0
  146. package/src/lib/gas-admin-ui.ts +9 -0
  147. package/src/lib/layouts/descriptors.ts +9 -0
  148. package/src/lib/pages/dashboard/dashboard.ts +167 -0
  149. package/src/lib/pages/detail-view/detail-view.spec.ts +333 -0
  150. package/src/lib/pages/detail-view/detail-view.ts +570 -0
  151. package/src/lib/pages/drawer-form/drawer-form.ts +228 -0
  152. package/src/lib/pages/form-view/form-model.ts +88 -0
  153. package/src/lib/pages/form-view/form-schema.ts +255 -0
  154. package/src/lib/pages/form-view/form-view.ts +1622 -0
  155. package/src/lib/pages/list-view/list-view.formats.spec.ts +214 -0
  156. package/src/lib/pages/list-view/list-view.ts +882 -0
  157. package/src/lib/pages/login/login.spec.ts +109 -0
  158. package/src/lib/pages/login/login.ts +227 -0
  159. package/src/lib/pages/resource-page/resource-page.ts +234 -0
  160. package/src/lib/shared/components/badge/badge.ts +35 -0
  161. package/src/lib/shared/components/button/button.ts +65 -0
  162. package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +48 -0
  163. package/src/lib/shared/components/copy-button/copy-button.ts +56 -0
  164. package/src/lib/shared/components/copy-share/copy-share.spec.ts +122 -0
  165. package/src/lib/shared/components/copy-share/copy-share.ts +107 -0
  166. package/src/lib/shared/components/drawer/drawer.spec.ts +127 -0
  167. package/src/lib/shared/components/drawer/drawer.ts +172 -0
  168. package/src/lib/shared/components/empty-state/empty-state.ts +30 -0
  169. package/src/lib/shared/components/modal/modal.spec.ts +149 -0
  170. package/src/lib/shared/components/modal/modal.ts +145 -0
  171. package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +165 -0
  172. package/src/lib/shared/components/post-create-modal/post-create-modal.ts +159 -0
  173. package/src/lib/shared/components/skeleton/skeleton.ts +31 -0
  174. package/src/lib/shared/components/toast/toast.ts +58 -0
  175. package/src/lib/shared/utils/col-span.ts +25 -0
  176. package/src/lib/shared/utils/condition-evaluator.ts +53 -0
  177. package/src/lib/shared/utils/depends-on.ts +48 -0
  178. package/src/lib/shared/utils/dialog-focus.ts +28 -0
  179. package/src/lib/shared/utils/field-path.ts +49 -0
  180. package/src/lib/shared/utils/gap-sorting.ts +144 -0
  181. package/src/lib/shared/utils/seed.spec.ts +64 -0
  182. package/src/lib/shared/utils/seed.ts +149 -0
  183. package/src/lib/shared/utils/slugify.ts +13 -0
  184. package/src/lib/shared/utils/validators.ts +41 -0
  185. package/src/lib/shell/layout/layout.ts +63 -0
  186. package/src/lib/shell/shell.routes.spec.ts +59 -0
  187. package/src/lib/shell/shell.routes.ts +122 -0
  188. package/src/lib/shell/sidebar/sidebar.ts +139 -0
  189. package/src/lib/shell/theme-toggle/theme-toggle.ts +74 -0
  190. package/src/lib/views/calendar-view/calendar-model.ts +426 -0
  191. package/src/lib/views/calendar-view/calendar-view.spec.ts +557 -0
  192. package/src/lib/views/calendar-view/calendar-view.ts +568 -0
  193. package/src/lib/views/composer/composer-host.spec.ts +301 -0
  194. package/src/lib/views/composer/composer-host.ts +248 -0
  195. package/src/lib/views/composer/composer-imports.spec.ts +54 -0
  196. package/src/lib/views/composer/view-context.spec.ts +117 -0
  197. package/src/lib/views/composer/view-context.ts +109 -0
  198. package/src/lib/views/composer/view-slot.spec.ts +130 -0
  199. package/src/lib/views/composer/view-slot.ts +178 -0
  200. package/src/lib/views/descriptors.ts +46 -0
  201. package/src/lib/views/kanban-view/kanban-model.ts +173 -0
  202. package/src/lib/views/kanban-view/kanban-view.spec.ts +540 -0
  203. package/src/lib/views/kanban-view/kanban-view.ts +327 -0
  204. package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +17 -0
  205. package/src/lib/widgets/bar-chart/bar-chart.spec.ts +66 -0
  206. package/src/lib/widgets/bar-chart/bar-chart.ts +76 -0
  207. package/src/lib/widgets/chart-line/chart-line.descriptor.ts +17 -0
  208. package/src/lib/widgets/chart-line/chart-line.spec.ts +113 -0
  209. package/src/lib/widgets/chart-line/chart-line.ts +219 -0
  210. package/src/lib/widgets/descriptors.ts +29 -0
  211. package/src/lib/widgets/metric-card/metric-card.descriptor.ts +41 -0
  212. package/src/lib/widgets/metric-card/metric-card.spec.ts +52 -0
  213. package/src/lib/widgets/metric-card/metric-card.ts +48 -0
  214. package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +13 -0
  215. package/src/lib/widgets/quick-actions/quick-actions.spec.ts +61 -0
  216. package/src/lib/widgets/quick-actions/quick-actions.ts +100 -0
  217. package/src/lib/widgets/record-list/record-list.descriptor.ts +16 -0
  218. package/src/lib/widgets/record-list/record-list.spec.ts +79 -0
  219. package/src/lib/widgets/record-list/record-list.ts +115 -0
  220. package/src/lib/widgets/series.spec.ts +42 -0
  221. package/src/lib/widgets/series.ts +56 -0
  222. package/src/lib/widgets/status-progress/status-progress.descriptor.ts +19 -0
  223. package/src/lib/widgets/status-progress/status-progress.spec.ts +63 -0
  224. package/src/lib/widgets/status-progress/status-progress.ts +104 -0
  225. package/src/lib/widgets/widget-host/widget-host.spec.ts +179 -0
  226. package/src/lib/widgets/widget-host/widget-host.ts +99 -0
  227. package/src/public-api.ts +104 -0
  228. package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
  229. package/tsconfig.lib.json +13 -0
  230. package/tsconfig.lib.prod.json +11 -0
  231. package/tsconfig.spec.json +10 -0
  232. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +0 -84
  233. package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +0 -1
  234. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +0 -140
  235. package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +0 -1
  236. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +0 -113
  237. package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +0 -1
  238. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +0 -163
  239. package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +0 -1
  240. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +0 -1027
  241. package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +0 -1
  242. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +0 -278
  243. package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +0 -1
  244. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +0 -107
  245. package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +0 -1
  246. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +0 -101
  247. package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +0 -1
  248. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +0 -141
  249. package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +0 -1
  250. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +0 -88
  251. package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +0 -1
  252. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +0 -107
  253. package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +0 -1
  254. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +0 -140
  255. package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +0 -1
  256. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +0 -119
  257. package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +0 -1
  258. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +0 -125
  259. package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +0 -1
  260. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +0 -152
  261. package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +0 -1
  262. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +0 -211
  263. package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +0 -1
  264. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +0 -116
  265. package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +0 -1
  266. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +0 -111
  267. package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +0 -1
  268. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +0 -122
  269. package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +0 -1
  270. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +0 -107
  271. package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +0 -1
  272. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +0 -109
  273. package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +0 -1
  274. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +0 -45
  275. package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +0 -1
  276. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +0 -50
  277. package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +0 -1
  278. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +0 -24
  279. package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +0 -1
  280. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +0 -27
  281. package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +0 -1
  282. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +0 -408
  283. package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +0 -1
  284. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs +0 -4516
  285. package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs.map +0 -1
  286. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +0 -82
  287. package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +0 -1
  288. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +0 -105
  289. package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +0 -1
  290. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +0 -65
  291. package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +0 -1
  292. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +0 -65
  293. package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +0 -1
  294. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +0 -65
  295. package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +0 -1
  296. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +0 -59
  297. package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +0 -1
  298. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +0 -94
  299. package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +0 -1
  300. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +0 -72
  301. package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +0 -1
  302. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +0 -238
  303. package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +0 -1
  304. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +0 -416
  305. package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +0 -1
  306. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +0 -439
  307. package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +0 -1
  308. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +0 -513
  309. package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +0 -1
  310. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs +0 -637
  311. package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs.map +0 -1
  312. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +0 -127
  313. package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +0 -1
  314. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +0 -251
  315. package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +0 -1
  316. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +0 -66
  317. package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +0 -1
  318. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +0 -114
  319. package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +0 -1
  320. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +0 -116
  321. package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +0 -1
  322. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +0 -235
  323. package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +0 -1
  324. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +0 -8
  325. package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +0 -1
  326. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +0 -124
  327. package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +0 -1
  328. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +0 -249
  329. package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +0 -1
  330. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +0 -39
  331. package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +0 -1
  332. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +0 -309
  333. package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +0 -1
  334. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs +0 -576
  335. package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs.map +0 -1
  336. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +0 -161
  337. package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +0 -1
  338. package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +0 -11
  339. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +0 -685
  340. package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +0 -1
  341. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs +0 -80
  342. package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs.map +0 -1
  343. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +0 -296
  344. package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +0 -1
  345. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +0 -119
  346. package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +0 -1
  347. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +0 -158
  348. package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +0 -1
  349. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +0 -26
  350. package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +0 -1
  351. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +0 -205
  352. package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +0 -1
  353. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +0 -432
  354. package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +0 -1
  355. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +0 -36
  356. package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +0 -1
  357. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +0 -107
  358. package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +0 -1
  359. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +0 -223
  360. package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +0 -1
  361. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +0 -107
  362. package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +0 -1
  363. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +0 -60
  364. package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +0 -1
  365. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +0 -141
  366. package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +0 -1
  367. package/fesm2022/tinya-code-gas-admin-ui.mjs +0 -4599
  368. package/fesm2022/tinya-code-gas-admin-ui.mjs.map +0 -1
  369. package/types/tinya-code-gas-admin-ui.d.ts +0 -3632
@@ -0,0 +1,258 @@
1
+ import type { ResourceSchema } from '../models/schema.model';
2
+
3
+ /**
4
+ * Colección con pestañas — base.md §11, api.md §3.2–§3.5.
5
+ * Imágenes, specs y FAQ viven en hojas hijas; la API los ensambla.
6
+ */
7
+ export const productsSchema: ResourceSchema = {
8
+ id: 'products',
9
+ label: 'Producto',
10
+ labelPlural: 'Productos',
11
+ kind: 'collection',
12
+ uiViews: {
13
+ list: { type: 'list' },
14
+ create: { type: 'form', path: 'new' },
15
+ edit: { type: 'form', path: ':key/edit' },
16
+ },
17
+ endpoint: {
18
+ list: '/admin/products',
19
+ get: '/admin/products/{key}',
20
+ create: '/admin/products',
21
+ update: '/admin/products/{key}',
22
+ remove: '/admin/products/{key}',
23
+ },
24
+ keyField: 'slug',
25
+ titleField: 'name',
26
+ search: ['name', 'sku'],
27
+ filters: [
28
+ {
29
+ key: 'availability',
30
+ label: 'Disponibilidad',
31
+ type: 'select',
32
+ options: [
33
+ { value: 'InStock', label: 'En stock' },
34
+ { value: 'PreOrder', label: 'Preventa' },
35
+ { value: 'OutOfStock', label: 'Agotado' },
36
+ ],
37
+ },
38
+ { key: 'active', label: 'Activo', type: 'boolean' },
39
+ ],
40
+ listColumns: [
41
+ { key: 'images', label: 'Imagen', format: 'thumbnail' },
42
+ { key: 'name', label: 'Nombre' },
43
+ { key: 'category_slug', label: 'Categoría' },
44
+ { key: 'price', label: 'Precio', format: 'currency' },
45
+ { key: 'availability', label: 'Disponibilidad' },
46
+ { key: 'registro_sanitario', label: 'Sanitario', format: 'badge' },
47
+ { key: 'active', label: 'Activo', format: 'boolean' },
48
+ ],
49
+ layout: {
50
+ mode: 'tabs',
51
+ sections: [
52
+ { id: 'general', label: 'General' },
53
+ { id: 'contenido', label: 'Contenido' },
54
+ { id: 'imagenes', label: 'Imágenes' },
55
+ { id: 'sanitario', label: 'Sanitario' },
56
+ { id: 'ficha', label: 'Ficha técnica' },
57
+ { id: 'faq', label: 'FAQ' },
58
+ ],
59
+ },
60
+ fields: [
61
+ // ── General ──
62
+ {
63
+ type: 'text',
64
+ key: 'name',
65
+ label: 'Nombre',
66
+ required: true,
67
+ section: 'general',
68
+ width: 6,
69
+ },
70
+ {
71
+ type: 'slug',
72
+ key: 'slug',
73
+ label: 'Slug',
74
+ from: 'name',
75
+ lockAfterCreate: true,
76
+ required: true,
77
+ validators: { unique: true },
78
+ help: 'Inmutable tras publicar.',
79
+ section: 'general',
80
+ width: 6,
81
+ },
82
+ {
83
+ type: 'relation',
84
+ key: 'category_slug',
85
+ label: 'Categoría',
86
+ required: true,
87
+ // F8 · R6.5 (D62): UN objeto `source` para todas las fuentes.
88
+ source: { resource: 'categories', valueField: 'slug', labelField: 'name' },
89
+ onlyActive: true,
90
+ section: 'general',
91
+ width: 6,
92
+ },
93
+ {
94
+ type: 'text',
95
+ key: 'sku',
96
+ label: 'SKU',
97
+ required: true,
98
+ validators: { unique: true },
99
+ section: 'general',
100
+ width: 6,
101
+ },
102
+ {
103
+ type: 'text',
104
+ key: 'brand',
105
+ label: 'Marca',
106
+ section: 'general',
107
+ width: 6,
108
+ },
109
+ {
110
+ type: 'currency',
111
+ key: 'price',
112
+ label: 'Precio',
113
+ required: true,
114
+ section: 'general',
115
+ width: 6,
116
+ },
117
+ {
118
+ type: 'select',
119
+ key: 'availability',
120
+ label: 'Disponibilidad',
121
+ required: true,
122
+ options: [
123
+ { value: 'InStock', label: 'En stock' },
124
+ { value: 'PreOrder', label: 'Preventa' },
125
+ { value: 'OutOfStock', label: 'Agotado' },
126
+ ],
127
+ section: 'general',
128
+ width: 6,
129
+ },
130
+ {
131
+ type: 'boolean',
132
+ key: 'featured',
133
+ label: 'Destacado',
134
+ required: true,
135
+ default: false,
136
+ trueLabel: 'Sí',
137
+ falseLabel: 'No',
138
+ section: 'general',
139
+ width: 6,
140
+ },
141
+ {
142
+ type: 'boolean',
143
+ key: 'active',
144
+ label: 'Activo',
145
+ required: true,
146
+ default: true,
147
+ trueLabel: 'Activo',
148
+ falseLabel: 'Inactivo',
149
+ section: 'general',
150
+ width: 6,
151
+ },
152
+ // ── Contenido ──
153
+ {
154
+ type: 'textarea',
155
+ key: 'description',
156
+ label: 'Descripción',
157
+ required: true,
158
+ rows: 8,
159
+ help: 'Entre 100 y 2000 caracteres.',
160
+ validators: { minLength: 100, maxLength: 2000 },
161
+ section: 'contenido',
162
+ width: 12,
163
+ },
164
+ {
165
+ type: 'text',
166
+ key: 'seo_title',
167
+ label: 'Título SEO',
168
+ section: 'contenido',
169
+ width: 12,
170
+ },
171
+ {
172
+ type: 'textarea',
173
+ key: 'seo_description',
174
+ label: 'Descripción SEO',
175
+ required: true,
176
+ rows: 3,
177
+ section: 'contenido',
178
+ width: 12,
179
+ },
180
+ // ── Imágenes (mín 1; la primera es la principal) ──
181
+ {
182
+ type: 'list',
183
+ key: 'images',
184
+ label: 'Imágenes',
185
+ required: true,
186
+ min: 1,
187
+ primaryFirst: true,
188
+ positionField: 'position',
189
+ addLabel: 'Agregar imagen',
190
+ emptyText: 'Sin imágenes. La primera será la imagen principal.',
191
+ itemDisplay: 'card',
192
+ itemTitle: 'image_alt',
193
+ itemFields: [
194
+ { type: 'image', key: 'image_url', label: 'Imagen', required: true },
195
+ { type: 'text', key: 'image_alt', label: 'Texto alternativo', required: true },
196
+ ],
197
+ section: 'imagenes',
198
+ width: 12,
199
+ },
200
+ // ── Sanitario ──
201
+ {
202
+ type: 'text',
203
+ key: 'registro_sanitario',
204
+ label: 'Registro sanitario',
205
+ help: 'Sin esto el producto no se publica.',
206
+ section: 'sanitario',
207
+ width: 4,
208
+ },
209
+ {
210
+ type: 'select',
211
+ key: 'clase_riesgo',
212
+ label: 'Clase de riesgo',
213
+ options: [
214
+ { value: 'I', label: 'I' },
215
+ { value: 'IIa', label: 'IIa' },
216
+ { value: 'IIb', label: 'IIb' },
217
+ { value: 'III', label: 'III' },
218
+ ],
219
+ section: 'sanitario',
220
+ width: 4,
221
+ },
222
+ {
223
+ type: 'text',
224
+ key: 'titular_registro',
225
+ label: 'Titular del registro',
226
+ section: 'sanitario',
227
+ width: 4,
228
+ },
229
+ // ── Ficha técnica ──
230
+ {
231
+ type: 'key-value',
232
+ key: 'specs',
233
+ label: 'Especificaciones',
234
+ positionField: 'position',
235
+ addLabel: 'Agregar especificación',
236
+ emptyText: 'Sin especificaciones.',
237
+ section: 'ficha',
238
+ width: 12,
239
+ },
240
+ // ── FAQ ──
241
+ {
242
+ type: 'list',
243
+ key: 'faq',
244
+ label: 'Preguntas frecuentes',
245
+ positionField: 'position',
246
+ addLabel: 'Agregar pregunta',
247
+ emptyText: 'Sin preguntas frecuentes.',
248
+ itemDisplay: 'card',
249
+ itemTitle: 'question',
250
+ itemFields: [
251
+ { type: 'text', key: 'question', label: 'Pregunta', required: true },
252
+ { type: 'textarea', key: 'answer', label: 'Respuesta', required: true, rows: 4 },
253
+ ],
254
+ section: 'faq',
255
+ width: 12,
256
+ },
257
+ ],
258
+ };
@@ -0,0 +1,195 @@
1
+ import type { ResourceSchema } from '../models/schema.model';
2
+
3
+ /**
4
+ * Singleton de configuración del sitio — base.md §11, api.md §3.6–§3.8.
5
+ * La API aplana `address_street` etc. a objetos anidados al responder.
6
+ */
7
+ export const siteSchema: ResourceSchema = {
8
+ id: 'site',
9
+ label: 'Sitio',
10
+ labelPlural: 'Sitio',
11
+ kind: 'singleton',
12
+ uiViews: {
13
+ settings: { type: 'form' },
14
+ },
15
+ endpoint: {
16
+ get: '/admin/site',
17
+ update: '/admin/site',
18
+ },
19
+ // Los singleton no tienen clave de registro; `get`/`update` no la usan.
20
+ keyField: 'key',
21
+ titleField: 'name',
22
+ // Sin listado: `listColumns` queda vacío por tipo.
23
+ listColumns: [],
24
+ layout: {
25
+ mode: 'sections',
26
+ sections: [
27
+ { id: 'negocio', label: 'Negocio' },
28
+ { id: 'contacto', label: 'Contacto' },
29
+ { id: 'direccion', label: 'Dirección' },
30
+ { id: 'horarios', label: 'Horarios' },
31
+ { id: 'redes', label: 'Redes' },
32
+ ],
33
+ },
34
+ fields: [
35
+ // ── Negocio ──
36
+ {
37
+ type: 'text',
38
+ key: 'name',
39
+ label: 'Nombre del negocio',
40
+ required: true,
41
+ section: 'negocio',
42
+ width: 6,
43
+ },
44
+ {
45
+ type: 'url',
46
+ key: 'url',
47
+ label: 'Sitio web',
48
+ required: true,
49
+ section: 'negocio',
50
+ width: 6,
51
+ },
52
+ {
53
+ type: 'textarea',
54
+ key: 'description',
55
+ label: 'Descripción',
56
+ required: true,
57
+ rows: 4,
58
+ section: 'negocio',
59
+ width: 12,
60
+ },
61
+ {
62
+ type: 'text',
63
+ key: 'currency',
64
+ label: 'Moneda',
65
+ required: true,
66
+ default: 'PEN',
67
+ help: 'Código ISO 4217 (ej. PEN).',
68
+ validators: { pattern: '^[A-Z]{3}$' },
69
+ section: 'negocio',
70
+ width: 6,
71
+ },
72
+ // ── Contacto ──
73
+ {
74
+ type: 'phone',
75
+ key: 'phone',
76
+ label: 'Teléfono',
77
+ required: true,
78
+ format: 'e164',
79
+ section: 'contacto',
80
+ width: 6,
81
+ },
82
+ {
83
+ type: 'phone',
84
+ key: 'whatsapp',
85
+ label: 'WhatsApp',
86
+ required: true,
87
+ format: 'digits',
88
+ help: 'Solo dígitos, sin +.',
89
+ section: 'contacto',
90
+ width: 6,
91
+ },
92
+ {
93
+ type: 'email',
94
+ key: 'email',
95
+ label: 'Correo',
96
+ required: true,
97
+ section: 'contacto',
98
+ width: 6,
99
+ },
100
+ // ── Dirección (grupos address y geo) ──
101
+ {
102
+ type: 'group',
103
+ key: 'address',
104
+ label: 'Dirección',
105
+ required: true,
106
+ display: 'card',
107
+ section: 'direccion',
108
+ width: 12,
109
+ fields: [
110
+ { type: 'text', key: 'street', label: 'Calle', required: true },
111
+ { type: 'text', key: 'city', label: 'Ciudad', required: true },
112
+ { type: 'text', key: 'region', label: 'Región', required: true },
113
+ { type: 'text', key: 'postal_code', label: 'Código postal', required: true },
114
+ {
115
+ type: 'text',
116
+ key: 'country',
117
+ label: 'País',
118
+ required: true,
119
+ help: 'ISO alpha-2 (ej. PE).',
120
+ validators: { pattern: '^[A-Z]{2}$' },
121
+ },
122
+ ],
123
+ },
124
+ {
125
+ type: 'group',
126
+ key: 'geo',
127
+ label: 'Coordenadas',
128
+ required: true,
129
+ display: 'card',
130
+ section: 'direccion',
131
+ width: 12,
132
+ fields: [
133
+ {
134
+ type: 'number',
135
+ key: 'lat',
136
+ label: 'Latitud',
137
+ required: true,
138
+ min: -90,
139
+ max: 90,
140
+ decimals: 6,
141
+ },
142
+ {
143
+ type: 'number',
144
+ key: 'lng',
145
+ label: 'Longitud',
146
+ required: true,
147
+ min: -180,
148
+ max: 180,
149
+ decimals: 6,
150
+ },
151
+ ],
152
+ },
153
+ // ── Horarios ──
154
+ {
155
+ type: 'list',
156
+ key: 'hours',
157
+ label: 'Horarios',
158
+ positionField: 'position',
159
+ addLabel: 'Agregar tramo',
160
+ emptyText: 'Sin horarios definidos.',
161
+ itemFields: [
162
+ {
163
+ type: 'multiselect',
164
+ key: 'days',
165
+ label: 'Días',
166
+ required: true,
167
+ options: [
168
+ { value: 'mon', label: 'Lunes' },
169
+ { value: 'tue', label: 'Martes' },
170
+ { value: 'wed', label: 'Miércoles' },
171
+ { value: 'thu', label: 'Jueves' },
172
+ { value: 'fri', label: 'Viernes' },
173
+ { value: 'sat', label: 'Sábado' },
174
+ { value: 'sun', label: 'Domingo' },
175
+ ],
176
+ },
177
+ { type: 'time', key: 'opens', label: 'Abre', required: true },
178
+ { type: 'time', key: 'closes', label: 'Cierra', required: true },
179
+ ],
180
+ section: 'horarios',
181
+ width: 12,
182
+ },
183
+ // ── Redes ──
184
+ {
185
+ type: 'string-list',
186
+ key: 'social',
187
+ label: 'Redes sociales',
188
+ itemType: 'url',
189
+ addLabel: 'Agregar red',
190
+ emptyText: 'Sin redes sociales.',
191
+ section: 'redes',
192
+ width: 12,
193
+ },
194
+ ],
195
+ };
@@ -0,0 +1,21 @@
1
+ import type { ResourceSchema } from '../models/schema.model';
2
+
3
+ import { categoriesSchema } from './categories.schema';
4
+ import { ordersSchema } from './orders.schema';
5
+ import { productsSchema } from './products.schema';
6
+ import { siteSchema } from './site.schema';
7
+
8
+ /**
9
+ * Catálogo de pruebas de la librería: copia CONGELADA de los schemas
10
+ * reales de `admin-schema` (orders, categories, products), del mismo modo
11
+ * que el motor backend congela fixtures de endpoints en sus tests. Los
12
+ * specs del motor prueban comportamiento (navegación, params, caché,
13
+ * composición) contra declaraciones con esa forma; los specs contra los
14
+ * schemas VIVOS del consumidor viven en el repo del consumidor.
15
+ */
16
+ export const testCatalog: readonly ResourceSchema[] = [
17
+ ordersSchema,
18
+ categoriesSchema,
19
+ productsSchema,
20
+ siteSchema,
21
+ ];
@@ -0,0 +1,112 @@
1
+ import { InjectionToken } from '@angular/core';
2
+
3
+ import type { ResponseUnwrap } from './models/schema.model';
4
+
5
+ /**
6
+ * URL base de la API (baseapi §2.3): es la URL directa del Web App de Apps
7
+ * Script; ahí se hace el `POST` del envelope `{ token, method, path, payload }`.
8
+ * OBLIGATORIO proporcionarlo en `app.config.ts`:
9
+ * `{ provide: API_URL, useValue: 'https://…' }` (Fase 3). Vacío = mismo origen.
10
+ */
11
+ export const API_URL = new InjectionToken<string>('API_URL');
12
+
13
+ /**
14
+ * Superficie mínima que `gas-admin-ui` usa de Firebase Auth.
15
+ * Implementada por la aplicación consumidora; inyectada vía `FIREBASE_AUTH_ADAPTER`.
16
+ * Mantener la interfaz fina evita acoplar la librería a una versión específica de Firebase.
17
+ */
18
+ export interface FirebaseAuthAdapter {
19
+ /**
20
+ * Abre un popup de Google sign-in y resuelve al ID token de Firebase.
21
+ * Rechaza si el usuario cancela o hay error.
22
+ */
23
+ signInWithGoogle(): Promise<string>;
24
+
25
+ /**
26
+ * Inicia sesión con email y contraseña vía Firebase y resuelve al ID token.
27
+ * Se usa cuando provider === 'password' Y firebase está configurado (Firebase email auth).
28
+ */
29
+ signInWithEmailAndPassword(email: string, password: string): Promise<string>;
30
+
31
+ /**
32
+ * Cierra sesión en Firebase (llamado junto al clear de la sesión de la app).
33
+ */
34
+ signOut(): Promise<void>;
35
+
36
+ /**
37
+ * Obtiene un ID token de Firebase FRESCO para usarlo en la cabecera
38
+ * `Authorization: Bearer <token>` de las peticiones REST.
39
+ *
40
+ * OPCIONAL: si el adaptador no lo implementa, `gas-admin-ui` envía el token
41
+ * de sesión almacenado tal cual (comportamiento actual). Implementarlo
42
+ * permite refrescar el ID token antes de cada petición REST, evitando
43
+ * errores "ID token inválido" tras la expiración de Firebase (1 hora).
44
+ *
45
+ * El adaptador decide cuándo refrescar (p. ej. `getIdToken(true)` de Firebase
46
+ * SDK fuerza la renovación; sin argumento devuelve el cacheado si aún es válido).
47
+ */
48
+ getIdToken?(): Promise<string>;
49
+ }
50
+
51
+ /**
52
+ * Token DI opcional para el adaptador de Firebase Auth.
53
+ * Proporcionado por la aplicación consumidora cuando usa proveedores federados o Firebase Auth.
54
+ */
55
+ export const FIREBASE_AUTH_ADAPTER = new InjectionToken<FirebaseAuthAdapter>(
56
+ 'gas.admin.firebaseAuthAdapter',
57
+ );
58
+
59
+ /**
60
+ * Driver de transporte HTTP del motor.
61
+ *
62
+ * Vive acá (capa de infraestructura) y NO en `ResourceSchema` (capa de dominio)
63
+ * porque es una decisión de red, no de modelo de datos. Cambiar el driver
64
+ * no debería requerir tocar ningún schema de recursos.
65
+ *
66
+ * - `'gas'` (default): tunnel `POST text/plain` con envelope
67
+ * `{ token, method, path, payload }` — contrato de Google Apps Script.
68
+ * - `'rest'`: verbos HTTP reales (`GET`, `POST`, `PUT`, `DELETE`) con
69
+ * `Authorization: Bearer <token>` en cabeceras y params en la URL (GET/DELETE)
70
+ * o en el body JSON (POST/PUT/PATCH).
71
+ *
72
+ * Se fija en `provideGasAdmin({ driver })`. Sin declaración explícita el
73
+ * motor usa `'gas'` — cero impacto para consumidores existentes.
74
+ */
75
+ export const API_DRIVER = new InjectionToken<'gas' | 'rest'>('gas.admin.driver');
76
+
77
+ /**
78
+ * Registro de FUENTES DE CONTEXTO para marcadores en paths de endpoints.
79
+ *
80
+ * Cada clave es el nombre de una fuente — `{ <fuente> }` o
81
+ * `{ <fuente>.<ruta.anidada> }` dentro de un path declarado en
82
+ * `ResourceEndpoints` — y cada valor es un getter sin argumentos que devuelve
83
+ * el dato ACTUAL en el momento de la petición (no al registrar).
84
+ *
85
+ * El motor ya aporta dos fuentes construidas y éstas NO se declaran acá:
86
+ *
87
+ * - `auth` → la sesión que dueña `AuthService` (usuario y token).
88
+ * - `config` → el mapa global que puebla `ConfigService` desde los singletons.
89
+ *
90
+ * Este registro es sólo para fuentes que aporta el consumidor, para que el
91
+ * motor no conozca nombres de dominio: qué campo se lee lo decide el schema,
92
+ * no el engine.
93
+ *
94
+ * Un marcador que apunte a una fuente no registrada, o a un valor ausente,
95
+ * revienta con un error que nombra el path y el marcador — jamás se manda un
96
+ * segmento vacío al backend.
97
+ */
98
+ export type ValueSources = Readonly<Record<string, () => unknown>>;
99
+
100
+ export const VALUE_SOURCES = new InjectionToken<ValueSources>('gas.admin.valueSources');
101
+
102
+ /**
103
+ * Unwrap de respuesta global por defecto (`GasAdminConfig.defaultResponseUnwrap`).
104
+ *
105
+ * Se fusiona con la declaración `endpoint.responseUnwrap` de cada recurso:
106
+ * la del recurso tiene prioridad en las claves que declara. Sin token, sólo
107
+ * aplica lo declarado por recurso — cero impacto en schemas existentes.
108
+ */
109
+ export const DEFAULT_RESPONSE_UNWRAP = new InjectionToken<ResponseUnwrap>(
110
+ 'gas.admin.defaultResponseUnwrap',
111
+ );
112
+
@@ -0,0 +1,55 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { buildShareMessage } from './clipboard';
4
+
5
+ const URL = 'https://ejemplo.test/p/abc123';
6
+
7
+ /**
8
+ * `buildShareMessage` es el único sitio que decide QUÉ se copia. Aquí vive el
9
+ * bug que motivó la función: `copy()` y la acción del listado escribían sólo
10
+ * `url`, dejando afuera el `shareTextTemplate` formateado (saludo, ref, PIN y
11
+ * el propio enlace) que sí viajaban por WhatsApp.
12
+ */
13
+ describe('buildShareMessage', () => {
14
+ it('sin shareText devuelve sólo la URL', () => {
15
+ expect(buildShareMessage(URL)).toBe(URL);
16
+ expect(buildShareMessage(URL, '')).toBe(URL);
17
+ expect(buildShareMessage(URL, ' ')).toBe(URL);
18
+ });
19
+
20
+ it('con shareText que YA trae la URL no duplica el enlace', () => {
21
+ // Este es el caso de `orders.shareTextTemplate`: el mensaje ya incluye
22
+ // el link escrito dentro. Un `join` a ciegas lo pegaba DOS veces.
23
+ const template = `Hola Ana, puede retirar su pedido A-100 aquí: ${URL}`;
24
+ expect(buildShareMessage(URL, template)).toBe(template);
25
+ });
26
+
27
+ it('con shareText SIN la URL completa el enlace al final', () => {
28
+ const text = 'Hola Ana, su pedido A-100 está listo';
29
+ expect(buildShareMessage(URL, text)).toBe(`${text} ${URL}`);
30
+ });
31
+
32
+ it('un mensaje que sólo menciona la base del sitio NO recibe el enlace', () => {
33
+ // Caso real reportado: la plantilla interpola `{public_base_url}` (la
34
+ // base, sin `/p/{ref}`) y el motor le pegaba la URL con código al final
35
+ // aunque el mensaje YA apuntaba al sitio. El criterio es el origin,
36
+ // no la URL exacta.
37
+ const text = '🔗 Consulta tu pedido en https://ejemplo.test';
38
+ expect(buildShareMessage(URL, text)).toBe(text);
39
+ });
40
+
41
+ it('un mensaje que apunta a OTRO sitio sí recibe el enlace', () => {
42
+ const text = 'Sigue el pedido en https://otro-sitio.test/pedidos';
43
+ expect(buildShareMessage(URL, text)).toBe(`${text} ${URL}`);
44
+ });
45
+
46
+ it('con URL relativa sólo casa la coincidencia exacta', () => {
47
+ expect(buildShareMessage('/p/abc123', 'Ver en /p/abc123')).toBe('Ver en /p/abc123');
48
+ expect(buildShareMessage('/p/abc123', 'Ver tu pedido')).toBe('Ver tu pedido /p/abc123');
49
+ });
50
+
51
+ it('recorta el shareText pero nunca la URL', () => {
52
+ expect(buildShareMessage(URL, ' Hola Ana ')).toBe(`Hola Ana ${URL}`);
53
+ expect(buildShareMessage('', 'Hola Ana')).toBe('Hola Ana');
54
+ });
55
+ });