@endora-commerce/mod-catalog 0.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/admin/components/PackagingUnitsEditor.d.ts +12 -0
- package/dist/admin/components/PackagingUnitsEditor.d.ts.map +1 -0
- package/dist/admin/components/PackagingUnitsEditor.js +99 -0
- package/dist/admin/components/PackagingUnitsEditor.js.map +1 -0
- package/dist/admin/components/ProductAttributesTab.d.ts +13 -0
- package/dist/admin/components/ProductAttributesTab.d.ts.map +1 -0
- package/dist/admin/components/ProductAttributesTab.js +140 -0
- package/dist/admin/components/ProductAttributesTab.js.map +1 -0
- package/dist/admin/components/ProductInventoryTab.d.ts +14 -0
- package/dist/admin/components/ProductInventoryTab.d.ts.map +1 -0
- package/dist/admin/components/ProductInventoryTab.js +284 -0
- package/dist/admin/components/ProductInventoryTab.js.map +1 -0
- package/dist/admin/components/ProductScopeEditor.d.ts +94 -0
- package/dist/admin/components/ProductScopeEditor.d.ts.map +1 -0
- package/dist/admin/components/ProductScopeEditor.js +395 -0
- package/dist/admin/components/ProductScopeEditor.js.map +1 -0
- package/dist/admin/components/ProductsBulkEditDialog.d.ts +11 -0
- package/dist/admin/components/ProductsBulkEditDialog.d.ts.map +1 -0
- package/dist/admin/components/ProductsBulkEditDialog.js +304 -0
- package/dist/admin/components/ProductsBulkEditDialog.js.map +1 -0
- package/dist/admin/index.d.ts +45 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +184 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/lib/resolve-product-selection.d.ts +21 -0
- package/dist/admin/lib/resolve-product-selection.d.ts.map +1 -0
- package/dist/admin/lib/resolve-product-selection.js +25 -0
- package/dist/admin/lib/resolve-product-selection.js.map +1 -0
- package/dist/admin/pages/AttachmentTypesPage.d.ts +18 -0
- package/dist/admin/pages/AttachmentTypesPage.d.ts.map +1 -0
- package/dist/admin/pages/AttachmentTypesPage.js +92 -0
- package/dist/admin/pages/AttachmentTypesPage.js.map +1 -0
- package/dist/admin/pages/AttributeSetsPage.d.ts +21 -0
- package/dist/admin/pages/AttributeSetsPage.d.ts.map +1 -0
- package/dist/admin/pages/AttributeSetsPage.js +158 -0
- package/dist/admin/pages/AttributeSetsPage.js.map +1 -0
- package/dist/admin/pages/AttributesManager.d.ts +9 -0
- package/dist/admin/pages/AttributesManager.d.ts.map +1 -0
- package/dist/admin/pages/AttributesManager.js +305 -0
- package/dist/admin/pages/AttributesManager.js.map +1 -0
- package/dist/admin/pages/BulkOperationDetailPage.d.ts +9 -0
- package/dist/admin/pages/BulkOperationDetailPage.d.ts.map +1 -0
- package/dist/admin/pages/BulkOperationDetailPage.js +187 -0
- package/dist/admin/pages/BulkOperationDetailPage.js.map +1 -0
- package/dist/admin/pages/BulkOperationsPage.d.ts +9 -0
- package/dist/admin/pages/BulkOperationsPage.d.ts.map +1 -0
- package/dist/admin/pages/BulkOperationsPage.js +98 -0
- package/dist/admin/pages/BulkOperationsPage.js.map +1 -0
- package/dist/admin/pages/CategoriesTree.d.ts +9 -0
- package/dist/admin/pages/CategoriesTree.d.ts.map +1 -0
- package/dist/admin/pages/CategoriesTree.js +176 -0
- package/dist/admin/pages/CategoriesTree.js.map +1 -0
- package/dist/admin/pages/ProductEditor.d.ts +13 -0
- package/dist/admin/pages/ProductEditor.d.ts.map +1 -0
- package/dist/admin/pages/ProductEditor.js +1050 -0
- package/dist/admin/pages/ProductEditor.js.map +1 -0
- package/dist/admin/pages/ProductsList.d.ts +9 -0
- package/dist/admin/pages/ProductsList.d.ts.map +1 -0
- package/dist/admin/pages/ProductsList.js +399 -0
- package/dist/admin/pages/ProductsList.js.map +1 -0
- package/dist/backend/commands/attribute-commands.d.ts +111 -0
- package/dist/backend/commands/attribute-commands.d.ts.map +1 -0
- package/dist/backend/commands/attribute-commands.js +482 -0
- package/dist/backend/commands/attribute-commands.js.map +1 -0
- package/dist/backend/demo/reset.d.ts +23 -0
- package/dist/backend/demo/reset.d.ts.map +1 -0
- package/dist/backend/demo/reset.js +41 -0
- package/dist/backend/demo/reset.js.map +1 -0
- package/dist/backend/demo/rows.d.ts +103 -0
- package/dist/backend/demo/rows.d.ts.map +1 -0
- package/dist/backend/demo/rows.js +162 -0
- package/dist/backend/demo/rows.js.map +1 -0
- package/dist/backend/demo/seed.d.ts +35 -0
- package/dist/backend/demo/seed.d.ts.map +1 -0
- package/dist/backend/demo/seed.js +177 -0
- package/dist/backend/demo/seed.js.map +1 -0
- package/dist/backend/entities/attachment-type.entity.d.ts +16 -0
- package/dist/backend/entities/attachment-type.entity.d.ts.map +1 -0
- package/dist/backend/entities/attachment-type.entity.js +57 -0
- package/dist/backend/entities/attachment-type.entity.js.map +1 -0
- package/dist/backend/entities/attribute-set-attribute.entity.d.ts +26 -0
- package/dist/backend/entities/attribute-set-attribute.entity.d.ts.map +1 -0
- package/dist/backend/entities/attribute-set-attribute.entity.js +55 -0
- package/dist/backend/entities/attribute-set-attribute.entity.js.map +1 -0
- package/dist/backend/entities/attribute-set.entity.d.ts +22 -0
- package/dist/backend/entities/attribute-set.entity.d.ts.map +1 -0
- package/dist/backend/entities/attribute-set.entity.js +67 -0
- package/dist/backend/entities/attribute-set.entity.js.map +1 -0
- package/dist/backend/entities/bulk-operation.entity.d.ts +78 -0
- package/dist/backend/entities/bulk-operation.entity.d.ts.map +1 -0
- package/dist/backend/entities/bulk-operation.entity.js +138 -0
- package/dist/backend/entities/bulk-operation.entity.js.map +1 -0
- package/dist/backend/entities/bundle-slot-option.entity.d.ts +23 -0
- package/dist/backend/entities/bundle-slot-option.entity.d.ts.map +1 -0
- package/dist/backend/entities/bundle-slot-option.entity.js +68 -0
- package/dist/backend/entities/bundle-slot-option.entity.js.map +1 -0
- package/dist/backend/entities/bundle-slot.entity.d.ts +25 -0
- package/dist/backend/entities/bundle-slot.entity.d.ts.map +1 -0
- package/dist/backend/entities/bundle-slot.entity.js +74 -0
- package/dist/backend/entities/bundle-slot.entity.js.map +1 -0
- package/dist/backend/entities/category.entity.d.ts +26 -0
- package/dist/backend/entities/category.entity.d.ts.map +1 -0
- package/dist/backend/entities/category.entity.js +119 -0
- package/dist/backend/entities/category.entity.js.map +1 -0
- package/dist/backend/entities/gallery-item-label.entity.d.ts +22 -0
- package/dist/backend/entities/gallery-item-label.entity.d.ts.map +1 -0
- package/dist/backend/entities/gallery-item-label.entity.js +50 -0
- package/dist/backend/entities/gallery-item-label.entity.js.map +1 -0
- package/dist/backend/entities/gallery-item.entity.d.ts +17 -0
- package/dist/backend/entities/gallery-item.entity.d.ts.map +1 -0
- package/dist/backend/entities/gallery-item.entity.js +58 -0
- package/dist/backend/entities/gallery-item.entity.js.map +1 -0
- package/dist/backend/entities/grouped-item.entity.d.ts +23 -0
- package/dist/backend/entities/grouped-item.entity.d.ts.map +1 -0
- package/dist/backend/entities/grouped-item.entity.js +68 -0
- package/dist/backend/entities/grouped-item.entity.js.map +1 -0
- package/dist/backend/entities/product-attachment.entity.d.ts +23 -0
- package/dist/backend/entities/product-attachment.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-attachment.entity.js +77 -0
- package/dist/backend/entities/product-attachment.entity.js.map +1 -0
- package/dist/backend/entities/product-attribute.entity.d.ts +72 -0
- package/dist/backend/entities/product-attribute.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-attribute.entity.js +161 -0
- package/dist/backend/entities/product-attribute.entity.js.map +1 -0
- package/dist/backend/entities/product-editor-preference.entity.d.ts +28 -0
- package/dist/backend/entities/product-editor-preference.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-editor-preference.entity.js +63 -0
- package/dist/backend/entities/product-editor-preference.entity.js.map +1 -0
- package/dist/backend/entities/product-link.entity.d.ts +25 -0
- package/dist/backend/entities/product-link.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-link.entity.js +70 -0
- package/dist/backend/entities/product-link.entity.js.map +1 -0
- package/dist/backend/entities/product-packaging-unit.entity.d.ts +26 -0
- package/dist/backend/entities/product-packaging-unit.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-packaging-unit.entity.js +76 -0
- package/dist/backend/entities/product-packaging-unit.entity.js.map +1 -0
- package/dist/backend/entities/product-value-override.entity.d.ts +43 -0
- package/dist/backend/entities/product-value-override.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-value-override.entity.js +90 -0
- package/dist/backend/entities/product-value-override.entity.js.map +1 -0
- package/dist/backend/entities/product-variant.entity.d.ts +18 -0
- package/dist/backend/entities/product-variant.entity.d.ts.map +1 -0
- package/dist/backend/entities/product-variant.entity.js +68 -0
- package/dist/backend/entities/product-variant.entity.js.map +1 -0
- package/dist/backend/entities/product.entity.d.ts +108 -0
- package/dist/backend/entities/product.entity.d.ts.map +1 -0
- package/dist/backend/entities/product.entity.js +230 -0
- package/dist/backend/entities/product.entity.js.map +1 -0
- package/dist/backend/index.d.ts +262 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +642 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/plugin.d.ts +216 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +223 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/prompt-tools.d.ts +47 -0
- package/dist/backend/prompt-tools.d.ts.map +1 -0
- package/dist/backend/prompt-tools.js +284 -0
- package/dist/backend/prompt-tools.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +105 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +1162 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.api-key.d.ts +33 -0
- package/dist/backend/routes.api-key.d.ts.map +1 -0
- package/dist/backend/routes.api-key.js +43 -0
- package/dist/backend/routes.api-key.js.map +1 -0
- package/dist/backend/routes.external.d.ts +32 -0
- package/dist/backend/routes.external.d.ts.map +1 -0
- package/dist/backend/routes.external.js +115 -0
- package/dist/backend/routes.external.js.map +1 -0
- package/dist/backend/routes.public.d.ts +46 -0
- package/dist/backend/routes.public.d.ts.map +1 -0
- package/dist/backend/routes.public.js +318 -0
- package/dist/backend/routes.public.js.map +1 -0
- package/dist/backend/services/asset-references.d.ts +4 -0
- package/dist/backend/services/asset-references.d.ts.map +1 -0
- package/dist/backend/services/asset-references.js +104 -0
- package/dist/backend/services/asset-references.js.map +1 -0
- package/dist/backend/services/attachment.service.d.ts +45 -0
- package/dist/backend/services/attachment.service.d.ts.map +1 -0
- package/dist/backend/services/attachment.service.js +268 -0
- package/dist/backend/services/attachment.service.js.map +1 -0
- package/dist/backend/services/attribute-option-validator.d.ts +47 -0
- package/dist/backend/services/attribute-option-validator.d.ts.map +1 -0
- package/dist/backend/services/attribute-option-validator.js +69 -0
- package/dist/backend/services/attribute-option-validator.js.map +1 -0
- package/dist/backend/services/attribute-set-validations.d.ts +65 -0
- package/dist/backend/services/attribute-set-validations.d.ts.map +1 -0
- package/dist/backend/services/attribute-set-validations.js +89 -0
- package/dist/backend/services/attribute-set-validations.js.map +1 -0
- package/dist/backend/services/attribute-set.service.d.ts +50 -0
- package/dist/backend/services/attribute-set.service.d.ts.map +1 -0
- package/dist/backend/services/attribute-set.service.js +401 -0
- package/dist/backend/services/attribute-set.service.js.map +1 -0
- package/dist/backend/services/attribute-type-mapping.d.ts +66 -0
- package/dist/backend/services/attribute-type-mapping.d.ts.map +1 -0
- package/dist/backend/services/attribute-type-mapping.js +121 -0
- package/dist/backend/services/attribute-type-mapping.js.map +1 -0
- package/dist/backend/services/attribute-value-key.service.d.ts +48 -0
- package/dist/backend/services/attribute-value-key.service.d.ts.map +1 -0
- package/dist/backend/services/attribute-value-key.service.js +118 -0
- package/dist/backend/services/attribute-value-key.service.js.map +1 -0
- package/dist/backend/services/audit-references.d.ts +13 -0
- package/dist/backend/services/audit-references.d.ts.map +1 -0
- package/dist/backend/services/audit-references.js +51 -0
- package/dist/backend/services/audit-references.js.map +1 -0
- package/dist/backend/services/bulk-operation-queue.d.ts +26 -0
- package/dist/backend/services/bulk-operation-queue.d.ts.map +1 -0
- package/dist/backend/services/bulk-operation-queue.js +34 -0
- package/dist/backend/services/bulk-operation-queue.js.map +1 -0
- package/dist/backend/services/bulk-operation.service.d.ts +195 -0
- package/dist/backend/services/bulk-operation.service.d.ts.map +1 -0
- package/dist/backend/services/bulk-operation.service.js +510 -0
- package/dist/backend/services/bulk-operation.service.js.map +1 -0
- package/dist/backend/services/bundle.service.d.ts +87 -0
- package/dist/backend/services/bundle.service.d.ts.map +1 -0
- package/dist/backend/services/bundle.service.js +286 -0
- package/dist/backend/services/bundle.service.js.map +1 -0
- package/dist/backend/services/catalog-admin.service.d.ts +398 -0
- package/dist/backend/services/catalog-admin.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-admin.service.js +1516 -0
- package/dist/backend/services/catalog-admin.service.js.map +1 -0
- package/dist/backend/services/catalog-attribute-read.service.d.ts +78 -0
- package/dist/backend/services/catalog-attribute-read.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-attribute-read.service.js +216 -0
- package/dist/backend/services/catalog-attribute-read.service.js.map +1 -0
- package/dist/backend/services/catalog-bulk-import.service.d.ts +30 -0
- package/dist/backend/services/catalog-bulk-import.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-bulk-import.service.js +136 -0
- package/dist/backend/services/catalog-bulk-import.service.js.map +1 -0
- package/dist/backend/services/catalog-bulk-update.service.d.ts +91 -0
- package/dist/backend/services/catalog-bulk-update.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-bulk-update.service.js +330 -0
- package/dist/backend/services/catalog-bulk-update.service.js.map +1 -0
- package/dist/backend/services/catalog-category-read.service.d.ts +66 -0
- package/dist/backend/services/catalog-category-read.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-category-read.service.js +248 -0
- package/dist/backend/services/catalog-category-read.service.js.map +1 -0
- package/dist/backend/services/catalog-org-price-decorator.d.ts +90 -0
- package/dist/backend/services/catalog-org-price-decorator.d.ts.map +1 -0
- package/dist/backend/services/catalog-org-price-decorator.js +184 -0
- package/dist/backend/services/catalog-org-price-decorator.js.map +1 -0
- package/dist/backend/services/catalog-product-filter.service.d.ts +82 -0
- package/dist/backend/services/catalog-product-filter.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-product-filter.service.js +275 -0
- package/dist/backend/services/catalog-product-filter.service.js.map +1 -0
- package/dist/backend/services/catalog-product-read.service.d.ts +46 -0
- package/dist/backend/services/catalog-product-read.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-product-read.service.js +197 -0
- package/dist/backend/services/catalog-product-read.service.js.map +1 -0
- package/dist/backend/services/catalog-query.service.d.ts +444 -0
- package/dist/backend/services/catalog-query.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-query.service.js +1633 -0
- package/dist/backend/services/catalog-query.service.js.map +1 -0
- package/dist/backend/services/catalog-quick-search.service.d.ts +78 -0
- package/dist/backend/services/catalog-quick-search.service.d.ts.map +1 -0
- package/dist/backend/services/catalog-quick-search.service.js +159 -0
- package/dist/backend/services/catalog-quick-search.service.js.map +1 -0
- package/dist/backend/services/catalog-write-ports.d.ts +25 -0
- package/dist/backend/services/catalog-write-ports.d.ts.map +1 -0
- package/dist/backend/services/catalog-write-ports.js +63 -0
- package/dist/backend/services/catalog-write-ports.js.map +1 -0
- package/dist/backend/services/category-admin.service.d.ts +102 -0
- package/dist/backend/services/category-admin.service.d.ts.map +1 -0
- package/dist/backend/services/category-admin.service.js +271 -0
- package/dist/backend/services/category-admin.service.js.map +1 -0
- package/dist/backend/services/gallery.service.d.ts +85 -0
- package/dist/backend/services/gallery.service.d.ts.map +1 -0
- package/dist/backend/services/gallery.service.js +326 -0
- package/dist/backend/services/gallery.service.js.map +1 -0
- package/dist/backend/services/grouped.service.d.ts +39 -0
- package/dist/backend/services/grouped.service.d.ts.map +1 -0
- package/dist/backend/services/grouped.service.js +136 -0
- package/dist/backend/services/grouped.service.js.map +1 -0
- package/dist/backend/services/label-resolver.d.ts +16 -0
- package/dist/backend/services/label-resolver.d.ts.map +1 -0
- package/dist/backend/services/label-resolver.js +43 -0
- package/dist/backend/services/label-resolver.js.map +1 -0
- package/dist/backend/services/packaging-unit.service.d.ts +28 -0
- package/dist/backend/services/packaging-unit.service.d.ts.map +1 -0
- package/dist/backend/services/packaging-unit.service.js +197 -0
- package/dist/backend/services/packaging-unit.service.js.map +1 -0
- package/dist/backend/services/primary-asset-url.d.ts +4 -0
- package/dist/backend/services/primary-asset-url.d.ts.map +1 -0
- package/dist/backend/services/primary-asset-url.js +55 -0
- package/dist/backend/services/primary-asset-url.js.map +1 -0
- package/dist/backend/services/product-editor-preferences.service.d.ts +20 -0
- package/dist/backend/services/product-editor-preferences.service.d.ts.map +1 -0
- package/dist/backend/services/product-editor-preferences.service.js +44 -0
- package/dist/backend/services/product-editor-preferences.service.js.map +1 -0
- package/dist/backend/services/product-link.service.d.ts +169 -0
- package/dist/backend/services/product-link.service.d.ts.map +1 -0
- package/dist/backend/services/product-link.service.js +297 -0
- package/dist/backend/services/product-link.service.js.map +1 -0
- package/dist/backend/services/product-overrides.service.d.ts +77 -0
- package/dist/backend/services/product-overrides.service.d.ts.map +1 -0
- package/dist/backend/services/product-overrides.service.js +204 -0
- package/dist/backend/services/product-overrides.service.js.map +1 -0
- package/dist/backend/services/product-scope-context.service.d.ts +36 -0
- package/dist/backend/services/product-scope-context.service.d.ts.map +1 -0
- package/dist/backend/services/product-scope-context.service.js +106 -0
- package/dist/backend/services/product-scope-context.service.js.map +1 -0
- package/dist/backend/services/product-type-validations.d.ts +42 -0
- package/dist/backend/services/product-type-validations.d.ts.map +1 -0
- package/dist/backend/services/product-type-validations.js +55 -0
- package/dist/backend/services/product-type-validations.js.map +1 -0
- package/dist/backend/services/product-value-resolver.service.d.ts +59 -0
- package/dist/backend/services/product-value-resolver.service.d.ts.map +1 -0
- package/dist/backend/services/product-value-resolver.service.js +111 -0
- package/dist/backend/services/product-value-resolver.service.js.map +1 -0
- package/dist/backend/services/system-attribute-scopes.d.ts +18 -0
- package/dist/backend/services/system-attribute-scopes.d.ts.map +1 -0
- package/dist/backend/services/system-attribute-scopes.js +18 -0
- package/dist/backend/services/system-attribute-scopes.js.map +1 -0
- package/dist/backend/services/viewer-organization.d.ts +25 -0
- package/dist/backend/services/viewer-organization.d.ts.map +1 -0
- package/dist/backend/services/viewer-organization.js +31 -0
- package/dist/backend/services/viewer-organization.js.map +1 -0
- package/dist/manifest.d.ts +204 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +686 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260429T064146_catalog_attribute_sets_init.d.ts +33 -0
- package/dist/migrations/20260429T064146_catalog_attribute_sets_init.d.ts.map +1 -0
- package/dist/migrations/20260429T064146_catalog_attribute_sets_init.js +118 -0
- package/dist/migrations/20260429T064146_catalog_attribute_sets_init.js.map +1 -0
- package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.d.ts +24 -0
- package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.d.ts.map +1 -0
- package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.js +31 -0
- package/dist/migrations/20260429T070004_catalog_product_attribute_extensions.js.map +1 -0
- package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.d.ts +32 -0
- package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.d.ts.map +1 -0
- package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.js +58 -0
- package/dist/migrations/20260429T102322_catalog_product_type_and_virtual_fields.js.map +1 -0
- package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.d.ts +22 -0
- package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.d.ts.map +1 -0
- package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.js +66 -0
- package/dist/migrations/20260429T111839_catalog_gallery_items_and_labels.js.map +1 -0
- package/dist/migrations/20260429T112543_catalog_product_attachments.d.ts +18 -0
- package/dist/migrations/20260429T112543_catalog_product_attachments.d.ts.map +1 -0
- package/dist/migrations/20260429T112543_catalog_product_attachments.js +73 -0
- package/dist/migrations/20260429T112543_catalog_product_attachments.js.map +1 -0
- package/dist/migrations/20260429T123726_catalog_product_links.d.ts +21 -0
- package/dist/migrations/20260429T123726_catalog_product_links.d.ts.map +1 -0
- package/dist/migrations/20260429T123726_catalog_product_links.js +48 -0
- package/dist/migrations/20260429T123726_catalog_product_links.js.map +1 -0
- package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.d.ts +23 -0
- package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.d.ts.map +1 -0
- package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.js +94 -0
- package/dist/migrations/20260429T130803_catalog_grouped_and_bundle.js.map +1 -0
- package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.d.ts +24 -0
- package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.d.ts.map +1 -0
- package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.js +31 -0
- package/dist/migrations/20260501T185835_catalog_product_attribute_is_comparable.js.map +1 -0
- package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.d.ts +31 -0
- package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.d.ts.map +1 -0
- package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.js +133 -0
- package/dist/migrations/20260505T060113_catalog_attribute_options_and_flags.js.map +1 -0
- package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.d.ts +16 -0
- package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.d.ts.map +1 -0
- package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.js +23 -0
- package/dist/migrations/20260515T082629_catalog_attribute_mass_editable.js.map +1 -0
- package/dist/migrations/20260526T124736_catalog_product_status_inactive.d.ts +10 -0
- package/dist/migrations/20260526T124736_catalog_product_status_inactive.d.ts.map +1 -0
- package/dist/migrations/20260526T124736_catalog_product_status_inactive.js +22 -0
- package/dist/migrations/20260526T124736_catalog_product_status_inactive.js.map +1 -0
- package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.d.ts +38 -0
- package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.d.ts.map +1 -0
- package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.js +98 -0
- package/dist/migrations/20260611T140346_catalog_product_value_overrides_init.js.map +1 -0
- package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.d.ts +13 -0
- package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.d.ts.map +1 -0
- package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.js +17 -0
- package/dist/migrations/20260611T140400_catalog_attribute_quick_searchable.js.map +1 -0
- package/dist/migrations/20260611T140407_catalog_bulk_operations.d.ts +16 -0
- package/dist/migrations/20260611T140407_catalog_bulk_operations.d.ts.map +1 -0
- package/dist/migrations/20260611T140407_catalog_bulk_operations.js +42 -0
- package/dist/migrations/20260611T140407_catalog_bulk_operations.js.map +1 -0
- package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.d.ts +14 -0
- package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.d.ts.map +1 -0
- package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.js +18 -0
- package/dist/migrations/20260611T140408_catalog_bulk_operation_logs.js.map +1 -0
- package/dist/migrations/20260611T140412_catalog_product_packaging_units.d.ts +11 -0
- package/dist/migrations/20260611T140412_catalog_product_packaging_units.d.ts.map +1 -0
- package/dist/migrations/20260611T140412_catalog_product_packaging_units.js +29 -0
- package/dist/migrations/20260611T140412_catalog_product_packaging_units.js.map +1 -0
- package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.d.ts +23 -0
- package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.d.ts.map +1 -0
- package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.js +35 -0
- package/dist/migrations/20260718T060659_catalog_bulk_operation_revert_state.js.map +1 -0
- package/dist/migrations/20260718T200343_catalog_category_custom_field_values.d.ts +12 -0
- package/dist/migrations/20260718T200343_catalog_category_custom_field_values.d.ts.map +1 -0
- package/dist/migrations/20260718T200343_catalog_category_custom_field_values.js +16 -0
- package/dist/migrations/20260718T200343_catalog_category_custom_field_values.js.map +1 -0
- package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.d.ts +32 -0
- package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.d.ts.map +1 -0
- package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.js +286 -0
- package/dist/migrations/20260723T230401_catalog_attributes_on_custom_fields.js.map +1 -0
- package/dist/migrations/20260804T152604_catalog_widen_product_sku.d.ts +36 -0
- package/dist/migrations/20260804T152604_catalog_widen_product_sku.d.ts.map +1 -0
- package/dist/migrations/20260804T152604_catalog_widen_product_sku.js +63 -0
- package/dist/migrations/20260804T152604_catalog_widen_product_sku.js.map +1 -0
- package/dist/migrations/20260804T160244_catalog_category_activation.d.ts +18 -0
- package/dist/migrations/20260804T160244_catalog_category_activation.d.ts.map +1 -0
- package/dist/migrations/20260804T160244_catalog_category_activation.js +22 -0
- package/dist/migrations/20260804T160244_catalog_category_activation.js.map +1 -0
- package/dist/migrations/20260912T094557_catalog_sales_channel_products.d.ts +27 -0
- package/dist/migrations/20260912T094557_catalog_sales_channel_products.d.ts.map +1 -0
- package/dist/migrations/20260912T094557_catalog_sales_channel_products.js +44 -0
- package/dist/migrations/20260912T094557_catalog_sales_channel_products.js.map +1 -0
- package/dist/migrations/20260912T094623_catalog_sales_channel_categories.d.ts +27 -0
- package/dist/migrations/20260912T094623_catalog_sales_channel_categories.d.ts.map +1 -0
- package/dist/migrations/20260912T094623_catalog_sales_channel_categories.js +44 -0
- package/dist/migrations/20260912T094623_catalog_sales_channel_categories.js.map +1 -0
- package/dist/migrations/20260925T125527_catalog_inventory_columns.d.ts +36 -0
- package/dist/migrations/20260925T125527_catalog_inventory_columns.d.ts.map +1 -0
- package/dist/migrations/20260925T125527_catalog_inventory_columns.js +87 -0
- package/dist/migrations/20260925T125527_catalog_inventory_columns.js.map +1 -0
- package/dist/migrations/index.d.ts +55 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +80 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/ports/index.d.ts +96 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +2 -0
- package/dist/ports/index.js.map +1 -0
- package/docs/catalog/attachments.md +69 -0
- package/docs/catalog/attribute-sets.md +63 -0
- package/docs/catalog/attributes.md +244 -0
- package/docs/catalog/composite-products.md +115 -0
- package/docs/catalog/gallery-and-labels.md +73 -0
- package/docs/catalog/packaging-units.md +67 -0
- package/docs/catalog/per-channel-per-language-overrides.md +234 -0
- package/docs/catalog/product-links.md +79 -0
- package/docs/catalog.md +207 -0
- package/i18n/en.json +649 -0
- package/i18n/pl.json +649 -0
- package/package.json +109 -0
- package/tailwind.css +14 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AttributeSetService — admin-only CRUD for Attribute Sets and their
|
|
3
|
+
* relationship with Product Attributes (feature 002,
|
|
4
|
+
* data-model.md §2.1, §2.2; contracts/catalog-002.contract.md).
|
|
5
|
+
*
|
|
6
|
+
* Composition pattern matches `category-admin.service.ts`:
|
|
7
|
+
* - constructor takes `emFactory: () => EntityManager`,
|
|
8
|
+
* - each call forks a fresh EM,
|
|
9
|
+
* - returns DTOs (matching the published Zod schemas) so route handlers
|
|
10
|
+
* are a thin wrapper.
|
|
11
|
+
*/
|
|
12
|
+
import { randomUUID } from 'node:crypto';
|
|
13
|
+
import { UniqueConstraintViolationException } from '@mikro-orm/core';
|
|
14
|
+
import { ERROR_CODES, } from '@endora-commerce/contracts';
|
|
15
|
+
import { HttpError } from '@endora-commerce/platform/http';
|
|
16
|
+
import { AttributeSet } from '../entities/attribute-set.entity.js';
|
|
17
|
+
import { assertCodeNotImmutable, assertNotInUse, AttributeSetValidationError, } from './attribute-set-validations.js';
|
|
18
|
+
export class AttributeSetService {
|
|
19
|
+
emFactory;
|
|
20
|
+
commandBus;
|
|
21
|
+
attributeRead;
|
|
22
|
+
constructor(emFactory,
|
|
23
|
+
/** Feature 054 — audits attribute-set writes co-transactionally when provided. */
|
|
24
|
+
commandBus,
|
|
25
|
+
/**
|
|
26
|
+
* Feature 061 — composed attribute read model. Set membership is stored by
|
|
27
|
+
* definition id, but the API keeps accepting/returning attribute
|
|
28
|
+
* (extension) ids — this service maps between the two at the boundary.
|
|
29
|
+
*/
|
|
30
|
+
attributeRead) {
|
|
31
|
+
this.emFactory = emFactory;
|
|
32
|
+
this.commandBus = commandBus;
|
|
33
|
+
this.attributeRead = attributeRead;
|
|
34
|
+
}
|
|
35
|
+
#requireAttributeRead() {
|
|
36
|
+
if (!this.attributeRead) {
|
|
37
|
+
throw new Error('AttributeSetService: CatalogAttributeReadService is not wired — attribute reads are unavailable.');
|
|
38
|
+
}
|
|
39
|
+
return this.attributeRead;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Feature 054 — run a write through the Command Bus (co-transactional audit)
|
|
43
|
+
* or a plain forked em (bus-less tests). All raw SQL inside `write` MUST pass
|
|
44
|
+
* `em.getTransactionContext()` so the bridge writes/reads join the command's
|
|
45
|
+
* transaction (undefined in the bus-less path = the pre-054 pool behavior).
|
|
46
|
+
*/
|
|
47
|
+
async #audited(action, objectId, write) {
|
|
48
|
+
if (this.commandBus) {
|
|
49
|
+
return this.commandBus.run({
|
|
50
|
+
action,
|
|
51
|
+
objectType: 'attribute_set',
|
|
52
|
+
objectId,
|
|
53
|
+
run: async ({ em }) => {
|
|
54
|
+
const w = await write(em);
|
|
55
|
+
return {
|
|
56
|
+
result: w.result,
|
|
57
|
+
before: w.before,
|
|
58
|
+
after: w.after,
|
|
59
|
+
...(w.skipAudit ? { skipAudit: true } : {}),
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
const em = this.emFactory();
|
|
65
|
+
const w = await write(em);
|
|
66
|
+
await em.flush();
|
|
67
|
+
return w.result;
|
|
68
|
+
}
|
|
69
|
+
// -- READ ------------------------------------------------------------------
|
|
70
|
+
async listSets() {
|
|
71
|
+
const em = this.emFactory();
|
|
72
|
+
const rows = (await em.execute(`select
|
|
73
|
+
s.id,
|
|
74
|
+
s.code,
|
|
75
|
+
s.name,
|
|
76
|
+
s.description,
|
|
77
|
+
s.is_system,
|
|
78
|
+
s.created_at,
|
|
79
|
+
s.updated_at,
|
|
80
|
+
(select count(*)::int from attribute_set_attributes a where a.attribute_set_id = s.id) as attribute_count,
|
|
81
|
+
(select count(*)::int from products p where p.attribute_set_id = s.id) as product_count
|
|
82
|
+
from attribute_sets s
|
|
83
|
+
order by s.is_system desc, s.code asc`));
|
|
84
|
+
return rows.map((r) => ({
|
|
85
|
+
id: r.id,
|
|
86
|
+
code: r.code,
|
|
87
|
+
name: r.name,
|
|
88
|
+
description: r.description,
|
|
89
|
+
isSystem: r.is_system,
|
|
90
|
+
attributeCount: r.attribute_count,
|
|
91
|
+
productCount: r.product_count,
|
|
92
|
+
createdAt: new Date(r.created_at).toISOString(),
|
|
93
|
+
updatedAt: new Date(r.updated_at).toISOString(),
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
async getSetDetail(id) {
|
|
97
|
+
const em = this.emFactory();
|
|
98
|
+
const set = await em.findOne(AttributeSet, { id });
|
|
99
|
+
if (!set) {
|
|
100
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_SET_NOT_FOUND, `Attribute Set ${id} not found.`);
|
|
101
|
+
}
|
|
102
|
+
const attrs = await this.#listAssignedAttributes(em, id);
|
|
103
|
+
const counts = await this.#computeCounts(em, id);
|
|
104
|
+
return this.#toDetailDto(set, attrs, counts);
|
|
105
|
+
}
|
|
106
|
+
// -- WRITE -----------------------------------------------------------------
|
|
107
|
+
async createSet(input) {
|
|
108
|
+
// Validate the initial attribute ids exist BEFORE creating the set.
|
|
109
|
+
// Input ids are attribute (extension) ids; membership persists definition ids.
|
|
110
|
+
let initialAttributes = [];
|
|
111
|
+
if (input.attributeIds && input.attributeIds.length > 0) {
|
|
112
|
+
const all = await this.#requireAttributeRead().listAll();
|
|
113
|
+
initialAttributes = input.attributeIds
|
|
114
|
+
.map((id) => all.find((v) => v.id === id))
|
|
115
|
+
.filter((v) => v !== undefined);
|
|
116
|
+
if (initialAttributes.length !== input.attributeIds.length) {
|
|
117
|
+
const found = new Set(initialAttributes.map((a) => a.id));
|
|
118
|
+
const missing = input.attributeIds.filter((id) => !found.has(id));
|
|
119
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_NOT_FOUND, `Attribute(s) not found: ${missing.join(', ')}.`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// The set create + its audit are co-transactional (Command Bus).
|
|
123
|
+
const id = randomUUID();
|
|
124
|
+
const set = await this.#audited('attribute_set.create', id, async (em) => {
|
|
125
|
+
const created = em.create(AttributeSet, {
|
|
126
|
+
id,
|
|
127
|
+
code: input.code,
|
|
128
|
+
name: input.name,
|
|
129
|
+
description: input.description ?? null,
|
|
130
|
+
isSystem: false,
|
|
131
|
+
});
|
|
132
|
+
try {
|
|
133
|
+
await em.flush();
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
if (err instanceof UniqueConstraintViolationException) {
|
|
137
|
+
throw new HttpError(409, ERROR_CODES.ATTRIBUTE_SET_CODE_TAKEN, `Attribute Set with code "${input.code}" already exists.`);
|
|
138
|
+
}
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
result: created,
|
|
143
|
+
before: null,
|
|
144
|
+
after: {
|
|
145
|
+
code: created.code,
|
|
146
|
+
name: created.name,
|
|
147
|
+
description: created.description ?? null,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
// Bridge assignments run AFTER the set commits (matches the pre-054
|
|
152
|
+
// two-step): the set FK target now exists, and a set with no attributes is
|
|
153
|
+
// a valid state — so a later failure orphans nothing.
|
|
154
|
+
const em = this.emFactory();
|
|
155
|
+
if (initialAttributes.length > 0) {
|
|
156
|
+
await this.#insertAssignments(em, set.id, initialAttributes.map((a, idx) => ({
|
|
157
|
+
definitionId: a.customFieldDefinitionId,
|
|
158
|
+
position: idx,
|
|
159
|
+
})));
|
|
160
|
+
}
|
|
161
|
+
const attrs = await this.#listAssignedAttributes(em, set.id);
|
|
162
|
+
const counts = await this.#computeCounts(em, set.id);
|
|
163
|
+
return this.#toDetailDto(set, attrs, counts);
|
|
164
|
+
}
|
|
165
|
+
async updateSet(id, input) {
|
|
166
|
+
const set = await this.#audited('attribute_set.update', id, async (em) => {
|
|
167
|
+
const s = await em.findOne(AttributeSet, { id });
|
|
168
|
+
if (!s) {
|
|
169
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_SET_NOT_FOUND, `Attribute Set ${id} not found.`);
|
|
170
|
+
}
|
|
171
|
+
// System set rule: `code` is immutable; `name` and `description` may
|
|
172
|
+
// still be edited. The pure helper raises a typed error → HTTP 409.
|
|
173
|
+
try {
|
|
174
|
+
assertCodeNotImmutable({ isSystem: s.isSystem, code: s.code }, input.code);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
if (err instanceof AttributeSetValidationError) {
|
|
178
|
+
throw new HttpError(409, ERROR_CODES.SYSTEM_ATTRIBUTE_SET_IMMUTABLE, err.message);
|
|
179
|
+
}
|
|
180
|
+
throw err;
|
|
181
|
+
}
|
|
182
|
+
const before = { code: s.code, name: s.name, description: s.description ?? null };
|
|
183
|
+
if (input.code !== undefined)
|
|
184
|
+
s.code = input.code;
|
|
185
|
+
if (input.name !== undefined)
|
|
186
|
+
s.name = input.name;
|
|
187
|
+
if (input.description !== undefined)
|
|
188
|
+
s.description = input.description;
|
|
189
|
+
try {
|
|
190
|
+
await em.flush();
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
if (err instanceof UniqueConstraintViolationException) {
|
|
194
|
+
throw new HttpError(409, ERROR_CODES.ATTRIBUTE_SET_CODE_TAKEN, `Attribute Set with code "${input.code}" already exists.`);
|
|
195
|
+
}
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
result: s,
|
|
200
|
+
before,
|
|
201
|
+
after: { code: s.code, name: s.name, description: s.description ?? null },
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
const counts = await this.#computeCounts(this.emFactory(), set.id);
|
|
205
|
+
return {
|
|
206
|
+
id: set.id,
|
|
207
|
+
code: set.code,
|
|
208
|
+
name: set.name,
|
|
209
|
+
description: set.description ?? null,
|
|
210
|
+
isSystem: set.isSystem,
|
|
211
|
+
attributeCount: counts.attributeCount,
|
|
212
|
+
productCount: counts.productCount,
|
|
213
|
+
createdAt: set.createdAt.toISOString(),
|
|
214
|
+
updatedAt: set.updatedAt.toISOString(),
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async deleteSet(id) {
|
|
218
|
+
await this.#audited('attribute_set.delete', id, async (em) => {
|
|
219
|
+
const set = await em.findOne(AttributeSet, { id });
|
|
220
|
+
if (!set) {
|
|
221
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_SET_NOT_FOUND, `Attribute Set ${id} not found.`);
|
|
222
|
+
}
|
|
223
|
+
// The system Default set is never deletable, even when nothing
|
|
224
|
+
// references it (the contract test expects this branch precedence
|
|
225
|
+
// — see specs/002-catalog-module/contracts/catalog-002.contract.md).
|
|
226
|
+
if (set.isSystem) {
|
|
227
|
+
throw new HttpError(409, ERROR_CODES.SYSTEM_ATTRIBUTE_SET_IMMUTABLE, `Attribute Set "${set.code}" is systemic and cannot be deleted.`);
|
|
228
|
+
}
|
|
229
|
+
const { productCount } = await this.#computeCounts(em, id);
|
|
230
|
+
try {
|
|
231
|
+
assertNotInUse(productCount);
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
if (err instanceof AttributeSetValidationError) {
|
|
235
|
+
throw new HttpError(409, ERROR_CODES.ATTRIBUTE_SET_IN_USE, err.message, [
|
|
236
|
+
{ path: 'productCount', issue: String(productCount) },
|
|
237
|
+
]);
|
|
238
|
+
}
|
|
239
|
+
throw err;
|
|
240
|
+
}
|
|
241
|
+
const before = { code: set.code, name: set.name };
|
|
242
|
+
em.remove(set);
|
|
243
|
+
return { result: undefined, before, after: null };
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
async assignAttributes(id, input) {
|
|
247
|
+
const readEm = this.emFactory();
|
|
248
|
+
const set = await readEm.findOne(AttributeSet, { id });
|
|
249
|
+
if (!set) {
|
|
250
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_SET_NOT_FOUND, `Attribute Set ${id} not found.`);
|
|
251
|
+
}
|
|
252
|
+
// Validate every attribute id exists. Input ids are attribute (extension)
|
|
253
|
+
// ids; membership persists definition ids (feature 061).
|
|
254
|
+
const attributeIds = input.assignments.map((a) => a.attributeId);
|
|
255
|
+
const allViews = await this.#requireAttributeRead().listAll();
|
|
256
|
+
const viewById = new Map(allViews.map((v) => [v.id, v]));
|
|
257
|
+
const missing = attributeIds.filter((aid) => !viewById.has(aid));
|
|
258
|
+
if (missing.length > 0) {
|
|
259
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_NOT_FOUND, `Attribute(s) not found: ${missing.join(', ')}.`);
|
|
260
|
+
}
|
|
261
|
+
// The bridge write + its audit are co-transactional (Command Bus,
|
|
262
|
+
// Principle XIII — replaces the hand audit the route used to emit).
|
|
263
|
+
await this.#audited('attribute_set.assign_attributes', id, async (em) => {
|
|
264
|
+
// Default position when omitted: append at the end of the current
|
|
265
|
+
// assignments. We compute the next-position once per call rather
|
|
266
|
+
// than per-assignment to avoid a roundtrip per row.
|
|
267
|
+
const conn = em.getConnection();
|
|
268
|
+
const rows = (await conn.execute(`select coalesce(max(position), -1) + 1 as next_position
|
|
269
|
+
from attribute_set_attributes where attribute_set_id = ?`, [id], 'all', em.getTransactionContext()));
|
|
270
|
+
let runningTail = rows[0]?.next_position ?? 0;
|
|
271
|
+
const resolved = input.assignments.map((a) => {
|
|
272
|
+
const definitionId = viewById.get(a.attributeId).customFieldDefinitionId;
|
|
273
|
+
if (a.position === undefined) {
|
|
274
|
+
const pos = runningTail;
|
|
275
|
+
runningTail += 1;
|
|
276
|
+
return { attributeId: a.attributeId, definitionId, position: pos };
|
|
277
|
+
}
|
|
278
|
+
return { attributeId: a.attributeId, definitionId, position: a.position };
|
|
279
|
+
});
|
|
280
|
+
await this.#insertAssignments(em, id, resolved);
|
|
281
|
+
return {
|
|
282
|
+
result: undefined,
|
|
283
|
+
before: null,
|
|
284
|
+
after: {
|
|
285
|
+
assignments: resolved.map((r) => ({
|
|
286
|
+
attributeId: r.attributeId,
|
|
287
|
+
position: r.position,
|
|
288
|
+
})),
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
const em = this.emFactory();
|
|
293
|
+
const attrs = await this.#listAssignedAttributes(em, id);
|
|
294
|
+
const counts = await this.#computeCounts(em, id);
|
|
295
|
+
return this.#toDetailDto(set, attrs, counts);
|
|
296
|
+
}
|
|
297
|
+
async unassignAttribute(id, attributeId) {
|
|
298
|
+
const readEm = this.emFactory();
|
|
299
|
+
const set = await readEm.findOne(AttributeSet, { id });
|
|
300
|
+
if (!set) {
|
|
301
|
+
throw new HttpError(404, ERROR_CODES.ATTRIBUTE_SET_NOT_FOUND, `Attribute Set ${id} not found.`);
|
|
302
|
+
}
|
|
303
|
+
// DELETE is idempotent — a missing assignment (or an unknown attribute id)
|
|
304
|
+
// is a no-op (matches the "DELETE returns 204 even if it wasn't there"
|
|
305
|
+
// REST convention). The URL carries the attribute (extension) id; the
|
|
306
|
+
// bridge row is keyed by definition id (feature 061).
|
|
307
|
+
const view = await this.#requireAttributeRead().getByIdOrKey(attributeId);
|
|
308
|
+
if (!view)
|
|
309
|
+
return;
|
|
310
|
+
// The bridge delete + its audit are co-transactional (Command Bus,
|
|
311
|
+
// Principle XIII — replaces the hand audit the route used to emit).
|
|
312
|
+
await this.#audited('attribute_set.unassign_attribute', id, async (em) => {
|
|
313
|
+
await em.getConnection().execute(`delete from attribute_set_attributes
|
|
314
|
+
where attribute_set_id = ? and custom_field_definition_id = ?`, [id, view.customFieldDefinitionId], 'run', em.getTransactionContext());
|
|
315
|
+
return {
|
|
316
|
+
result: undefined,
|
|
317
|
+
before: { attributeId: view.id, key: view.key },
|
|
318
|
+
after: null,
|
|
319
|
+
};
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// -- INTERNAL HELPERS ------------------------------------------------------
|
|
323
|
+
async #listAssignedAttributes(em, setId) {
|
|
324
|
+
// Membership is definition-keyed (feature 061); the attribute identity —
|
|
325
|
+
// extension id + key + label + legacy valueType — comes from the composed
|
|
326
|
+
// view so the API keeps returning attribute (extension) ids.
|
|
327
|
+
const rows = (await em.execute(`select custom_field_definition_id, position
|
|
328
|
+
from attribute_set_attributes
|
|
329
|
+
where attribute_set_id = ?`, [setId]));
|
|
330
|
+
if (rows.length === 0)
|
|
331
|
+
return [];
|
|
332
|
+
const views = await this.#requireAttributeRead().listAll();
|
|
333
|
+
const viewByDefinitionId = new Map(views.map((v) => [v.customFieldDefinitionId, v]));
|
|
334
|
+
const assigned = rows
|
|
335
|
+
.map((r) => {
|
|
336
|
+
const view = viewByDefinitionId.get(r.custom_field_definition_id);
|
|
337
|
+
if (!view)
|
|
338
|
+
return undefined;
|
|
339
|
+
return {
|
|
340
|
+
id: view.id,
|
|
341
|
+
key: view.key,
|
|
342
|
+
label: view.label,
|
|
343
|
+
valueType: view.valueType,
|
|
344
|
+
position: r.position,
|
|
345
|
+
languageScoped: view.languageScoped,
|
|
346
|
+
};
|
|
347
|
+
})
|
|
348
|
+
.filter((a) => a !== undefined);
|
|
349
|
+
assigned.sort((a, b) => a.position - b.position || a.key.localeCompare(b.key));
|
|
350
|
+
return assigned;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* `em.execute`, not `em.getConnection().execute`: `deleteSet` calls this on
|
|
354
|
+
* the Command's `em` to decide whether the set is still in use, so read on a
|
|
355
|
+
* pooled connection the guard answered from outside the transaction it is
|
|
356
|
+
* guarding (issue #207).
|
|
357
|
+
*/
|
|
358
|
+
async #computeCounts(em, setId) {
|
|
359
|
+
const [row] = (await em.execute(`select
|
|
360
|
+
(select count(*)::int from attribute_set_attributes where attribute_set_id = ?) as attribute_count,
|
|
361
|
+
(select count(*)::int from products where attribute_set_id = ?) as product_count`, [setId, setId]));
|
|
362
|
+
return {
|
|
363
|
+
attributeCount: row?.attribute_count ?? 0,
|
|
364
|
+
productCount: row?.product_count ?? 0,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
async #insertAssignments(em, setId, assignments) {
|
|
368
|
+
if (assignments.length === 0)
|
|
369
|
+
return;
|
|
370
|
+
const conn = em.getConnection();
|
|
371
|
+
const values = assignments.map(() => '(?, ?, ?)').join(', ');
|
|
372
|
+
const params = assignments.flatMap((a) => [setId, a.definitionId, a.position]);
|
|
373
|
+
// Joins the caller's transaction when run inside a Command (undefined
|
|
374
|
+
// context = plain pool execution, e.g. the post-commit createSet path).
|
|
375
|
+
await conn.execute(`insert into attribute_set_attributes (attribute_set_id, custom_field_definition_id, position) values ${values}
|
|
376
|
+
on conflict (attribute_set_id, custom_field_definition_id) do update set position = excluded.position`, params, 'run', em.getTransactionContext());
|
|
377
|
+
}
|
|
378
|
+
#toDetailDto(set, attributes, counts) {
|
|
379
|
+
return {
|
|
380
|
+
id: set.id,
|
|
381
|
+
code: set.code,
|
|
382
|
+
name: set.name,
|
|
383
|
+
description: set.description ?? null,
|
|
384
|
+
isSystem: set.isSystem,
|
|
385
|
+
attributeCount: counts.attributeCount,
|
|
386
|
+
productCount: counts.productCount,
|
|
387
|
+
createdAt: set.createdAt.toISOString(),
|
|
388
|
+
updatedAt: set.updatedAt.toISOString(),
|
|
389
|
+
attributes,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
// Validations are kept in their pure module so they're unit-testable
|
|
393
|
+
// without an EM; the service layer simply re-exports them so callers
|
|
394
|
+
// can invoke them in custom flows.
|
|
395
|
+
static validations = {
|
|
396
|
+
assertCodeNotImmutable,
|
|
397
|
+
assertNotInUse,
|
|
398
|
+
isValidationError: (err) => err instanceof AttributeSetValidationError,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=attribute-set.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute-set.service.js","sourceRoot":"","sources":["../../../src/backend/services/attribute-set.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ApiAttributeType as ContractApiAttributeType, type AttributeValueType, type NumericKind } from '@endora-commerce/contracts';
|
|
2
|
+
/**
|
|
3
|
+
* Attribute type mapping between the API surface (feature 002) and the
|
|
4
|
+
* legacy 8-value `value_type` form inherited from foundation 001, plus the
|
|
5
|
+
* feature-061 bijection onto the Custom Fields triple
|
|
6
|
+
* (`cf value_type`, `select_display`, `numeric_kind`).
|
|
7
|
+
*
|
|
8
|
+
* See:
|
|
9
|
+
* - specs/002-catalog-module/data-model.md §1.2 (mapping table)
|
|
10
|
+
* - specs/061-attributes-on-custom-fields/research.md §R7 (CF triple map)
|
|
11
|
+
*/
|
|
12
|
+
/** Legacy DB-level types — superset of foundation 001's `attributeValueTypeSchema`. */
|
|
13
|
+
export type DbAttributeValueType = 'string' | 'number' | 'boolean' | 'enum' | 'date' | 'multiselect' | 'price';
|
|
14
|
+
/** The legacy persisted form (pre-061 `product_attributes.value_type`). */
|
|
15
|
+
export type LegacyAttributeValueType = DbAttributeValueType | 'select';
|
|
16
|
+
/** Generic Custom Fields value types the product host maps onto. */
|
|
17
|
+
export type CfAttributeValueType = 'text' | 'number' | 'boolean' | 'date' | 'select' | 'multiselect';
|
|
18
|
+
/** Extension refinement: how a cf `select` renders (legacy `enum` vs `select`). */
|
|
19
|
+
export type SelectDisplay = 'pill' | 'dropdown';
|
|
20
|
+
/** Extension refinement: which numeric semantics back a cf `number`. */
|
|
21
|
+
export type NumericKindRefinement = 'number' | 'price';
|
|
22
|
+
export interface CfTypeTriple {
|
|
23
|
+
cfValueType: CfAttributeValueType;
|
|
24
|
+
selectDisplay: SelectDisplay | null;
|
|
25
|
+
numericKind: NumericKindRefinement | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Legacy `value_type` → (cf `value_type`, selectDisplay, numericKind).
|
|
29
|
+
* Bijective per research §R7 — every legacy value produces a distinct triple.
|
|
30
|
+
*/
|
|
31
|
+
export declare function legacyToCfType(valueType: LegacyAttributeValueType): CfTypeTriple;
|
|
32
|
+
/**
|
|
33
|
+
* (cf `value_type`, selectDisplay, numericKind) → legacy 8-value form.
|
|
34
|
+
* Inverse of {@link legacyToCfType}. A missing refinement defaults to the
|
|
35
|
+
* non-refined legacy value (`number` / `select`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function cfToLegacyValueType(cfValueType: string, selectDisplay: SelectDisplay | null | undefined, numericKind: NumericKindRefinement | null | undefined): LegacyAttributeValueType;
|
|
38
|
+
/**
|
|
39
|
+
* Maps an API-form attribute request onto the persisted `valueType` +
|
|
40
|
+
* `displayAsSlider` pair (research R-7). Either `type` (preferred) or
|
|
41
|
+
* `valueType` (legacy) MUST be set — Zod refines guarantee it for create;
|
|
42
|
+
* update callers pass `type` explicitly so it's always present here.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveAttributeApiType(req: {
|
|
45
|
+
type?: ContractApiAttributeType | undefined;
|
|
46
|
+
valueType?: AttributeValueType | undefined;
|
|
47
|
+
numericKind?: NumericKind | undefined;
|
|
48
|
+
displayAsSlider?: boolean | undefined;
|
|
49
|
+
}): {
|
|
50
|
+
valueType: AttributeValueType;
|
|
51
|
+
displayAsSlider: boolean;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Inverse of `resolveAttributeApiType` — derives the API-form `type` +
|
|
55
|
+
* `numericKind` from the persisted (`valueType`, `displayAsSlider`) pair
|
|
56
|
+
* so list/detail responses surface the form admins authored against.
|
|
57
|
+
*/
|
|
58
|
+
export declare function dbToApiAttributeType(valueType: AttributeValueType, displayAsSlider: boolean): {
|
|
59
|
+
type: ContractApiAttributeType;
|
|
60
|
+
numericKind: NumericKind | null;
|
|
61
|
+
};
|
|
62
|
+
export declare class InvalidAttributeMappingError extends Error {
|
|
63
|
+
readonly code: 'INVALID_DB_TYPE';
|
|
64
|
+
constructor(message: string, code: 'INVALID_DB_TYPE');
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=attribute-type-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute-type-mapping.d.ts","sourceRoot":"","sources":["../../../src/backend/services/attribute-type-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,gBAAgB,IAAI,wBAAwB,EACjD,KAAK,kBAAkB,EACvB,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AAGpC;;;;;;;;;GASG;AAEH,uFAAuF;AACvF,MAAM,MAAM,oBAAoB,GAC5B,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,MAAM,GACN,MAAM,GACN,aAAa,GACb,OAAO,CAAC;AAMZ,2EAA2E;AAC3E,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,GAAG,QAAQ,CAAC;AAEvE,oEAAoE;AACpE,MAAM,MAAM,oBAAoB,GAC5B,MAAM,GACN,QAAQ,GACR,SAAS,GACT,MAAM,GACN,QAAQ,GACR,aAAa,CAAC;AAElB,mFAAmF;AACnF,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,CAAC;AAEhD,wEAAwE;AACxE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,oBAAoB,CAAC;IAClC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,wBAAwB,GAAG,YAAY,CA0BhF;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,EAC/C,WAAW,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,GACpD,wBAAwB,CAoB1B;AAOD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE;IAC3C,IAAI,CAAC,EAAE,wBAAwB,GAAG,SAAS,CAAC;IAC5C,SAAS,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IAC3C,WAAW,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;IACtC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACvC,GAAG;IAAE,SAAS,EAAE,kBAAkB,CAAC;IAAC,eAAe,EAAE,OAAO,CAAA;CAAE,CAyC9D;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,kBAAkB,EAC7B,eAAe,EAAE,OAAO,GACvB;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CASrE;AAED,qBAAa,4BAA6B,SAAQ,KAAK;aAGnC,IAAI,EAAE,iBAAiB;gBADvC,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,iBAAiB;CAK1C"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { ERROR_CODES, apiAttributeTypeOf, } from '@endora-commerce/contracts';
|
|
2
|
+
import { HttpError } from '@endora-commerce/platform/http';
|
|
3
|
+
/**
|
|
4
|
+
* Legacy `value_type` → (cf `value_type`, selectDisplay, numericKind).
|
|
5
|
+
* Bijective per research §R7 — every legacy value produces a distinct triple.
|
|
6
|
+
*/
|
|
7
|
+
export function legacyToCfType(valueType) {
|
|
8
|
+
switch (valueType) {
|
|
9
|
+
case 'string':
|
|
10
|
+
return { cfValueType: 'text', selectDisplay: null, numericKind: null };
|
|
11
|
+
case 'number':
|
|
12
|
+
return { cfValueType: 'number', selectDisplay: null, numericKind: 'number' };
|
|
13
|
+
case 'price':
|
|
14
|
+
return { cfValueType: 'number', selectDisplay: null, numericKind: 'price' };
|
|
15
|
+
case 'boolean':
|
|
16
|
+
return { cfValueType: 'boolean', selectDisplay: null, numericKind: null };
|
|
17
|
+
case 'date':
|
|
18
|
+
return { cfValueType: 'date', selectDisplay: null, numericKind: null };
|
|
19
|
+
case 'enum':
|
|
20
|
+
return { cfValueType: 'select', selectDisplay: 'pill', numericKind: null };
|
|
21
|
+
case 'select':
|
|
22
|
+
return { cfValueType: 'select', selectDisplay: 'dropdown', numericKind: null };
|
|
23
|
+
case 'multiselect':
|
|
24
|
+
return { cfValueType: 'multiselect', selectDisplay: null, numericKind: null };
|
|
25
|
+
default: {
|
|
26
|
+
const _exhaustive = valueType;
|
|
27
|
+
throw new InvalidAttributeMappingError(`Unsupported legacy attribute valueType: ${String(_exhaustive)}`, 'INVALID_DB_TYPE');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* (cf `value_type`, selectDisplay, numericKind) → legacy 8-value form.
|
|
33
|
+
* Inverse of {@link legacyToCfType}. A missing refinement defaults to the
|
|
34
|
+
* non-refined legacy value (`number` / `select`).
|
|
35
|
+
*/
|
|
36
|
+
export function cfToLegacyValueType(cfValueType, selectDisplay, numericKind) {
|
|
37
|
+
switch (cfValueType) {
|
|
38
|
+
case 'text':
|
|
39
|
+
return 'string';
|
|
40
|
+
case 'number':
|
|
41
|
+
return numericKind === 'price' ? 'price' : 'number';
|
|
42
|
+
case 'boolean':
|
|
43
|
+
return 'boolean';
|
|
44
|
+
case 'date':
|
|
45
|
+
return 'date';
|
|
46
|
+
case 'select':
|
|
47
|
+
return selectDisplay === 'pill' ? 'enum' : 'select';
|
|
48
|
+
case 'multiselect':
|
|
49
|
+
return 'multiselect';
|
|
50
|
+
default:
|
|
51
|
+
throw new InvalidAttributeMappingError(`Unsupported cf attribute valueType: ${cfValueType}`, 'INVALID_DB_TYPE');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// API-form resolution (feature 002; moved here from catalog-admin.service.ts by
|
|
56
|
+
// feature 061 so the attribute Commands can consume it without an import cycle).
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Maps an API-form attribute request onto the persisted `valueType` +
|
|
60
|
+
* `displayAsSlider` pair (research R-7). Either `type` (preferred) or
|
|
61
|
+
* `valueType` (legacy) MUST be set — Zod refines guarantee it for create;
|
|
62
|
+
* update callers pass `type` explicitly so it's always present here.
|
|
63
|
+
*/
|
|
64
|
+
export function resolveAttributeApiType(req) {
|
|
65
|
+
if (req.type === undefined) {
|
|
66
|
+
if (req.valueType === undefined) {
|
|
67
|
+
throw new HttpError(400, ERROR_CODES.VALIDATION_FAILED, 'either type or valueType is required');
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
valueType: req.valueType,
|
|
71
|
+
displayAsSlider: req.displayAsSlider ?? false,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
switch (req.type) {
|
|
75
|
+
case 'input':
|
|
76
|
+
return { valueType: 'string', displayAsSlider: false };
|
|
77
|
+
case 'number':
|
|
78
|
+
return { valueType: 'number', displayAsSlider: req.displayAsSlider ?? false };
|
|
79
|
+
case 'select':
|
|
80
|
+
return { valueType: 'enum', displayAsSlider: false };
|
|
81
|
+
case 'multiselect':
|
|
82
|
+
return { valueType: 'multiselect', displayAsSlider: false };
|
|
83
|
+
case 'price':
|
|
84
|
+
return { valueType: 'price', displayAsSlider: req.displayAsSlider ?? false };
|
|
85
|
+
case 'slider': {
|
|
86
|
+
// Zod refine catches the missing-numericKind path; this is a
|
|
87
|
+
// belt-and-braces guard for direct service callers (seeders, etc).
|
|
88
|
+
if (req.numericKind === undefined) {
|
|
89
|
+
throw new HttpError(400, ERROR_CODES.VALIDATION_FAILED, 'numericKind is required when type=slider');
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
valueType: req.numericKind === 'price' ? 'price' : 'number',
|
|
93
|
+
displayAsSlider: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Inverse of `resolveAttributeApiType` — derives the API-form `type` +
|
|
100
|
+
* `numericKind` from the persisted (`valueType`, `displayAsSlider`) pair
|
|
101
|
+
* so list/detail responses surface the form admins authored against.
|
|
102
|
+
*/
|
|
103
|
+
export function dbToApiAttributeType(valueType, displayAsSlider) {
|
|
104
|
+
// The `type` is the contract's single projection (`apiAttributeTypeOf`,
|
|
105
|
+
// feature 134 D19); `numericKind` is this module's own business: it names
|
|
106
|
+
// the numeric storage a slider sits on so an update can round-trip it.
|
|
107
|
+
const type = apiAttributeTypeOf(valueType, displayAsSlider);
|
|
108
|
+
if (type === 'slider' && (valueType === 'number' || valueType === 'price')) {
|
|
109
|
+
return { type, numericKind: valueType };
|
|
110
|
+
}
|
|
111
|
+
return { type, numericKind: null };
|
|
112
|
+
}
|
|
113
|
+
export class InvalidAttributeMappingError extends Error {
|
|
114
|
+
code;
|
|
115
|
+
constructor(message, code) {
|
|
116
|
+
super(message);
|
|
117
|
+
this.code = code;
|
|
118
|
+
this.name = 'InvalidAttributeMappingError';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=attribute-type-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute-type-mapping.js","sourceRoot":"","sources":["../../../src/backend/services/attribute-type-mapping.ts"],"names":[],"mappings":"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"}
|