@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.
- package/README.md +222 -0
- package/ng-package.json +7 -0
- package/package.json +3 -15
- package/src/lib/actions/action-registry.spec.ts +52 -0
- package/src/lib/actions/action-registry.ts +126 -0
- package/src/lib/actions/action-service.spec.ts +215 -0
- package/src/lib/actions/action-service.ts +87 -0
- package/src/lib/actions/descriptors.spec.ts +155 -0
- package/src/lib/actions/descriptors.ts +154 -0
- package/src/lib/columns/column-cell.ts +33 -0
- package/src/lib/columns/column-defaults.spec.ts +99 -0
- package/src/lib/columns/column-defaults.ts +84 -0
- package/src/lib/columns/column-format.spec.ts +274 -0
- package/src/lib/columns/descriptors.ts +113 -0
- package/src/lib/columns/format-badge.ts +51 -0
- package/src/lib/columns/format-boolean.ts +58 -0
- package/src/lib/columns/format-currency.ts +30 -0
- package/src/lib/columns/format-date.ts +35 -0
- package/src/lib/columns/format-number.ts +32 -0
- package/src/lib/columns/format-text.ts +23 -0
- package/src/lib/columns/format-thumbnail.ts +63 -0
- package/src/lib/core/adapters/firebase-auth.adapter.ts +6 -0
- package/src/lib/core/guards/auth.guard.spec.ts +88 -0
- package/src/lib/core/guards/auth.guard.ts +48 -0
- package/src/lib/core/guards/unsaved-changes.guard.ts +16 -0
- package/src/lib/core/interceptors/api-error.interceptor.spec.ts +182 -0
- package/src/lib/core/interceptors/api-error.interceptor.ts +87 -0
- package/src/lib/core/models/api.model.ts +104 -0
- package/src/lib/core/models/schema-descriptions.ts +118 -0
- package/src/lib/core/models/schema.model.ts +1097 -0
- package/src/lib/core/registry/composition-validator.spec.ts +358 -0
- package/src/lib/core/registry/composition-validator.ts +270 -0
- package/src/lib/core/registry/field-validators.spec.ts +199 -0
- package/src/lib/core/registry/field-validators.ts +440 -0
- package/src/lib/core/registry/render-host.spec.ts +208 -0
- package/src/lib/core/registry/render-host.ts +646 -0
- package/src/lib/core/registry/render-registry.spec.ts +96 -0
- package/src/lib/core/registry/render-registry.ts +312 -0
- package/src/lib/core/registry/schema-catalog.ts +156 -0
- package/src/lib/core/services/api.service.spec.ts +1142 -0
- package/src/lib/core/services/api.service.ts +371 -0
- package/src/lib/core/services/auth.service.spec.ts +653 -0
- package/src/lib/core/services/auth.service.ts +503 -0
- package/src/lib/core/services/config.service.spec.ts +121 -0
- package/src/lib/core/services/config.service.ts +119 -0
- package/src/lib/core/services/data-source.service.spec.ts +179 -0
- package/src/lib/core/services/data-source.service.ts +142 -0
- package/src/lib/core/services/error-mapper.service.spec.ts +50 -0
- package/src/lib/core/services/error-mapper.service.ts +49 -0
- package/src/lib/core/services/notification.service.ts +73 -0
- package/src/lib/core/services/relation-drawer.service.ts +41 -0
- package/src/lib/core/services/theme.service.spec.ts +106 -0
- package/src/lib/core/services/theme.service.ts +86 -0
- package/src/lib/core/services/transport.spec.ts +198 -0
- package/src/lib/core/services/transport.ts +164 -0
- package/src/lib/core/services/upload.service.ts +81 -0
- package/src/lib/core/testing/categories.schema.ts +125 -0
- package/src/lib/core/testing/orders.schema.ts +372 -0
- package/src/lib/core/testing/products.schema.ts +258 -0
- package/src/lib/core/testing/site.schema.ts +195 -0
- package/src/lib/core/testing/test-catalog.ts +21 -0
- package/src/lib/core/tokens.ts +112 -0
- package/src/lib/core/utils/clipboard.spec.ts +55 -0
- package/src/lib/core/utils/clipboard.ts +90 -0
- package/src/lib/core/utils/context-resolver.spec.ts +95 -0
- package/src/lib/core/utils/context-resolver.ts +101 -0
- package/src/lib/core/utils/response-unwrapper.spec.ts +70 -0
- package/src/lib/core/utils/response-unwrapper.ts +103 -0
- package/src/lib/core/utils/source-options.spec.ts +96 -0
- package/src/lib/core/utils/source-options.ts +54 -0
- package/src/lib/core/utils/template-interpolator.spec.ts +59 -0
- package/src/lib/core/utils/template-interpolator.ts +56 -0
- package/src/lib/core/view-navigation/view-navigation.service.spec.ts +207 -0
- package/src/lib/core/view-navigation/view-navigation.service.ts +132 -0
- package/src/lib/fields/boolean/boolean.descriptor.ts +11 -0
- package/src/lib/fields/boolean/boolean.ts +40 -0
- package/src/lib/fields/color/color.descriptor.ts +12 -0
- package/src/lib/fields/color/color.ts +34 -0
- package/src/lib/fields/currency/currency.descriptor.ts +12 -0
- package/src/lib/fields/currency/currency.ts +67 -0
- package/src/lib/fields/date/date.descriptor.ts +12 -0
- package/src/lib/fields/date/date.ts +36 -0
- package/src/lib/fields/descriptors.ts +122 -0
- package/src/lib/fields/display/display-badge.ts +65 -0
- package/src/lib/fields/display/display-date.ts +39 -0
- package/src/lib/fields/display/display-defaults.ts +84 -0
- package/src/lib/fields/display/display-file.ts +41 -0
- package/src/lib/fields/display/display-image.ts +54 -0
- package/src/lib/fields/display/display-list.ts +107 -0
- package/src/lib/fields/display/display-number.ts +41 -0
- package/src/lib/fields/display/display-text.ts +42 -0
- package/src/lib/fields/display/display.spec.ts +242 -0
- package/src/lib/fields/dropdown/dropdown.descriptor.ts +12 -0
- package/src/lib/fields/dropdown/dropdown.ts +45 -0
- package/src/lib/fields/email/email.descriptor.ts +12 -0
- package/src/lib/fields/email/email.ts +28 -0
- package/src/lib/fields/field-aria.ts +60 -0
- package/src/lib/fields/field-host/field-host.spec.ts +118 -0
- package/src/lib/fields/field-host/field-host.ts +47 -0
- package/src/lib/fields/field-node.ts +88 -0
- package/src/lib/fields/file/file.descriptor.ts +14 -0
- package/src/lib/fields/file/file.spec.ts +134 -0
- package/src/lib/fields/file/file.ts +281 -0
- package/src/lib/fields/group/group.descriptor.ts +21 -0
- package/src/lib/fields/group/group.ts +110 -0
- package/src/lib/fields/image/image.descriptor.ts +12 -0
- package/src/lib/fields/image/image.spec.ts +117 -0
- package/src/lib/fields/image/image.ts +281 -0
- package/src/lib/fields/key-value/key-value.descriptor.ts +11 -0
- package/src/lib/fields/key-value/key-value.ts +283 -0
- package/src/lib/fields/list/list.descriptor.ts +21 -0
- package/src/lib/fields/list/list.ts +376 -0
- package/src/lib/fields/multiselect/multiselect.descriptor.ts +11 -0
- package/src/lib/fields/multiselect/multiselect.spec.ts +142 -0
- package/src/lib/fields/multiselect/multiselect.ts +152 -0
- package/src/lib/fields/number/number.descriptor.ts +12 -0
- package/src/lib/fields/number/number.ts +40 -0
- package/src/lib/fields/phone/phone.descriptor.ts +12 -0
- package/src/lib/fields/phone/phone.ts +46 -0
- package/src/lib/fields/readonly-text/readonly-text.descriptor.ts +12 -0
- package/src/lib/fields/readonly-text/readonly-text.ts +58 -0
- package/src/lib/fields/relation/relation.descriptor.ts +12 -0
- package/src/lib/fields/relation/relation.spec.ts +193 -0
- package/src/lib/fields/relation/relation.ts +224 -0
- package/src/lib/fields/rich-select/rich-select.descriptor.ts +12 -0
- package/src/lib/fields/rich-select/rich-select.ts +175 -0
- package/src/lib/fields/select/radio-mode.ts +25 -0
- package/src/lib/fields/select/select.descriptor.ts +12 -0
- package/src/lib/fields/select/select.spec.ts +162 -0
- package/src/lib/fields/select/select.ts +210 -0
- package/src/lib/fields/slug/slug.descriptor.ts +19 -0
- package/src/lib/fields/slug/slug.ts +67 -0
- package/src/lib/fields/string-list/string-list.descriptor.ts +11 -0
- package/src/lib/fields/string-list/string-list.ts +222 -0
- package/src/lib/fields/text/text.descriptor.ts +12 -0
- package/src/lib/fields/text/text.ts +35 -0
- package/src/lib/fields/textarea/textarea.descriptor.ts +12 -0
- package/src/lib/fields/textarea/textarea.spec.ts +117 -0
- package/src/lib/fields/textarea/textarea.ts +126 -0
- package/src/lib/fields/time/time.descriptor.ts +12 -0
- package/src/lib/fields/time/time.ts +28 -0
- package/src/lib/fields/unknown-render/unknown-render.ts +49 -0
- package/src/lib/fields/url/url.descriptor.ts +12 -0
- package/src/lib/fields/url/url.ts +53 -0
- package/src/lib/gas-admin-ui.spec.ts +21 -0
- package/src/lib/gas-admin-ui.ts +9 -0
- package/src/lib/layouts/descriptors.ts +9 -0
- package/src/lib/pages/dashboard/dashboard.ts +167 -0
- package/src/lib/pages/detail-view/detail-view.spec.ts +333 -0
- package/src/lib/pages/detail-view/detail-view.ts +570 -0
- package/src/lib/pages/drawer-form/drawer-form.ts +228 -0
- package/src/lib/pages/form-view/form-model.ts +88 -0
- package/src/lib/pages/form-view/form-schema.ts +255 -0
- package/src/lib/pages/form-view/form-view.ts +1622 -0
- package/src/lib/pages/list-view/list-view.formats.spec.ts +214 -0
- package/src/lib/pages/list-view/list-view.ts +882 -0
- package/src/lib/pages/login/login.spec.ts +109 -0
- package/src/lib/pages/login/login.ts +227 -0
- package/src/lib/pages/resource-page/resource-page.ts +234 -0
- package/src/lib/shared/components/badge/badge.ts +35 -0
- package/src/lib/shared/components/button/button.ts +65 -0
- package/src/lib/shared/components/confirm-dialog/confirm-dialog.ts +48 -0
- package/src/lib/shared/components/copy-button/copy-button.ts +56 -0
- package/src/lib/shared/components/copy-share/copy-share.spec.ts +122 -0
- package/src/lib/shared/components/copy-share/copy-share.ts +107 -0
- package/src/lib/shared/components/drawer/drawer.spec.ts +127 -0
- package/src/lib/shared/components/drawer/drawer.ts +172 -0
- package/src/lib/shared/components/empty-state/empty-state.ts +30 -0
- package/src/lib/shared/components/modal/modal.spec.ts +149 -0
- package/src/lib/shared/components/modal/modal.ts +145 -0
- package/src/lib/shared/components/post-create-modal/post-create-modal.spec.ts +165 -0
- package/src/lib/shared/components/post-create-modal/post-create-modal.ts +159 -0
- package/src/lib/shared/components/skeleton/skeleton.ts +31 -0
- package/src/lib/shared/components/toast/toast.ts +58 -0
- package/src/lib/shared/utils/col-span.ts +25 -0
- package/src/lib/shared/utils/condition-evaluator.ts +53 -0
- package/src/lib/shared/utils/depends-on.ts +48 -0
- package/src/lib/shared/utils/dialog-focus.ts +28 -0
- package/src/lib/shared/utils/field-path.ts +49 -0
- package/src/lib/shared/utils/gap-sorting.ts +144 -0
- package/src/lib/shared/utils/seed.spec.ts +64 -0
- package/src/lib/shared/utils/seed.ts +149 -0
- package/src/lib/shared/utils/slugify.ts +13 -0
- package/src/lib/shared/utils/validators.ts +41 -0
- package/src/lib/shell/layout/layout.ts +63 -0
- package/src/lib/shell/shell.routes.spec.ts +59 -0
- package/src/lib/shell/shell.routes.ts +122 -0
- package/src/lib/shell/sidebar/sidebar.ts +139 -0
- package/src/lib/shell/theme-toggle/theme-toggle.ts +74 -0
- package/src/lib/views/calendar-view/calendar-model.ts +426 -0
- package/src/lib/views/calendar-view/calendar-view.spec.ts +557 -0
- package/src/lib/views/calendar-view/calendar-view.ts +568 -0
- package/src/lib/views/composer/composer-host.spec.ts +301 -0
- package/src/lib/views/composer/composer-host.ts +248 -0
- package/src/lib/views/composer/composer-imports.spec.ts +54 -0
- package/src/lib/views/composer/view-context.spec.ts +117 -0
- package/src/lib/views/composer/view-context.ts +109 -0
- package/src/lib/views/composer/view-slot.spec.ts +130 -0
- package/src/lib/views/composer/view-slot.ts +178 -0
- package/src/lib/views/descriptors.ts +46 -0
- package/src/lib/views/kanban-view/kanban-model.ts +173 -0
- package/src/lib/views/kanban-view/kanban-view.spec.ts +540 -0
- package/src/lib/views/kanban-view/kanban-view.ts +327 -0
- package/src/lib/widgets/bar-chart/bar-chart.descriptor.ts +17 -0
- package/src/lib/widgets/bar-chart/bar-chart.spec.ts +66 -0
- package/src/lib/widgets/bar-chart/bar-chart.ts +76 -0
- package/src/lib/widgets/chart-line/chart-line.descriptor.ts +17 -0
- package/src/lib/widgets/chart-line/chart-line.spec.ts +113 -0
- package/src/lib/widgets/chart-line/chart-line.ts +219 -0
- package/src/lib/widgets/descriptors.ts +29 -0
- package/src/lib/widgets/metric-card/metric-card.descriptor.ts +41 -0
- package/src/lib/widgets/metric-card/metric-card.spec.ts +52 -0
- package/src/lib/widgets/metric-card/metric-card.ts +48 -0
- package/src/lib/widgets/quick-actions/quick-actions.descriptor.ts +13 -0
- package/src/lib/widgets/quick-actions/quick-actions.spec.ts +61 -0
- package/src/lib/widgets/quick-actions/quick-actions.ts +100 -0
- package/src/lib/widgets/record-list/record-list.descriptor.ts +16 -0
- package/src/lib/widgets/record-list/record-list.spec.ts +79 -0
- package/src/lib/widgets/record-list/record-list.ts +115 -0
- package/src/lib/widgets/series.spec.ts +42 -0
- package/src/lib/widgets/series.ts +56 -0
- package/src/lib/widgets/status-progress/status-progress.descriptor.ts +19 -0
- package/src/lib/widgets/status-progress/status-progress.spec.ts +63 -0
- package/src/lib/widgets/status-progress/status-progress.ts +104 -0
- package/src/lib/widgets/widget-host/widget-host.spec.ts +179 -0
- package/src/lib/widgets/widget-host/widget-host.ts +99 -0
- package/src/public-api.ts +104 -0
- package/tinya-code-gas-admin-ui-0.2.0-alpha.15.tgz +0 -0
- package/tsconfig.lib.json +13 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +10 -0
- package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs +0 -84
- package/fesm2022/tinya-code-gas-admin-ui-badge-EeCA_l-o.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs +0 -140
- package/fesm2022/tinya-code-gas-admin-ui-bar-chart-G7sEMSBY.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs +0 -113
- package/fesm2022/tinya-code-gas-admin-ui-boolean-B2ASKL0E.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs +0 -163
- package/fesm2022/tinya-code-gas-admin-ui-button-BQjNW8KB.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs +0 -1027
- package/fesm2022/tinya-code-gas-admin-ui-calendar-view-DCY8bj2V.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs +0 -278
- package/fesm2022/tinya-code-gas-admin-ui-chart-line-BjdlKHoH.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs +0 -107
- package/fesm2022/tinya-code-gas-admin-ui-color-Dljh_By3.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs +0 -101
- package/fesm2022/tinya-code-gas-admin-ui-condition-evaluator-DY2k1M3C.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs +0 -141
- package/fesm2022/tinya-code-gas-admin-ui-currency-BvuF3Z63.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs +0 -88
- package/fesm2022/tinya-code-gas-admin-ui-data-source.service-96FSbN72.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs +0 -107
- package/fesm2022/tinya-code-gas-admin-ui-date-1SJGXZrd.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs +0 -140
- package/fesm2022/tinya-code-gas-admin-ui-display-badge-fwk6sDU7.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs +0 -119
- package/fesm2022/tinya-code-gas-admin-ui-display-date-D7zLiDiG.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs +0 -125
- package/fesm2022/tinya-code-gas-admin-ui-display-file-BiIhqvQC.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs +0 -152
- package/fesm2022/tinya-code-gas-admin-ui-display-image-C1dhnZi1.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs +0 -211
- package/fesm2022/tinya-code-gas-admin-ui-display-list-DOEuUbGe.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs +0 -116
- package/fesm2022/tinya-code-gas-admin-ui-display-number-DDMzr4Hn.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs +0 -111
- package/fesm2022/tinya-code-gas-admin-ui-display-text-B8CdVNpv.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs +0 -122
- package/fesm2022/tinya-code-gas-admin-ui-dropdown-C3blvmE1.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs +0 -107
- package/fesm2022/tinya-code-gas-admin-ui-email-CT_O5ihA.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs +0 -109
- package/fesm2022/tinya-code-gas-admin-ui-empty-state-BMc0QtoT.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs +0 -45
- package/fesm2022/tinya-code-gas-admin-ui-error-mapper.service-DY5y1FjE.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs +0 -50
- package/fesm2022/tinya-code-gas-admin-ui-field-aria-BD1Wiggc.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs +0 -24
- package/fesm2022/tinya-code-gas-admin-ui-field-node-CIK6KNN_.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs +0 -27
- package/fesm2022/tinya-code-gas-admin-ui-field-path-B4-FTBGZ.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs +0 -408
- package/fesm2022/tinya-code-gas-admin-ui-file-Dmxioog7.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs +0 -4516
- package/fesm2022/tinya-code-gas-admin-ui-form-view-C709rc57.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs +0 -82
- package/fesm2022/tinya-code-gas-admin-ui-format-badge-CK8ct5Wk.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs +0 -105
- package/fesm2022/tinya-code-gas-admin-ui-format-boolean-ClzezZz-.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs +0 -65
- package/fesm2022/tinya-code-gas-admin-ui-format-currency-CVmniKml.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs +0 -65
- package/fesm2022/tinya-code-gas-admin-ui-format-date-Dr1YsDd_.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs +0 -65
- package/fesm2022/tinya-code-gas-admin-ui-format-number-CWCjpI4n.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs +0 -59
- package/fesm2022/tinya-code-gas-admin-ui-format-text-DBOgJkH0.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs +0 -94
- package/fesm2022/tinya-code-gas-admin-ui-format-thumbnail-PCRvxWKt.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs +0 -72
- package/fesm2022/tinya-code-gas-admin-ui-gap-sorting-iTdy_DYG.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs +0 -238
- package/fesm2022/tinya-code-gas-admin-ui-group-h7-O8tt4.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs +0 -416
- package/fesm2022/tinya-code-gas-admin-ui-image-7UhJ7nqI.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs +0 -439
- package/fesm2022/tinya-code-gas-admin-ui-kanban-view-Dl0Ol5Kb.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs +0 -513
- package/fesm2022/tinya-code-gas-admin-ui-key-value-nVdgg5at.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs +0 -637
- package/fesm2022/tinya-code-gas-admin-ui-list-C8ijJHAx.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs +0 -127
- package/fesm2022/tinya-code-gas-admin-ui-metric-card-DnGMQL8l.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs +0 -251
- package/fesm2022/tinya-code-gas-admin-ui-multiselect-PB28e-jl.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs +0 -66
- package/fesm2022/tinya-code-gas-admin-ui-notification.service-LjSULER6.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs +0 -114
- package/fesm2022/tinya-code-gas-admin-ui-number-JNr7glc8.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs +0 -116
- package/fesm2022/tinya-code-gas-admin-ui-phone-jR417hPf.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs +0 -235
- package/fesm2022/tinya-code-gas-admin-ui-quick-actions-DCQ6emmF.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs +0 -8
- package/fesm2022/tinya-code-gas-admin-ui-radio-mode-DxvN07DY.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs +0 -124
- package/fesm2022/tinya-code-gas-admin-ui-readonly-text-BL7-4qie.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs +0 -249
- package/fesm2022/tinya-code-gas-admin-ui-record-list-BiZfnd_7.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs +0 -39
- package/fesm2022/tinya-code-gas-admin-ui-relation-drawer.service-B0kT8EiW.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs +0 -309
- package/fesm2022/tinya-code-gas-admin-ui-relation-ykpJ3PYl.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs +0 -576
- package/fesm2022/tinya-code-gas-admin-ui-render-registry-CULkxrSt.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs +0 -161
- package/fesm2022/tinya-code-gas-admin-ui-rich-select-CIHaOrbU.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-rolldown-runtime-DpJrqANO.mjs +0 -11
- package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs +0 -685
- package/fesm2022/tinya-code-gas-admin-ui-schema-catalog-D0Pk0wAN.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs +0 -80
- package/fesm2022/tinya-code-gas-admin-ui-seed-CcCA3FdQ.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs +0 -296
- package/fesm2022/tinya-code-gas-admin-ui-select-CDwX9yNO.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs +0 -119
- package/fesm2022/tinya-code-gas-admin-ui-skeleton-DnWK0tcZ.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs +0 -158
- package/fesm2022/tinya-code-gas-admin-ui-slug-DU58cbiY.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs +0 -26
- package/fesm2022/tinya-code-gas-admin-ui-source-options-B9R4mw8-.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs +0 -205
- package/fesm2022/tinya-code-gas-admin-ui-status-progress-DmeG8htE.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs +0 -432
- package/fesm2022/tinya-code-gas-admin-ui-string-list-gleasqzD.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs +0 -36
- package/fesm2022/tinya-code-gas-admin-ui-template-interpolator-ewv7CkNX.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs +0 -107
- package/fesm2022/tinya-code-gas-admin-ui-text-CUPmL7W_.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs +0 -223
- package/fesm2022/tinya-code-gas-admin-ui-textarea-CGLSIW13.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs +0 -107
- package/fesm2022/tinya-code-gas-admin-ui-time-BcHzsTWf.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs +0 -60
- package/fesm2022/tinya-code-gas-admin-ui-upload.service-CZPEPCeN.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs +0 -141
- package/fesm2022/tinya-code-gas-admin-ui-url-GO4LZi__.mjs.map +0 -1
- package/fesm2022/tinya-code-gas-admin-ui.mjs +0 -4599
- package/fesm2022/tinya-code-gas-admin-ui.mjs.map +0 -1
- package/types/tinya-code-gas-admin-ui.d.ts +0 -3632
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { inject, Injector, Service } from '@angular/core';
|
|
3
|
+
import { map, Observable, tap, throwError } from 'rxjs';
|
|
4
|
+
|
|
5
|
+
import { renewedTokenOf } from '../models/api.model';
|
|
6
|
+
import type { PageResult } from '../models/api.model';
|
|
7
|
+
import type { CustomEndpointDefinition, ResourceEndpoints, ResourceSchema, ResponseUnwrap } from '../models/schema.model';
|
|
8
|
+
import { extractPagination, unwrapResponse } from '../utils/response-unwrapper';
|
|
9
|
+
import { DEFAULT_RESPONSE_UNWRAP, API_DRIVER, API_URL, FIREBASE_AUTH_ADAPTER, VALUE_SOURCES } from '../tokens';
|
|
10
|
+
import type { ValueSources } from '../tokens';
|
|
11
|
+
import { resolveEndpointPath } from '../utils/context-resolver';
|
|
12
|
+
import { sendGas, sendRest, type EnvelopeMethod, type TransportDeps } from './transport';
|
|
13
|
+
import { ConfigService } from './config.service';
|
|
14
|
+
import { AuthService } from './auth.service';
|
|
15
|
+
|
|
16
|
+
export type { EnvelopeMethod } from './transport';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* CRUD genérico sobre el contrato v2 (baseapi §2.3) con soporte dual-driver:
|
|
20
|
+
*
|
|
21
|
+
* - **`gas` (default)**: TODA llamada a la API es un `POST` a `API_URL` con cuerpo
|
|
22
|
+
* `text/plain` y el JSON `{ token, method, path, payload }`.
|
|
23
|
+
* - **`rest`**: Verbos HTTP reales (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) hacia
|
|
24
|
+
* `${API_URL}${path}` con `Authorization: Bearer ${token}`. `payload` va como query
|
|
25
|
+
* params en GET/DELETE (aplanando objetos anidados como `params`) o como body JSON
|
|
26
|
+
* en POST/PUT/PATCH.
|
|
27
|
+
*/
|
|
28
|
+
@Service()
|
|
29
|
+
export class ApiService {
|
|
30
|
+
private readonly http = inject(HttpClient);
|
|
31
|
+
private readonly apiUrl = inject(API_URL);
|
|
32
|
+
private readonly auth = inject(AuthService);
|
|
33
|
+
private readonly driver = inject(API_DRIVER, { optional: true }) ?? 'gas';
|
|
34
|
+
/** Fuentes que aporta el consumidor (`provideGasAdmin({ valueSources })`). */
|
|
35
|
+
private readonly valueSources: ValueSources = inject(VALUE_SOURCES, { optional: true }) ?? {};
|
|
36
|
+
/** Adaptador opcional de Firebase Auth para refrescar el ID token antes de peticiones REST. */
|
|
37
|
+
private readonly firebaseAuthAdapter = inject(FIREBASE_AUTH_ADAPTER, { optional: true });
|
|
38
|
+
/**
|
|
39
|
+
* Acceso PEREZOSO a `ConfigService` (R2 · plan doc/context-sources-plan.md).
|
|
40
|
+
*
|
|
41
|
+
* `config` es fuente construida del motor, pero inyectarla en el constructor
|
|
42
|
+
* formaría un ciclo: `ConfigService` inyecta `ApiService` (opcional) para
|
|
43
|
+
* cargar los singletons ⇒ NG0200 en el arranque. Se pide en el momento de la
|
|
44
|
+
* petición, cuando ambos servicios ya están vivos. Si no existe (TestBed
|
|
45
|
+
* parcial), devuelve `null` y el resolver falla ruidoso con «sin valor».
|
|
46
|
+
*/
|
|
47
|
+
private readonly injector = inject(Injector);
|
|
48
|
+
/** Unwrap global por defecto (`GasAdminConfig.defaultResponseUnwrap`); opcional. */
|
|
49
|
+
private readonly defaultUnwrap: ResponseUnwrap | undefined = inject(
|
|
50
|
+
DEFAULT_RESPONSE_UNWRAP,
|
|
51
|
+
{ optional: true },
|
|
52
|
+
) ?? undefined;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Declaración de unwrap EFECTIVA para un endpoint: fusión del default
|
|
56
|
+
* global con la declaración por recurso (recurso gana en las claves que
|
|
57
|
+
* declara). Sin ninguna de las dos ⇒ `undefined` (comportamiento actual).
|
|
58
|
+
*/
|
|
59
|
+
private effectiveUnwrap(endpoint: ResourceEndpoints): ResponseUnwrap | undefined {
|
|
60
|
+
const global = this.defaultUnwrap;
|
|
61
|
+
const local = endpoint.responseUnwrap;
|
|
62
|
+
if (!global) return local;
|
|
63
|
+
if (!local) return global;
|
|
64
|
+
return { ...global, ...local };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Listado. El backend envuelve la respuesta cuando la operación declara
|
|
69
|
+
* `shape.envelope: 'list'` (F5) ⇒ `{ items, nextCursor, total }` (R6.4);
|
|
70
|
+
* la UI consume `T[]` en todos lados (F7-3) y este es el ÚNICO punto que
|
|
71
|
+
* habla de listas, así que el desenvolvimiento vive acá. `nextCursor` es
|
|
72
|
+
* el token de la página siguiente y `null` en la última — éste servicio
|
|
73
|
+
* lo descarta hoy porque la lista no pagina todavía (backlog-ui-ux).
|
|
74
|
+
* Un listado sin envelope (arreglo plano, el contrato histórico) pasa
|
|
75
|
+
* tal cual.
|
|
76
|
+
*
|
|
77
|
+
* `payload` sólo lo usa una fuente declarada (F8 · R6.5): `{ view, params }`
|
|
78
|
+
* pide el listado filtrado por una vista y sus parámetros. Sin él, la
|
|
79
|
+
* llamada es la de siempre — la lectura llana del recurso.
|
|
80
|
+
*/
|
|
81
|
+
list<T>(endpoint: ResourceEndpoints, payload?: Record<string, unknown>): Observable<T[]> {
|
|
82
|
+
const unwrap = this.effectiveUnwrap(endpoint);
|
|
83
|
+
return this.send<unknown>(endpoint.list, 'GET', payload).pipe(
|
|
84
|
+
map((raw) => {
|
|
85
|
+
if (unwrap && (unwrap.apply === 'list' || unwrap.apply === 'all' || !unwrap.apply)) {
|
|
86
|
+
return unwrapResponse(raw, unwrap, 'list') as T[];
|
|
87
|
+
}
|
|
88
|
+
return unwrapList<T>(raw);
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Listado paginado OPT-IN (plan doc/engine-refactor-plan.md · Fase 3).
|
|
95
|
+
*
|
|
96
|
+
* Misma petición que `list()` pero devuelve `PageResult<T>` con la metadata
|
|
97
|
+
* de paginación que el backend envía en el sobre (`{ items, nextCursor,
|
|
98
|
+
* total }` o dentro de `meta` con unwrap declarado). Las claves se leen
|
|
99
|
+
* según `responseUnwrap.pagination` (cursorKey/totalKey/hasMoreKey) o se
|
|
100
|
+
* auto-detectan (`nextCursor`, `total`, `hasMore`).
|
|
101
|
+
*
|
|
102
|
+
* `payload` acepta normalmente `{ cursor, limit }` para pedir la página
|
|
103
|
+
* siguiente; viaja como cualquier otro payload (query params en GET REST,
|
|
104
|
+
* campo `payload` del envelope en GAS). `list()` no cambia: sigue
|
|
105
|
+
* devolviendo `T[]` (R11).
|
|
106
|
+
*/
|
|
107
|
+
listPage<T>(
|
|
108
|
+
endpoint: ResourceEndpoints,
|
|
109
|
+
payload?: Record<string, unknown>,
|
|
110
|
+
): Observable<PageResult<T>> {
|
|
111
|
+
const unwrap = this.effectiveUnwrap(endpoint);
|
|
112
|
+
const applies = !unwrap || unwrap.apply === 'list' || unwrap.apply === 'all' || !unwrap.apply;
|
|
113
|
+
return this.send<unknown>(endpoint.list, 'GET', payload).pipe(
|
|
114
|
+
map((raw) => {
|
|
115
|
+
const items =
|
|
116
|
+
unwrap && applies
|
|
117
|
+
? (unwrapResponse(raw, unwrap, 'list') as T[])
|
|
118
|
+
: unwrapList<T>(raw);
|
|
119
|
+
return { items, ...extractPagination(raw, unwrap) };
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** `key` solo aplica a colecciones (`{key}` en la plantilla); los singleton no la llevan. */
|
|
125
|
+
get<T>(endpoint: ResourceEndpoints, key?: string): Observable<T> { const unwrap = this.effectiveUnwrap(endpoint);
|
|
126
|
+
return this.send<unknown>(this.withKey(endpoint.get, key), 'GET').pipe(
|
|
127
|
+
map((raw) => {
|
|
128
|
+
if (unwrap && (unwrap.apply === 'get' || unwrap.apply === 'all' || !unwrap.apply)) {
|
|
129
|
+
return unwrapResponse(raw, unwrap, 'get') as T;
|
|
130
|
+
}
|
|
131
|
+
return raw as T;
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
create<T>(endpoint: ResourceEndpoints, payload: Record<string, unknown>): Observable<T> {
|
|
137
|
+
const unwrap = this.effectiveUnwrap(endpoint);
|
|
138
|
+
return this.send<unknown>(endpoint.create, 'POST', payload).pipe(
|
|
139
|
+
map((raw) => {
|
|
140
|
+
if (unwrap && (unwrap.apply === 'create' || unwrap.apply === 'all' || !unwrap.apply)) {
|
|
141
|
+
return unwrapResponse(raw, unwrap, 'create') as T;
|
|
142
|
+
}
|
|
143
|
+
return raw as T;
|
|
144
|
+
}),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
update<T>(
|
|
149
|
+
endpoint: ResourceEndpoints,
|
|
150
|
+
key: string | undefined,
|
|
151
|
+
payload: Record<string, unknown>,
|
|
152
|
+
): Observable<T> {
|
|
153
|
+
const unwrap = this.effectiveUnwrap(endpoint);
|
|
154
|
+
return this.send<unknown>(this.withKey(endpoint.update, key), 'PUT', payload).pipe(
|
|
155
|
+
map((raw) => {
|
|
156
|
+
if (unwrap && (unwrap.apply === 'update' || unwrap.apply === 'all' || !unwrap.apply)) {
|
|
157
|
+
return unwrapResponse(raw, unwrap, 'update') as T;
|
|
158
|
+
}
|
|
159
|
+
return raw as T;
|
|
160
|
+
}),
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
remove(endpoint: ResourceEndpoints, key?: string): Observable<void> {
|
|
165
|
+
const unwrap = endpoint.responseUnwrap;
|
|
166
|
+
return this.send<unknown>(this.withKey(endpoint.remove, key), 'DELETE').pipe(
|
|
167
|
+
map(() => void 0),
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Operación genérica sobre una ruta ya resuelta: reorder de colección
|
|
173
|
+
* (`PUT /admin/x` con `{ reorder: … }`), `/admin/schema`,
|
|
174
|
+
* `/admin/upload-signature`, etc.
|
|
175
|
+
*/
|
|
176
|
+
request<T>(
|
|
177
|
+
method: EnvelopeMethod,
|
|
178
|
+
path: string | undefined,
|
|
179
|
+
payload?: Record<string, unknown>,
|
|
180
|
+
): Observable<T> {
|
|
181
|
+
const dataKey = this.defaultUnwrap?.dataKey ?? 'data';
|
|
182
|
+
return this.send<T>(path, method, payload).pipe(
|
|
183
|
+
map((raw: unknown) => {
|
|
184
|
+
// Desenvolvimiento passthrough (como el interceptor viejo): sólo si la
|
|
185
|
+
// respuesta trae la clave `data`, se desenvuelve; si no, pasa tal cual.
|
|
186
|
+
// Evita romper endpoints que no envuelven (ej. upload-signature).
|
|
187
|
+
if (raw !== null && typeof raw === 'object' && !Array.isArray(raw)) {
|
|
188
|
+
const rec = raw as Record<string, unknown>;
|
|
189
|
+
if (Object.prototype.hasOwnProperty.call(rec, dataKey)) {
|
|
190
|
+
return rec[dataKey] as T;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return raw as T;
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Invoca un endpoint personalizado declarado por el consumidor.
|
|
200
|
+
*
|
|
201
|
+
* Acepta bien la definición directa (`CustomEndpointDefinition`) o un schema
|
|
202
|
+
* + nombre (resuelve en `schema.customEndpoints`). El despacho respeta el
|
|
203
|
+
* método, la ruta, el modo de payload (json/multipart) y el unwrap propios
|
|
204
|
+
* de la declaración.
|
|
205
|
+
*/
|
|
206
|
+
invokeCustomEndpoint<T>(
|
|
207
|
+
definitionOrSchema: CustomEndpointDefinition | ResourceSchema,
|
|
208
|
+
nameOrPayload?: string | Record<string, unknown> | FormData,
|
|
209
|
+
payload?: Record<string, unknown> | FormData,
|
|
210
|
+
key?: string,
|
|
211
|
+
): Observable<T> {
|
|
212
|
+
let definition: CustomEndpointDefinition | undefined;
|
|
213
|
+
let actualPayload: Record<string, unknown> | FormData | undefined;
|
|
214
|
+
let actualKey: string | undefined = key;
|
|
215
|
+
|
|
216
|
+
if (isResourceSchema(definitionOrSchema)) {
|
|
217
|
+
const name = typeof nameOrPayload === 'string' ? nameOrPayload : undefined;
|
|
218
|
+
if (!name) {
|
|
219
|
+
throw new Error('invokeCustomEndpoint requires an endpoint name when given a schema');
|
|
220
|
+
}
|
|
221
|
+
definition = definitionOrSchema.customEndpoints?.[name];
|
|
222
|
+
if (!definition) {
|
|
223
|
+
throw new Error(`Custom endpoint '${name}' is not declared for resource '${definitionOrSchema.id}'`);
|
|
224
|
+
}
|
|
225
|
+
actualPayload = (typeof nameOrPayload === 'string' ? payload : (nameOrPayload as Record<string, unknown> | FormData | undefined)) ?? payload;
|
|
226
|
+
} else {
|
|
227
|
+
definition = definitionOrSchema;
|
|
228
|
+
actualPayload =
|
|
229
|
+
(nameOrPayload as Record<string, unknown> | FormData | undefined) ?? payload;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (!definition) {
|
|
233
|
+
return throwError(() => new Error('Custom endpoint definition is required'));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const multipart = definition.payloadMode === 'multipart' || actualPayload instanceof FormData;
|
|
237
|
+
const path = this.withKey(definition.path, actualKey);
|
|
238
|
+
const method = definition.method;
|
|
239
|
+
|
|
240
|
+
const unwrap = definition.responseUnwrap;
|
|
241
|
+
return this.send<unknown>(path, method, actualPayload, multipart).pipe(
|
|
242
|
+
map((raw) => {
|
|
243
|
+
if (unwrap) {
|
|
244
|
+
return unwrapResponse(raw, unwrap, 'get') as T;
|
|
245
|
+
}
|
|
246
|
+
return raw as T;
|
|
247
|
+
}),
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Alias corto de `invokeCustomEndpoint`. */
|
|
252
|
+
invokeCustom<T>(
|
|
253
|
+
schemaOrDefinition: ResourceSchema | CustomEndpointDefinition,
|
|
254
|
+
nameOrPayload?: string | Record<string, unknown> | FormData,
|
|
255
|
+
payload?: Record<string, unknown> | FormData,
|
|
256
|
+
key?: string,
|
|
257
|
+
): Observable<T> {
|
|
258
|
+
return this.invokeCustomEndpoint<T>(schemaOrDefinition, nameOrPayload, payload, key);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Alias adicional por compatibilidad. */
|
|
262
|
+
custom<T>(
|
|
263
|
+
schemaOrDefinition: ResourceSchema | CustomEndpointDefinition,
|
|
264
|
+
nameOrPayload?: string | Record<string, unknown> | FormData,
|
|
265
|
+
payload?: Record<string, unknown> | FormData,
|
|
266
|
+
key?: string,
|
|
267
|
+
): Observable<T> {
|
|
268
|
+
return this.invokeCustomEndpoint<T>(schemaOrDefinition, nameOrPayload, payload, key);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private send<T>(
|
|
272
|
+
path: string | undefined,
|
|
273
|
+
method: EnvelopeMethod,
|
|
274
|
+
payload?: Record<string, unknown> | FormData,
|
|
275
|
+
multipart = false,
|
|
276
|
+
): Observable<T> {
|
|
277
|
+
if (!path) {
|
|
278
|
+
return throwError(() => new Error('Operación no disponible para este recurso'));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Resolución de marcadores de contexto ANTES del despacho (plan Fase 3):
|
|
282
|
+
// un solo punto para todas las operaciones y para ambos drivers. Sin
|
|
283
|
+
// marcadores el path vuelve intacto y ninguna fuente se evalúa.
|
|
284
|
+
let resolvedPath: string;
|
|
285
|
+
try {
|
|
286
|
+
resolvedPath = resolveEndpointPath(path, this.buildSources());
|
|
287
|
+
} catch (error) {
|
|
288
|
+
// Fail loud por el CANAL de errores (no como throw síncrono): el
|
|
289
|
+
// consumidor lo trata como cualquier otro fallo de petición y JAMÁS
|
|
290
|
+
// sale un request con un segmento vacío o el marcador literal.
|
|
291
|
+
return throwError(() => error);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const deps = this.transportDeps();
|
|
295
|
+
const request$ =
|
|
296
|
+
this.driver === 'rest'
|
|
297
|
+
? sendRest<T>(deps, resolvedPath, method, payload, multipart)
|
|
298
|
+
: sendGas<T>(deps, resolvedPath, method, payload, multipart);
|
|
299
|
+
|
|
300
|
+
return request$.pipe(
|
|
301
|
+
// Renovación deslizante (§3.2): si el back adjuntó `meta.renewedToken`
|
|
302
|
+
// se adopta YA, con lo que la siguiente petición ya va firmada nueva.
|
|
303
|
+
tap((res) => {
|
|
304
|
+
const renewed = renewedTokenOf(res);
|
|
305
|
+
if (renewed !== null) this.auth.applyRenewedToken(renewed);
|
|
306
|
+
}),
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Dependencias del transporte (Fase 4): la fachada sólo arma este objeto y
|
|
312
|
+
* delega en `transport.ts`. El token de sesión y el ID token fresco se
|
|
313
|
+
* resuelven vía getters en el momento de la petición (R2.8 / refresh).
|
|
314
|
+
*/
|
|
315
|
+
private transportDeps(): TransportDeps {
|
|
316
|
+
const adapter = this.firebaseAuthAdapter;
|
|
317
|
+
return {
|
|
318
|
+
http: this.http,
|
|
319
|
+
apiUrl: this.apiUrl,
|
|
320
|
+
sessionToken: () => this.auth.token(),
|
|
321
|
+
getIdToken: adapter?.getIdToken ? () => adapter.getIdToken!() : undefined,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Fuentes de contexto de ESTA petición: getters, no valores — se evalúan
|
|
327
|
+
* sólo si el path trae marcadores.
|
|
328
|
+
*
|
|
329
|
+
* Las construidas del motor (`auth`, `config`) van ÚLTIMAS: el motor es
|
|
330
|
+
* dueño de sus fuentes y el registro del consumidor no las pisa.
|
|
331
|
+
*/
|
|
332
|
+
private buildSources(): Readonly<Record<string, () => unknown>> {
|
|
333
|
+
return {
|
|
334
|
+
...this.valueSources,
|
|
335
|
+
auth: () => ({ user: this.auth.user(), token: this.auth.token() }),
|
|
336
|
+
config: () => this.injector.get(ConfigService, null)?.globalConfig() ?? null,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private withKey(path: string | undefined, key?: string): string | undefined {
|
|
341
|
+
if (!path) {
|
|
342
|
+
return undefined;
|
|
343
|
+
}
|
|
344
|
+
return path.includes('{key}') ? path.replace('{key}', encodeURIComponent(key ?? '')) : path;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Guard de forma: ¿es un `ResourceSchema` completo (endpoint + fields)? */
|
|
349
|
+
function isResourceSchema(value: unknown): value is ResourceSchema {
|
|
350
|
+
return typeof value === 'object' && value !== null && 'endpoint' in value && 'fields' in value;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** `{ items, nextCursor, total }` (F5/R6.4) → `T[]`; arreglo plano → tal cual. */
|
|
354
|
+
function unwrapList<T>(raw: unknown): T[] {
|
|
355
|
+
if (Array.isArray(raw)) {
|
|
356
|
+
return raw as T[];
|
|
357
|
+
}
|
|
358
|
+
if (raw !== null && typeof raw === 'object') {
|
|
359
|
+
const items = (raw as { items?: unknown }).items;
|
|
360
|
+
if (Array.isArray(items)) {
|
|
361
|
+
return items as T[];
|
|
362
|
+
}
|
|
363
|
+
// Objeto sin clave reconocida: compat con el baseline (R9) ⇒ [].
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
// Cuerpo ni array ni objeto (null, string, número): el contrato de listado
|
|
367
|
+
// está roto — fallar ruidoso en vez de devolver [] silenciosamente.
|
|
368
|
+
throw new Error(
|
|
369
|
+
`List response must be an array or an object with an 'items' array; received ${raw === null ? 'null' : typeof raw}`,
|
|
370
|
+
);
|
|
371
|
+
}
|