From 993f83c786d37cf34cc80d4bc152626d70b318ea Mon Sep 17 00:00:00 2001 From: Amritanshu Date: Tue, 18 Aug 2026 06:32:16 +0000 Subject: [PATCH] toSignal via Gemini --- .agents/rules/angular.md | 117 + .vscode/settings.json | 11 +- Dockerfile | 2 +- barker/.pre-commit-config.yaml | 2 +- barker/pyproject.toml | 38 +- barker/uv.lock | 770 +-- bookie/package.json | 34 +- bookie/src/app/app.config.ts | 3 +- bookie/src/app/app.environment.ts | 3 + .../src/app/auth/login/login.component.html | 12 +- bookie/src/app/auth/login/login.component.ts | 55 +- .../beer-sale-report-datasource.ts | 16 - .../beer-sale-report.component.html | 138 +- .../beer-sale-report.component.ts | 152 +- .../beer-sale-report.resolver.spec.ts | 15 - .../beer-sale-report.resolver.ts | 16 - .../beer-sale-report.routes.ts | 6 - .../beer-sale-report.service.ts | 64 +- .../bill-settlement-report-datasource.ts | 16 - .../bill-settlement-report.component.html | 12 +- .../bill-settlement-report.component.ts | 69 +- .../bill-settlement-report.resolver.spec.ts | 15 - .../bill-settlement-report.resolver.ts | 11 - .../bill-settlement-report.routes.ts | 4 - .../bill-settlement-report.service.ts | 38 +- .../bundle-detail/bundle-detail-datasource.ts | 16 - .../bundle-detail-dialog.component.html | 14 +- .../bundle-detail-dialog.component.ts | 79 +- .../bundle-detail.component.html | 46 +- .../bundle-detail/bundle-detail.component.ts | 264 +- .../app/bundles/bundle-list.resolver.spec.ts | 15 - .../src/app/bundles/bundle-list.resolver.ts | 9 - .../bundle-list/bundle-list-datasource.ts | 67 - .../bundle-list/bundle-list.component.html | 12 +- .../bundle-list/bundle-list.component.ts | 92 +- .../src/app/bundles/bundle.resolver.spec.ts | 15 - bookie/src/app/bundles/bundle.resolver.ts | 10 - bookie/src/app/bundles/bundle.service.ts | 20 +- bookie/src/app/bundles/bundles.routes.ts | 18 - .../active-cashiers.resolver.spec.ts | 15 - .../active-cashiers.resolver.ts | 11 - .../cashier-report-datasource.ts | 16 - .../cashier-report.component.html | 18 +- .../cashier-report.component.ts | 88 +- .../cashier-report.resolver.spec.ts | 15 - .../cashier-report/cashier-report.resolver.ts | 12 - .../cashier-report/cashier-report.routes.ts | 10 - .../cashier-report/cashier-report.service.ts | 63 +- bookie/src/app/core/user-role.ts | 12 + .../customer-detail.component.html | 32 +- .../customer-detail.component.ts | 126 +- .../customers/customer-list.resolver.spec.ts | 15 - .../app/customers/customer-list.resolver.ts | 15 - .../customer-list/customer-list-datasource.ts | 161 - .../customer-list.component.html | 8 +- .../customer-list/customer-list.component.ts | 134 +- .../app/customers/customer.resolver.spec.ts | 15 - bookie/src/app/customers/customer.resolver.ts | 10 - bookie/src/app/customers/customer.routes.ts | 11 - bookie/src/app/customers/customer.service.ts | 43 +- .../device-detail.component.html | 18 +- .../device-detail/device-detail.component.ts | 88 +- .../app/devices/device-list.resolver.spec.ts | 15 - .../src/app/devices/device-list.resolver.ts | 9 - .../device-list/device-list-datasource.ts | 16 - .../device-list/device-list.component.html | 2 +- .../device-list/device-list.component.ts | 21 +- .../src/app/devices/device.resolver.spec.ts | 15 - bookie/src/app/devices/device.resolver.ts | 10 - bookie/src/app/devices/device.service.ts | 20 +- bookie/src/app/devices/devices.routes.ts | 14 - .../discount-report-datasource.ts | 16 - .../discount-report.component.html | 14 +- .../discount-report.component.ts | 74 +- .../discount-report.resolver.spec.ts | 15 - .../discount-report.resolver.ts | 11 - .../discount-report/discount-report.routes.ts | 4 - .../discount-report.service.ts | 31 +- .../guest-book/guest-book-detail.resolver.ts | 11 - .../guest-book-detail.component.html | 43 +- .../guest-book-detail.component.ts | 195 +- .../guest-book/guest-book-list.resolver.ts | 9 - .../guest-book-list-datasource.ts | 20 - .../guest-book-list.component.html | 6 +- .../guest-book-list.component.ts | 69 +- .../src/app/guest-book/guest-book.routes.ts | 11 - .../src/app/guest-book/guest-book.service.ts | 34 +- bookie/src/app/guest-book/guest-book.ts | 4 +- .../header-footer.component.html | 10 +- .../header-footer/header-footer.component.ts | 88 +- .../header-footer.resolver.spec.ts | 15 - .../header-footer/header-footer.resolver.ts | 9 - .../app/header-footer/header-footer.routes.ts | 7 - .../header-footer/header-footer.service.ts | 8 +- .../menu-category/menu-categories.routes.ts | 11 - .../menu-category-detail.component.html | 16 +- .../menu-category-detail.component.ts | 75 +- .../menu-category-list.resolver.spec.ts | 15 - .../menu-category-list.resolver.ts | 9 - .../menu-category-list-datasource.ts | 24 - .../menu-category-list.component.html | 6 +- .../menu-category-list.component.ts | 55 +- .../menu-category.resolver.spec.ts | 15 - .../menu-category/menu-category.resolver.ts | 10 - .../menu-category/menu-category.service.ts | 30 +- .../menu-engineering-report-datasource.ts | 172 - .../menu-engineering-report.component.html | 18 +- .../menu-engineering-report.component.ts | 87 +- .../menu-engineering-report.resolver.spec.ts | 15 - .../menu-engineering-report.resolver.ts | 11 - .../menu-engineering-report.routes.ts | 4 - .../menu-engineering-report.service.ts | 31 +- .../modifier-categories.routes.ts | 11 - .../modifier-category-detail.component.html | 18 +- .../modifier-category-detail.component.ts | 121 +- .../modifier-category-list.resolver.spec.ts | 15 - .../modifier-category-list.resolver.ts | 9 - .../modifier-category-list-datasource.ts | 16 - .../modifier-category-list.component.html | 2 +- .../modifier-category-list.component.ts | 22 +- .../modifier-category.resolver.spec.ts | 15 - .../modifier-category.resolver.ts | 10 - .../modifier-category.service.ts | 20 +- .../modifier-detail.component.html | 23 +- .../modifier-detail.component.ts | 105 +- .../modifiers/modifier-list.resolver.spec.ts | 15 - .../app/modifiers/modifier-list.resolver.ts | 9 - .../modifier-list/modifier-list-datasource.ts | 50 - .../modifier-list.component.html | 8 +- .../modifier-list/modifier-list.component.ts | 64 +- .../app/modifiers/modifier.resolver.spec.ts | 15 - bookie/src/app/modifiers/modifier.resolver.ts | 10 - bookie/src/app/modifiers/modifier.service.ts | 20 +- bookie/src/app/modifiers/modifiers.routes.ts | 15 - .../printer-detail.component.html | 14 +- .../printer-detail.component.ts | 82 +- .../printers/printer-list.resolver.spec.ts | 15 - .../src/app/printers/printer-list.resolver.ts | 9 - .../printer-list/printer-list-datasource.ts | 16 - .../printer-list/printer-list.component.html | 2 +- .../printer-list/printer-list.component.ts | 21 +- .../src/app/printers/printer.resolver.spec.ts | 15 - bookie/src/app/printers/printer.resolver.ts | 10 - bookie/src/app/printers/printer.service.ts | 20 +- bookie/src/app/printers/printers.routes.ts | 11 - .../product-sale-report-datasource.ts | 16 - .../product-sale-report.component.html | 18 +- .../product-sale-report.component.ts | 89 +- .../product-sale-report.resolver.spec.ts | 15 - .../product-sale-report.resolver.ts | 12 - .../product-sale-report.routes.ts | 6 - .../product-sale-report.service.ts | 39 +- .../product-updates-report-datasource.ts | 14 - .../product-updates-report.component.html | 12 +- .../product-updates-report.component.ts | 70 +- .../product-updates-report.resolver.spec.ts | 15 - .../product-updates-report.resolver.ts | 11 - .../product-updates-report.routes.ts | 4 - .../product-updates-report.service.ts | 38 +- .../product-detail-datasource.ts | 16 - .../product-detail-dialog.component.html | 35 +- .../product-detail-dialog.component.ts | 86 +- .../product-detail.component.html | 73 +- .../product-detail.component.ts | 303 +- .../app/product/product-list.resolver.spec.ts | 15 - .../src/app/product/product-list.resolver.ts | 9 - .../product-list/product-list-datasource.ts | 78 - .../product-list/product-list.component.html | 17 +- .../product-list/product-list.component.ts | 134 +- .../src/app/product/product.resolver.spec.ts | 15 - bookie/src/app/product/product.resolver.ts | 10 - bookie/src/app/product/product.service.ts | 50 +- bookie/src/app/product/products.routes.ts | 18 - .../regime-detail.component.html | 18 +- .../regime-detail/regime-detail.component.ts | 82 +- .../app/regimes/regime-list.resolver.spec.ts | 15 - .../src/app/regimes/regime-list.resolver.ts | 9 - .../regime-list/regime-list-datasource.ts | 16 - .../regime-list/regime-list.component.html | 2 +- .../regime-list/regime-list.component.ts | 21 +- .../src/app/regimes/regime.resolver.spec.ts | 15 - bookie/src/app/regimes/regime.resolver.ts | 10 - bookie/src/app/regimes/regime.service.ts | 20 +- bookie/src/app/regimes/regimes.routes.ts | 11 - .../role-detail/role-detail.component.html | 29 +- .../role-detail/role-detail.component.ts | 178 +- .../src/app/roles/role-list.resolver.spec.ts | 15 - bookie/src/app/roles/role-list.resolver.ts | 9 - .../roles/role-list/role-list-datasource.ts | 16 - .../roles/role-list/role-list.component.html | 2 +- .../roles/role-list/role-list.component.ts | 21 +- bookie/src/app/roles/role.resolver.spec.ts | 15 - bookie/src/app/roles/role.resolver.ts | 10 - bookie/src/app/roles/role.service.ts | 20 +- bookie/src/app/roles/roles.routes.ts | 11 - .../sale-category/product-list.resolver.ts | 14 - .../sale-category/sale-categories.routes.ts | 17 - .../sale-category-detail-datasource.ts | 24 - .../sale-category-detail.component.html | 18 +- .../sale-category-detail.component.ts | 109 +- .../sale-category-list.resolver.spec.ts | 15 - .../sale-category-list.resolver.ts | 9 - .../sale-category-list-datasource.ts | 24 - .../sale-category-list.component.html | 2 +- .../sale-category-list.component.ts | 28 +- .../sale-category.resolver.spec.ts | 15 - .../sale-category/sale-category.resolver.ts | 10 - .../sale-category/sale-category.service.ts | 20 +- .../app/sale-report/sale-report-datasource.ts | 16 - .../sale-report/sale-report.component.html | 18 +- .../app/sale-report/sale-report.component.ts | 89 +- .../sale-report/sale-report.resolver.spec.ts | 15 - .../app/sale-report/sale-report.resolver.ts | 12 - .../src/app/sale-report/sale-report.routes.ts | 6 - .../app/sale-report/sale-report.service.ts | 39 +- .../bill-number/bill-number.component.html | 8 +- .../bill-number/bill-number.component.ts | 30 +- bookie/src/app/sales/bills/bill.resolver.ts | 22 - .../src/app/sales/bills/bills-datasource.ts | 52 - .../src/app/sales/bills/bills.component.html | 30 +- bookie/src/app/sales/bills/bills.component.ts | 19 +- .../app/sales/bills/update-table.resolver.ts | 6 - bookie/src/app/sales/bills/voucher.service.ts | 8 +- .../choose-customer.component.html | 20 +- .../choose-customer.component.ts | 138 +- .../discount/customer-discounts.service.ts | 9 +- .../app/sales/discount/discount-datasource.ts | 14 - .../sales/discount/discount.component.html | 10 +- .../app/sales/discount/discount.component.ts | 82 +- .../app/sales/home/sales-home.component.ts | 13 +- .../menu-categories.component.html | 2 +- .../menu-categories.component.ts | 20 +- .../menu-categories.resolver.spec.ts | 17 - .../menu-categories.resolver.ts | 9 - bookie/src/app/sales/pax/pax.component.html | 6 +- bookie/src/app/sales/pax/pax.component.ts | 33 +- .../sales/products/products.component.html | 2 +- .../app/sales/products/products.component.ts | 19 +- .../sales/products/products.resolver.spec.ts | 17 - .../app/sales/products/products.resolver.ts | 10 - .../sales/quantity/quantity.component.html | 6 +- .../app/sales/quantity/quantity.component.ts | 33 +- .../src/app/sales/reason/reason-datasource.ts | 14 - .../app/sales/reason/reason.component.html | 8 +- .../src/app/sales/reason/reason.component.ts | 26 +- .../receive-payment-datasource.ts | 16 - .../receive-payment.component.html | 21 +- .../receive-payment.component.ts | 120 +- .../running-tables.component.html | 2 +- .../running-tables.component.ts | 24 +- .../running-tables/running-tables.resolver.ts | 9 - bookie/src/app/sales/sales.routes.ts | 27 - .../split-bill/split-bill.component.html | 12 +- .../sales/split-bill/split-bill.component.ts | 64 +- .../tables-dialog.component.html | 2 +- .../section-printer-datasource.ts | 16 - .../section-printer.component.html | 28 +- .../section-printer.component.ts | 145 +- .../section-printer.resolver.spec.ts | 15 - .../section-printer.resolver.ts | 10 - .../section-printer.service.ts | 14 +- .../section-printers.routes.ts | 13 - .../section-detail.component.html | 10 +- .../section-detail.component.ts | 68 +- .../sections/section-list.resolver.spec.ts | 15 - .../src/app/sections/section-list.resolver.ts | 9 - .../section-list/section-list-datasource.ts | 16 - .../section-list/section-list.component.html | 2 +- .../section-list/section-list.component.ts | 21 +- .../src/app/sections/section.resolver.spec.ts | 15 - bookie/src/app/sections/section.resolver.ts | 10 - bookie/src/app/sections/section.service.ts | 20 +- bookie/src/app/sections/sections.routes.ts | 11 - .../prefill-customer-discount.resolver.ts | 8 - .../src/app/settings/settings.component.html | 8 +- bookie/src/app/settings/settings.component.ts | 51 +- bookie/src/app/settings/settings.routes.ts | 4 - bookie/src/app/settings/settings.service.ts | 22 +- .../settle-option-detail.component.html | 16 +- .../settle-option-detail.component.ts | 90 +- .../settle-option-list.resolver.spec.ts | 15 - .../settle-option-list.resolver.ts | 9 - .../settle-option-list-datasource.ts | 24 - .../settle-option-list.component.html | 2 +- .../settle-option-list.component.ts | 34 +- .../settle-option.resolver.spec.ts | 15 - .../settle-option/settle-option.resolver.ts | 10 - .../settle-option/settle-option.service.ts | 20 +- .../settle-option/settle-options.routes.ts | 11 - .../table-detail/table-detail.component.html | 18 +- .../table-detail/table-detail.component.ts | 97 +- .../app/tables/table-list.resolver.spec.ts | 15 - bookie/src/app/tables/table-list.resolver.ts | 9 - .../table-list/table-list-datasource.ts | 24 - .../table-list/table-list.component.html | 6 +- .../tables/table-list/table-list.component.ts | 55 +- bookie/src/app/tables/table.resolver.spec.ts | 15 - bookie/src/app/tables/table.resolver.ts | 10 - bookie/src/app/tables/table.service.ts | 26 +- bookie/src/app/tables/tables.routes.ts | 14 - .../app/tax-report/tax-report-datasource.ts | 16 - .../app/tax-report/tax-report.component.html | 12 +- .../app/tax-report/tax-report.component.ts | 70 +- .../tax-report/tax-report.resolver.spec.ts | 15 - .../src/app/tax-report/tax-report.resolver.ts | 11 - .../src/app/tax-report/tax-report.routes.ts | 4 - .../src/app/tax-report/tax-report.service.ts | 35 +- .../tax-detail/tax-detail.component.html | 20 +- .../taxes/tax-detail/tax-detail.component.ts | 89 +- .../src/app/taxes/tax-list.resolver.spec.ts | 15 - bookie/src/app/taxes/tax-list.resolver.ts | 9 - .../app/taxes/tax-list/tax-list-datasource.ts | 16 - .../taxes/tax-list/tax-list.component.html | 2 +- .../app/taxes/tax-list/tax-list.component.ts | 21 +- bookie/src/app/taxes/tax.resolver.spec.ts | 15 - bookie/src/app/taxes/tax.resolver.ts | 10 - bookie/src/app/taxes/tax.service.ts | 20 +- bookie/src/app/taxes/taxes.routes.ts | 14 - .../temporal-product-detail.component.html | 56 +- .../temporal-product-detail.component.ts | 300 +- .../temporal-product-list.resolver.spec.ts | 18 - .../temporal-product-list.resolver.ts | 9 - .../temporal-product-list-datasource.ts | 98 - .../temporal-product-list.component.html | 14 +- .../temporal-product-list.component.ts | 123 +- .../temporal-product.resolver.spec.ts | 15 - .../temporal-product.resolver.ts | 10 - .../temporal-product.service.ts | 19 +- .../temporal-products.routes.ts | 19 - .../update-product-prices-datasource.ts | 16 - .../update-product-prices.component.html | 20 +- .../update-product-prices.component.ts | 115 +- .../update-product-prices.resolver.spec.ts | 15 - .../update-product-prices.resolver.ts | 11 - .../update-product-prices.routes.ts | 10 - .../update-product-prices.service.ts | 24 +- .../user-detail/user-detail.component.html | 20 +- .../user-detail/user-detail.component.ts | 104 +- .../src/app/users/user-list.resolver.spec.ts | 15 - bookie/src/app/users/user-list.resolver.ts | 9 - .../users/user-list/user-list-datasource.ts | 16 - .../users/user-list/user-list.component.html | 2 +- .../users/user-list/user-list.component.ts | 22 +- bookie/src/app/users/user.resolver.spec.ts | 15 - bookie/src/app/users/user.resolver.ts | 10 - bookie/src/app/users/user.service.ts | 20 +- bookie/src/app/users/users.routes.ts | 11 - bookie/src/styles.sass | 12 +- bookie/tsconfig.app.json | 10 +- bookie/yarn.lock | 4701 ++++++++--------- 350 files changed, 6231 insertions(+), 9801 deletions(-) create mode 100644 .agents/rules/angular.md delete mode 100644 bookie/src/app/beer-sale-report/beer-sale-report-datasource.ts delete mode 100644 bookie/src/app/beer-sale-report/beer-sale-report.resolver.spec.ts delete mode 100644 bookie/src/app/beer-sale-report/beer-sale-report.resolver.ts delete mode 100644 bookie/src/app/bill-settlement-report/bill-settlement-report-datasource.ts delete mode 100644 bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.spec.ts delete mode 100644 bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.ts delete mode 100644 bookie/src/app/bundles/bundle-detail/bundle-detail-datasource.ts delete mode 100644 bookie/src/app/bundles/bundle-list.resolver.spec.ts delete mode 100644 bookie/src/app/bundles/bundle-list.resolver.ts delete mode 100644 bookie/src/app/bundles/bundle-list/bundle-list-datasource.ts delete mode 100644 bookie/src/app/bundles/bundle.resolver.spec.ts delete mode 100644 bookie/src/app/bundles/bundle.resolver.ts delete mode 100644 bookie/src/app/cashier-report/active-cashiers.resolver.spec.ts delete mode 100644 bookie/src/app/cashier-report/active-cashiers.resolver.ts delete mode 100644 bookie/src/app/cashier-report/cashier-report-datasource.ts delete mode 100644 bookie/src/app/cashier-report/cashier-report.resolver.spec.ts delete mode 100644 bookie/src/app/cashier-report/cashier-report.resolver.ts create mode 100644 bookie/src/app/core/user-role.ts delete mode 100644 bookie/src/app/customers/customer-list.resolver.spec.ts delete mode 100644 bookie/src/app/customers/customer-list.resolver.ts delete mode 100644 bookie/src/app/customers/customer-list/customer-list-datasource.ts delete mode 100644 bookie/src/app/customers/customer.resolver.spec.ts delete mode 100644 bookie/src/app/customers/customer.resolver.ts delete mode 100644 bookie/src/app/devices/device-list.resolver.spec.ts delete mode 100644 bookie/src/app/devices/device-list.resolver.ts delete mode 100644 bookie/src/app/devices/device-list/device-list-datasource.ts delete mode 100644 bookie/src/app/devices/device.resolver.spec.ts delete mode 100644 bookie/src/app/devices/device.resolver.ts delete mode 100644 bookie/src/app/discount-report/discount-report-datasource.ts delete mode 100644 bookie/src/app/discount-report/discount-report.resolver.spec.ts delete mode 100644 bookie/src/app/discount-report/discount-report.resolver.ts delete mode 100644 bookie/src/app/guest-book/guest-book-detail.resolver.ts delete mode 100644 bookie/src/app/guest-book/guest-book-list.resolver.ts delete mode 100644 bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts delete mode 100644 bookie/src/app/header-footer/header-footer.resolver.spec.ts delete mode 100644 bookie/src/app/header-footer/header-footer.resolver.ts delete mode 100644 bookie/src/app/menu-category/menu-category-list.resolver.spec.ts delete mode 100644 bookie/src/app/menu-category/menu-category-list.resolver.ts delete mode 100644 bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts delete mode 100644 bookie/src/app/menu-category/menu-category.resolver.spec.ts delete mode 100644 bookie/src/app/menu-category/menu-category.resolver.ts delete mode 100644 bookie/src/app/menu-engineering-report/menu-engineering-report-datasource.ts delete mode 100644 bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.spec.ts delete mode 100644 bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.ts delete mode 100644 bookie/src/app/modifier-categories/modifier-category-list.resolver.spec.ts delete mode 100644 bookie/src/app/modifier-categories/modifier-category-list.resolver.ts delete mode 100644 bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list-datasource.ts delete mode 100644 bookie/src/app/modifier-categories/modifier-category.resolver.spec.ts delete mode 100644 bookie/src/app/modifier-categories/modifier-category.resolver.ts delete mode 100644 bookie/src/app/modifiers/modifier-list.resolver.spec.ts delete mode 100644 bookie/src/app/modifiers/modifier-list.resolver.ts delete mode 100644 bookie/src/app/modifiers/modifier-list/modifier-list-datasource.ts delete mode 100644 bookie/src/app/modifiers/modifier.resolver.spec.ts delete mode 100644 bookie/src/app/modifiers/modifier.resolver.ts delete mode 100644 bookie/src/app/printers/printer-list.resolver.spec.ts delete mode 100644 bookie/src/app/printers/printer-list.resolver.ts delete mode 100644 bookie/src/app/printers/printer-list/printer-list-datasource.ts delete mode 100644 bookie/src/app/printers/printer.resolver.spec.ts delete mode 100644 bookie/src/app/printers/printer.resolver.ts delete mode 100644 bookie/src/app/product-sale-report/product-sale-report-datasource.ts delete mode 100644 bookie/src/app/product-sale-report/product-sale-report.resolver.spec.ts delete mode 100644 bookie/src/app/product-sale-report/product-sale-report.resolver.ts delete mode 100644 bookie/src/app/product-updates-report/product-updates-report-datasource.ts delete mode 100644 bookie/src/app/product-updates-report/product-updates-report.resolver.spec.ts delete mode 100644 bookie/src/app/product-updates-report/product-updates-report.resolver.ts delete mode 100644 bookie/src/app/product/product-detail/product-detail-datasource.ts delete mode 100644 bookie/src/app/product/product-list.resolver.spec.ts delete mode 100644 bookie/src/app/product/product-list.resolver.ts delete mode 100644 bookie/src/app/product/product-list/product-list-datasource.ts delete mode 100644 bookie/src/app/product/product.resolver.spec.ts delete mode 100644 bookie/src/app/product/product.resolver.ts delete mode 100644 bookie/src/app/regimes/regime-list.resolver.spec.ts delete mode 100644 bookie/src/app/regimes/regime-list.resolver.ts delete mode 100644 bookie/src/app/regimes/regime-list/regime-list-datasource.ts delete mode 100644 bookie/src/app/regimes/regime.resolver.spec.ts delete mode 100644 bookie/src/app/regimes/regime.resolver.ts delete mode 100644 bookie/src/app/roles/role-list.resolver.spec.ts delete mode 100644 bookie/src/app/roles/role-list.resolver.ts delete mode 100644 bookie/src/app/roles/role-list/role-list-datasource.ts delete mode 100644 bookie/src/app/roles/role.resolver.spec.ts delete mode 100644 bookie/src/app/roles/role.resolver.ts delete mode 100644 bookie/src/app/sale-category/product-list.resolver.ts delete mode 100644 bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts delete mode 100644 bookie/src/app/sale-category/sale-category-list.resolver.spec.ts delete mode 100644 bookie/src/app/sale-category/sale-category-list.resolver.ts delete mode 100644 bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts delete mode 100644 bookie/src/app/sale-category/sale-category.resolver.spec.ts delete mode 100644 bookie/src/app/sale-category/sale-category.resolver.ts delete mode 100644 bookie/src/app/sale-report/sale-report-datasource.ts delete mode 100644 bookie/src/app/sale-report/sale-report.resolver.spec.ts delete mode 100644 bookie/src/app/sale-report/sale-report.resolver.ts delete mode 100644 bookie/src/app/sales/bills/bill.resolver.ts delete mode 100644 bookie/src/app/sales/bills/bills-datasource.ts delete mode 100644 bookie/src/app/sales/bills/update-table.resolver.ts delete mode 100644 bookie/src/app/sales/discount/discount-datasource.ts delete mode 100644 bookie/src/app/sales/menu-categories/menu-categories.resolver.spec.ts delete mode 100644 bookie/src/app/sales/menu-categories/menu-categories.resolver.ts delete mode 100644 bookie/src/app/sales/products/products.resolver.spec.ts delete mode 100644 bookie/src/app/sales/products/products.resolver.ts delete mode 100644 bookie/src/app/sales/reason/reason-datasource.ts delete mode 100644 bookie/src/app/sales/receive-payment/receive-payment-datasource.ts delete mode 100644 bookie/src/app/sales/running-tables/running-tables.resolver.ts delete mode 100644 bookie/src/app/section-printers/section-printer-datasource.ts delete mode 100644 bookie/src/app/section-printers/section-printer.resolver.spec.ts delete mode 100644 bookie/src/app/section-printers/section-printer.resolver.ts delete mode 100644 bookie/src/app/sections/section-list.resolver.spec.ts delete mode 100644 bookie/src/app/sections/section-list.resolver.ts delete mode 100644 bookie/src/app/sections/section-list/section-list-datasource.ts delete mode 100644 bookie/src/app/sections/section.resolver.spec.ts delete mode 100644 bookie/src/app/sections/section.resolver.ts delete mode 100644 bookie/src/app/settings/prefill-customer-discount.resolver.ts delete mode 100644 bookie/src/app/settle-option/settle-option-list.resolver.spec.ts delete mode 100644 bookie/src/app/settle-option/settle-option-list.resolver.ts delete mode 100644 bookie/src/app/settle-option/settle-option-list/settle-option-list-datasource.ts delete mode 100644 bookie/src/app/settle-option/settle-option.resolver.spec.ts delete mode 100644 bookie/src/app/settle-option/settle-option.resolver.ts delete mode 100644 bookie/src/app/tables/table-list.resolver.spec.ts delete mode 100644 bookie/src/app/tables/table-list.resolver.ts delete mode 100644 bookie/src/app/tables/table-list/table-list-datasource.ts delete mode 100644 bookie/src/app/tables/table.resolver.spec.ts delete mode 100644 bookie/src/app/tables/table.resolver.ts delete mode 100644 bookie/src/app/tax-report/tax-report-datasource.ts delete mode 100644 bookie/src/app/tax-report/tax-report.resolver.spec.ts delete mode 100644 bookie/src/app/tax-report/tax-report.resolver.ts delete mode 100644 bookie/src/app/taxes/tax-list.resolver.spec.ts delete mode 100644 bookie/src/app/taxes/tax-list.resolver.ts delete mode 100644 bookie/src/app/taxes/tax-list/tax-list-datasource.ts delete mode 100644 bookie/src/app/taxes/tax.resolver.spec.ts delete mode 100644 bookie/src/app/taxes/tax.resolver.ts delete mode 100644 bookie/src/app/temporal-product/temporal-product-list.resolver.spec.ts delete mode 100644 bookie/src/app/temporal-product/temporal-product-list.resolver.ts delete mode 100644 bookie/src/app/temporal-product/temporal-product-list/temporal-product-list-datasource.ts delete mode 100644 bookie/src/app/temporal-product/temporal-product.resolver.spec.ts delete mode 100644 bookie/src/app/temporal-product/temporal-product.resolver.ts delete mode 100644 bookie/src/app/update-product-prices/update-product-prices-datasource.ts delete mode 100644 bookie/src/app/update-product-prices/update-product-prices.resolver.spec.ts delete mode 100644 bookie/src/app/update-product-prices/update-product-prices.resolver.ts delete mode 100644 bookie/src/app/users/user-list.resolver.spec.ts delete mode 100644 bookie/src/app/users/user-list.resolver.ts delete mode 100644 bookie/src/app/users/user-list/user-list-datasource.ts delete mode 100644 bookie/src/app/users/user.resolver.spec.ts delete mode 100644 bookie/src/app/users/user.resolver.ts diff --git a/.agents/rules/angular.md b/.agents/rules/angular.md new file mode 100644 index 0000000..c9e1149 --- /dev/null +++ b/.agents/rules/angular.md @@ -0,0 +1,117 @@ +--- +trigger: glob +globs: ./bookie/**/** +--- + +# Persona + +You are a dedicated Angular developer who thrives on leveraging the absolute latest features of the framework to build cutting-edge applications. You are currently immersed in Angular v20+, passionately adopting signals for reactive state management, embracing standalone components for streamlined architecture, and utilizing the new control flow for more intuitive template logic. Performance is paramount to you, who constantly seeks to optimize change detection and improve user experience through these modern Angular paradigms. When prompted, assume You are familiar with all the newest APIs and best practices, valuing clean, efficient, and maintainable code. + +## Examples + +These are modern examples of how to write an Angular 20 component with signals + +```ts +import { ChangeDetectionStrategy, Component, signal } from '@angular/core'; + + +@Component({ + selector: '{{tag-name}}-root', + templateUrl: '{{tag-name}}.html', +}) +export class {{ClassName}} { + protected readonly isServerRunning = signal(true); + toggleServerStatus() { + this.isServerRunning.update(isServerRunning => !isServerRunning); + } +} +``` + +```css +.container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + + button { + margin-top: 10px; + } +} +``` + +```html +
+ @if (isServerRunning()) { + Yes, the server is running + } @else { + No, the server is not running + } + +
+``` + +When you update a component, be sure to put the logic in the ts file, the styles in the css file and the html template in the html file. + +## Resources + +Here are the some links to the essentials for building Angular applications. Use these to get an understanding of how some of the core functionality works +https://angular.dev/essentials/components +https://angular.dev/essentials/signals +https://angular.dev/essentials/templates +https://angular.dev/essentials/dependency-injection + +## Best practices & Style guide + +Here are the best practices and the style guide information. + +### Coding Style guide + +Here is a link to the most recent Angular style guide https://angular.dev/style-guide + +### TypeScript Best Practices + +- Use strict type checking +- Prefer type inference when the type is obvious +- Avoid the `any` type; use `unknown` when type is uncertain + +### Angular Best Practices + +- Always use standalone components over `NgModules` +- Do NOT set `standalone: true` inside the `@Component`, `@Directive` and `@Pipe` decorators +- Use signals for state management +- Implement lazy loading for feature routes +- Use `NgOptimizedImage` for all static images. +- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead + +### Components + +- Keep components small and focused on a single responsibility +- Use `input()` signal instead of decorators, learn more here https://angular.dev/guide/components/inputs +- Use `output()` function instead of decorators, learn more here https://angular.dev/guide/components/outputs +- Use `computed()` for derived state learn more about signals here https://angular.dev/guide/signals. +- Prefer inline templates for small components +- Prefer Reactive forms instead of Template-driven ones +- Do NOT use `ngClass`, use `class` bindings instead, for context: https://angular.dev/guide/templates/binding#css-class-and-style-property-bindings +- Do NOT use `ngStyle`, use `style` bindings instead, for context: https://angular.dev/guide/templates/binding#css-class-and-style-property-bindings + +### State Management + +- Use signals for local component state +- Use `computed()` for derived state +- Keep state transformations pure and predictable +- Do NOT use `mutate` on signals, use `update` or `set` instead + +### Templates + +- Keep templates simple and avoid complex logic +- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` +- Use the async pipe to handle observables +- Use built in pipes and import pipes when being used in a template, learn more https://angular.dev/guide/templates/pipes# + +### Services + +- Design services around a single responsibility +- Use the `providedIn: 'root'` option for singleton services +- Use the `inject()` function instead of constructor injection diff --git a/.vscode/settings.json b/.vscode/settings.json index 88c89d4..8c97ed6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,7 +14,6 @@ "[python]": { "editor.defaultFormatter": "charliermarsh.ruff" }, - "ruff.enable": true, "files.eol": "\n", "eslint.workingDirectories": [ { @@ -29,7 +28,7 @@ ".idea": true, "**/node_modules": true, "**/.venv": true, - "typings": true, + "typings": true }, "search.exclude": { "**/__pycache__": true, @@ -40,12 +39,10 @@ "**/package-lock.json": true, "/bookie/.angular/**": true, "**/.venv": true, - "typings": true, + "typings": true }, "editor.codeActionsOnSave": { "source.fixAll.ruff": "always", - "source.fixAll.eslint": "always", - }, - "python-envs.defaultEnvManager": "ms-python.python:venv", - "python-envs.pythonProjects": [] + "source.fixAll.eslint": "always" + } } diff --git a/Dockerfile b/Dockerfile index 097ad19..41a2a83 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:lts-trixie-slim AS base +FROM node:current-trixie-slim AS base # Install dependencies only when needed FROM base AS deps diff --git a/barker/.pre-commit-config.yaml b/barker/.pre-commit-config.yaml index 60f6ff5..1d09a93 100644 --- a/barker/.pre-commit-config.yaml +++ b/barker/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.2 + rev: v0.16.2 hooks: # Run the linter. - id: ruff diff --git a/barker/pyproject.toml b/barker/pyproject.toml index 3b75011..e2d70aa 100644 --- a/barker/pyproject.toml +++ b/barker/pyproject.toml @@ -5,31 +5,31 @@ description = "Point of Sale for a restaurant" requires-python = ">=3.14" authors = [{ name = "tanshu", email = "git@tanshu.com" }] dependencies = [ - "aiohttp>=3.13.3", - "alembic>=1.18.4", - "arq>=0.27.0", - "cryptography>=46.0.5", - "fastapi[all]>=0.129.0", - "gunicorn>=25.1.0", + "aiohttp>=3.14.3", + "alembic>=1.19.1", + "arq>=0.28.0", + "cryptography>=50.0.0", + "fastapi[all]>=0.141.1", + "gunicorn>=26.0.0", "itsdangerous>=2.2.0", "passlib[bcrypt]>=1.7.4", - "psycopg[binary,pool]>=3.3.3", - "pydantic>=2.12.5", - "pydantic-settings>=2.13.1", - "pyjwt>=2.11.0", - "python-dotenv>=1.2.1", - "python-multipart>=0.0.22", - "sqlalchemy>=2.0.46", - "uvicorn[standard]>=0.41.0", + "psycopg[binary,pool]>=3.3.4", + "pydantic>=2.13.4", + "pydantic-settings>=2.15.0", + "pyjwt>=2.13.0", + "python-dotenv>=1.2.2", + "python-multipart>=0.0.32", + "sqlalchemy>=2.0.51", + "uvicorn[standard]>=0.52.1", ] [dependency-groups] dev = [ - "bandit>=1.9.3", - "mypy>=1.19.1", - "pre-commit>=4.5.1", - "ruff>=0.15.2", - "safety>=3.7.0", + "bandit>=1.9.4", + "mypy>=2.3.0", + "pre-commit>=4.6.1", + "ruff>=0.16.2", + "safety>=3.8.1", ] [build-system] diff --git a/barker/uv.lock b/barker/uv.lock index 5f1d482..4e10573 100644 --- a/barker/uv.lock +++ b/barker/uv.lock @@ -1,6 +1,10 @@ version = 1 revision = 3 requires-python = ">=3.14" +resolution-markers = [ + "python_full_version >= '3.15'", + "python_full_version < '3.15'", +] [[package]] name = "aiohappyeyeballs" @@ -13,7 +17,7 @@ wheels = [ [[package]] name = "aiohttp" -version = "3.13.3" +version = "3.14.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, @@ -24,42 +28,49 @@ dependencies = [ { name = "propcache" }, { name = "yarl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/50/42/32cf8e7704ceb4481406eb87161349abb46a57fee3f008ba9cb610968646/aiohttp-3.13.3.tar.gz", hash = "sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88", size = 7844556, upload-time = "2026-01-03T17:33:05.204Z" } +sdist = { url = "https://files.pythonhosted.org/packages/58/d9/22ce5786ac0c1653ae8b6c23bded02c1686d11f0dbb45b31ce128e0df985/aiohttp-3.14.3.tar.gz", hash = "sha256:9491196535a88924a60afd5b5f434b5b203b6cc616250878dbdb223a8f7844bc", size = 7971213, upload-time = "2026-07-23T01:57:27.037Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808", size = 737238, upload-time = "2026-01-03T17:31:17.909Z" }, - { url = "https://files.pythonhosted.org/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415", size = 492292, upload-time = "2026-01-03T17:31:19.919Z" }, - { url = "https://files.pythonhosted.org/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f", size = 493021, upload-time = "2026-01-03T17:31:21.636Z" }, - { url = "https://files.pythonhosted.org/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6", size = 1717263, upload-time = "2026-01-03T17:31:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687", size = 1669107, upload-time = "2026-01-03T17:31:25.334Z" }, - { url = "https://files.pythonhosted.org/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26", size = 1760196, upload-time = "2026-01-03T17:31:27.394Z" }, - { url = "https://files.pythonhosted.org/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a", size = 1843591, upload-time = "2026-01-03T17:31:29.238Z" }, - { url = "https://files.pythonhosted.org/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1", size = 1720277, upload-time = "2026-01-03T17:31:31.053Z" }, - { url = "https://files.pythonhosted.org/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25", size = 1548575, upload-time = "2026-01-03T17:31:32.87Z" }, - { url = "https://files.pythonhosted.org/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603", size = 1679455, upload-time = "2026-01-03T17:31:34.76Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a", size = 1687417, upload-time = "2026-01-03T17:31:36.699Z" }, - { url = "https://files.pythonhosted.org/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926", size = 1729968, upload-time = "2026-01-03T17:31:38.622Z" }, - { url = "https://files.pythonhosted.org/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba", size = 1545690, upload-time = "2026-01-03T17:31:40.57Z" }, - { url = "https://files.pythonhosted.org/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c", size = 1746390, upload-time = "2026-01-03T17:31:42.857Z" }, - { url = "https://files.pythonhosted.org/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43", size = 1702188, upload-time = "2026-01-03T17:31:44.984Z" }, - { url = "https://files.pythonhosted.org/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1", size = 433126, upload-time = "2026-01-03T17:31:47.463Z" }, - { url = "https://files.pythonhosted.org/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984", size = 459128, upload-time = "2026-01-03T17:31:49.2Z" }, - { url = "https://files.pythonhosted.org/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c", size = 769512, upload-time = "2026-01-03T17:31:51.134Z" }, - { url = "https://files.pythonhosted.org/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592", size = 506444, upload-time = "2026-01-03T17:31:52.85Z" }, - { url = "https://files.pythonhosted.org/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f", size = 510798, upload-time = "2026-01-03T17:31:54.91Z" }, - { url = "https://files.pythonhosted.org/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29", size = 1868835, upload-time = "2026-01-03T17:31:56.733Z" }, - { url = "https://files.pythonhosted.org/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc", size = 1720486, upload-time = "2026-01-03T17:31:58.65Z" }, - { url = "https://files.pythonhosted.org/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2", size = 1847951, upload-time = "2026-01-03T17:32:00.989Z" }, - { url = "https://files.pythonhosted.org/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587", size = 1941001, upload-time = "2026-01-03T17:32:03.122Z" }, - { url = "https://files.pythonhosted.org/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8", size = 1797246, upload-time = "2026-01-03T17:32:05.255Z" }, - { url = "https://files.pythonhosted.org/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632", size = 1627131, upload-time = "2026-01-03T17:32:07.607Z" }, - { url = "https://files.pythonhosted.org/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64", size = 1795196, upload-time = "2026-01-03T17:32:09.59Z" }, - { url = "https://files.pythonhosted.org/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0", size = 1782841, upload-time = "2026-01-03T17:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56", size = 1795193, upload-time = "2026-01-03T17:32:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72", size = 1621979, upload-time = "2026-01-03T17:32:15.965Z" }, - { url = "https://files.pythonhosted.org/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df", size = 1822193, upload-time = "2026-01-03T17:32:18.219Z" }, - { url = "https://files.pythonhosted.org/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa", size = 1769801, upload-time = "2026-01-03T17:32:20.25Z" }, - { url = "https://files.pythonhosted.org/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767", size = 466523, upload-time = "2026-01-03T17:32:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344", size = 499694, upload-time = "2026-01-03T17:32:24.546Z" }, + { url = "https://files.pythonhosted.org/packages/c8/20/887fdcf832326571b370ffc347b3e70abe101096f3720126aac161b1d872/aiohttp-3.14.3-cp314-cp314-android_24_arm64_v8a.whl", hash = "sha256:49f7325beb0f85ef4aef5f48f490269575f83e6e2acad00a1d80b807eb027062", size = 509067, upload-time = "2026-07-23T01:55:42.618Z" }, + { url = "https://files.pythonhosted.org/packages/ad/a3/92cec936f78cc4bf0fa5554ebe593b73459d94e3c62303e1902a4cccb6f7/aiohttp-3.14.3-cp314-cp314-android_24_x86_64.whl", hash = "sha256:e3be98a7c30b8c25d573dafba7171d66dfb05ee6a9070fc46535464ff97700a6", size = 514774, upload-time = "2026-07-23T01:55:44.937Z" }, + { url = "https://files.pythonhosted.org/packages/29/ba/2a0c38df3fc557620b6a5acd98364af050053b6285b4dc7ee74100c63c18/aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:614c61d478b83953e261d02bb2df750f17227cd33ef8002945bf5aebbde21919", size = 488134, upload-time = "2026-07-23T01:55:47.135Z" }, + { url = "https://files.pythonhosted.org/packages/48/d6/d51b7d4bf309af3693940d8ffd2b9ed0b682434ef85959b7c9c137f60cf8/aiohttp-3.14.3-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:1caa7b0d05f3e3a36f87788c59e970a7ee1cefcfcbb924a9f138c4a6551c9cb7", size = 494201, upload-time = "2026-07-23T01:55:49.451Z" }, + { url = "https://files.pythonhosted.org/packages/3f/5a/8f624384e5f1efabb5229b94157eb966b021e97bdb188c62860c2ae243c2/aiohttp-3.14.3-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:dfa68deb2a443bdaa3ea5297b0699c1464f08aef3812b486d1348eee61b07dc0", size = 502766, upload-time = "2026-07-23T01:55:51.656Z" }, + { url = "https://files.pythonhosted.org/packages/a6/26/4ff0164370deec18fb19254ee4ab10b7a73304ac0c860b13f5f84663759b/aiohttp-3.14.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:e72ee89e28d907a18f46959b4eb0bb06701cc7f8cf4366e00029e2ccfaaf5924", size = 756557, upload-time = "2026-07-23T01:55:53.964Z" }, + { url = "https://files.pythonhosted.org/packages/97/a3/7056b86dc0d9ec709ea9777eae3b0161428f943372f8b98c01c11593b682/aiohttp-3.14.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ad4c8b7488d745d2ca4838ebd8ae5ba9b56341d30b1da43640e4ce87f9f49646", size = 510168, upload-time = "2026-07-23T01:55:56.22Z" }, + { url = "https://files.pythonhosted.org/packages/85/ed/0357a015892fd68058bf2d39d3fd1958e459b997a7db30aaa6aaa434ae96/aiohttp-3.14.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:db332af25642007330fca8be5c4d194caf2bea7a7fc84415aff3497af5dfee6b", size = 512957, upload-time = "2026-07-23T01:55:58.437Z" }, + { url = "https://files.pythonhosted.org/packages/47/d1/8aba53f15ccb2238405f5e9d30e2a8ca44f93878c26e7165ade00d374b1c/aiohttp-3.14.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:25bd2708db6bdf6a6630dd37bdcdfcb47c4434d22ac69c64665b802910140b30", size = 1750149, upload-time = "2026-07-23T01:56:00.856Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/40c3fee327529284375c6701cbb0fa4600cc2e8432af1378f897e2ef7d3a/aiohttp-3.14.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:cef89a58e628c4efcac3275c2d68083f82426dcdc89c1492a6f654f9f7ea6ab9", size = 1707685, upload-time = "2026-07-23T01:56:03.371Z" }, + { url = "https://files.pythonhosted.org/packages/2a/a3/ca0cc6724cca8114b05694abd916060758c79894c3aa5b012cdadc1bc28e/aiohttp-3.14.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c23ec8ee9d5ab2f5421f9c7fffce208435607af27fd46d4a44e031954352838f", size = 1803911, upload-time = "2026-07-23T01:56:05.817Z" }, + { url = "https://files.pythonhosted.org/packages/95/b5/85b099c299c3ffd38ad9b3e43694c8a346934e4a30c88c4fd5a841234f77/aiohttp-3.14.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e2667f0bbe7eb6c74eae5e9691441ad186e5845ca3cff63230fc09c4e7514f5d", size = 1876929, upload-time = "2026-07-23T01:56:08.413Z" }, + { url = "https://files.pythonhosted.org/packages/d5/b7/1da684a04175473fa4cddbf9a2f572e79514c3fd27a74597f43057d4f3da/aiohttp-3.14.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18cb43369747b2ae007bd2655fb8e63a099c2ff1d207962943636dac989b3147", size = 1761112, upload-time = "2026-07-23T01:56:10.918Z" }, + { url = "https://files.pythonhosted.org/packages/d1/16/bc4b55e3e5cb175fd69c53c90d60d2f47797cb343da5106e23863dc4dba4/aiohttp-3.14.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d77640cc618c1d99fc4f8589c0f24a730adfa54eb1e57ef7bf0c8dfb78da898c", size = 1583500, upload-time = "2026-07-23T01:56:13.613Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e8/13a9d957a1ee40837f46aa30f0f4c657e673ad86a2e6362a9f9be20d26d9/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:53e5179d8abb5710f8e83ba207c41c8d1261fcffd4616500e15ca2b7a33be10a", size = 1713940, upload-time = "2026-07-23T01:56:15.969Z" }, + { url = "https://files.pythonhosted.org/packages/38/05/d33c680c1bcf1c7e130f9cbfc1fc02fe8bb0c4af2a94a53dd5fb56131e5c/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:cd817772b2fcf2b8c0905795318485f9ec16eae60b29feb7f4c77085311637f0", size = 1724413, upload-time = "2026-07-23T01:56:18.591Z" }, + { url = "https://files.pythonhosted.org/packages/85/1d/af798d306f7a74b6a632dbcabcf62a4c91391b7582d2a8c6d7712e2cc54e/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4e3ac92d90e92773b2362d506068e9a948192bd553e743c5b2429e28527c8661", size = 1770748, upload-time = "2026-07-23T01:56:21.074Z" }, + { url = "https://files.pythonhosted.org/packages/a8/92/ad720d472556a995049206867765e9410969684f86ee09423ff9969044c1/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:3f42e9b78301f11c8f861746175d8b9c1ccef713fcad9eab396e2f6db8ed4a22", size = 1577564, upload-time = "2026-07-23T01:56:23.475Z" }, + { url = "https://files.pythonhosted.org/packages/60/ad/0ed7586cbef7a884e23a752fa2bb987a122e6a5dd50dab109258d0a95193/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9d9edccfe496b476db5f398d97b865e9a6752bcf8aec4eef8390ce20fb64bb41", size = 1782080, upload-time = "2026-07-23T01:56:25.994Z" }, + { url = "https://files.pythonhosted.org/packages/97/ea/dbaed0d73e8a69aad653b045dab451c67c2454bb731a37b45a86593e9422/aiohttp-3.14.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c5ec8fb1bcc31a8466f74aaf26c345d5c386fa4bd08a3f0eb9c7a4a3fe8b5bf", size = 1745813, upload-time = "2026-07-23T01:56:28.604Z" }, + { url = "https://files.pythonhosted.org/packages/81/1b/6893d4bc57e434fc93a6c9217c637d967a0b651d989f6e3265179375754a/aiohttp-3.14.3-cp314-cp314-win32.whl", hash = "sha256:38901a84da3ce22249f6e860bf8f90d141bcab7da090cc398f8bb58c0e44b7da", size = 455872, upload-time = "2026-07-23T01:56:31.031Z" }, + { url = "https://files.pythonhosted.org/packages/f5/8b/c7baa1ba1eda4db6989baefe5de6d99834921b84ebd7918624febcb9f290/aiohttp-3.14.3-cp314-cp314-win_amd64.whl", hash = "sha256:8b3b60de05f3dcb6f6a00f818bb2ec781cee4de0645f59ccaf99b1d1823b6100", size = 481030, upload-time = "2026-07-23T01:56:33.365Z" }, + { url = "https://files.pythonhosted.org/packages/22/8c/c29d067df825a2df88ca432db848aa2fe8199598359cc06c12b09320cac9/aiohttp-3.14.3-cp314-cp314-win_arm64.whl", hash = "sha256:1576145bdceeb92382d899751e12743a3a5b8e460a841e3e50543859e54864dc", size = 453669, upload-time = "2026-07-23T01:56:35.731Z" }, + { url = "https://files.pythonhosted.org/packages/6a/a4/9c033beb355d39b6147980597ec9645e4729243f686ee4dc73945de72030/aiohttp-3.14.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:8800c996b01c2772a783e3e46f3e1abd5823029adca0df54231960de9bfefa5b", size = 791403, upload-time = "2026-07-23T01:56:37.972Z" }, + { url = "https://files.pythonhosted.org/packages/80/ca/87c32a0a7704583cfc49660bd817889bae5b830bf53b5dcb4e92145ac2da/aiohttp-3.14.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:ebe8e504f058fe91223351cecd2d9d6946c9d241bb0250d898ffbdf584cc72b0", size = 526413, upload-time = "2026-07-23T01:56:40.523Z" }, + { url = "https://files.pythonhosted.org/packages/9e/d8/8ec0e471248c500acdce2be3f46db8fb62b5eb60efef072529cc85ee1d26/aiohttp-3.14.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:30402d03a7c0ff52bce290b57e564e9079fd9d0cb545c8aba73f86a103162d2e", size = 532135, upload-time = "2026-07-23T01:56:42.876Z" }, + { url = "https://files.pythonhosted.org/packages/fe/45/f8919fd936e8b79fcd9bda7b6d8e62613462a713f4f17987fd7c34399142/aiohttp-3.14.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fc7b5bfec6573f3ae844f457fdde5adeb713f8b8e4a81ad64fc207b49383716", size = 1922742, upload-time = "2026-07-23T01:56:45.528Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ec/9ca76b28a27525b0cc53e20842e0228b022f301ce1f436b7d814b4aaf2df/aiohttp-3.14.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8a5fd34f7f7410d1730d5c2ba873cacb2eed3fede366feb268a70ba22581ed8f", size = 1787371, upload-time = "2026-07-23T01:56:48.045Z" }, + { url = "https://files.pythonhosted.org/packages/b1/04/6acdbf17315f7b55f1937e3387acb89a3cddeb4995689553d064af8e92ab/aiohttp-3.14.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:270d3dace9ca2f10f0da5d8ebe519b7a310fc6112ed916e32df5866df0888553", size = 1912623, upload-time = "2026-07-23T01:56:50.605Z" }, + { url = "https://files.pythonhosted.org/packages/86/e6/438b0c79ca6f45eb9fd9817dd4c01a91919a38c0de5ee9e05e2b4dc0ece7/aiohttp-3.14.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3ae5b3a59436d089b5395d910121a390feed4d00578eb95a0fd1a329fe963100", size = 2005515, upload-time = "2026-07-23T01:56:53.153Z" }, + { url = "https://files.pythonhosted.org/packages/bb/6b/62cbd6577758699525f5c712d1ddef57d9875fbab0ae8d5f5a202fd598f8/aiohttp-3.14.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2498f0fe69ead802f9675beca44a7c21c62fdaa4ec5145ea1c3ad6edbee29f85", size = 1879906, upload-time = "2026-07-23T01:56:55.818Z" }, + { url = "https://files.pythonhosted.org/packages/00/95/18bcbf830a21dc3aae24d8f6b6feaf3db1d2090242d00a7868db2ffb0b67/aiohttp-3.14.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a0dc483c00da8b673abbb367eb6f8d8f4bcec30eb58529ea13cb42e7fd2dfa33", size = 1675849, upload-time = "2026-07-23T01:56:58.861Z" }, + { url = "https://files.pythonhosted.org/packages/a9/19/47f4968659c5e23606c3790c80fc624e691c153d036148449ee84d31b287/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c7d3a97c678d34fc5b59da671ee9cd630096ddc643e7b5a30d54a2a6f3574d3f", size = 1843496, upload-time = "2026-07-23T01:57:01.591Z" }, + { url = "https://files.pythonhosted.org/packages/64/af/38c33c4dd82fddcb4e56c4653b6f1072a8edbc6b7fa15809f14932c41e2d/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f8fb78a83c9e5f741ca3a68cfb455c1f5bb83b4e7249a3848b3cd78d0a8563b0", size = 1827746, upload-time = "2026-07-23T01:57:05.131Z" }, + { url = "https://files.pythonhosted.org/packages/a1/9d/0537cda4885ac8f5b7053d164dd06312f4c483a4edcb8ee5b8aaf2a989bf/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:74ab5b6a9fb13e873e5a90946588baecaf488745e1db1a4a5c433f971f035098", size = 1853810, upload-time = "2026-07-23T01:57:08.043Z" }, + { url = "https://files.pythonhosted.org/packages/19/fe/26f9c5e6458385aa86497836b0dea6fb2f027827d63f37c7856cce9286ee/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:bd52f811e65f6fb634b1047159657c98f52b407f8efec907bcfc09da9a4c0a25", size = 1668895, upload-time = "2026-07-23T01:57:10.837Z" }, + { url = "https://files.pythonhosted.org/packages/ec/4c/618b1db9b9ba079b8875d2cdf78e7c4a3bf72903bd5850fee7dd9544600a/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:f0f177d1b195b9e06376cfd7d308d8a1b920909a609d03ac82a8c73bbb16d3b9", size = 1883833, upload-time = "2026-07-23T01:57:13.672Z" }, + { url = "https://files.pythonhosted.org/packages/94/c6/bd959bd1e4771f9fd944e9e436224c48c77b018b73b519b5aad346335bcc/aiohttp-3.14.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:498c6c623134f8e09a3c4e60bcd607a0b4590dd7dbf08dd40851b27cbb520ccb", size = 1844251, upload-time = "2026-07-23T01:57:16.593Z" }, + { url = "https://files.pythonhosted.org/packages/5e/19/08d41839658bdd44a0ed2480f3891705ecb487ce28c0dde62c9040c997e0/aiohttp-3.14.3-cp314-cp314t-win32.whl", hash = "sha256:b304db572b4368edd8dda8a2274f73156fe15558fca4a917cb8a09fc47af5963", size = 474180, upload-time = "2026-07-23T01:57:19.306Z" }, + { url = "https://files.pythonhosted.org/packages/99/5d/3cd6ef0a2b2851f7ab913b5b079334781bd50ff56a323e4454063377a080/aiohttp-3.14.3-cp314-cp314t-win_amd64.whl", hash = "sha256:b20032766aedf6261c7a566585a40867d092ac03a0d81592d5370ef9b054f99b", size = 500528, upload-time = "2026-07-23T01:57:21.762Z" }, + { url = "https://files.pythonhosted.org/packages/a4/37/cfd1ed540a4d318da025590d96b728e63713c09e9377950fc655dadeb856/aiohttp-3.14.3-cp314-cp314t-win_arm64.whl", hash = "sha256:2e1161602f45a54de2ce0905243a95f58cb42dcd378402f3697f5e0b21e9d2e7", size = 469280, upload-time = "2026-07-23T01:57:24.241Z" }, ] [[package]] @@ -76,16 +87,16 @@ wheels = [ [[package]] name = "alembic" -version = "1.18.4" +version = "1.19.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mako" }, { name = "sqlalchemy" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/94/13/8b084e0f2efb0275a1d534838844926f798bd766566b1375174e2448cd31/alembic-1.18.4.tar.gz", hash = "sha256:cb6e1fd84b6174ab8dbb2329f86d631ba9559dd78df550b57804d607672cedbc", size = 2056725, upload-time = "2026-02-10T16:00:47.195Z" } +sdist = { url = "https://files.pythonhosted.org/packages/16/2b/e4153978368de59918115c9e01d3ebf58a558a7285efa7e960c383c4b59a/alembic-1.19.1.tar.gz", hash = "sha256:e0fca0518118c78acc493e31bcb5402f190057aaf6df8b5b95ce94c4789cf648", size = 2070816, upload-time = "2026-08-08T16:32:01.565Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/29/6533c317b74f707ea28f8d633734dbda2119bbadfc61b2f3640ba835d0f7/alembic-1.18.4-py3-none-any.whl", hash = "sha256:a5ed4adcf6d8a4cb575f3d759f071b03cd6e5c7618eb796cb52497be25bfe19a", size = 263893, upload-time = "2026-02-10T16:00:49.997Z" }, + { url = "https://files.pythonhosted.org/packages/20/89/e62cc37b69ad357cc8ecd6e7367f5245f523d3cbb338a66197212bdf6749/alembic-1.19.1-py3-none-any.whl", hash = "sha256:b39018cb3d9413a19cbd54cf3c02ad33998641f0538eb77413a488a21c3e14be", size = 265946, upload-time = "2026-08-08T16:32:03.153Z" }, ] [[package]] @@ -120,15 +131,79 @@ wheels = [ [[package]] name = "arq" -version = "0.27.0" +version = "0.28.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "redis", extra = ["hiredis"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/f9/0f1df9a39b36fc4df590a5f2fca010e6bc8ba2635b75f0368f41722ef24e/arq-0.27.0.tar.gz", hash = "sha256:302a16e78396923fbff0f542fee0e04c731cc549195d18d039be3cc1a3431106", size = 415951, upload-time = "2026-02-02T14:38:21.509Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/81/7f9db65a89c29ba374000309b9dd95509500045df5c7e22f26c3731b7380/arq-0.28.0.tar.gz", hash = "sha256:a458188aefc2d7ee17d136f80d8fa8df1d6eba4ceebdead87e9f172d027dc311", size = 416141, upload-time = "2026-04-16T10:50:23.893Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/89/e28a3a82da9b3d5ccacf143013b8911501c3593cf976b14b34711766fd4c/arq-0.27.0-py3-none-any.whl", hash = "sha256:4ca085671520472e45f09f5c37a1495097e5c4a79faaf18efcb9a759f8917f87", size = 26026, upload-time = "2026-02-02T14:38:19.375Z" }, + { url = "https://files.pythonhosted.org/packages/48/32/66b616976c5058d434ca2017979bfffd784888177b16b5038abcec93954a/arq-0.28.0-py3-none-any.whl", hash = "sha256:b1696bf5614d60f4172a2c0cbdc177e23ba03a5eb9acc29bd8181f4ea71fff94", size = 26061, upload-time = "2026-04-16T10:50:22.321Z" }, +] + +[[package]] +name = "ast-serialize" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e1/a9/11851c3e02a3fea2ddc9932d1fdc7d2edaeecc0d2e11bc5f2a7fde2b0934/ast_serialize-0.8.0.tar.gz", hash = "sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010", size = 845638, upload-time = "2026-08-07T11:29:02.152Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/16/6e520b57cd8c75914b38c670ad4593d13c22911e4306cc7165dab8b0789b/ast_serialize-0.8.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3d822605fa7bb326ef868d25fafced7fc660fa46d9b90c02ea86d5e2f5d325f7", size = 863924, upload-time = "2026-08-07T11:27:34.579Z" }, + { url = "https://files.pythonhosted.org/packages/03/e1/48802de9b22a2bcad42ec80601a17e3f69172fe4f590e6311bcc2b323aeb/ast_serialize-0.8.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:2efa40b068197d5efb62655b43baadb842ed71c4958cccd3e8b86a35726f0119", size = 1177662, upload-time = "2026-08-07T11:27:36.196Z" }, + { url = "https://files.pythonhosted.org/packages/38/d4/323438db76bded3a1f3523a3167b8325916b2ddceb2107a330c6ec9fcf4d/ast_serialize-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:db1b957291bca08c7e72f43a12357b2948e20775d970e3fc3dac0aa3160ab725", size = 1167072, upload-time = "2026-08-07T11:27:37.646Z" }, + { url = "https://files.pythonhosted.org/packages/77/82/53c5400b54144b56de8ed7f957fd1ccd97e42482009292ab46121d15f8dd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdc0d5b18ff8fb364e87923e47c0a91d0d69dbcaeaa274591f7fd26892cc3a3a", size = 1225497, upload-time = "2026-08-07T11:27:39.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/5f/36c07327a8b91303fbf1382c7c3e8a2902072dbe1b9546138a5288e75ff0/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9da7330f3e235bf7da89b8d39205c6350fc0c08a85379743f2df9fff87d6d980", size = 1227101, upload-time = "2026-08-07T11:27:40.799Z" }, + { url = "https://files.pythonhosted.org/packages/9d/48/5adf5c67addc7ddb328122208c6d375a84cf154984f412b4087330a157bd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3186969ee66a9863b00acc6523ace44c56974eecb348a7ea4b228d9f0b80e19", size = 1424001, upload-time = "2026-08-07T11:27:42.708Z" }, + { url = "https://files.pythonhosted.org/packages/38/a1/70074dd3869d2b0e934f91891d8d6b734361cd3b80f85ca7ece2e668ecdd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40a57b73731be45da4fa41430c4d5dc94a24b3a4faba7b9e069978c0402064ea", size = 1245545, upload-time = "2026-08-07T11:27:44.4Z" }, + { url = "https://files.pythonhosted.org/packages/e3/be/53b9c0a8a6399950c2e3546bdfab96d2b299d5b114b47eb94fd3c49c4054/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b9da3ef807eda752502446dfecea3b381c4900b7e27a5d5f4f899eb39951", size = 1248961, upload-time = "2026-08-07T11:27:45.781Z" }, + { url = "https://files.pythonhosted.org/packages/eb/13/3651d3812548a2bda15e26e5dd51aadb48cf682d0865370255fcf0e367dd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:293cc1c5bfa741f8e3fbe8175b9c07beee487c9a6fdbb25a5acad9f1df2d30a9", size = 1243877, upload-time = "2026-08-07T11:27:47.325Z" }, + { url = "https://files.pythonhosted.org/packages/21/a0/521f0bf000f675e9312a4aae2c8ba7a992405d072a85c485e08fd59433b9/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0910c3442a75216dde0f102d854ba2aaa71d2482e0ee213630b9bf29584fba3", size = 1293903, upload-time = "2026-08-07T11:27:49.264Z" }, + { url = "https://files.pythonhosted.org/packages/b1/7e/402fc902568aa2ee65865a3e151f000db0153da8ce6b1be4c9c349025f8d/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43dd6d596879bb1cb8a12cc9dae7bb10090a39a35883026c24f82488a195619a", size = 1401070, upload-time = "2026-08-07T11:27:50.947Z" }, + { url = "https://files.pythonhosted.org/packages/ff/7c/97d4b66c057f1706fc8be6dd532cc77c988794357c8f4ffdb6adabb39562/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8c9d537f59e936392cfd3597789d1390304dd659efc3c486ce7f40fb6b8a9f53", size = 1502602, upload-time = "2026-08-07T11:27:52.364Z" }, + { url = "https://files.pythonhosted.org/packages/89/6f/72cc3b71562001bba46e898ccfbf1844f7939b3e28912736206102f2e5a8/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f0190a33d7f97c65e9069f7a7f40499eea6b5cbe260c558378109caf20ce934b", size = 1495848, upload-time = "2026-08-07T11:27:53.803Z" }, + { url = "https://files.pythonhosted.org/packages/a0/53/d6f629d1e49308b2f363dae028baa213ec222c9106fa1f7f0d1f7b41499a/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:77308ae6c5cf5264cc0f01a7c556ec77a9e68eb1f61b093534d698139fdc3b14", size = 1556556, upload-time = "2026-08-07T11:27:55.342Z" }, + { url = "https://files.pythonhosted.org/packages/ee/22/340f35dd8dfc6d412d53dc20699ca014b8d228db923e8ed4759c512b162c/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8d53a23f27e1ed3a36b2d26fd2a1a6228c8e85a1ed62ff7cdb44bd610769f20a", size = 1417822, upload-time = "2026-08-07T11:27:56.712Z" }, + { url = "https://files.pythonhosted.org/packages/11/29/6dde5c13fbebc051d3a6df4ec0a6fd1d5359333cc1193f7f609f3410b4d8/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa5e7cb08f96fed9121f77b224151e41caf88feab9d652bb46c78202b6fbeda", size = 1445153, upload-time = "2026-08-07T11:27:58.275Z" }, + { url = "https://files.pythonhosted.org/packages/62/c5/f473a8ed030f7a0ca24b9849cca184677a50c053867a7b808c2e1289bbd3/ast_serialize-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:fa70ed4dea0bb18b30a1789c77baa701d0ef30c474f2ccabdea61e25623a8827", size = 1063711, upload-time = "2026-08-07T11:27:59.793Z" }, + { url = "https://files.pythonhosted.org/packages/23/63/39e171fcd38ca057c2e1979d5ee81ac7a3502784abe3d83df7454f7a0978/ast_serialize-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d8b3c8eee4c1baef9d4e84d2a59a805501617127be42615cb48970b15b0892b6", size = 1103740, upload-time = "2026-08-07T11:28:01.405Z" }, + { url = "https://files.pythonhosted.org/packages/21/1c/d00762b399e7726d68d0a088cc946e3a4c60f1c6176f557608f672f627f3/ast_serialize-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:ac4f0a83c55a9b782f79ad55a5247b7db123c1db405959791c2ef886e9710c9f", size = 1076021, upload-time = "2026-08-07T11:28:02.947Z" }, + { url = "https://files.pythonhosted.org/packages/4c/11/911210c3c78923273a9211a2b6cfc4c8aa723b30dab3e1c8d19afb983b40/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0", size = 1177715, upload-time = "2026-08-07T11:28:04.654Z" }, + { url = "https://files.pythonhosted.org/packages/77/89/6282881c8587606638db153cbe21e1e0c4d1f3970dee1aa0610a1c62a026/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068", size = 1169347, upload-time = "2026-08-07T11:28:06.1Z" }, + { url = "https://files.pythonhosted.org/packages/97/78/a9f846a03a340ff3728c915f23338ca742742f3292700559cdb3ad999b1e/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15", size = 1225916, upload-time = "2026-08-07T11:28:07.654Z" }, + { url = "https://files.pythonhosted.org/packages/c0/15/aba6ef8a988a6eceb6f0359589aac509e29ae2dba67fd9bfd5af0c3f13e7/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371", size = 1227135, upload-time = "2026-08-07T11:28:09.504Z" }, + { url = "https://files.pythonhosted.org/packages/94/29/3f63d696ea7c5b8abadcecc3505be51bd900daaccc522ed8322fa5b05a93/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba", size = 1425040, upload-time = "2026-08-07T11:28:11.044Z" }, + { url = "https://files.pythonhosted.org/packages/e2/5d/0aac338604ff59df5774d4304307898982252f325ff7cafe31d52fedcb65/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5", size = 1246278, upload-time = "2026-08-07T11:28:12.519Z" }, + { url = "https://files.pythonhosted.org/packages/23/ca/9f1ef795bb724719532bd86dbec11e5b66857d3fbe9b6772baec0191a6ed/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c", size = 1250029, upload-time = "2026-08-07T11:28:13.896Z" }, + { url = "https://files.pythonhosted.org/packages/dc/25/5e061372d2ed953b9ba3b9c4f73de3b8e9234cda3f6c088db4686801d0e1/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd", size = 1243575, upload-time = "2026-08-07T11:28:15.37Z" }, + { url = "https://files.pythonhosted.org/packages/a8/c1/ae7da218053120635a4ca802366c69f707203641af95372eeb83f70dfd52/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64", size = 1294396, upload-time = "2026-08-07T11:28:16.813Z" }, + { url = "https://files.pythonhosted.org/packages/2e/89/271d1f49c5269fcddcc789ea3f25be401f6723fc1138aeda539f4d05516d/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27", size = 1401987, upload-time = "2026-08-07T11:28:18.333Z" }, + { url = "https://files.pythonhosted.org/packages/55/be/4e7d77fcf571ac7cb5cf7115a20c36642bd7d29473b45dfaaefeb9618f90/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6", size = 1502904, upload-time = "2026-08-07T11:28:20.039Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ae/ed1de2db7e019d4236fbc164ffa5ef9a6022a300a342bbf142d21b7c141e/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534", size = 1496967, upload-time = "2026-08-07T11:28:21.734Z" }, + { url = "https://files.pythonhosted.org/packages/92/89/5fea507fae5c5f18b7dc7f95e5c00956574b8c717b8fd2049c504fab0b18/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b", size = 1559041, upload-time = "2026-08-07T11:28:23.194Z" }, + { url = "https://files.pythonhosted.org/packages/42/71/478d69df21b64e064554a68134c94be304270316ca676a94e63c389a636a/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06", size = 1417367, upload-time = "2026-08-07T11:28:24.601Z" }, + { url = "https://files.pythonhosted.org/packages/5e/2d/8962dc8d5b3a9dc27b36f9db199afa25264c741505469d9ec10ffbfd2ba7/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958", size = 1446178, upload-time = "2026-08-07T11:28:26.152Z" }, + { url = "https://files.pythonhosted.org/packages/4f/22/14d2ad4fd1d1bcd0dc687ca268e0630069f45162496260c0efb70ee0ea72/ast_serialize-0.8.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a", size = 1063811, upload-time = "2026-08-07T11:28:27.864Z" }, + { url = "https://files.pythonhosted.org/packages/18/1d/84a327c0202a41aa5fdba3ade33904d6d8f3b9e6806fa83568d835395850/ast_serialize-0.8.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16", size = 1105518, upload-time = "2026-08-07T11:28:29.691Z" }, + { url = "https://files.pythonhosted.org/packages/8c/92/74556dec52fde85a2ad84ed159991b916241043788609c15d8b77e14570b/ast_serialize-0.8.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc", size = 1076319, upload-time = "2026-08-07T11:28:31.282Z" }, + { url = "https://files.pythonhosted.org/packages/d1/5d/c650b1f2cc1e75193358da95a080261422e8cd10b66d7370b1688c9915c5/ast_serialize-0.8.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:a02cbed7d8bfdcdee88edaac12bd50d53d9953aaa2e1852ef078625be5f1c0b5", size = 852914, upload-time = "2026-08-07T11:28:32.929Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e3/6142e920fec6ef7bccabd8c24ed8ed99f8bdc6cb8b065e1df7c6a3b2d667/ast_serialize-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87", size = 1184007, upload-time = "2026-08-07T11:28:34.654Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e9/6e8be8df02b35d85e2b8809f7f1cfa290bdf5882b55127a539d049482db0/ast_serialize-0.8.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06", size = 1177588, upload-time = "2026-08-07T11:28:36.318Z" }, + { url = "https://files.pythonhosted.org/packages/8c/80/7e0fd2e2e2aba257820db4a8657c4c356844d36b914b20a4af294bcfb902/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6", size = 1234575, upload-time = "2026-08-07T11:28:37.772Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6a/3bae0af06f9b1bae3001c44d64215f5b567877e7aae9ffd45db11c3a7647/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405", size = 1236015, upload-time = "2026-08-07T11:28:39.14Z" }, + { url = "https://files.pythonhosted.org/packages/6f/c4/ce2d41a1bc22508e82618901f7e10f2a5e2f9556553fea90624daf9875e2/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab", size = 1432808, upload-time = "2026-08-07T11:28:40.664Z" }, + { url = "https://files.pythonhosted.org/packages/1a/90/f5058f209756dd70e958b7538aaa82d25d24944baf9ec8ae6f27b06fcacc/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3", size = 1256251, upload-time = "2026-08-07T11:28:42.223Z" }, + { url = "https://files.pythonhosted.org/packages/bf/32/7f77ea87fa0836daab706ed5cb7f903bb25fa26a77439011aee626af11d8/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331", size = 1258574, upload-time = "2026-08-07T11:28:43.751Z" }, + { url = "https://files.pythonhosted.org/packages/eb/5a/75b82ad2725b5e8e8c742732f9e76c6738a292d0709e1f60d10a973730b4/ast_serialize-0.8.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6", size = 1254075, upload-time = "2026-08-07T11:28:45.28Z" }, + { url = "https://files.pythonhosted.org/packages/4e/54/8c20ed4eea805516a3fd23dd4a721ce28c64f50f0e4b359969f60a8c97a6/ast_serialize-0.8.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06", size = 1301018, upload-time = "2026-08-07T11:28:46.851Z" }, + { url = "https://files.pythonhosted.org/packages/cb/5b/9f14430f12fe830b656fb38f8e2e05ee13b02a88967660bef46af0ab22a8/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3", size = 1409951, upload-time = "2026-08-07T11:28:48.312Z" }, + { url = "https://files.pythonhosted.org/packages/2d/3d/084882eca93c842bd4262591a071ec7f825340644035e51501208cc5a8d4/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8", size = 1509544, upload-time = "2026-08-07T11:28:49.847Z" }, + { url = "https://files.pythonhosted.org/packages/ce/73/ea84852096c2036c61cc0b2f97b90242207419f534dc671060ee1c8e05cb/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3", size = 1505671, upload-time = "2026-08-07T11:28:51.239Z" }, + { url = "https://files.pythonhosted.org/packages/cb/88/287b9a5300c1f2f651d259f670931b63110adc265b7613c885b44c5bc53d/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7", size = 1563685, upload-time = "2026-08-07T11:28:53.112Z" }, + { url = "https://files.pythonhosted.org/packages/ee/f3/1bc3a79afcf0c2a8d2c37182d0d659d1545a9d7f7f6dc9cf3e63d6c17135/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe", size = 1427977, upload-time = "2026-08-07T11:28:54.418Z" }, + { url = "https://files.pythonhosted.org/packages/5c/cd/440c798957e14e31776bfeb024d8fafe0bb1d5b89c51c2f067e69938f7b0/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a", size = 1454335, upload-time = "2026-08-07T11:28:55.968Z" }, + { url = "https://files.pythonhosted.org/packages/4f/4a/587eb36dcc240a54c8660f599464516b469ecad96f0dbdb6bccbedb50745/ast_serialize-0.8.0-cp39-abi3-win32.whl", hash = "sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed", size = 1068858, upload-time = "2026-08-07T11:28:57.541Z" }, + { url = "https://files.pythonhosted.org/packages/5f/a4/3e887bbd92164e183cb6e412c6a3e9198ddd446d7fe405958293ef5ef49c/ast_serialize-0.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51", size = 1111839, upload-time = "2026-08-07T11:28:59Z" }, + { url = "https://files.pythonhosted.org/packages/25/6c/b400476d3ceba681ab929787edc9554f6d88fcc69435eb681b00fc0457a5/ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0", size = 1083655, upload-time = "2026-08-07T11:29:00.349Z" }, ] [[package]] @@ -154,7 +229,7 @@ wheels = [ [[package]] name = "bandit" -version = "1.9.3" +version = "1.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, @@ -162,14 +237,14 @@ dependencies = [ { name = "rich" }, { name = "stevedore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/89/76/a7f3e639b78601118aaa4a394db2c66ae2597fbd8c39644c32874ed11e0c/bandit-1.9.3.tar.gz", hash = "sha256:ade4b9b7786f89ef6fc7344a52b34558caec5da74cb90373aed01de88472f774", size = 4242154, upload-time = "2026-01-19T04:05:22.802Z" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c3/0cb80dfe0f3076e5da7e4c5ad8e57bac6ac357ff4a6406205501cade4965/bandit-1.9.4.tar.gz", hash = "sha256:b589e5de2afe70bd4d53fa0c1da6199f4085af666fde00e8a034f152a52cd628", size = 4242677, upload-time = "2026-02-25T06:44:15.503Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/0b/8bdc52111c83e2dc2f97403dc87c0830b8989d9ae45732b34b686326fb2c/bandit-1.9.3-py3-none-any.whl", hash = "sha256:4745917c88d2246def79748bde5e08b9d5e9b92f877863d43fab70cd8814ce6a", size = 134451, upload-time = "2026-01-19T04:05:20.938Z" }, + { url = "https://files.pythonhosted.org/packages/05/a4/a26d5b25671d27e03afb5401a0be5899d94ff8fab6a698b1ac5be3ec29ef/bandit-1.9.4-py3-none-any.whl", hash = "sha256:f89ffa663767f5a0585ea075f01020207e966a9c0f2b9ef56a57c7963a3f6f8e", size = 134741, upload-time = "2026-02-25T06:44:13.694Z" }, ] [[package]] name = "barker" -version = "14.3.1" +version = "14.5.0" source = { editable = "." } dependencies = [ { name = "aiohttp" }, @@ -201,31 +276,31 @@ dev = [ [package.metadata] requires-dist = [ - { name = "aiohttp", specifier = ">=3.13.3" }, - { name = "alembic", specifier = ">=1.18.4" }, - { name = "arq", specifier = ">=0.27.0" }, - { name = "cryptography", specifier = ">=46.0.5" }, - { name = "fastapi", extras = ["all"], specifier = ">=0.129.0" }, - { name = "gunicorn", specifier = ">=25.1.0" }, + { name = "aiohttp", specifier = ">=3.14.3" }, + { name = "alembic", specifier = ">=1.19.1" }, + { name = "arq", specifier = ">=0.28.0" }, + { name = "cryptography", specifier = ">=50.0.0" }, + { name = "fastapi", extras = ["all"], specifier = ">=0.141.1" }, + { name = "gunicorn", specifier = ">=26.0.0" }, { name = "itsdangerous", specifier = ">=2.2.0" }, { name = "passlib", extras = ["bcrypt"], specifier = ">=1.7.4" }, - { name = "psycopg", extras = ["binary", "pool"], specifier = ">=3.3.3" }, - { name = "pydantic", specifier = ">=2.12.5" }, - { name = "pydantic-settings", specifier = ">=2.13.1" }, - { name = "pyjwt", specifier = ">=2.11.0" }, - { name = "python-dotenv", specifier = ">=1.2.1" }, - { name = "python-multipart", specifier = ">=0.0.22" }, - { name = "sqlalchemy", specifier = ">=2.0.46" }, - { name = "uvicorn", extras = ["standard"], specifier = ">=0.41.0" }, + { name = "psycopg", extras = ["binary", "pool"], specifier = ">=3.3.4" }, + { name = "pydantic", specifier = ">=2.13.4" }, + { name = "pydantic-settings", specifier = ">=2.15.0" }, + { name = "pyjwt", specifier = ">=2.13.0" }, + { name = "python-dotenv", specifier = ">=1.2.2" }, + { name = "python-multipart", specifier = ">=0.0.32" }, + { name = "sqlalchemy", specifier = ">=2.0.51" }, + { name = "uvicorn", extras = ["standard"], specifier = ">=0.52.1" }, ] [package.metadata.requires-dev] dev = [ - { name = "bandit", specifier = ">=1.9.3" }, - { name = "mypy", specifier = ">=1.19.1" }, - { name = "pre-commit", specifier = ">=4.5.1" }, - { name = "ruff", specifier = ">=0.15.2" }, - { name = "safety", specifier = ">=3.7.0" }, + { name = "bandit", specifier = ">=1.9.4" }, + { name = "mypy", specifier = ">=2.3.0" }, + { name = "pre-commit", specifier = ">=4.6.1" }, + { name = "ruff", specifier = ">=0.16.2" }, + { name = "safety", specifier = ">=3.8.1" }, ] [[package]] @@ -330,31 +405,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, ] -[[package]] -name = "charset-normalizer" -version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, -] - [[package]] name = "click" version = "8.3.1" @@ -378,55 +428,52 @@ wheels = [ [[package]] name = "cryptography" -version = "46.0.5" +version = "50.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/60/04/ee2a9e8542e4fa2773b81771ff8349ff19cdd56b7258a0cc442639052edb/cryptography-46.0.5.tar.gz", hash = "sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d", size = 750064, upload-time = "2026-02-10T19:18:38.255Z" } +sdist = { url = "https://files.pythonhosted.org/packages/de/41/6cbdcf9142d00fe82836fbb51e503e58088575cf7a0fe1dbff6695bf0840/cryptography-50.0.0.tar.gz", hash = "sha256:eeac2acb5a20ed25e0ad6d1df9891a520b78b404266b6d11778f25d5d691a6c9", size = 880201, upload-time = "2026-07-31T14:25:10.11Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f7/81/b0bb27f2ba931a65409c6b8a8b358a7f03c0e46eceacddff55f7c84b1f3b/cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad", size = 7176289, upload-time = "2026-02-10T19:17:08.274Z" }, - { url = "https://files.pythonhosted.org/packages/ff/9e/6b4397a3e3d15123de3b1806ef342522393d50736c13b20ec4c9ea6693a6/cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b", size = 4275637, upload-time = "2026-02-10T19:17:10.53Z" }, - { url = "https://files.pythonhosted.org/packages/63/e7/471ab61099a3920b0c77852ea3f0ea611c9702f651600397ac567848b897/cryptography-46.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b", size = 4424742, upload-time = "2026-02-10T19:17:12.388Z" }, - { url = "https://files.pythonhosted.org/packages/37/53/a18500f270342d66bf7e4d9f091114e31e5ee9e7375a5aba2e85a91e0044/cryptography-46.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263", size = 4277528, upload-time = "2026-02-10T19:17:13.853Z" }, - { url = "https://files.pythonhosted.org/packages/22/29/c2e812ebc38c57b40e7c583895e73c8c5adb4d1e4a0cc4c5a4fdab2b1acc/cryptography-46.0.5-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:803812e111e75d1aa73690d2facc295eaefd4439be1023fefc4995eaea2af90d", size = 4947993, upload-time = "2026-02-10T19:17:15.618Z" }, - { url = "https://files.pythonhosted.org/packages/6b/e7/237155ae19a9023de7e30ec64e5d99a9431a567407ac21170a046d22a5a3/cryptography-46.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed", size = 4456855, upload-time = "2026-02-10T19:17:17.221Z" }, - { url = "https://files.pythonhosted.org/packages/2d/87/fc628a7ad85b81206738abbd213b07702bcbdada1dd43f72236ef3cffbb5/cryptography-46.0.5-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2", size = 3984635, upload-time = "2026-02-10T19:17:18.792Z" }, - { url = "https://files.pythonhosted.org/packages/84/29/65b55622bde135aedf4565dc509d99b560ee4095e56989e815f8fd2aa910/cryptography-46.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2", size = 4277038, upload-time = "2026-02-10T19:17:20.256Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/45e76c68d7311432741faf1fbf7fac8a196a0a735ca21f504c75d37e2558/cryptography-46.0.5-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:47fb8a66058b80e509c47118ef8a75d14c455e81ac369050f20ba0d23e77fee0", size = 4912181, upload-time = "2026-02-10T19:17:21.825Z" }, - { url = "https://files.pythonhosted.org/packages/6d/1a/c1ba8fead184d6e3d5afcf03d569acac5ad063f3ac9fb7258af158f7e378/cryptography-46.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731", size = 4456482, upload-time = "2026-02-10T19:17:25.133Z" }, - { url = "https://files.pythonhosted.org/packages/f9/e5/3fb22e37f66827ced3b902cf895e6a6bc1d095b5b26be26bd13c441fdf19/cryptography-46.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82", size = 4405497, upload-time = "2026-02-10T19:17:26.66Z" }, - { url = "https://files.pythonhosted.org/packages/1a/df/9d58bb32b1121a8a2f27383fabae4d63080c7ca60b9b5c88be742be04ee7/cryptography-46.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1", size = 4667819, upload-time = "2026-02-10T19:17:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ed/325d2a490c5e94038cdb0117da9397ece1f11201f425c4e9c57fe5b9f08b/cryptography-46.0.5-cp311-abi3-win32.whl", hash = "sha256:60ee7e19e95104d4c03871d7d7dfb3d22ef8a9b9c6778c94e1c8fcc8365afd48", size = 3028230, upload-time = "2026-02-10T19:17:30.518Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5a/ac0f49e48063ab4255d9e3b79f5def51697fce1a95ea1370f03dc9db76f6/cryptography-46.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:38946c54b16c885c72c4f59846be9743d699eee2b69b6988e0a00a01f46a61a4", size = 3480909, upload-time = "2026-02-10T19:17:32.083Z" }, - { url = "https://files.pythonhosted.org/packages/00/13/3d278bfa7a15a96b9dc22db5a12ad1e48a9eb3d40e1827ef66a5df75d0d0/cryptography-46.0.5-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:94a76daa32eb78d61339aff7952ea819b1734b46f73646a07decb40e5b3448e2", size = 7119287, upload-time = "2026-02-10T19:17:33.801Z" }, - { url = "https://files.pythonhosted.org/packages/67/c8/581a6702e14f0898a0848105cbefd20c058099e2c2d22ef4e476dfec75d7/cryptography-46.0.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678", size = 4265728, upload-time = "2026-02-10T19:17:35.569Z" }, - { url = "https://files.pythonhosted.org/packages/dd/4a/ba1a65ce8fc65435e5a849558379896c957870dd64fecea97b1ad5f46a37/cryptography-46.0.5-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87", size = 4408287, upload-time = "2026-02-10T19:17:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/f8/67/8ffdbf7b65ed1ac224d1c2df3943553766914a8ca718747ee3871da6107e/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee", size = 4270291, upload-time = "2026-02-10T19:17:38.748Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e5/f52377ee93bc2f2bba55a41a886fd208c15276ffbd2569f2ddc89d50e2c5/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:8293f3dea7fc929ef7240796ba231413afa7b68ce38fd21da2995549f5961981", size = 4927539, upload-time = "2026-02-10T19:17:40.241Z" }, - { url = "https://files.pythonhosted.org/packages/3b/02/cfe39181b02419bbbbcf3abdd16c1c5c8541f03ca8bda240debc467d5a12/cryptography-46.0.5-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9", size = 4442199, upload-time = "2026-02-10T19:17:41.789Z" }, - { url = "https://files.pythonhosted.org/packages/c0/96/2fcaeb4873e536cf71421a388a6c11b5bc846e986b2b069c79363dc1648e/cryptography-46.0.5-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648", size = 3960131, upload-time = "2026-02-10T19:17:43.379Z" }, - { url = "https://files.pythonhosted.org/packages/d8/d2/b27631f401ddd644e94c5cf33c9a4069f72011821cf3dc7309546b0642a0/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4", size = 4270072, upload-time = "2026-02-10T19:17:45.481Z" }, - { url = "https://files.pythonhosted.org/packages/f4/a7/60d32b0370dae0b4ebe55ffa10e8599a2a59935b5ece1b9f06edb73abdeb/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:68f68d13f2e1cb95163fa3b4db4bf9a159a418f5f6e7242564fc75fcae667fd0", size = 4892170, upload-time = "2026-02-10T19:17:46.997Z" }, - { url = "https://files.pythonhosted.org/packages/d2/b9/cf73ddf8ef1164330eb0b199a589103c363afa0cf794218c24d524a58eab/cryptography-46.0.5-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663", size = 4441741, upload-time = "2026-02-10T19:17:48.661Z" }, - { url = "https://files.pythonhosted.org/packages/5f/eb/eee00b28c84c726fe8fa0158c65afe312d9c3b78d9d01daf700f1f6e37ff/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826", size = 4396728, upload-time = "2026-02-10T19:17:50.058Z" }, - { url = "https://files.pythonhosted.org/packages/65/f4/6bc1a9ed5aef7145045114b75b77c2a8261b4d38717bd8dea111a63c3442/cryptography-46.0.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d", size = 4652001, upload-time = "2026-02-10T19:17:51.54Z" }, - { url = "https://files.pythonhosted.org/packages/86/ef/5d00ef966ddd71ac2e6951d278884a84a40ffbd88948ef0e294b214ae9e4/cryptography-46.0.5-cp314-cp314t-win32.whl", hash = "sha256:c3bcce8521d785d510b2aad26ae2c966092b7daa8f45dd8f44734a104dc0bc1a", size = 3003637, upload-time = "2026-02-10T19:17:52.997Z" }, - { url = "https://files.pythonhosted.org/packages/b7/57/f3f4160123da6d098db78350fdfd9705057aad21de7388eacb2401dceab9/cryptography-46.0.5-cp314-cp314t-win_amd64.whl", hash = "sha256:4d8ae8659ab18c65ced284993c2265910f6c9e650189d4e3f68445ef82a810e4", size = 3469487, upload-time = "2026-02-10T19:17:54.549Z" }, - { url = "https://files.pythonhosted.org/packages/e2/fa/a66aa722105ad6a458bebd64086ca2b72cdd361fed31763d20390f6f1389/cryptography-46.0.5-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:4108d4c09fbbf2789d0c926eb4152ae1760d5a2d97612b92d508d96c861e4d31", size = 7170514, upload-time = "2026-02-10T19:17:56.267Z" }, - { url = "https://files.pythonhosted.org/packages/0f/04/c85bdeab78c8bc77b701bf0d9bdcf514c044e18a46dcff330df5448631b0/cryptography-46.0.5-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18", size = 4275349, upload-time = "2026-02-10T19:17:58.419Z" }, - { url = "https://files.pythonhosted.org/packages/5c/32/9b87132a2f91ee7f5223b091dc963055503e9b442c98fc0b8a5ca765fab0/cryptography-46.0.5-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235", size = 4420667, upload-time = "2026-02-10T19:18:00.619Z" }, - { url = "https://files.pythonhosted.org/packages/a1/a6/a7cb7010bec4b7c5692ca6f024150371b295ee1c108bdc1c400e4c44562b/cryptography-46.0.5-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a", size = 4276980, upload-time = "2026-02-10T19:18:02.379Z" }, - { url = "https://files.pythonhosted.org/packages/8e/7c/c4f45e0eeff9b91e3f12dbd0e165fcf2a38847288fcfd889deea99fb7b6d/cryptography-46.0.5-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:61aa400dce22cb001a98014f647dc21cda08f7915ceb95df0c9eaf84b4b6af76", size = 4939143, upload-time = "2026-02-10T19:18:03.964Z" }, - { url = "https://files.pythonhosted.org/packages/37/19/e1b8f964a834eddb44fa1b9a9976f4e414cbb7aa62809b6760c8803d22d1/cryptography-46.0.5-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614", size = 4453674, upload-time = "2026-02-10T19:18:05.588Z" }, - { url = "https://files.pythonhosted.org/packages/db/ed/db15d3956f65264ca204625597c410d420e26530c4e2943e05a0d2f24d51/cryptography-46.0.5-cp38-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229", size = 3978801, upload-time = "2026-02-10T19:18:07.167Z" }, - { url = "https://files.pythonhosted.org/packages/41/e2/df40a31d82df0a70a0daf69791f91dbb70e47644c58581d654879b382d11/cryptography-46.0.5-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1", size = 4276755, upload-time = "2026-02-10T19:18:09.813Z" }, - { url = "https://files.pythonhosted.org/packages/33/45/726809d1176959f4a896b86907b98ff4391a8aa29c0aaaf9450a8a10630e/cryptography-46.0.5-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:bfd56bb4b37ed4f330b82402f6f435845a5f5648edf1ad497da51a8452d5d62d", size = 4901539, upload-time = "2026-02-10T19:18:11.263Z" }, - { url = "https://files.pythonhosted.org/packages/99/0f/a3076874e9c88ecb2ecc31382f6e7c21b428ede6f55aafa1aa272613e3cd/cryptography-46.0.5-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c", size = 4452794, upload-time = "2026-02-10T19:18:12.914Z" }, - { url = "https://files.pythonhosted.org/packages/02/ef/ffeb542d3683d24194a38f66ca17c0a4b8bf10631feef44a7ef64e631b1a/cryptography-46.0.5-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4", size = 4404160, upload-time = "2026-02-10T19:18:14.375Z" }, - { url = "https://files.pythonhosted.org/packages/96/93/682d2b43c1d5f1406ed048f377c0fc9fc8f7b0447a478d5c65ab3d3a66eb/cryptography-46.0.5-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9", size = 4667123, upload-time = "2026-02-10T19:18:15.886Z" }, - { url = "https://files.pythonhosted.org/packages/45/2d/9c5f2926cb5300a8eefc3f4f0b3f3df39db7f7ce40c8365444c49363cbda/cryptography-46.0.5-cp38-abi3-win32.whl", hash = "sha256:02f547fce831f5096c9a567fd41bc12ca8f11df260959ecc7c3202555cc47a72", size = 3010220, upload-time = "2026-02-10T19:18:17.361Z" }, - { url = "https://files.pythonhosted.org/packages/48/ef/0c2f4a8e31018a986949d34a01115dd057bf536905dca38897bacd21fac3/cryptography-46.0.5-cp38-abi3-win_amd64.whl", hash = "sha256:556e106ee01aa13484ce9b0239bca667be5004efb0aabbed28d353df86445595", size = 3467050, upload-time = "2026-02-10T19:18:18.899Z" }, + { url = "https://files.pythonhosted.org/packages/c5/5c/59086b4aac5e879d38ddbcf74e4be7ade89cebc3eb199a55da998c3bb46a/cryptography-50.0.0-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:031e2d5dd4bb9caa3ca9c82e5a197fd8ae680232cee62603d1a813f3f07e3d03", size = 4001252, upload-time = "2026-07-31T14:23:33.331Z" }, + { url = "https://files.pythonhosted.org/packages/57/ef/8f2df13c7216bcad3e1c74e07f6e193d93e998e114f524a53877c9af27ad/cryptography-50.0.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd9192b7b70c573d7f214eb1ae35e00d359f6f5e4b27c7e21e30de1fc6204645", size = 4719554, upload-time = "2026-07-31T14:23:35.611Z" }, + { url = "https://files.pythonhosted.org/packages/d9/41/029086c34d91052fc3b88bcc8056f709a7c915c7a23b235a54eb800b1c97/cryptography-50.0.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:06a32a980526a6ab9a4b9bf8f7385800791e2bb960903cb6b530e4817509a3b7", size = 4702130, upload-time = "2026-07-31T14:23:37.635Z" }, + { url = "https://files.pythonhosted.org/packages/7d/ff/b6ce0954962e7f7b969f850a883744197bb3910bdfd7b6da162eab7d9f68/cryptography-50.0.0-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:a1b30560f2acc95aa8b2e06e716a13dbfc97314747b80d9707e307f77b40d6b3", size = 4725244, upload-time = "2026-07-31T14:23:39.471Z" }, + { url = "https://files.pythonhosted.org/packages/06/1e/63a1027cb7fec360a182208e1b7767d5aa1fe57be3d6aa856e69a321edc0/cryptography-50.0.0-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:8d89f3976b10b4ce31118de72329025f70d2c6ead14a8217c5514dd2c6d5a78f", size = 5342265, upload-time = "2026-07-31T14:23:41.286Z" }, + { url = "https://files.pythonhosted.org/packages/6b/72/a1116d683a6d7ece94590013882515de087edf9ef0e6292aae615a44df73/cryptography-50.0.0-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b42a28c1844fd9de8f3f7d540e36b66f3a9c83fceac7170ebc7a6a19edd9dcae", size = 4734609, upload-time = "2026-07-31T14:23:43.139Z" }, + { url = "https://files.pythonhosted.org/packages/15/37/36a9c479bbe49acea2636c7fd3360d20f7b7e079c300352011c44850b181/cryptography-50.0.0-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:900131fafd8aead39ac7dd3a7e833be754c17a95cfd91221636949fe4eb0aa8a", size = 4356517, upload-time = "2026-07-31T14:23:44.939Z" }, + { url = "https://files.pythonhosted.org/packages/32/98/8a151d64367204cbc63ec65d37502f1d9c53cf4bfc6ec3c532614dbec60d/cryptography-50.0.0-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:07949c449a1abcf60d1ee6e88956d89404c7df3c8258f46589e912988e551987", size = 4724529, upload-time = "2026-07-31T14:23:46.93Z" }, + { url = "https://files.pythonhosted.org/packages/22/f6/ec13b470172126464a86bf54d2294a46d29837fc51ba3e45d4047946fb5e/cryptography-50.0.0-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f89831ef99dd7dd169ab06d63a831adb9e20a87aac6d380266bbda5823349169", size = 5299852, upload-time = "2026-07-31T14:23:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/da/3a/f05e32c99d440c9bb891ea0e36c9091891e36be5a9a87ab2ee6ea20729f6/cryptography-50.0.0-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:82148ec5bddac30b51a5b3c1945075f896fa022cb93f8e4a01e9f6ee95292c5f", size = 4734462, upload-time = "2026-07-31T14:23:50.861Z" }, + { url = "https://files.pythonhosted.org/packages/ca/dc/bd72b26be8953f80625f63151efd38eee71c76ca6cf591c08ff34615a79e/cryptography-50.0.0-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1489e263a8048bb8b6a8bac662eb2d402ea5d2b7b4699b72f385f1e2772db105", size = 4852708, upload-time = "2026-07-31T14:23:52.715Z" }, + { url = "https://files.pythonhosted.org/packages/27/20/c930314a2ab476d15dec966ec87e2e9637bb02b06106b12c0396c57bb603/cryptography-50.0.0-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7cec5b856506da6defb290f30c9ee687d5f5e8cb0bd3f6459dde43b0b4fa40ef", size = 5004179, upload-time = "2026-07-31T14:23:54.887Z" }, + { url = "https://files.pythonhosted.org/packages/32/2e/c9db68a0c4bfa28e310707527c0ee3a2bd254104d2e02e68f368e197aa4c/cryptography-50.0.0-cp311-abi3-win_amd64.whl", hash = "sha256:bd1c592e4d5974f0d08d4888e432157adba757c66da0246918e43677fafa2d30", size = 3840395, upload-time = "2026-07-31T14:23:56.677Z" }, + { url = "https://files.pythonhosted.org/packages/c3/fb/951032a3bf22a5697c83183fb6294a4843772947a70e616c57b3ff5f522e/cryptography-50.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e7d93abdbd2990caced757e5fade25302f719c3c8fb6e6fff2dde98999fc41", size = 3989258, upload-time = "2026-07-31T14:23:58.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/67/91eb047e69c5e845f2f14b8a2e4a1aab0f283cb885531e9e22c8adb176bc/cryptography-50.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:19736989797678c6af1e55cd49055cdbcb55d8f6b5583ac5335f933aba9101dc", size = 4700648, upload-time = "2026-07-31T14:24:00.702Z" }, + { url = "https://files.pythonhosted.org/packages/30/82/85f0f7425c856b9f96459411eb12e74ef72df9caf6f8f15bf23a33ff131f/cryptography-50.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:80b63928fa35083b33966ce1efb70e5b9607181e49dcd1c22c8c005e319f667f", size = 4682442, upload-time = "2026-07-31T14:24:02.538Z" }, + { url = "https://files.pythonhosted.org/packages/1a/28/b555a365adff1cca2fbe7b9e487d68a40de6bc67ff2cb587473eb43de0e7/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:d58c3db7cd6eed54e6c06744db55456b65ebd7492ddeae9c1e93cfca7aa857d3", size = 4707596, upload-time = "2026-07-31T14:24:04.394Z" }, + { url = "https://files.pythonhosted.org/packages/72/d8/f52538140cc719df62a01cf87d1c7142318d235817109d6f4054d7c352d6/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:df2a58a472f332225671c35b0a830208b86d004f82baa8530fa3782c85646533", size = 5314552, upload-time = "2026-07-31T14:24:06.31Z" }, + { url = "https://files.pythonhosted.org/packages/38/14/6120e5bd7c5aa022ad15424ba4d5c5269d0d9448ed4d55e492ea91e3c1c4/cryptography-50.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:11b74db56cdbe3cdee6e3f6982ecb70334fa10dce99ed58bf7894aaaa3b2a037", size = 4717113, upload-time = "2026-07-31T14:24:08.349Z" }, + { url = "https://files.pythonhosted.org/packages/fa/71/190bf38c3ee2e0f8efc9860ae100c9df4169742eef274b91e7aa1cb133b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:f59e38625469987d7ef6d495323c55e7db6c212eaf6112267e0d3b565a2e9c9f", size = 4338580, upload-time = "2026-07-31T14:24:10.227Z" }, + { url = "https://files.pythonhosted.org/packages/3a/63/504ccfbbe61fd8aa983f7f146399cdf034c72c2fc55f5b2dfdcdcdb20c99/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:ecfed7367f965a0328cfbdd70da860f15441f002f613185668c6e6ebf5a0ac11", size = 4707038, upload-time = "2026-07-31T14:24:12.169Z" }, + { url = "https://files.pythonhosted.org/packages/01/77/2cf79bbfc4d12ca106437a6e170d6aaa01a373e93093118aaaef0e801bd4/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:9aa87839c383bdbab6ef865787a1fb877af8dd03464c4400322726feaaadfc6d", size = 5273110, upload-time = "2026-07-31T14:24:14.38Z" }, + { url = "https://files.pythonhosted.org/packages/e5/45/8aae2972c520145377ea3559a605a899bebe227bf070b33cdb445929a9b9/cryptography-50.0.0-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:6ba6a53445bd3cfa809ef3ef5f1589aa6ba08784a1d962bf47d0940e871dab1c", size = 4716439, upload-time = "2026-07-31T14:24:16.415Z" }, + { url = "https://files.pythonhosted.org/packages/7b/20/4fe50b619a48c2525cc46e2dbc1ac490708d704be5d467bdaac6dc955682/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3f5735ffe4996d28b809371756219f5354864902a3b9e7c0b9ee87041209fc9c", size = 4837383, upload-time = "2026-07-31T14:24:18.553Z" }, + { url = "https://files.pythonhosted.org/packages/92/91/3a31366e183343d3703f8995c095f5734676bd6938118047e50fcf279eb4/cryptography-50.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1b4a266766514614f8aa60416e71f2fc6e575d36e7bdc90f644fadb2f4b75b95", size = 4985772, upload-time = "2026-07-31T14:24:20.385Z" }, + { url = "https://files.pythonhosted.org/packages/74/9a/02ffe35b2853d121689871eb5dce862092562b3a1ed5cc98f1aaed441506/cryptography-50.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:12b9c6996425c76ea6c457ace4f3073e715b8c545add07cd1a8f3a4f90691269", size = 3816291, upload-time = "2026-07-31T14:24:22.125Z" }, + { url = "https://files.pythonhosted.org/packages/03/37/73d005be173aff344af30e9fd2a576575cb2391a7101d9cd3842e1fa8cce/cryptography-50.0.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ccdc4a71a4dabae05de219404f9f4abc38e3b58422177ff93d0da05967dafa07", size = 4036009, upload-time = "2026-07-31T14:24:24.122Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c6/7a6202a534e32103a285b7834a120869557fe198d51d7cfe59754c8bda9c/cryptography-50.0.0-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:910e1d2668e7de9648f2bcee30e180db2a6b15c30f887d7c4c93ddf96e3992e3", size = 4745252, upload-time = "2026-07-31T14:24:26.118Z" }, + { url = "https://files.pythonhosted.org/packages/85/4f/0fa8c2f4428198f15d9ff8d63400e27afbf94ce833f6108da1eb3753f945/cryptography-50.0.0-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a91296cb61e8df6f86d0c19cc4068228da256bf59bf86049fbd821084565327f", size = 4728939, upload-time = "2026-07-31T14:24:27.994Z" }, + { url = "https://files.pythonhosted.org/packages/d1/63/54dd723490ba2dc09b299682c10b38db38f159728bcaae8c591b8af2f22d/cryptography-50.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e722f16708d854fe924790e051061f6704a472c3bac347b6fd88033ea8dd0dc5", size = 4748483, upload-time = "2026-07-31T14:24:30.254Z" }, + { url = "https://files.pythonhosted.org/packages/1d/dd/7c77d26285cc7f6991efce64a0f5b4f9383bfa5dd8c5033003eaf7db4cdb/cryptography-50.0.0-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:d764dcf130c428ef66786f866dd750f53182bc608813489915e9fc106bb0c82f", size = 5367599, upload-time = "2026-07-31T14:24:32.457Z" }, + { url = "https://files.pythonhosted.org/packages/46/c9/f60aed34c013f317f92817b6c171c2d22a78270fa41109bd4b08af26b194/cryptography-50.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:105110f43a471dbd0060b9c9516cb8a6a79233631a04cc2ba16f28323ac6e025", size = 4762647, upload-time = "2026-07-31T14:24:34.599Z" }, + { url = "https://files.pythonhosted.org/packages/be/f3/f9a0173b139372c3a48ed98154b45cc6b9de17c789d5ab552e621c293609/cryptography-50.0.0-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:828743d939e9629bc267b8e2d08d8bb67cd4319c771a33d4b18b22dd8fb7440a", size = 4385197, upload-time = "2026-07-31T14:24:36.647Z" }, + { url = "https://files.pythonhosted.org/packages/d8/36/83bb81f6e569bc38e1e4a7bc80f29b46bb9601920bc455fc8e888f5d5742/cryptography-50.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a8183b489dc1f7f80f135780fadc1108f14b31b8a40411c7a5b17425f65f28b", size = 4748095, upload-time = "2026-07-31T14:24:39.493Z" }, + { url = "https://files.pythonhosted.org/packages/6b/16/d3008eff98c764979865834c3d386d4fd041b5f52e7f34fc29ac1a5eb515/cryptography-50.0.0-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:6e7d61120573a7f2cd94cc095f9e81f6967c61ccdf194285aa143ecec8e0b708", size = 5325948, upload-time = "2026-07-31T14:24:41.556Z" }, + { url = "https://files.pythonhosted.org/packages/9c/f8/d97f9603efda3888187bfdb893f26c41be4735c10631d05d284ee6b047c4/cryptography-50.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:37fdb0d0111f1e2ff07139dfb79f1b49531f8e213c46f1163dd7642979b58c47", size = 4762400, upload-time = "2026-07-31T14:24:43.636Z" }, + { url = "https://files.pythonhosted.org/packages/64/a2/4615c8f7d81a00b1d6e6afe19f694e1543582349fb5f4076f6cb5dc36485/cryptography-50.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87f62a3d3b9888ed0fdde100ec06aa61ca9cd44bad9057d1dff9a516b5f5bb9", size = 4878208, upload-time = "2026-07-31T14:24:45.522Z" }, + { url = "https://files.pythonhosted.org/packages/d2/1a/efcfb02f91407149a0dacffffab791f7e19bf6385f63b3666dc8b5e5c9c8/cryptography-50.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:65c2c3add92b45fd0709db8594536aea39c2a67af0e27ffcf049c498501140b7", size = 5037050, upload-time = "2026-07-31T14:24:47.697Z" }, + { url = "https://files.pythonhosted.org/packages/57/30/4a22984d4f1bdfb8c054f07a92bc176b97a3134cc1d6c4b3bffb1f3688b4/cryptography-50.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:d24fead1d4d076e1bfb006dcec392074a3cd8d7b4fc8a595aa64073b2b7a96ba", size = 3874135, upload-time = "2026-07-31T14:24:50.085Z" }, ] [[package]] @@ -474,7 +521,7 @@ wheels = [ [[package]] name = "fastapi" -version = "0.129.0" +version = "0.141.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -483,9 +530,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/48/47/75f6bea02e797abff1bca968d5997793898032d9923c1935ae2efdece642/fastapi-0.129.0.tar.gz", hash = "sha256:61315cebd2e65df5f97ec298c888f9de30430dd0612d59d6480beafbc10655af", size = 375450, upload-time = "2026-02-12T13:54:52.541Z" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/02/91e3416a8fdd715abb903a952a6bec7cdd8d14eed55d415fc8595524c319/fastapi-0.141.1.tar.gz", hash = "sha256:e8822fc40db1e1858054d7a949a888695bc9bdce70139178e33bd2871a453ca1", size = 425799, upload-time = "2026-07-29T17:18:05.568Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/dd/d0ee25348ac58245ee9f90b6f3cbb666bf01f69be7e0911f9851bddbda16/fastapi-0.129.0-py3-none-any.whl", hash = "sha256:b4946880e48f462692b31c083be0432275cbfb6e2274566b1be91479cc1a84ec", size = 102950, upload-time = "2026-02-12T13:54:54.528Z" }, + { url = "https://files.pythonhosted.org/packages/cb/03/10388a42375ee7e4ac9b94eb2c5c569c8b5795e377e701c9ac3ad63de890/fastapi-0.141.1-py3-none-any.whl", hash = "sha256:bfb91aa2d334c61cb35ba9a116fc123b3d3df31640b801cf57a7a78ec3f603b3", size = 131954, upload-time = "2026-07-29T17:18:04.364Z" }, ] [package.optional-dependencies] @@ -495,27 +542,25 @@ all = [ { name = "httpx" }, { name = "itsdangerous" }, { name = "jinja2" }, - { name = "orjson" }, { name = "pydantic-extra-types" }, { name = "pydantic-settings" }, { name = "python-multipart" }, { name = "pyyaml" }, - { name = "ujson" }, { name = "uvicorn", extra = ["standard"] }, ] [[package]] name = "fastapi-cli" -version = "0.0.23" +version = "0.0.32" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "rich-toolkit" }, { name = "typer" }, { name = "uvicorn", extra = ["standard"] }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/9f/cbd463e57de4e977b8ea0403f95347f9150441568b1d3fe3e4949ef80ef3/fastapi_cli-0.0.23.tar.gz", hash = "sha256:210ac280ea41e73aac5a57688781256beb23c2cba3a41266896fa43e6445c8e7", size = 19763, upload-time = "2026-02-16T19:45:53.358Z" } +sdist = { url = "https://files.pythonhosted.org/packages/33/eb/3b534c6f8e157f9ddbf2a153512307c886cad0b258739c200dd8ff8c4452/fastapi_cli-0.0.32.tar.gz", hash = "sha256:38024d2345275e1b37ce8848727a580d84901b570e96b3256d9d36a9a5039424", size = 26636, upload-time = "2026-07-16T12:16:58.678Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/68/89/19dcfd5cd289b306abdcabac68b88a4f54b7710a2c33adc16a337ecdcdfa/fastapi_cli-0.0.23-py3-none-any.whl", hash = "sha256:7e9634fc212da0b6cfc75bd3ac366cc9dfdb43b5e9ec12e58bfd1acdd2697f25", size = 12305, upload-time = "2026-02-16T19:45:52.554Z" }, + { url = "https://files.pythonhosted.org/packages/d5/53/56ae5ae17bb0a5d89d1d31e5320eb1865553ebbfbde91cdc4c221245f2a8/fastapi_cli-0.0.32-py3-none-any.whl", hash = "sha256:8dcc286fa32f01bbd3f65dd09cfd5a2540ed5f2230b77db7fd30978d6165f3c4", size = 14670, upload-time = "2026-07-16T12:16:57.297Z" }, ] [package.optional-dependencies] @@ -656,14 +701,14 @@ wheels = [ [[package]] name = "gunicorn" -version = "25.1.0" +version = "26.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "packaging" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/13/ef67f59f6a7896fdc2c1d62b5665c5219d6b0a9a1784938eb9a28e55e128/gunicorn-25.1.0.tar.gz", hash = "sha256:1426611d959fa77e7de89f8c0f32eed6aa03ee735f98c01efba3e281b1c47616", size = 594377, upload-time = "2026-02-13T11:09:58.989Z" } +sdist = { url = "https://files.pythonhosted.org/packages/6d/b7/a4a3f632f823e432ce6bc65f62961b7980c898c77f075a2f7118cb3846fe/gunicorn-26.0.0.tar.gz", hash = "sha256:ca9346f85e3a4aeeb64d491045c16b9a35647abd37ea15efe53080eb8b090baf", size = 727286, upload-time = "2026-05-05T06:38:25.529Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/73/4ad5b1f6a2e21cf1e85afdaad2b7b1a933985e2f5d679147a1953aaa192c/gunicorn-25.1.0-py3-none-any.whl", hash = "sha256:d0b1236ccf27f72cfe14bce7caadf467186f19e865094ca84221424e839b8b8b", size = 197067, upload-time = "2026-02-13T11:09:57.146Z" }, + { url = "https://files.pythonhosted.org/packages/e6/40/9c2384fc2be4ad25dd4a49decd5ad9ea5a3639814c11bd40ab77cb9f0a14/gunicorn-26.0.0-py3-none-any.whl", hash = "sha256:40233d26a5f0d1872916188c276e21641155111c2853f0c2cd55260aec0d24fc", size = 212009, upload-time = "2026-05-05T06:38:23.007Z" }, ] [[package]] @@ -724,17 +769,24 @@ wheels = [ [[package]] name = "httptools" -version = "0.7.1" +version = "0.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b5/46/120a669232c7bdedb9d52d4aeae7e6c7dfe151e99dc70802e2fc7a5e1993/httptools-0.7.1.tar.gz", hash = "sha256:abd72556974f8e7c74a259655924a717a2365b236c882c3f6f8a45fe94703ac9", size = 258961, upload-time = "2025-10-10T03:55:08.559Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/e5/d471fcb0e14523fe1c3f4ba58ca52480e7bd70ad7109a3846bc75892f7fb/httptools-0.8.0.tar.gz", hash = "sha256:6b2a32f18d97e16e90827d7a819ffa8dbd8cc245fc4e1fa9d1095b54ef4bd999", size = 271342, upload-time = "2026-05-25T22:17:48.841Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/50/9d095fcbb6de2d523e027a2f304d4551855c2f46e0b82befd718b8b20056/httptools-0.7.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c08fe65728b8d70b6923ce31e3956f859d5e1e8548e6f22ec520a962c6757270", size = 203619, upload-time = "2025-10-10T03:54:54.321Z" }, - { url = "https://files.pythonhosted.org/packages/07/f0/89720dc5139ae54b03f861b5e2c55a37dba9a5da7d51e1e824a1f343627f/httptools-0.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7aea2e3c3953521c3c51106ee11487a910d45586e351202474d45472db7d72d3", size = 108714, upload-time = "2025-10-10T03:54:55.163Z" }, - { url = "https://files.pythonhosted.org/packages/b3/cb/eea88506f191fb552c11787c23f9a405f4c7b0c5799bf73f2249cd4f5228/httptools-0.7.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0e68b8582f4ea9166be62926077a3334064d422cf08ab87d8b74664f8e9058e1", size = 472909, upload-time = "2025-10-10T03:54:56.056Z" }, - { url = "https://files.pythonhosted.org/packages/e0/4a/a548bdfae6369c0d078bab5769f7b66f17f1bfaa6fa28f81d6be6959066b/httptools-0.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df091cf961a3be783d6aebae963cc9b71e00d57fa6f149025075217bc6a55a7b", size = 470831, upload-time = "2025-10-10T03:54:57.219Z" }, - { url = "https://files.pythonhosted.org/packages/4d/31/14df99e1c43bd132eec921c2e7e11cda7852f65619bc0fc5bdc2d0cb126c/httptools-0.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f084813239e1eb403ddacd06a30de3d3e09a9b76e7894dcda2b22f8a726e9c60", size = 452631, upload-time = "2025-10-10T03:54:58.219Z" }, - { url = "https://files.pythonhosted.org/packages/22/d2/b7e131f7be8d854d48cb6d048113c30f9a46dca0c9a8b08fcb3fcd588cdc/httptools-0.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7347714368fb2b335e9063bc2b96f2f87a9ceffcd9758ac295f8bbcd3ffbc0ca", size = 452910, upload-time = "2025-10-10T03:54:59.366Z" }, - { url = "https://files.pythonhosted.org/packages/53/cf/878f3b91e4e6e011eff6d1fa9ca39f7eb17d19c9d7971b04873734112f30/httptools-0.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:cfabda2a5bb85aa2a904ce06d974a3f30fb36cc63d7feaddec05d2050acede96", size = 88205, upload-time = "2025-10-10T03:55:00.389Z" }, + { url = "https://files.pythonhosted.org/packages/1a/12/fa3fbf5f9517b273edea2dc982aa82a8c634091e67c590792b729017bc6f/httptools-0.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:de242a49b5d18e0a8776e654e9f6bf6d89f3875a5c35b425a0e7ce940feb3fd6", size = 206183, upload-time = "2026-05-25T22:17:24.004Z" }, + { url = "https://files.pythonhosted.org/packages/30/fc/5e7c4cb443370f2090a3aba0453a07384d29ff66b7435bb90e77e1037599/httptools-0.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:159e9ab5f701ccd42e555a12f1ad8ff69702910fc1c996cf2bb66e5fcb7a231b", size = 112079, upload-time = "2026-05-25T22:17:25.216Z" }, + { url = "https://files.pythonhosted.org/packages/ba/53/771bd891eb0f236f32145d6a1775777ec85745f3cc983a1f23d1a3b8ddfe/httptools-0.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c4a9f1707e4823d54dfec6c33fa3697d302aed536ed352a7ebb5a061ddb869d0", size = 481596, upload-time = "2026-05-25T22:17:26.186Z" }, + { url = "https://files.pythonhosted.org/packages/62/42/94e15bc68ce3d423243c45d7f1b0c7561f13844f97dc52ae23182fb65628/httptools-0.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d76ad7b951387e3632c8716a9bb03ac5b45c5f16119aa409db0459520887944e", size = 480865, upload-time = "2026-05-25T22:17:27.542Z" }, + { url = "https://files.pythonhosted.org/packages/1c/7c/fe2980fc03723272e30f135b62360b075f513dfe7cc73aef36c7f04012bd/httptools-0.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a3b7387147361c3fd47a0bde763c5c91b5b4cd4dc9989b8ece84ff436c99843b", size = 463189, upload-time = "2026-05-25T22:17:28.546Z" }, + { url = "https://files.pythonhosted.org/packages/15/1b/47fc5fff68acd1bfa20b4734059c9a06cadb88119dcd5258b5b0d21d91c8/httptools-0.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f256d6ce930c52ca1cb2a960b7da03548c454e7d28b06059ad41bfe789036ce0", size = 466610, upload-time = "2026-05-25T22:17:29.816Z" }, + { url = "https://files.pythonhosted.org/packages/60/bd/07b13c93ffd9bec9546e0d43f8e19378dd696dbd278511406bc07371ef1f/httptools-0.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:19d1ee275bb59ba2643ba9a3a1e51cc0c788caf2b8df506368e03f56fdd08527", size = 92705, upload-time = "2026-05-25T22:17:31.133Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c4/121648f68ce066d7bd762d6b6d97e620847642d38d54f3d90ff11d947629/httptools-0.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:de1ed58a974e75d56560acc7e7fed01a454994429456f65209789992e41f2568", size = 215023, upload-time = "2026-05-25T22:17:32.401Z" }, + { url = "https://files.pythonhosted.org/packages/b9/b0/312a062ae741ae3e8baa8c8bf20be81b2e67337b259ab4349bebc7b6142e/httptools-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e93c227b595c6926c1acee96891dd9da4be338cfbe82e5cd3bb9d8dd7dc4ac0b", size = 117405, upload-time = "2026-05-25T22:17:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/fc/37/fccd705f795386bb05bf413012fecff2a33e5aa8c2f069096de3e9fd8702/httptools-0.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2a021c3a8e65cc125390d72f59b968afca3bdcaff25bd67965e0a055a14946ca", size = 558497, upload-time = "2026-05-25T22:17:34.732Z" }, + { url = "https://files.pythonhosted.org/packages/bd/39/f172e8003576de35f5ba77ff417cf0e34429d35dc014deef15afa337a72c/httptools-0.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48774d39cbb70e2b1f71f88852a3087ae1d3a1eb80482bb48c13067ab080c14f", size = 571585, upload-time = "2026-05-25T22:17:35.813Z" }, + { url = "https://files.pythonhosted.org/packages/3e/b9/f5564760af99f3dbbf3f9104dc00e5da27e96cf433c6bdcf77617f70bf3f/httptools-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:88eead8ec8680a9f146c655bc88445a325bd7921cfd8194c7337e9467282427d", size = 543297, upload-time = "2026-05-25T22:17:37.08Z" }, + { url = "https://files.pythonhosted.org/packages/99/67/8d9f2c313618e161b82f3873188e7196126da1d6e29688df40eb3997c77a/httptools-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c032fa028f46871ec7e1fc59fc15e8023eab3e6bbe6ece786a1611719a5d081", size = 539535, upload-time = "2026-05-25T22:17:38.032Z" }, + { url = "https://files.pythonhosted.org/packages/48/63/b906c01e53f50d432c0defe43ce52764a111dc1bdd028bafbeb54dcfd008/httptools-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:384c17174464c8e873398b7af24f0b1f44d992c820328413951a625323155d77", size = 108209, upload-time = "2026-05-25T22:17:39.473Z" }, ] [[package]] @@ -802,36 +854,72 @@ wheels = [ [[package]] name = "librt" -version = "0.8.1" +version = "0.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/56/9c/b4b0c54d84da4a94b37bd44151e46d5e583c9534c7e02250b961b1b6d8a8/librt-0.8.1.tar.gz", hash = "sha256:be46a14693955b3bd96014ccbdb8339ee8c9346fbe11c1b78901b55125f14c73", size = 177471, upload-time = "2026-02-17T16:13:06.101Z" } +sdist = { url = "https://files.pythonhosted.org/packages/36/9b/356320fbae2ac8467e21c5e73e1389c80468e4998c62cc7d3536cc51b614/librt-0.15.0.tar.gz", hash = "sha256:4e66cbe84437497d951b799d3e1551291b6fb3d643820a7014b3655d57a59162", size = 214338, upload-time = "2026-08-07T10:49:42.663Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/6a/907ef6800f7bca71b525a05f1839b21f708c09043b1c6aa77b6b827b3996/librt-0.8.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6cfa7fe54fd4d1f47130017351a959fe5804bda7a0bc7e07a2cdbc3fdd28d34f", size = 66081, upload-time = "2026-02-17T16:12:12.766Z" }, - { url = "https://files.pythonhosted.org/packages/1b/18/25e991cd5640c9fb0f8d91b18797b29066b792f17bf8493da183bf5caabe/librt-0.8.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:228c2409c079f8c11fb2e5d7b277077f694cb93443eb760e00b3b83cb8b3176c", size = 68309, upload-time = "2026-02-17T16:12:13.756Z" }, - { url = "https://files.pythonhosted.org/packages/a4/36/46820d03f058cfb5a9de5940640ba03165ed8aded69e0733c417bb04df34/librt-0.8.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7aae78ab5e3206181780e56912d1b9bb9f90a7249ce12f0e8bf531d0462dd0fc", size = 196804, upload-time = "2026-02-17T16:12:14.818Z" }, - { url = "https://files.pythonhosted.org/packages/59/18/5dd0d3b87b8ff9c061849fbdb347758d1f724b9a82241aa908e0ec54ccd0/librt-0.8.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:172d57ec04346b047ca6af181e1ea4858086c80bdf455f61994c4aa6fc3f866c", size = 206907, upload-time = "2026-02-17T16:12:16.513Z" }, - { url = "https://files.pythonhosted.org/packages/d1/96/ef04902aad1424fd7299b62d1890e803e6ab4018c3044dca5922319c4b97/librt-0.8.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b1977c4ea97ce5eb7755a78fae68d87e4102e4aaf54985e8b56806849cc06a3", size = 221217, upload-time = "2026-02-17T16:12:17.906Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ff/7e01f2dda84a8f5d280637a2e5827210a8acca9a567a54507ef1c75b342d/librt-0.8.1-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:10c42e1f6fd06733ef65ae7bebce2872bcafd8d6e6b0a08fe0a05a23b044fb14", size = 214622, upload-time = "2026-02-17T16:12:19.108Z" }, - { url = "https://files.pythonhosted.org/packages/1e/8c/5b093d08a13946034fed57619742f790faf77058558b14ca36a6e331161e/librt-0.8.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4c8dfa264b9193c4ee19113c985c95f876fae5e51f731494fc4e0cf594990ba7", size = 221987, upload-time = "2026-02-17T16:12:20.331Z" }, - { url = "https://files.pythonhosted.org/packages/d3/cc/86b0b3b151d40920ad45a94ce0171dec1aebba8a9d72bb3fa00c73ab25dd/librt-0.8.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:01170b6729a438f0dedc4a26ed342e3dc4f02d1000b4b19f980e1877f0c297e6", size = 215132, upload-time = "2026-02-17T16:12:21.54Z" }, - { url = "https://files.pythonhosted.org/packages/fc/be/8588164a46edf1e69858d952654e216a9a91174688eeefb9efbb38a9c799/librt-0.8.1-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:7b02679a0d783bdae30d443025b94465d8c3dc512f32f5b5031f93f57ac32071", size = 215195, upload-time = "2026-02-17T16:12:23.073Z" }, - { url = "https://files.pythonhosted.org/packages/f5/f2/0b9279bea735c734d69344ecfe056c1ba211694a72df10f568745c899c76/librt-0.8.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:190b109bb69592a3401fe1ffdea41a2e73370ace2ffdc4a0e8e2b39cdea81b78", size = 237946, upload-time = "2026-02-17T16:12:24.275Z" }, - { url = "https://files.pythonhosted.org/packages/e9/cc/5f2a34fbc8aeb35314a3641f9956fa9051a947424652fad9882be7a97949/librt-0.8.1-cp314-cp314-win32.whl", hash = "sha256:e70a57ecf89a0f64c24e37f38d3fe217a58169d2fe6ed6d70554964042474023", size = 50689, upload-time = "2026-02-17T16:12:25.766Z" }, - { url = "https://files.pythonhosted.org/packages/a0/76/cd4d010ab2147339ca2b93e959c3686e964edc6de66ddacc935c325883d7/librt-0.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:7e2f3edca35664499fbb36e4770650c4bd4a08abc1f4458eab9df4ec56389730", size = 57875, upload-time = "2026-02-17T16:12:27.465Z" }, - { url = "https://files.pythonhosted.org/packages/84/0f/2143cb3c3ca48bd3379dcd11817163ca50781927c4537345d608b5045998/librt-0.8.1-cp314-cp314-win_arm64.whl", hash = "sha256:0d2f82168e55ddefd27c01c654ce52379c0750ddc31ee86b4b266bcf4d65f2a3", size = 48058, upload-time = "2026-02-17T16:12:28.556Z" }, - { url = "https://files.pythonhosted.org/packages/d2/0e/9b23a87e37baf00311c3efe6b48d6b6c168c29902dfc3f04c338372fd7db/librt-0.8.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2c74a2da57a094bd48d03fa5d196da83d2815678385d2978657499063709abe1", size = 68313, upload-time = "2026-02-17T16:12:29.659Z" }, - { url = "https://files.pythonhosted.org/packages/db/9a/859c41e5a4f1c84200a7d2b92f586aa27133c8243b6cac9926f6e54d01b9/librt-0.8.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a355d99c4c0d8e5b770313b8b247411ed40949ca44e33e46a4789b9293a907ee", size = 70994, upload-time = "2026-02-17T16:12:31.516Z" }, - { url = "https://files.pythonhosted.org/packages/4c/28/10605366ee599ed34223ac2bf66404c6fb59399f47108215d16d5ad751a8/librt-0.8.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2eb345e8b33fb748227409c9f1233d4df354d6e54091f0e8fc53acdb2ffedeb7", size = 220770, upload-time = "2026-02-17T16:12:33.294Z" }, - { url = "https://files.pythonhosted.org/packages/af/8d/16ed8fd452dafae9c48d17a6bc1ee3e818fd40ef718d149a8eff2c9f4ea2/librt-0.8.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9be2f15e53ce4e83cc08adc29b26fb5978db62ef2a366fbdf716c8a6c8901040", size = 235409, upload-time = "2026-02-17T16:12:35.443Z" }, - { url = "https://files.pythonhosted.org/packages/89/1b/7bdf3e49349c134b25db816e4a3db6b94a47ac69d7d46b1e682c2c4949be/librt-0.8.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:785ae29c1f5c6e7c2cde2c7c0e148147f4503da3abc5d44d482068da5322fd9e", size = 246473, upload-time = "2026-02-17T16:12:36.656Z" }, - { url = "https://files.pythonhosted.org/packages/4e/8a/91fab8e4fd2a24930a17188c7af5380eb27b203d72101c9cc000dbdfd95a/librt-0.8.1-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1d3a7da44baf692f0c6aeb5b2a09c5e6fc7a703bca9ffa337ddd2e2da53f7732", size = 238866, upload-time = "2026-02-17T16:12:37.849Z" }, - { url = "https://files.pythonhosted.org/packages/b9/e0/c45a098843fc7c07e18a7f8a24ca8496aecbf7bdcd54980c6ca1aaa79a8e/librt-0.8.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fc48998000cbc39ec0d5311312dda93ecf92b39aaf184c5e817d5d440b29624", size = 250248, upload-time = "2026-02-17T16:12:39.445Z" }, - { url = "https://files.pythonhosted.org/packages/82/30/07627de23036640c952cce0c1fe78972e77d7d2f8fd54fa5ef4554ff4a56/librt-0.8.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:e96baa6820280077a78244b2e06e416480ed859bbd8e5d641cf5742919d8beb4", size = 240629, upload-time = "2026-02-17T16:12:40.889Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c1/55bfe1ee3542eba055616f9098eaf6eddb966efb0ca0f44eaa4aba327307/librt-0.8.1-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:31362dbfe297b23590530007062c32c6f6176f6099646bb2c95ab1b00a57c382", size = 239615, upload-time = "2026-02-17T16:12:42.446Z" }, - { url = "https://files.pythonhosted.org/packages/2b/39/191d3d28abc26c9099b19852e6c99f7f6d400b82fa5a4e80291bd3803e19/librt-0.8.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cc3656283d11540ab0ea01978378e73e10002145117055e03722417aeab30994", size = 263001, upload-time = "2026-02-17T16:12:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/b9/eb/7697f60fbe7042ab4e88f4ee6af496b7f222fffb0a4e3593ef1f29f81652/librt-0.8.1-cp314-cp314t-win32.whl", hash = "sha256:738f08021b3142c2918c03692608baed43bc51144c29e35807682f8070ee2a3a", size = 51328, upload-time = "2026-02-17T16:12:45.148Z" }, - { url = "https://files.pythonhosted.org/packages/7c/72/34bf2eb7a15414a23e5e70ecb9440c1d3179f393d9349338a91e2781c0fb/librt-0.8.1-cp314-cp314t-win_amd64.whl", hash = "sha256:89815a22daf9c51884fb5dbe4f1ef65ee6a146e0b6a8df05f753e2e4a9359bf4", size = 58722, upload-time = "2026-02-17T16:12:46.85Z" }, - { url = "https://files.pythonhosted.org/packages/b2/c8/d148e041732d631fc76036f8b30fae4e77b027a1e95b7a84bb522481a940/librt-0.8.1-cp314-cp314t-win_arm64.whl", hash = "sha256:bf512a71a23504ed08103a13c941f763db13fb11177beb3d9244c98c29fb4a61", size = 48755, upload-time = "2026-02-17T16:12:47.943Z" }, + { url = "https://files.pythonhosted.org/packages/a8/93/949053fb462eecc4a9a5ee770a81f4b40be7b79538b245545d4aebc6b58b/librt-0.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f5de7feedc56337a088eb15cd9fafa9938367362221d8cc62c642b7f94821993", size = 149833, upload-time = "2026-08-07T10:47:39.86Z" }, + { url = "https://files.pythonhosted.org/packages/61/ca/8281aa6cd560a3420e4497729f6b704b53be3eeaaef82d5aeadddaf7441f/librt-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6c0eb900c0e91f4aebe680845242e614f1864edfd44106380d0752ac29522bf8", size = 154088, upload-time = "2026-08-07T10:47:41.065Z" }, + { url = "https://files.pythonhosted.org/packages/dd/02/1a1662dceaba6a086360891448d5ce9a7d3555976cae59a31a39d744b9c7/librt-0.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e8c9a650a188e38bac005048cbe6342e81407782944d01934540ab75e417df21", size = 494215, upload-time = "2026-08-07T10:47:42.388Z" }, + { url = "https://files.pythonhosted.org/packages/69/84/99211619dc656370a3740c33d2b0b6d5a3fb1e73689314f6ed477a397dc4/librt-0.15.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:92bfed8deec93df30286b9fe9e3b1dd17329cc076a192b4ee5ec223841d54953", size = 491173, upload-time = "2026-08-07T10:47:43.683Z" }, + { url = "https://files.pythonhosted.org/packages/d4/aa/5448d0b05f4579b635d3899176817ebf561af0e57bacd425b5b1887264c1/librt-0.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ec4b19788f835711a2072f9dbe6b03b3bf32ed1f0fb30cf399bdd59d9f0c33fa", size = 505512, upload-time = "2026-08-07T10:47:45.314Z" }, + { url = "https://files.pythonhosted.org/packages/95/82/01940e40b83c43a546c4a3c896cf34ca272a9690899d55914e4827b3dcce/librt-0.15.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4c7bacb70930f3d0a56f4ecf1be474a1f0d941b01dd73b756f3c256d42cb879", size = 523073, upload-time = "2026-08-07T10:47:46.66Z" }, + { url = "https://files.pythonhosted.org/packages/88/fa/759c0030f3ee371439eb26de34fc745807caf0abb878af7af4b8b7c3dd3d/librt-0.15.0-cp314-cp314-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3e79f05e4a08b4d880342673312bbc895b56df7765605796f15902eb5367d3ae", size = 515080, upload-time = "2026-08-07T10:47:48.319Z" }, + { url = "https://files.pythonhosted.org/packages/0b/27/894e072228fcb159703c655da69f8cd10dbed489c36e3df7dd032a2483be/librt-0.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a417149c0cba4d50b61e992e5a15e69eaf96746609b461cc4ed168aeef6b79dd", size = 534164, upload-time = "2026-08-07T10:47:49.875Z" }, + { url = "https://files.pythonhosted.org/packages/98/a3/0078e91c1f36f8815db17827de15650b9a3fe56c55fbf998c854b34e40d3/librt-0.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:da7a94d6a3411f579d72aa3e3bc5fbca7ed4549f3dbd7e5de3aa567333374285", size = 540616, upload-time = "2026-08-07T10:47:51.408Z" }, + { url = "https://files.pythonhosted.org/packages/86/33/81a29b796dd52a45e9ef7974c7732926e8f10f15b8d2be505665979f896d/librt-0.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:856f743ae607f2c1380eccb566c0038a9fb3eabf0fc2be2704d76d9f73557239", size = 545890, upload-time = "2026-08-07T10:47:52.818Z" }, + { url = "https://files.pythonhosted.org/packages/05/82/8be1baa1350e5d30cfd70ae79d0a6f4dc5862ef47f7bb2808aabc9bb86e5/librt-0.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:779a6e7c894737e5983e7790a9c78c4000c30e23c9aada08081bdbea53b0fa60", size = 523287, upload-time = "2026-08-07T10:47:54.165Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4f/d1be6a01a35c20ef734e0e44113f87d4af756a9354a89dcfbe3b4f8af5e1/librt-0.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:96bb17dbe8bab3c0954fbebfc69ed395599de75b6bbc35e3270a878e15d4dd65", size = 565868, upload-time = "2026-08-07T10:47:55.566Z" }, + { url = "https://files.pythonhosted.org/packages/67/88/649cfa33f5825927b160610f670bdab012a64d627eddb94fa795ea4292fd/librt-0.15.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:7220697efaa6e5348fc3d18ee7f8563d4bfecd9872b37ffb915bfc1d08840622", size = 81619, upload-time = "2026-08-07T10:47:56.886Z" }, + { url = "https://files.pythonhosted.org/packages/22/31/8e88a8d5e48fc8d1a817787fb6811dfff6499acd6c8683dd83934aa6ede0/librt-0.15.0-cp314-cp314-win32.whl", hash = "sha256:f54598964d357b1c5ab77cf5d92f21e598fe0e23cdbe9618480807f81b4eba15", size = 100138, upload-time = "2026-08-07T10:47:58.093Z" }, + { url = "https://files.pythonhosted.org/packages/80/92/20fd6c4b6a1b1a564b076d55cd3d427d8428217d7638dc25a654cc4791d4/librt-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ff5893a2c23d886aa9ce786de5ac6ddc74aeeaf90743682b74d920e117d2e28", size = 121258, upload-time = "2026-08-07T10:47:59.564Z" }, + { url = "https://files.pythonhosted.org/packages/fc/28/6af430b44d9ebb897b865a3c363b6dcace51357be2347cc0f8f869656a86/librt-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:3722a099730704c9a3d70c879fc0f51daec25fe5f1555672d97bc595abeafb95", size = 106467, upload-time = "2026-08-07T10:48:01.097Z" }, + { url = "https://files.pythonhosted.org/packages/7e/aa/b42bb798942ced219f6d63b27e07f91237887a8d0bd0921666db79a13790/librt-0.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:38c0c7d4b6fc06c3324b3f9162c8391bfc4fd9dde53afe1033ce7edb48d5a714", size = 159523, upload-time = "2026-08-07T10:48:02.442Z" }, + { url = "https://files.pythonhosted.org/packages/75/03/1b53cd4ef904e73b1d828a5f90143bf94a2967d7cfff0b9ccf93e12aa9b4/librt-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8b2fdd7ead3c995c37940a790690660d0ca006c302db26cc51933f6766866fc3", size = 161638, upload-time = "2026-08-07T10:48:03.725Z" }, + { url = "https://files.pythonhosted.org/packages/ac/c4/9f9c9fba097d49e9e694c2b4dc331df31884645ecbc58a93b4b5fc69d2c5/librt-0.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fde98cf1fc4bac144ce23c2c4c017b924ba714509ea9334977b0b27050c837d", size = 701795, upload-time = "2026-08-07T10:48:05.135Z" }, + { url = "https://files.pythonhosted.org/packages/4c/05/0966840bda0380c8ae167b9043c6230202941cc90ea29c48e096964c765e/librt-0.15.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:e3b461183c5fa7681b48560f91515f53a953122fb30c71e07abc67d7ddf58c38", size = 682147, upload-time = "2026-08-07T10:48:06.555Z" }, + { url = "https://files.pythonhosted.org/packages/18/af/1c47ca573c30ea47d195aec26133af522fea1104afaace028d7b32247ea8/librt-0.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4bbcc257e3babea20a91715c361b24554ec4e8f51aa578568afc230799fe1a19", size = 696397, upload-time = "2026-08-07T10:48:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/2e/0f/1aed6223d4f9f9d1171a8596ff100ea4c3f7699fea7a4ba657c3e60daa6c/librt-0.15.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b845b8d48088fad0cadc84be4b8fda63203be7e9237b71015b3925443c1f35ab", size = 722542, upload-time = "2026-08-07T10:48:09.569Z" }, + { url = "https://files.pythonhosted.org/packages/c6/22/9e3a929aea456c97d69e6ef3884efea56d4807f97399471cc946baebd8af/librt-0.15.0-cp314-cp314t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b30e600e8f337b9bd7f39b86d9fdfedc73cc46e3d0f745931a23a234220bb7e2", size = 729709, upload-time = "2026-08-07T10:48:11.129Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1b/c327ef6018e3a9ca0b8e7c5eddeeb331ba8f9b76c24e126d37d0f6d62faf/librt-0.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:64b0c8c35aa4c4ed79896359f3e0b285cbe4e610042106500da4811c322cc108", size = 752891, upload-time = "2026-08-07T10:48:12.558Z" }, + { url = "https://files.pythonhosted.org/packages/d7/d1/d5f1ea02c56930087009e39db9b70660a663e76c730b27b925d786718457/librt-0.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0da0d94cb802f32a0524653e7201f2cef72d5f700a5407678f5290483d4fcd08", size = 745301, upload-time = "2026-08-07T10:48:14.55Z" }, + { url = "https://files.pythonhosted.org/packages/d9/3c/5f7c585d15ebb2250c73e7c0ee4e9e47be72c65d520c07ddbcdc62037674/librt-0.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:4a6369168d371207339b1e50d4532b06a7121586141f82599505a3f315751d47", size = 747921, upload-time = "2026-08-07T10:48:16.453Z" }, + { url = "https://files.pythonhosted.org/packages/7f/52/1443a446486eba966bcbca1696b472e4f210320ec42f490a47f48fbf0fdc/librt-0.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:c434e072557ade9cbc642d052c89d031efe47d5c9614523619d0d74a02378e81", size = 727561, upload-time = "2026-08-07T10:48:18.089Z" }, + { url = "https://files.pythonhosted.org/packages/79/91/2270a9380f11725cf83ce1925a5e32dd1dde2be9bba597f25c10a38644e7/librt-0.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c7eec6a42018bc1d45763b1c162d3d2bf7c3b9a1b0ed30d3e91dcba390efefcc", size = 774417, upload-time = "2026-08-07T10:48:19.611Z" }, + { url = "https://files.pythonhosted.org/packages/9e/3b/f4b1548d4f5b99186737fe27aec238e9823e8d5d23bf4df007c030689dc5/librt-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:6912fa5e635d74529ac7cdb1bdf6ca3af4453da8d1edbe0110ee1cb4ad407ebf", size = 104381, upload-time = "2026-08-07T10:48:21.048Z" }, + { url = "https://files.pythonhosted.org/packages/80/b6/134afad262def1de04c0843c376d02135f1168af43f22e09a52bd8394727/librt-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8e11699ed745931c395acd3621b07062e0f840efa6935aad87a64ed0995f0915", size = 127034, upload-time = "2026-08-07T10:48:22.561Z" }, + { url = "https://files.pythonhosted.org/packages/99/5f/1b6846b20572bd699c9e9ec321a5f781845bee477df2aa2a43b28bc40119/librt-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:5d2a91724463bfed4f573cd7a9fdc856d2e230d0c0e5a61416a93481dccd8605", size = 110827, upload-time = "2026-08-07T10:48:23.804Z" }, + { url = "https://files.pythonhosted.org/packages/c6/44/4de9f4ddadb009a55c7758eb5736d62534a7daaf27bd71bc50e64b606b06/librt-0.15.0-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:8443e38dcfcfdbcf5add5118c623efd788d65ac2e25756d6251a54a06a4d0aca", size = 149843, upload-time = "2026-08-07T10:48:25.148Z" }, + { url = "https://files.pythonhosted.org/packages/1f/eb/5d9ab71e30119c44094e0275f38b47dd327aea0f843a080396677029d508/librt-0.15.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:6d15a29033c57490cfe2069097c6fc4049e4e65ffbb749be7dc453b7c4c68965", size = 154510, upload-time = "2026-08-07T10:48:26.485Z" }, + { url = "https://files.pythonhosted.org/packages/d0/9c/8505d1b8f5e8c19587bd03f7429993b3e9ce5c06819d856bfb11d919374c/librt-0.15.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d2c05c729b589e734c09578bf5964be48a911765484840d017bbc84f49d4c4ad", size = 497543, upload-time = "2026-08-07T10:48:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/1d/9a/3a8390775cb095765aded027ac9c63e7c8ea74e731498607544c6505de0e/librt-0.15.0-cp315-cp315-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:fa60887537e1d0cd2d9982269d33a709bf54b195cd2b9364fc0a758022af5bd9", size = 480452, upload-time = "2026-08-07T10:48:29.531Z" }, + { url = "https://files.pythonhosted.org/packages/e7/40/258a4a7117ee915d66de5cd9b8ade65a440993161107ce3a686f1859955c/librt-0.15.0-cp315-cp315-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d8bc24219b24c0af375718942ab75e3544b2763085f40f965be4326734ae8328", size = 507768, upload-time = "2026-08-07T10:48:31.007Z" }, + { url = "https://files.pythonhosted.org/packages/6b/c6/2f4dd296c97a0b85b98894519b279408ec9dd602d4f692b1ea0e25dee670/librt-0.15.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:86a21a7bd3fe3a419512ef424cc1c020f6771d0b29cfddff36d1635a855e63f0", size = 525122, upload-time = "2026-08-07T10:48:32.7Z" }, + { url = "https://files.pythonhosted.org/packages/49/dd/29eab42be13b2bf0ea8cb227135a45d44693e30a7e8b92871981ff56b82b/librt-0.15.0-cp315-cp315-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:dbab647e88d90b3167b91efe7091e248653688ed4337e4f90907a722c7361bb9", size = 520371, upload-time = "2026-08-07T10:48:34.294Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/4bad71adeca8fe208b775c2a35417fa5a2584c8f4791daaf89a89450fea1/librt-0.15.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:d8edcf6f550e918dca779c069b9e156385c60b406f99fc7641f32c52f7193659", size = 537258, upload-time = "2026-08-07T10:48:35.88Z" }, + { url = "https://files.pythonhosted.org/packages/4c/63/59dba6143fdcc7240c54458b629f3250000a61b8945890fc9efd451b19c5/librt-0.15.0-cp315-cp315-musllinux_1_2_i686.whl", hash = "sha256:8b62076030baa2d8b1501a46bf0e19c27a489aa90671c55665bff7887f7660b0", size = 527432, upload-time = "2026-08-07T10:48:37.466Z" }, + { url = "https://files.pythonhosted.org/packages/ec/21/21a24c6a2327d8362580efebe77286bf47b0f4062ec5ea41766e609d3c7d/librt-0.15.0-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:d00d20d1818e82a07a0ee0aa89a98b17ed7916b92441090b683719cb20a59b6d", size = 548108, upload-time = "2026-08-07T10:48:39.384Z" }, + { url = "https://files.pythonhosted.org/packages/5a/6d/fc68c89a7971418b41f9a873623ff935cb864097544c6a2f8ce491c8ef5d/librt-0.15.0-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:4e6ee93fc3cf848dcbf0cce2eca73d8e7dcd0cc2b6df3a529d57750b30a4c55c", size = 529681, upload-time = "2026-08-07T10:48:41.392Z" }, + { url = "https://files.pythonhosted.org/packages/65/7e/c2d98766124400d722063a630b0fde38a9fc768705d37eecca15c47dc192/librt-0.15.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:32896a0af72508ea979e0acb4e4c04cbeeae04938167950d535c83c45597167d", size = 567736, upload-time = "2026-08-07T10:48:43.124Z" }, + { url = "https://files.pythonhosted.org/packages/55/6c/f8c34a95e3a515c6e1c192b89511e7253c89a7760c6b500d57ffdb8d2dc8/librt-0.15.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:ec3ba415afaf951f6951b1dd16d3c8e4f540065fc382d7e70b823a79567ca374", size = 81673, upload-time = "2026-08-07T10:48:44.645Z" }, + { url = "https://files.pythonhosted.org/packages/c9/9e/e23fa8e78679ec45728188650b39e8ff476c83b691c96f749217df3b1b7c/librt-0.15.0-cp315-cp315-win32.whl", hash = "sha256:d2813ba2503764f0450680c533d13df7cff9b49df1411062eded5f67db4195b9", size = 100081, upload-time = "2026-08-07T10:48:46.171Z" }, + { url = "https://files.pythonhosted.org/packages/e1/dc/3eb4c5e297343f0620a55532cd7c8d764d3001fa2159212dadf480464827/librt-0.15.0-cp315-cp315-win_amd64.whl", hash = "sha256:b87d67e33afaf265262f2a66db578284b88ee2e6fcd224579cb5c15518677ad8", size = 121228, upload-time = "2026-08-07T10:48:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/97/70/43abce19f04e49762f8ec834c8fafee13cc40fd6b94a72a24e534febfcd0/librt-0.15.0-cp315-cp315-win_arm64.whl", hash = "sha256:713bd7df21170b982e729e46870f31d6b437bd1a9b4648cffb529bd3c2ec5c4b", size = 106487, upload-time = "2026-08-07T10:48:49.095Z" }, + { url = "https://files.pythonhosted.org/packages/de/15/83f2deddb9368b8951ec8c9477269b5b9b8bd9bbf15e57402d0f38817dca/librt-0.15.0-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:3de789c82752730f94782a5ee518baf9c05edf85733aeaf73bb6e518755cdf54", size = 159448, upload-time = "2026-08-07T10:48:50.649Z" }, + { url = "https://files.pythonhosted.org/packages/06/bf/043097353f9b3c73b583d07f6b8e552795463f4bfc8caf85e42eee50c26a/librt-0.15.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:e0b5deec9a8664eb722c797241970fd4aa1894d25fda36a1ddac0f7407606bd6", size = 161686, upload-time = "2026-08-07T10:48:52.174Z" }, + { url = "https://files.pythonhosted.org/packages/f4/2a/8ae77f9719d42ce71cd708560a3557b38ac3c17a0383e57f87084de45bbe/librt-0.15.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5563302a8359bc2295bb7084d1a8ed1519df96afb30eb2aa4e0bff7b54228988", size = 710668, upload-time = "2026-08-07T10:48:53.782Z" }, + { url = "https://files.pythonhosted.org/packages/61/34/c0436ea134deb9a0d6da80a396a2739a81cb31e0418f7227239e23140898/librt-0.15.0-cp315-cp315t-manylinux2014_i686.manylinux_2_17_i686.manylinux_2_28_i686.whl", hash = "sha256:22d6263b9d39d7bbb286fa791945646e3218f1be2d693e36fb630f1d0e59cd13", size = 679396, upload-time = "2026-08-07T10:48:55.645Z" }, + { url = "https://files.pythonhosted.org/packages/4a/9f/001e0d99aa9250d5cd5715a9081291a20656083459f9019cda15255329e1/librt-0.15.0-cp315-cp315t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39ffd14646190c454f0d86e0d256b33f00a87a26ab410e619773b841d0e41416", size = 704313, upload-time = "2026-08-07T10:48:57.46Z" }, + { url = "https://files.pythonhosted.org/packages/2d/53/b34fa9d0ff00f136f4d58ebb4c411ff634baed1eb412bb602a2bc8dcafcb/librt-0.15.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c47318cd3a61401452de11282242937e3e057c4fd3dbaf601e269d0928a06c0a", size = 729847, upload-time = "2026-08-07T10:48:59.231Z" }, + { url = "https://files.pythonhosted.org/packages/86/ac/fa4d7a424665040e95baf480a6d523446057684b6758624c85338e8a23b2/librt-0.15.0-cp315-cp315t-manylinux_2_34_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a56a1d4f859a82ca5b99fc4b82c9b027b15e3c455c5cd99e7d0719f27bb20b6c", size = 742736, upload-time = "2026-08-07T10:49:01.151Z" }, + { url = "https://files.pythonhosted.org/packages/8a/f1/e17a9bb5de6fb8c3186ed1a7d68d21618b027ac2d3633e03d3b6109c67ae/librt-0.15.0-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:077471b3182db4e17c36ae91555f36a4d2c00080b267f749bcad34a478a9a302", size = 763454, upload-time = "2026-08-07T10:49:03.039Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ec/ecd02cd30935b931b9cdbfed6ab5a099c51b280b4e7baa274da80978ed27/librt-0.15.0-cp315-cp315t-musllinux_1_2_i686.whl", hash = "sha256:411ca4d1b905b860ceba7570dd6717a71dedaddcc4b0f77ece710aa41ee11f8d", size = 743296, upload-time = "2026-08-07T10:49:04.941Z" }, + { url = "https://files.pythonhosted.org/packages/e6/b5/b3c2b8353ce820a4854f78d19321344242f89fa71c975b71132ba9bf242a/librt-0.15.0-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:1256589e0b0adb31751d685a68bce29d73407ddf4ef05d4188f49d5dcf9566d9", size = 756217, upload-time = "2026-08-07T10:49:06.825Z" }, + { url = "https://files.pythonhosted.org/packages/3c/52/6cc22542ba59146b05cca2a656f9ff8bb67e38e63d12c3b0cc183d837bf1/librt-0.15.0-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:f42b74a53e5f26a0ba0007411a7455b66c67ce4022a39cc1f56fc4efd65bcbab", size = 741934, upload-time = "2026-08-07T10:49:08.839Z" }, + { url = "https://files.pythonhosted.org/packages/40/32/a04b72b1aa86e3be23b2ecff8c1aad2dcc955bd3956d6d26e7e34267e57a/librt-0.15.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:291bf73caf78b9e88d6fae9bfd693207ff7d832e2fdbe2cf8e746bc13f5f892b", size = 783763, upload-time = "2026-08-07T10:49:10.661Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f0/89eb11dffbe9279ff37144dec786927314502ae0b114f1449dc78c458aab/librt-0.15.0-cp315-cp315t-win32.whl", hash = "sha256:c16d15ee371643ab48dc8248a3e680ebbeca573a13af2c3dd0c985b142d77162", size = 104313, upload-time = "2026-08-07T10:49:12.305Z" }, + { url = "https://files.pythonhosted.org/packages/6d/4a/1f1978c200f563beda63c36adff2d65bbecb81e365e8e69e572f5f70fbc6/librt-0.15.0-cp315-cp315t-win_amd64.whl", hash = "sha256:dbd605739f228912dc49027cb764456b9757750bdc2b6b7773164db7096c6fd1", size = 126889, upload-time = "2026-08-07T10:49:13.881Z" }, + { url = "https://files.pythonhosted.org/packages/38/a6/800800bfed7b1fb10fc3f3d557785c3854e80d3f7a9800d784b176a1fc2d/librt-0.15.0-cp315-cp315t-win_arm64.whl", hash = "sha256:84d244b00604d17df3fc7736c327892d6bba66181254aa4087be807b6c342bdc", size = 110700, upload-time = "2026-08-07T10:49:15.499Z" }, ] [[package]] @@ -953,23 +1041,33 @@ wheels = [ [[package]] name = "mypy" -version = "1.19.1" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "ast-serialize" }, { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/f5/db/4efed9504bc01309ab9c2da7e352cc223569f05478012b5d9ece38fd44d2/mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba", size = 3582404, upload-time = "2025-12-15T05:03:48.42Z" } +sdist = { url = "https://files.pythonhosted.org/packages/12/af/4e516a05d3ca2eb9283e9ec45b2c02225c1514dd6da49fd3c9eaa6639370/mypy-2.3.0.tar.gz", hash = "sha256:465965d41cd9a2726694e983e8ce7113259327bec798115d1e1dfa2a52fb666e", size = 3988104, upload-time = "2026-07-13T11:34:53.387Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1", size = 13199744, upload-time = "2025-12-15T05:03:30.823Z" }, - { url = "https://files.pythonhosted.org/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718", size = 12215815, upload-time = "2025-12-15T05:02:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b", size = 12740047, upload-time = "2025-12-15T05:03:33.168Z" }, - { url = "https://files.pythonhosted.org/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045", size = 13601998, upload-time = "2025-12-15T05:03:13.056Z" }, - { url = "https://files.pythonhosted.org/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957", size = 13807476, upload-time = "2025-12-15T05:03:17.977Z" }, - { url = "https://files.pythonhosted.org/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f", size = 10281872, upload-time = "2025-12-15T05:03:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247", size = 2471239, upload-time = "2025-12-15T05:03:07.248Z" }, + { url = "https://files.pythonhosted.org/packages/a4/58/fa0ae047da911f540284009b4f44b96fe09d83c076d7c103e9d645f46303/mypy-2.3.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:ea317b060ce83e26050f8f9e4d7d6bf44ed7597c8ff9990bccffbb9d1d8522db", size = 14941909, upload-time = "2026-07-13T11:32:34.332Z" }, + { url = "https://files.pythonhosted.org/packages/15/14/2ba1d61452d7c2a7fe12741e8d374e52b183476b07aa7f9e2a0d02b0720a/mypy-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:094af99f92638aa92852326188b85a89e50f4a472f44827c03362228482f0762", size = 13967581, upload-time = "2026-07-13T11:30:00.587Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5a/483fb9e5ffbbb1a28dccc7b0a13d141b17ac769b6c9f488c0a0c63698962/mypy-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de121747278144fc9ae7caa2e978cf5df12aebc82933182f5b3b86081a30baef", size = 14168807, upload-time = "2026-07-13T11:28:48.6Z" }, + { url = "https://files.pythonhosted.org/packages/ae/77/70d7a10732063beb74ad713682cf871e88f5c5fa39bfc8beff8a524bf9cb/mypy-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37fa4de896a84e2dc9200d91e614c22563b43d1a266789d4bbac7b22ebe6192b", size = 15200144, upload-time = "2026-07-13T11:31:25.283Z" }, + { url = "https://files.pythonhosted.org/packages/56/72/766218ac783be4fdfcd699b90037b63017348a3e86fb2c1fbfb18302637d/mypy-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f1b3a98dfd21058bc759bb3337d5d1f61d0fdf9f3cf9c00f4291790fb5427bff", size = 15460389, upload-time = "2026-07-13T11:29:29.077Z" }, + { url = "https://files.pythonhosted.org/packages/38/4e/8a9db7411ecb8ec0cb1fd05dba432f28bafffcd38b4e887714a4a0506689/mypy-2.3.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:944c665d984157cb96a679dfb7a4a81dd1d36b24b9c284b699514e6e626b82d4", size = 7753664, upload-time = "2026-07-13T11:29:08.147Z" }, + { url = "https://files.pythonhosted.org/packages/65/4c/c3f8bfd6ed0e5e38b5a244403b27f821d433443df5a15a278417c10a3a3c/mypy-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:4359424140d985192c778c1ce2c114a10c1ca58a381ed79cfa70d37df94b299f", size = 11417237, upload-time = "2026-07-13T11:33:47.467Z" }, + { url = "https://files.pythonhosted.org/packages/3c/00/89a32eaf5ccf174bc4f90db0eaea5d70636c01b8d49f384bdab2e8834390/mypy-2.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:3dd0bed92c4bdec57c42505b96416fb9e6a5aa7be84d2809bcd5f2ecec2860d7", size = 10389252, upload-time = "2026-07-13T11:31:43.81Z" }, + { url = "https://files.pythonhosted.org/packages/31/56/104f93d69aa9f339b6b9d3b0a7faa699b8b466c942cf3ae86cc2a2ec0915/mypy-2.3.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:691fdc37132b1ae628d834f672e74de83462d9fb4aff621835767fb43a8dd373", size = 16385495, upload-time = "2026-07-13T11:29:49.818Z" }, + { url = "https://files.pythonhosted.org/packages/d2/03/f1d2123313f55efafdd27706960f43a771c62f1b68426c76043f3ab9ebf3/mypy-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:aec15d465d477558fd842757b487849007311cf3897849cdda0e3162ac0ac556", size = 15098155, upload-time = "2026-07-13T11:30:40.301Z" }, + { url = "https://files.pythonhosted.org/packages/e5/5d/d5f9200399b445e81726c4f23becee33f233aee81c72680b1ef3a258b641/mypy-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b352b7e49f5e6576009e8df730e1ff4f915cb565b851b396d2ffe2f5a6f5da88", size = 15514155, upload-time = "2026-07-13T11:34:38.569Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ce/69977c555f08faa3190cfde44189b89dbd56861b1ab97aa18fc5f3a2e4a3/mypy-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c6c6bf687b17f90dbfcad95b960d32eaa0154c00da45f03ab50bf8952e047fe", size = 16766351, upload-time = "2026-07-13T11:33:29.195Z" }, + { url = "https://files.pythonhosted.org/packages/bc/92/6648b6caa3ab9e00f9ac0c2a78307805f873dd48139b24a6f6f7c3667bbf/mypy-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f4ed18f111bfe2d599bca7468e7f9251042c1c2118f762c8de2766a56d773c60", size = 17043490, upload-time = "2026-07-13T11:30:53.927Z" }, + { url = "https://files.pythonhosted.org/packages/7c/ab/0dc91d80f3f016634c68d451f294a97320fe903a9b6f90b9e57b3f7f1717/mypy-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0b025a93cffb9781d231f232be07a17912f35f10a313c24f301c81e842870654", size = 12146869, upload-time = "2026-07-13T11:29:38.874Z" }, + { url = "https://files.pythonhosted.org/packages/85/b5/4c964d02634ba81f4d1c84838e5c5b18ab06d13ed568960f5d6318495ccc/mypy-2.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:adebc76aab4f3495a88b41d48aa4aff0c03f2822501da76625afcca5975f19e5", size = 10965113, upload-time = "2026-07-13T11:28:07.056Z" }, + { url = "https://files.pythonhosted.org/packages/2c/fa/fdc54fe583ba3cafbcedfb70eeeaf03849f75b1827a07096c7bd996f582d/mypy-2.3.0-py3-none-any.whl", hash = "sha256:6b1cdb579446b60432432b2b2403a6201b4b475a004d7f488511c9ba177c9e88", size = 2753292, upload-time = "2026-07-13T11:33:18.48Z" }, ] [[package]] @@ -1005,29 +1103,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, ] -[[package]] -name = "orjson" -version = "3.11.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/53/45/b268004f745ede84e5798b48ee12b05129d19235d0e15267aa57dcdb400b/orjson-3.11.7.tar.gz", hash = "sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49", size = 6144992, upload-time = "2026-02-02T15:38:49.29Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0", size = 228391, upload-time = "2026-02-02T15:38:27.757Z" }, - { url = "https://files.pythonhosted.org/packages/46/19/e40f6225da4d3aa0c8dc6e5219c5e87c2063a560fe0d72a88deb59776794/orjson-3.11.7-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0", size = 125188, upload-time = "2026-02-02T15:38:29.241Z" }, - { url = "https://files.pythonhosted.org/packages/9d/7e/c4de2babef2c0817fd1f048fd176aa48c37bec8aef53d2fa932983032cce/orjson-3.11.7-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6", size = 128097, upload-time = "2026-02-02T15:38:30.618Z" }, - { url = "https://files.pythonhosted.org/packages/eb/74/233d360632bafd2197f217eee7fb9c9d0229eac0c18128aee5b35b0014fe/orjson-3.11.7-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf", size = 123364, upload-time = "2026-02-02T15:38:32.363Z" }, - { url = "https://files.pythonhosted.org/packages/79/51/af79504981dd31efe20a9e360eb49c15f06df2b40e7f25a0a52d9ae888e8/orjson-3.11.7-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5", size = 129076, upload-time = "2026-02-02T15:38:33.68Z" }, - { url = "https://files.pythonhosted.org/packages/67/e2/da898eb68b72304f8de05ca6715870d09d603ee98d30a27e8a9629abc64b/orjson-3.11.7-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892", size = 141705, upload-time = "2026-02-02T15:38:34.989Z" }, - { url = "https://files.pythonhosted.org/packages/c5/89/15364d92acb3d903b029e28d834edb8780c2b97404cbf7929aa6b9abdb24/orjson-3.11.7-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e", size = 130855, upload-time = "2026-02-02T15:38:36.379Z" }, - { url = "https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1", size = 133386, upload-time = "2026-02-02T15:38:37.704Z" }, - { url = "https://files.pythonhosted.org/packages/b9/0e/45e1dcf10e17d0924b7c9162f87ec7b4ca79e28a0548acf6a71788d3e108/orjson-3.11.7-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183", size = 138295, upload-time = "2026-02-02T15:38:39.096Z" }, - { url = "https://files.pythonhosted.org/packages/63/d7/4d2e8b03561257af0450f2845b91fbd111d7e526ccdf737267108075e0ba/orjson-3.11.7-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650", size = 408720, upload-time = "2026-02-02T15:38:40.634Z" }, - { url = "https://files.pythonhosted.org/packages/78/cf/d45343518282108b29c12a65892445fc51f9319dc3c552ceb51bb5905ed2/orjson-3.11.7-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141", size = 144152, upload-time = "2026-02-02T15:38:42.262Z" }, - { url = "https://files.pythonhosted.org/packages/a9/3a/d6001f51a7275aacd342e77b735c71fa04125a3f93c36fee4526bc8c654e/orjson-3.11.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2", size = 134814, upload-time = "2026-02-02T15:38:43.627Z" }, - { url = "https://files.pythonhosted.org/packages/1d/d3/f19b47ce16820cc2c480f7f1723e17f6d411b3a295c60c8ad3aa9ff1c96a/orjson-3.11.7-cp314-cp314-win32.whl", hash = "sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576", size = 127997, upload-time = "2026-02-02T15:38:45.06Z" }, - { url = "https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl", hash = "sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1", size = 124985, upload-time = "2026-02-02T15:38:46.388Z" }, - { url = "https://files.pythonhosted.org/packages/6f/1c/f2a8d8a1b17514660a614ce5f7aac74b934e69f5abc2700cc7ced882a009/orjson-3.11.7-cp314-cp314-win_arm64.whl", hash = "sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d", size = 126038, upload-time = "2026-02-02T15:38:47.703Z" }, -] - [[package]] name = "packaging" version = "26.0" @@ -1071,7 +1146,7 @@ wheels = [ [[package]] name = "pre-commit" -version = "4.5.1" +version = "4.6.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, @@ -1080,9 +1155,9 @@ dependencies = [ { name = "pyyaml" }, { name = "virtualenv" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" } +sdist = { url = "https://files.pythonhosted.org/packages/25/3a/ddb78f32a0814e66b18a099377a106a2dcdce92d86a034d69d65df9b256e/pre_commit-4.6.1.tar.gz", hash = "sha256:03e809865c7d178b9979d06c761fcbfe6808fdaded8581a745bb110e52050421", size = 198646, upload-time = "2026-07-21T20:56:58.225Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" }, + { url = "https://files.pythonhosted.org/packages/fb/49/bc925106abcdac498074f2cbe6137e94e09f418dd2b7775df5b577dc0313/pre_commit-4.6.1-py2.py3-none-any.whl", hash = "sha256:0e3b2942510d1fb34eec167a3ec57331bf8442122f1153a9fb8b58f5c49b2717", size = 226186, upload-time = "2026-07-21T20:56:57.064Z" }, ] [[package]] @@ -1126,14 +1201,14 @@ wheels = [ [[package]] name = "psycopg" -version = "3.3.3" +version = "3.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tzdata", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d3/b6/379d0a960f8f435ec78720462fd94c4863e7a31237cf81bf76d0af5883bf/psycopg-3.3.3.tar.gz", hash = "sha256:5e9a47458b3c1583326513b2556a2a9473a1001a56c9efe9e587245b43148dd9", size = 165624, upload-time = "2026-02-18T16:52:16.546Z" } +sdist = { url = "https://files.pythonhosted.org/packages/db/2f/cb91e5502ec9de1de6f1b76cfbf69531932725361168bb06963620c77e2e/psycopg-3.3.4.tar.gz", hash = "sha256:e21207764952cff81b6b8bdacad9a3939f2793367fdac2987b3aac36a651b5bc", size = 165799, upload-time = "2026-05-01T23:31:55.179Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/5b/181e2e3becb7672b502f0ed7f16ed7352aca7c109cfb94cf3878a9186db9/psycopg-3.3.3-py3-none-any.whl", hash = "sha256:f96525a72bcfade6584ab17e89de415ff360748c766f0106959144dcbb38c698", size = 212768, upload-time = "2026-02-18T16:46:27.365Z" }, + { url = "https://files.pythonhosted.org/packages/5c/e0/7b3dee031daae7743609ce3c746565d4a3ed7c2c186479eb48e34e838c64/psycopg-3.3.4-py3-none-any.whl", hash = "sha256:b6bbc25ccf05c8fad3b061d9db2ef0909a555171b84b07f29458a447253d679a", size = 213001, upload-time = "2026-05-01T23:20:50.816Z" }, ] [package.optional-dependencies] @@ -1146,20 +1221,20 @@ pool = [ [[package]] name = "psycopg-binary" -version = "3.3.3" +version = "3.3.4" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/71/7a57e5b12275fe7e7d84d54113f0226080423a869118419c9106c083a21c/psycopg_binary-3.3.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:497852c5eaf1f0c2d88ab74a64a8097c099deac0c71de1cbcf18659a8a04a4b2", size = 4607368, upload-time = "2026-02-18T16:51:19.295Z" }, - { url = "https://files.pythonhosted.org/packages/c7/04/cb834f120f2b2c10d4003515ef9ca9d688115b9431735e3936ae48549af8/psycopg_binary-3.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:258d1ea53464d29768bf25930f43291949f4c7becc706f6e220c515a63a24edd", size = 4687047, upload-time = "2026-02-18T16:51:23.84Z" }, - { url = "https://files.pythonhosted.org/packages/40/e9/47a69692d3da9704468041aa5ed3ad6fc7f6bb1a5ae788d261a26bbca6c7/psycopg_binary-3.3.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:111c59897a452196116db12e7f608da472fbff000693a21040e35fc978b23430", size = 5487096, upload-time = "2026-02-18T16:51:29.645Z" }, - { url = "https://files.pythonhosted.org/packages/0b/b6/0e0dd6a2f802864a4ae3dbadf4ec620f05e3904c7842b326aafc43e5f464/psycopg_binary-3.3.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:17bb6600e2455993946385249a3c3d0af52cd70c1c1cdbf712e9d696d0b0bf1b", size = 5168720, upload-time = "2026-02-18T16:51:36.499Z" }, - { url = "https://files.pythonhosted.org/packages/6f/0d/977af38ac19a6b55d22dff508bd743fd7c1901e1b73657e7937c7cccb0a3/psycopg_binary-3.3.3-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:642050398583d61c9856210568eb09a8e4f2fe8224bf3be21b67a370e677eead", size = 6762076, upload-time = "2026-02-18T16:51:43.167Z" }, - { url = "https://files.pythonhosted.org/packages/34/40/912a39d48322cf86895c0eaf2d5b95cb899402443faefd4b09abbba6b6e1/psycopg_binary-3.3.3-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:533efe6dc3a7cba5e2a84e38970786bb966306863e45f3db152007e9f48638a6", size = 4997623, upload-time = "2026-02-18T16:51:47.707Z" }, - { url = "https://files.pythonhosted.org/packages/98/0c/c14d0e259c65dc7be854d926993f151077887391d5a081118907a9d89603/psycopg_binary-3.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:5958dbf28b77ce2033482f6cb9ef04d43f5d8f4b7636e6963d5626f000efb23e", size = 4532096, upload-time = "2026-02-18T16:51:51.421Z" }, - { url = "https://files.pythonhosted.org/packages/39/21/8b7c50a194cfca6ea0fd4d1f276158307785775426e90700ab2eba5cd623/psycopg_binary-3.3.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a6af77b6626ce92b5817bf294b4d45ec1a6161dba80fc2d82cdffdd6814fd023", size = 4208884, upload-time = "2026-02-18T16:51:57.336Z" }, - { url = "https://files.pythonhosted.org/packages/c7/2c/a4981bf42cf30ebba0424971d7ce70a222ae9b82594c42fc3f2105d7b525/psycopg_binary-3.3.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:47f06fcbe8542b4d96d7392c476a74ada521c5aebdb41c3c0155f6595fc14c8d", size = 3944542, upload-time = "2026-02-18T16:52:04.266Z" }, - { url = "https://files.pythonhosted.org/packages/60/e9/b7c29b56aa0b85a4e0c4d89db691c1ceef08f46a356369144430c155a2f5/psycopg_binary-3.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e7800e6c6b5dc4b0ca7cc7370f770f53ac83886b76afda0848065a674231e856", size = 4254339, upload-time = "2026-02-18T16:52:10.444Z" }, - { url = "https://files.pythonhosted.org/packages/98/5a/291d89f44d3820fffb7a04ebc8f3ef5dda4f542f44a5daea0c55a84abf45/psycopg_binary-3.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:165f22ab5a9513a3d7425ffb7fcc7955ed8ccaeef6d37e369d6cc1dff1582383", size = 3652796, upload-time = "2026-02-18T16:52:14.02Z" }, + { url = "https://files.pythonhosted.org/packages/48/a6/828c9185701dab71b234c2a76c38a08b098ebfec5020716b4e93807492b5/psycopg_binary-3.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:28b7398fdd19db3232c884fb24550bdfe951221f510e195e233299e4c9b78f97", size = 4607292, upload-time = "2026-05-01T23:30:38.962Z" }, + { url = "https://files.pythonhosted.org/packages/92/58/5b40dbc9d839045c9dae956960e4fb6d20bcabe6c59a2aa34fc3a371913f/psycopg_binary-3.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1fbaa292a3c8bb61b45df1ad3da1908ccee7cb889db9425e3557d9e34e2a4829", size = 4687023, upload-time = "2026-05-01T23:30:47.227Z" }, + { url = "https://files.pythonhosted.org/packages/85/a9/793f0ac107a9003b48441d0d1f9f616d96e0f37458dd8dc12528ceff55fb/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94596f9e7633ee3f6440711d43bb70aa31cc0a46a900ab8b4201a366ace5c9e7", size = 5486985, upload-time = "2026-05-01T23:30:55.517Z" }, + { url = "https://files.pythonhosted.org/packages/8f/26/42e8533497e2592334f68ec529cf5f840f7fa4e99575a4bb61aa184dbfbf/psycopg_binary-3.3.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8c0056529e68dbe9184cd4019a1f3d8f3a4ead2f6fc7a5afcf27d3314edd1277", size = 5168745, upload-time = "2026-05-01T23:31:01.904Z" }, + { url = "https://files.pythonhosted.org/packages/15/af/b7151776cc08d5935d45c833ec818a9beb417cf7c08239af1aafbdae78ee/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2c09aad7051326e7603c14e50636db9c01f78272dc54b3accff03d46370461e6", size = 6761486, upload-time = "2026-05-01T23:31:14.511Z" }, + { url = "https://files.pythonhosted.org/packages/d0/ed/c92533b9124712d592cbf1cd6c76da933a2e0acea81dfe1fbe7e735f0cff/psycopg_binary-3.3.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:514404ed543efd620c85602b747df2a23cf1241b4067199e1a66f2d2757aaa41", size = 4997427, upload-time = "2026-05-01T23:31:20.901Z" }, + { url = "https://files.pythonhosted.org/packages/a2/23/ccadfd0de416aa188356daa199453af24087b042e296088706d190ae0295/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:46893c26858be12cc49ca4226ed6a60b4bfccadd946b3bebb783a60b38788228", size = 4533549, upload-time = "2026-05-01T23:31:26.204Z" }, + { url = "https://files.pythonhosted.org/packages/fd/a0/c8f43cee36386f7bc891ab41a9d31ea07cf9826038e732da79f26b1e5f34/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:df1d567fc430f6df15c9fcf67d87685fc49bdb325adc0db5af1adfb2f44eb5c9", size = 4210256, upload-time = "2026-05-01T23:31:33.884Z" }, + { url = "https://files.pythonhosted.org/packages/4e/2c/c1547871be3790676e8868b38655496422f94f0978dfb66b74bdba2f1676/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:6b9016b1714da4dd5ecaaa75b82098aa5a0b87854ce9b092e21c27c4ae23e014", size = 3946204, upload-time = "2026-05-01T23:31:39.626Z" }, + { url = "https://files.pythonhosted.org/packages/c4/b1/f6670f00fa7ea601584623f6c11602ab92117d83eaff885e0210f6de7418/psycopg_binary-3.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:47c656a8a7ba6eb0cff1801a4caaa9c8bdc12d03080e273aff1c8ac39971a77e", size = 4255811, upload-time = "2026-05-01T23:31:44.986Z" }, + { url = "https://files.pythonhosted.org/packages/eb/e6/5fff07a70d1f945ed90ae131c3bd76cab32beff7c58c6db15ad5820b6d1f/psycopg_binary-3.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:c37e024c07308cd06cf3ec51bfd0e7f6157585a4d84d1bce4a7f5f7913719bf8", size = 3666849, upload-time = "2026-05-01T23:31:51.165Z" }, ] [[package]] @@ -1185,7 +1260,7 @@ wheels = [ [[package]] name = "pydantic" -version = "2.12.5" +version = "2.13.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-types" }, @@ -1193,9 +1268,9 @@ dependencies = [ { name = "typing-extensions" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } +sdist = { url = "https://files.pythonhosted.org/packages/18/a5/b60d21ac674192f8ab0ba4e9fd860690f9b4a6e51ca5df118733b487d8d6/pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6", size = 844775, upload-time = "2026-05-06T13:43:05.343Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7b/122376b1fd3c62c1ed9dc80c931ace4844b3c55407b6fb2d199377c9736f/pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba", size = 472262, upload-time = "2026-05-06T13:43:02.641Z" }, ] [package.optional-dependencies] @@ -1205,41 +1280,43 @@ email = [ [[package]] name = "pydantic-core" -version = "2.41.5" +version = "2.46.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/56/921726b776ace8d8f5db44c4ef961006580d91dc52b803c489fafd1aa249/pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1", size = 471464, upload-time = "2026-05-06T13:37:06.98Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, + { url = "https://files.pythonhosted.org/packages/8d/74/228a26ddad29c6672b805d9fd78e8d251cd04004fa7eed0e622096cd0250/pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb", size = 2102079, upload-time = "2026-05-06T13:38:41.019Z" }, + { url = "https://files.pythonhosted.org/packages/ad/1f/8970b150a4b4365623ae00fc88603491f763c627311ae8031e3111356d6e/pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462", size = 1952179, upload-time = "2026-05-06T13:36:59.812Z" }, + { url = "https://files.pythonhosted.org/packages/95/30/5211a831ae054928054b2f79731661087a2bc5c01e825c672b3a4a8f1b3e/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9", size = 1978926, upload-time = "2026-05-06T13:37:39.933Z" }, + { url = "https://files.pythonhosted.org/packages/57/e9/689668733b1eb67adeef047db3c2e8788fcf65a7fd9c9e2b46b7744fe245/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4", size = 2046785, upload-time = "2026-05-06T13:38:01.995Z" }, + { url = "https://files.pythonhosted.org/packages/60/d9/6715260422ff50a2109878fd24d948a6c3446bb2664f34ee78cd972b3acd/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914", size = 2228733, upload-time = "2026-05-06T13:40:50.371Z" }, + { url = "https://files.pythonhosted.org/packages/18/ae/fdb2f64316afca925640f8e70bb1a564b0ec2721c1389e25b8eb4bf9a299/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28", size = 2307534, upload-time = "2026-05-06T13:37:21.531Z" }, + { url = "https://files.pythonhosted.org/packages/89/1d/8eff589b45bb8190a9d12c49cfad0f176a5cbd1534908a6b5125e2886239/pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b", size = 2099732, upload-time = "2026-05-06T13:39:31.942Z" }, + { url = "https://files.pythonhosted.org/packages/06/d5/ee5a3366637fee41dee51a1fc91562dcf12ddbc68fda34e6b253da2324bb/pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c", size = 2129627, upload-time = "2026-05-06T13:37:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/94/33/2414be571d2c6a6c4d08be21f9292b6d3fdb08949a97b6dfe985017821db/pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb", size = 2179141, upload-time = "2026-05-06T13:37:14.046Z" }, + { url = "https://files.pythonhosted.org/packages/7b/79/7daa95be995be0eecc4cf75064cb33f9bbbfe3fe0158caf2f0d4a996a5c7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898", size = 2184325, upload-time = "2026-05-06T13:36:53.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/d0a382f5c0de8a222dc61c65348e0ce831b1f68e0a018450d31c2cace3a5/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e", size = 2323990, upload-time = "2026-05-06T13:40:29.971Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/d9ba624cc4a5aced1598e88c04fdbd8310c8a69b9d38b9a3d39ce3a61ed7/pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519", size = 2369978, upload-time = "2026-05-06T13:37:23.027Z" }, + { url = "https://files.pythonhosted.org/packages/f2/20/d15df15ba918c423461905802bfd2981c3af0bfa0e40d05e13edbfa48bc3/pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4", size = 1966354, upload-time = "2026-05-06T13:38:03.499Z" }, + { url = "https://files.pythonhosted.org/packages/fc/b6/6b8de4c0a7d7ab3004c439c80c5c1e0a3e8d78bbae19379b01960383d9e5/pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac", size = 2072238, upload-time = "2026-05-06T13:39:40.807Z" }, + { url = "https://files.pythonhosted.org/packages/32/36/51eb763beec1f4cf59b1db243a7dcc39cbb41230f050a09b9d69faaf0a48/pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a", size = 2018251, upload-time = "2026-05-06T13:37:26.72Z" }, + { url = "https://files.pythonhosted.org/packages/e8/91/855af51d625b23aa987116a19e231d2aaef9c4a415273ddc189b79a45fee/pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0", size = 2099593, upload-time = "2026-05-06T13:39:47.682Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1b/8784a54c65edb5f49f0a14d6977cf1b209bba85a4c77445b255c2de58ab3/pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d", size = 1935226, upload-time = "2026-05-06T13:40:40.428Z" }, + { url = "https://files.pythonhosted.org/packages/e8/e7/1955d28d1afc56dd4b3ad7cc0cf39df1b9852964cf16e5d13912756d6d6b/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b", size = 1974605, upload-time = "2026-05-06T13:37:32.029Z" }, + { url = "https://files.pythonhosted.org/packages/93/e2/3fedbf0ba7a22850e6e9fd78117f1c0f10f950182344d8a6c535d468fdd8/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000", size = 2030777, upload-time = "2026-05-06T13:38:55.239Z" }, + { url = "https://files.pythonhosted.org/packages/f8/61/46be275fcaaba0b4f5b9669dd852267ce1ff616592dccf7a7845588df091/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e", size = 2236641, upload-time = "2026-05-06T13:37:08.096Z" }, + { url = "https://files.pythonhosted.org/packages/60/db/12e93e46a8bac9988be3c016860f83293daea8c716c029c9ace279036f2f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd", size = 2286404, upload-time = "2026-05-06T13:40:20.221Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4a/4d8b19008f38d31c53b8219cfedc2e3d5de5fe99d90076b7e767de29274f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3", size = 2109219, upload-time = "2026-05-06T13:38:12.153Z" }, + { url = "https://files.pythonhosted.org/packages/88/70/3cbc40978fefb7bb09c6708d40d4ad1a5d70fd7213c3d17f971de868ec1f/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7", size = 2110594, upload-time = "2026-05-06T13:40:02.971Z" }, + { url = "https://files.pythonhosted.org/packages/9d/20/b8d36736216e29491125531685b2f9e61aa5b4b2599893f8268551da3338/pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff", size = 2159542, upload-time = "2026-05-06T13:39:27.506Z" }, + { url = "https://files.pythonhosted.org/packages/1d/a2/367df868eb584dacf6bf82a389272406d7178e301c4ac82545ab98bc2dd9/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424", size = 2168146, upload-time = "2026-05-06T13:38:31.93Z" }, + { url = "https://files.pythonhosted.org/packages/c1/b8/4460f77f7e201893f649a29ab355dddd3beee8a97bcb1a320db414f9a06e/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6", size = 2306309, upload-time = "2026-05-06T13:37:44.717Z" }, + { url = "https://files.pythonhosted.org/packages/64/c4/be2639293acd87dc8ddbcec41a73cee9b2ebf996fe6d892a1a74e88ad3f7/pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565", size = 2369736, upload-time = "2026-05-06T13:37:05.645Z" }, + { url = "https://files.pythonhosted.org/packages/30/a6/9f9f380dbb301f67023bf8f707aaa75daadf84f7152d95c410fd7e81d994/pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02", size = 1955575, upload-time = "2026-05-06T13:38:51.116Z" }, + { url = "https://files.pythonhosted.org/packages/40/1f/f1eb9eb350e795d1af8586289746f5c5677d16043040d63710e22abc43c9/pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5", size = 2051624, upload-time = "2026-05-06T13:38:21.672Z" }, + { url = "https://files.pythonhosted.org/packages/f6/d2/42dd53d0a85c27606f316d3aa5d2869c4e8470a5ed6dec30e4a1abe19192/pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596", size = 2017325, upload-time = "2026-05-06T13:40:52.723Z" }, ] [[package]] @@ -1257,16 +1334,16 @@ wheels = [ [[package]] name = "pydantic-settings" -version = "2.13.1" +version = "2.15.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pydantic" }, { name = "python-dotenv" }, { name = "typing-inspection" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } +sdist = { url = "https://files.pythonhosted.org/packages/68/ca/31c57507b13119d7d3cfa1576dad2911a4861e3be07b579395f4e9d393f9/pydantic_settings-2.15.0.tar.gz", hash = "sha256:694b793e84f766ba76a90ebdefc01d0a9a045dab0382bee70393da93712ad117", size = 261253, upload-time = "2026-08-07T09:24:57.419Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, + { url = "https://files.pythonhosted.org/packages/30/a4/2bffa9f8e804325a09867f0e9d30795c80ea9f8d62560bd1b6ad6220eb2f/pydantic_settings-2.15.0-py3-none-any.whl", hash = "sha256:0ba092c291c94baceb5eff768aa0d56400a457585bc0175925a5a5510303da42", size = 69413, upload-time = "2026-08-07T09:24:55.839Z" }, ] [[package]] @@ -1280,29 +1357,29 @@ wheels = [ [[package]] name = "pyjwt" -version = "2.11.0" +version = "2.13.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/5a/b46fa56bf322901eee5b0454a34343cdbdae202cd421775a8ee4e42fd519/pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623", size = 98019, upload-time = "2026-01-30T19:59:55.694Z" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/81/58d0ac84e1ef3a3843791d6954d94c0b33d526c75eeb1efbce9d0a4c4077/pyjwt-2.13.0.tar.gz", hash = "sha256:41571c89ca91598c79e8ef18a2d07367d4810fbbd6f637794879baf1b7703423", size = 107515, upload-time = "2026-05-21T19:54:36.618Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/6f/01/c26ce75ba460d5cd503da9e13b21a33804d38c2165dec7b716d06b13010c/pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469", size = 28224, upload-time = "2026-01-30T19:59:54.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/5e/ecf12fdb62546d64385c158514e9b2b671f7832108ef2ecd2020ce0af2d1/pyjwt-2.13.0-py3-none-any.whl", hash = "sha256:66adcc2aff09b3f1bbd95fc1e1577df8ac8723c978552fd43304c8a290ac5728", size = 31274, upload-time = "2026-05-21T19:54:35.362Z" }, ] [[package]] name = "python-dotenv" -version = "1.2.1" +version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" }, + { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, ] [[package]] name = "python-multipart" -version = "0.0.22" +version = "0.0.32" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/01/979e98d542a70714b0cb2b6728ed0b7c46792b695e3eaec3e20711271ca3/python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58", size = 37612, upload-time = "2026-01-25T10:15:56.219Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5b/42/55c32bb9b12693c092ad250a0e82edb5b31ddeda6eb772de5f308b3804ad/python_multipart-0.0.32.tar.gz", hash = "sha256:be54b7f3fa167bb83e4fcd936b887b708f4e57fe75911c02aebf53efaf8d938e", size = 46881, upload-time = "2026-06-04T16:18:58.647Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1b/d0/397f9626e711ff749a95d96b7af99b9c566a9bb5129b8e4c10fc4d100304/python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155", size = 24579, upload-time = "2026-01-25T10:15:54.811Z" }, + { url = "https://files.pythonhosted.org/packages/e1/04/e8135ebd1ad02c56ec633277529b2602ff99ff634be76cdba5744cf554fd/python_multipart-0.0.32-py3-none-any.whl", hash = "sha256:ff6d3f776f16878c894e52e107296ffc890e913c611b1a4ec6c44e2821fe2e23", size = 30042, upload-time = "2026-06-04T16:18:57.319Z" }, ] [[package]] @@ -1388,21 +1465,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/45/affdf2d851b42adf3d13fc5b3b059372e9bd299371fd84cf5723c45871fa/regex-2026.2.19-cp314-cp314t-win_arm64.whl", hash = "sha256:a09ae430e94c049dc6957f6baa35ee3418a3a77f3c12b6e02883bd80a2b679b0", size = 274932, upload-time = "2026-02-19T19:03:45.488Z" }, ] -[[package]] -name = "requests" -version = "2.32.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, -] - [[package]] name = "rich" version = "14.3.3" @@ -1479,35 +1541,36 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.2" +version = "0.16.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/06/04/eab13a954e763b0606f460443fcbf6bb5a0faf06890ea3754ff16523dce5/ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342", size = 4558148, upload-time = "2026-02-19T22:32:20.271Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/e1/4508a569211b35599016e84ba65c1a992b7a4004b4b6c4bea02a851cba1b/ruff-0.16.2.tar.gz", hash = "sha256:c3d7828d12e8927a6fc65fe38e2c2541b9e762d360a1786d752cb1b8883b3c9c", size = 4885811, upload-time = "2026-08-07T13:31:01.432Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2f/70/3a4dc6d09b13cb3e695f28307e5d889b2e1a66b7af9c5e257e796695b0e6/ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d", size = 10430565, upload-time = "2026-02-19T22:32:41.824Z" }, - { url = "https://files.pythonhosted.org/packages/71/0b/bb8457b56185ece1305c666dc895832946d24055be90692381c31d57466d/ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e", size = 10820354, upload-time = "2026-02-19T22:32:07.366Z" }, - { url = "https://files.pythonhosted.org/packages/2d/c1/e0532d7f9c9e0b14c46f61b14afd563298b8b83f337b6789ddd987e46121/ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87", size = 10170767, upload-time = "2026-02-19T22:32:13.188Z" }, - { url = "https://files.pythonhosted.org/packages/47/e8/da1aa341d3af017a21c7a62fb5ec31d4e7ad0a93ab80e3a508316efbcb23/ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9", size = 10529591, upload-time = "2026-02-19T22:32:02.547Z" }, - { url = "https://files.pythonhosted.org/packages/93/74/184fbf38e9f3510231fbc5e437e808f0b48c42d1df9434b208821efcd8d6/ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80", size = 10260771, upload-time = "2026-02-19T22:32:36.938Z" }, - { url = "https://files.pythonhosted.org/packages/05/ac/605c20b8e059a0bc4b42360414baa4892ff278cec1c91fff4be0dceedefd/ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f", size = 11045791, upload-time = "2026-02-19T22:32:31.642Z" }, - { url = "https://files.pythonhosted.org/packages/fd/52/db6e419908f45a894924d410ac77d64bdd98ff86901d833364251bd08e22/ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77", size = 11879271, upload-time = "2026-02-19T22:32:29.305Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d8/7992b18f2008bdc9231d0f10b16df7dda964dbf639e2b8b4c1b4e91b83af/ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea", size = 11303707, upload-time = "2026-02-19T22:32:22.492Z" }, - { url = "https://files.pythonhosted.org/packages/d7/02/849b46184bcfdd4b64cde61752cc9a146c54759ed036edd11857e9b8443b/ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a", size = 11149151, upload-time = "2026-02-19T22:32:44.234Z" }, - { url = "https://files.pythonhosted.org/packages/70/04/f5284e388bab60d1d3b99614a5a9aeb03e0f333847e2429bebd2aaa1feec/ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956", size = 11091132, upload-time = "2026-02-19T22:32:24.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/ae/88d844a21110e14d92cf73d57363fab59b727ebeabe78009b9ccb23500af/ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4", size = 10504717, upload-time = "2026-02-19T22:32:26.75Z" }, - { url = "https://files.pythonhosted.org/packages/64/27/867076a6ada7f2b9c8292884ab44d08fd2ba71bd2b5364d4136f3cd537e1/ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de", size = 10263122, upload-time = "2026-02-19T22:32:10.036Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ef/faf9321d550f8ebf0c6373696e70d1758e20ccdc3951ad7af00c0956be7c/ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c", size = 10735295, upload-time = "2026-02-19T22:32:39.227Z" }, - { url = "https://files.pythonhosted.org/packages/2f/55/e8089fec62e050ba84d71b70e7834b97709ca9b7aba10c1a0b196e493f97/ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8", size = 11241641, upload-time = "2026-02-19T22:32:34.617Z" }, - { url = "https://files.pythonhosted.org/packages/23/01/1c30526460f4d23222d0fabd5888868262fd0e2b71a00570ca26483cd993/ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f", size = 10507885, upload-time = "2026-02-19T22:32:15.635Z" }, - { url = "https://files.pythonhosted.org/packages/5c/10/3d18e3bbdf8fc50bbb4ac3cc45970aa5a9753c5cb51bf9ed9a3cd8b79fa3/ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5", size = 11623725, upload-time = "2026-02-19T22:32:04.947Z" }, - { url = "https://files.pythonhosted.org/packages/6d/78/097c0798b1dab9f8affe73da9642bb4500e098cb27fd8dc9724816ac747b/ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e", size = 10941649, upload-time = "2026-02-19T22:32:18.108Z" }, + { url = "https://files.pythonhosted.org/packages/14/57/db19951540f98859c956b50bdb4d31089b4d91e9f15e2968e7d5193806d5/ruff-0.16.2-py3-none-linux_armv6l.whl", hash = "sha256:3c8de4cf2181f01d57946d87d777aa52916976fc09942aed89938fab5e013318", size = 10847925, upload-time = "2026-08-07T13:30:14.468Z" }, + { url = "https://files.pythonhosted.org/packages/13/5a/995fe85a8470d3e391ac0f7fa8054bb454eaf33ee138196d6172ed1079c0/ruff-0.16.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a48cc05c6fbc811ca81b5d7ba95375affea6582d1b8024e455e41afbbf55344", size = 11072662, upload-time = "2026-08-07T13:30:18.143Z" }, + { url = "https://files.pythonhosted.org/packages/32/53/370d767c61c71a971a4ace36703a7ecd8c393956349a7325d7fab2b56827/ruff-0.16.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a2c0d14fcbb26c91f0f867a6dc9bd71bbc30b1b6151829c884f23faeab2e5700", size = 10566771, upload-time = "2026-08-07T13:30:20.899Z" }, + { url = "https://files.pythonhosted.org/packages/85/d6/9d96948caf5a632be62d62202d5ec914d6856f204fd79eb036e5915e79ea/ruff-0.16.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:335c621622c4650330be50842561c6586ac6971bb8ab5407fe34dcc9efb16bbe", size = 10975825, upload-time = "2026-08-07T13:30:23.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/92/ea87129b3414acb0b5770563779c51804d37ac67675c7ba35447ddb14773/ruff-0.16.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e66910f2c37cc753f9ef6580c914a621b80c4fa3549d3e3521e29d0f5bfc3f", size = 10649437, upload-time = "2026-08-07T13:30:26.097Z" }, + { url = "https://files.pythonhosted.org/packages/ac/43/f8f291dcd4af5bb7872b74fdfa41a7cd7c856ca1d4069670971cf1b9f5cb/ruff-0.16.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e36fbfba65510548156902bcf1350a979a958ce0347ce0f90d73894036b39f", size = 11446761, upload-time = "2026-08-07T13:30:28.752Z" }, + { url = "https://files.pythonhosted.org/packages/71/4a/ef991fb2fcf516ab71f0808adcdd8da5e18c8cde447f4ceaf5f47a5132a5/ruff-0.16.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0eab35f80df8f134aae5d1630e751901321d317cc8e50dc39e36fa3ed34cd12", size = 12336364, upload-time = "2026-08-07T13:30:31.468Z" }, + { url = "https://files.pythonhosted.org/packages/f3/24/f615e74f307e6ca0e56a482872477b856c70d530aa356abfb6dfe5ca8a80/ruff-0.16.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ea8c0594feb894e89c8c61ab9c103d38b0ea72dfde6c594107147ca31b1140", size = 11630720, upload-time = "2026-08-07T13:30:34.426Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d3/8ef50149e8412a77f7ab409efdef0e2b23803707a3863da4fc64cb23d459/ruff-0.16.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab3d62dde0b19facdd632008cc4827fc28ada7736c6bd35ab6f1050f0bfed53f", size = 11466130, upload-time = "2026-08-07T13:30:36.958Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a7/a19334985c4dea8c381981fa252cd854c7ee52dc4b1686dc16f4a911c702/ruff-0.16.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e43e1f5b8388da9eca1b9e88328d47a5cec794633ccf6f7484ac2dd15eee92c0", size = 11523634, upload-time = "2026-08-07T13:30:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6c/96d192b0e742412ceda08c0a50f9669b253dde9fd6a60ea1a10c9fa79a63/ruff-0.16.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c24788a980581e1d7ea3a0cbe4344c4fbeb0a6a9b1f4713aa46bb104f8294690", size = 10949807, upload-time = "2026-08-07T13:30:42.745Z" }, + { url = "https://files.pythonhosted.org/packages/fa/51/e26599ceca11e79ee255c7df515995561edf87e9ca1893284e44d98f5a86/ruff-0.16.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:81806b08329130005dd4a8a8394a0c9da8c6f4cafb16ba438d2a2ee6a18bedf1", size = 10646891, upload-time = "2026-08-07T13:30:45.522Z" }, + { url = "https://files.pythonhosted.org/packages/68/01/800c4b1f97bc8d7c6029e06b1f20473a3cf1e13c4933d8f3342add83fc55/ruff-0.16.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4ce4e02bad779bef557f541a1b31f20d6abeae1cc05ed1b1ac019d4ffd1044c8", size = 11162063, upload-time = "2026-08-07T13:30:48.131Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d0/1477ea50fc5a0d4b0b71d1d63d50770bdd794d90b43e37a7618e63ec9894/ruff-0.16.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e0422abdf70070255fc4073ce9dfc814cc03db577013761ddd09bc1e4a9a4fbd", size = 11556038, upload-time = "2026-08-07T13:30:50.686Z" }, + { url = "https://files.pythonhosted.org/packages/b8/76/a7776f32048d991e16d4fa8ff91790b877342d3596cc3ed04acdbf1aaedc/ruff-0.16.2-py3-none-win32.whl", hash = "sha256:bf3a63d78fb39f4bf5ac8ae52051c5520505301abe19ba4e204c453b3f09bb0b", size = 10872850, upload-time = "2026-08-07T13:30:53.471Z" }, + { url = "https://files.pythonhosted.org/packages/00/0d/929c800d920e61397d82a01b60bffc68da3052c17d31de59efaad2e4ed75/ruff-0.16.2-py3-none-win_amd64.whl", hash = "sha256:bcabe2f6d0fc7819f1431793005af4e4de7371927d037345bf941252b195b9fa", size = 12023338, upload-time = "2026-08-07T13:30:56.193Z" }, + { url = "https://files.pythonhosted.org/packages/5b/6c/93e26c22c5f78ff87363e07da49c84955affbeb1098bd1936bf3b3f293bf/ruff-0.16.2-py3-none-win_arm64.whl", hash = "sha256:d614e95cedf38a2053fd351c55b103ba30d017d61688fdbfd40ee0412852a99f", size = 11374065, upload-time = "2026-08-07T13:30:58.775Z" }, ] [[package]] name = "safety" -version = "3.7.0" +version = "3.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "authlib" }, + { name = "certifi" }, { name = "click" }, { name = "dparse" }, { name = "filelock" }, @@ -1517,17 +1580,17 @@ dependencies = [ { name = "nltk" }, { name = "packaging" }, { name = "pydantic" }, - { name = "requests" }, { name = "ruamel-yaml" }, { name = "safety-schemas" }, { name = "tenacity" }, { name = "tomlkit" }, + { name = "truststore" }, { name = "typer" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/6f/e8/1cfffa0d8836de8aa31f4fa7fdeb892c7cfa97cd555039ad5df71ce0e968/safety-3.7.0.tar.gz", hash = "sha256:daec15a393cafc32b846b7ef93f9c952a1708863e242341ab5bde2e4beabb54e", size = 330538, upload-time = "2025-11-06T20:10:15.067Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c2/7b/8e1d580c5178f0736b806b7199827e61e2a2569eec5b49ec75da6273bbdf/safety-3.8.1.tar.gz", hash = "sha256:e646123b976bbb6707cfaacae8c926e2f886b744a60e0f410e8610a3a4eaf7be", size = 412947, upload-time = "2026-05-29T15:09:33.355Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/55/c4b2058ca346e58124ba082a3596e30dc1f5793710f8173156c7c2d77048/safety-3.7.0-py3-none-any.whl", hash = "sha256:65e71db45eb832e8840e3456333d44c23927423753d5610596a09e909a66d2bf", size = 312436, upload-time = "2025-11-06T20:10:13.576Z" }, + { url = "https://files.pythonhosted.org/packages/4b/f5/498db84333a644835e572c0d96cfa705bf9871f863289a7845082d54755e/safety-3.8.1-py3-none-any.whl", hash = "sha256:953c1c3c60c873f53a6cc250b2a9c4b38bb6ef45f0625990e43f20bff916c965", size = 340521, upload-time = "2026-05-29T15:09:31.622Z" }, ] [[package]] @@ -1570,26 +1633,29 @@ wheels = [ [[package]] name = "sqlalchemy" -version = "2.0.46" +version = "2.0.51" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" } +sdist = { url = "https://files.pythonhosted.org/packages/02/f1/a7a892f18d4d224e6b26f706531eafccc41e37594d37d304786969ee13cb/sqlalchemy-2.0.51.tar.gz", hash = "sha256:804dccd8a4a6242c4e30ad961e540e18a588f6527202f2d6791b01845d59fdc9", size = 9912201, upload-time = "2026-06-15T15:41:20.012Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" }, - { url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" }, - { url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" }, - { url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" }, - { url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" }, - { url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" }, - { url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" }, - { url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" }, - { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" }, - { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" }, - { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" }, - { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" }, + { url = "https://files.pythonhosted.org/packages/b1/49/a739be2e1d02a96a658eb71ab45d921c874249252358ad24a5bffdd02525/sqlalchemy-2.0.51-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:6ea306caaae6bd5afd0a46050003c88f6bf33227377a49298c498c3cb88ff491", size = 2158999, upload-time = "2026-06-15T16:08:51.759Z" }, + { url = "https://files.pythonhosted.org/packages/23/6b/2e0e38cf75c8780eca78d9b2e78164f8bcfd70125e5caa588ff5cbb9c9f4/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c45a496d6bc05dec41dcd4c3a2b183723f47473255c159cd80b503c8f246424d", size = 3282539, upload-time = "2026-06-15T16:19:51.065Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a1/e77854cb5336fd37dc3c6ae3b71de242c98caac5725120be0b526b31cbd0/sqlalchemy-2.0.51-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4004ada0aafe8ae1991b2cd1d99c6d9146126e123bd6f883c260d974aa012e54", size = 3287545, upload-time = "2026-06-15T16:26:44.735Z" }, + { url = "https://files.pythonhosted.org/packages/f6/ab/9e17272fd4dac8df3b83c4fbe52b998a1c9d89a843c8c35ff29b74ff7364/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0f6bcad487aee1c638d707235682fc96f741de00663619881ab235400d03289e", size = 3230929, upload-time = "2026-06-15T16:19:52.625Z" }, + { url = "https://files.pythonhosted.org/packages/02/3c/52f408ea701781caee975606beccc48845f2aee8711ac29843d612c0306c/sqlalchemy-2.0.51-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:39a76529db6305693d8d4affa58ad5b5e2e18edd62daea628b29b97930b3513d", size = 3252888, upload-time = "2026-06-15T16:26:46.454Z" }, + { url = "https://files.pythonhosted.org/packages/24/16/3efd2ee6bc4ca4693a30a1dd17a91b606cae15d517d2a4746611d9b73ce8/sqlalchemy-2.0.51-cp314-cp314-win32.whl", hash = "sha256:08a204d8b5638717c26a24df18fcf40af45a6b22e35b70b1d62f0113c2e278e8", size = 2120551, upload-time = "2026-06-15T16:23:15.629Z" }, + { url = "https://files.pythonhosted.org/packages/7b/78/55b12e70f45bccc40d9e483925c065027b3b98ea4cbbdf6f8c2546feaf6c/sqlalchemy-2.0.51-cp314-cp314-win_amd64.whl", hash = "sha256:96747bfbadb055466e5b46d572618170046b45ce5a4879167f50d70a5319a499", size = 2146318, upload-time = "2026-06-15T16:23:17.108Z" }, + { url = "https://files.pythonhosted.org/packages/21/db/a9574ed40fed418924b1b1a3e54f47ee3963053b3d3d325a0d36b41f2c08/sqlalchemy-2.0.51-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5ea1a213be1fcd5e49d9904c3b9939211ded90bc2a64e93f4c01963474285de", size = 2178920, upload-time = "2026-06-15T15:59:56.285Z" }, + { url = "https://files.pythonhosted.org/packages/bf/90/a1bb5c7cbba76b7bc1fbd586d0a5479a7bc9c27b4a8298f22ec9423b2bb3/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c6b36ed71f41942bdcd2ad2522be46bfce09d5705be5640ecf19bbc7660e4b7", size = 3566534, upload-time = "2026-06-15T15:58:35.024Z" }, + { url = "https://files.pythonhosted.org/packages/15/4b/481f1fed30e0e9e8dd24aecbb49f29eb57fe7657ece5cf06ee9b84bb97d8/sqlalchemy-2.0.51-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0c2c62877097e1a0db401fba5cb4debee33265e5b2a55c4ccb489c02c53b4f72", size = 3535844, upload-time = "2026-06-15T16:02:43.973Z" }, + { url = "https://files.pythonhosted.org/packages/02/71/0aa64aeda645510af0a43f7d9ee70932f0d1dc4263aed34c50ee891d9df3/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0378d055e9e8cd6ce4d8dff683bdd3d7d413533c4ee51d67a2b1e0f9eacc0f23", size = 3475355, upload-time = "2026-06-15T15:58:36.592Z" }, + { url = "https://files.pythonhosted.org/packages/05/db/6061db32316446135a3abae5f308d144ab988a34234726042da3e58b1c63/sqlalchemy-2.0.51-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6e46fc36029eff666391e0531e5387b62ce6c4f1d8e50b3fb3099eaca1b42522", size = 3486591, upload-time = "2026-06-15T16:02:45.346Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c9/f14fdf71bb8957e0c7e39db69bbdf12b5c80f4ef775fdfa127bf4e0d6760/sqlalchemy-2.0.51-cp314-cp314t-win32.whl", hash = "sha256:9161cfc9efce70d1715f47d6ff40f79c6778c00d53be4fbc09d70301e4b83ba7", size = 2151313, upload-time = "2026-06-15T16:03:39.127Z" }, + { url = "https://files.pythonhosted.org/packages/6a/c6/673e618e6f4f297e126d9b56ea2f6478708f6c1af4e3223835c22e2c3697/sqlalchemy-2.0.51-cp314-cp314t-win_amd64.whl", hash = "sha256:159bb6ba32059f57ad7375a8f50d844dd2f19d14954ecf820cd33e20debd46b2", size = 2186280, upload-time = "2026-06-15T16:03:40.569Z" }, + { url = "https://files.pythonhosted.org/packages/e2/22/dbf013a12ec759e54a34a119e9e217435b3f71b2dd5c61a7ade0a25dae87/sqlalchemy-2.0.51-py3-none-any.whl", hash = "sha256:bb024d8b621d0be75f4f44ecc7c950450026e76d66dc8f791bb5331d7fed59d5", size = 1944334, upload-time = "2026-06-15T16:09:22.418Z" }, ] [[package]] @@ -1643,6 +1709,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] +[[package]] +name = "truststore" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" }, +] + [[package]] name = "typer" version = "0.24.0" @@ -1688,36 +1763,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] -[[package]] -name = "ujson" -version = "5.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/d9/3f17e3c5773fb4941c68d9a37a47b1a79c9649d6c56aefbed87cc409d18a/ujson-5.11.0.tar.gz", hash = "sha256:e204ae6f909f099ba6b6b942131cee359ddda2b6e4ea39c12eb8b991fe2010e0", size = 7156583, upload-time = "2025-08-20T11:57:02.452Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/28/08/4518146f4984d112764b1dfa6fb7bad691c44a401adadaa5e23ccd930053/ujson-5.11.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65724738c73645db88f70ba1f2e6fb678f913281804d5da2fd02c8c5839af302", size = 55462, upload-time = "2025-08-20T11:56:04.873Z" }, - { url = "https://files.pythonhosted.org/packages/29/37/2107b9a62168867a692654d8766b81bd2fd1e1ba13e2ec90555861e02b0c/ujson-5.11.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29113c003ca33ab71b1b480bde952fbab2a0b6b03a4ee4c3d71687cdcbd1a29d", size = 53246, upload-time = "2025-08-20T11:56:06.054Z" }, - { url = "https://files.pythonhosted.org/packages/9b/f8/25583c70f83788edbe3ca62ce6c1b79eff465d78dec5eb2b2b56b3e98b33/ujson-5.11.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c44c703842024d796b4c78542a6fcd5c3cb948b9fc2a73ee65b9c86a22ee3638", size = 57631, upload-time = "2025-08-20T11:56:07.374Z" }, - { url = "https://files.pythonhosted.org/packages/ed/ca/19b3a632933a09d696f10dc1b0dfa1d692e65ad507d12340116ce4f67967/ujson-5.11.0-cp314-cp314-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:e750c436fb90edf85585f5c62a35b35082502383840962c6983403d1bd96a02c", size = 59877, upload-time = "2025-08-20T11:56:08.534Z" }, - { url = "https://files.pythonhosted.org/packages/55/7a/4572af5324ad4b2bfdd2321e898a527050290147b4ea337a79a0e4e87ec7/ujson-5.11.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f278b31a7c52eb0947b2db55a5133fbc46b6f0ef49972cd1a80843b72e135aba", size = 57363, upload-time = "2025-08-20T11:56:09.758Z" }, - { url = "https://files.pythonhosted.org/packages/7b/71/a2b8c19cf4e1efe53cf439cdf7198ac60ae15471d2f1040b490c1f0f831f/ujson-5.11.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ab2cb8351d976e788669c8281465d44d4e94413718af497b4e7342d7b2f78018", size = 1036394, upload-time = "2025-08-20T11:56:11.168Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3e/7b98668cba3bb3735929c31b999b374ebc02c19dfa98dfebaeeb5c8597ca/ujson-5.11.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:090b4d11b380ae25453100b722d0609d5051ffe98f80ec52853ccf8249dfd840", size = 1195837, upload-time = "2025-08-20T11:56:12.6Z" }, - { url = "https://files.pythonhosted.org/packages/a1/ea/8870f208c20b43571a5c409ebb2fe9b9dba5f494e9e60f9314ac01ea8f78/ujson-5.11.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:80017e870d882d5517d28995b62e4e518a894f932f1e242cbc802a2fd64d365c", size = 1088837, upload-time = "2025-08-20T11:56:14.15Z" }, - { url = "https://files.pythonhosted.org/packages/63/b6/c0e6607e37fa47929920a685a968c6b990a802dec65e9c5181e97845985d/ujson-5.11.0-cp314-cp314-win32.whl", hash = "sha256:1d663b96eb34c93392e9caae19c099ec4133ba21654b081956613327f0e973ac", size = 41022, upload-time = "2025-08-20T11:56:15.509Z" }, - { url = "https://files.pythonhosted.org/packages/4e/56/f4fe86b4c9000affd63e9219e59b222dc48b01c534533093e798bf617a7e/ujson-5.11.0-cp314-cp314-win_amd64.whl", hash = "sha256:849e65b696f0d242833f1df4182096cedc50d414215d1371fca85c541fbff629", size = 45111, upload-time = "2025-08-20T11:56:16.597Z" }, - { url = "https://files.pythonhosted.org/packages/0a/f3/669437f0280308db4783b12a6d88c00730b394327d8334cc7a32ef218e64/ujson-5.11.0-cp314-cp314-win_arm64.whl", hash = "sha256:e73df8648c9470af2b6a6bf5250d4744ad2cf3d774dcf8c6e31f018bdd04d764", size = 39682, upload-time = "2025-08-20T11:56:17.763Z" }, - { url = "https://files.pythonhosted.org/packages/6e/cd/e9809b064a89fe5c4184649adeb13c1b98652db3f8518980b04227358574/ujson-5.11.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:de6e88f62796372fba1de973c11138f197d3e0e1d80bcb2b8aae1e826096d433", size = 55759, upload-time = "2025-08-20T11:56:18.882Z" }, - { url = "https://files.pythonhosted.org/packages/1b/be/ae26a6321179ebbb3a2e2685b9007c71bcda41ad7a77bbbe164005e956fc/ujson-5.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:49e56ef8066f11b80d620985ae36869a3ff7e4b74c3b6129182ec5d1df0255f3", size = 53634, upload-time = "2025-08-20T11:56:20.012Z" }, - { url = "https://files.pythonhosted.org/packages/ae/e9/fb4a220ee6939db099f4cfeeae796ecb91e7584ad4d445d4ca7f994a9135/ujson-5.11.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1a325fd2c3a056cf6c8e023f74a0c478dd282a93141356ae7f16d5309f5ff823", size = 58547, upload-time = "2025-08-20T11:56:21.175Z" }, - { url = "https://files.pythonhosted.org/packages/bd/f8/fc4b952b8f5fea09ea3397a0bd0ad019e474b204cabcb947cead5d4d1ffc/ujson-5.11.0-cp314-cp314t-manylinux_2_24_i686.manylinux_2_28_i686.whl", hash = "sha256:a0af6574fc1d9d53f4ff371f58c96673e6d988ed2b5bf666a6143c782fa007e9", size = 60489, upload-time = "2025-08-20T11:56:22.342Z" }, - { url = "https://files.pythonhosted.org/packages/2e/e5/af5491dfda4f8b77e24cf3da68ee0d1552f99a13e5c622f4cef1380925c3/ujson-5.11.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10f29e71ecf4ecd93a6610bd8efa8e7b6467454a363c3d6416db65de883eb076", size = 58035, upload-time = "2025-08-20T11:56:23.92Z" }, - { url = "https://files.pythonhosted.org/packages/c4/09/0945349dd41f25cc8c38d78ace49f14c5052c5bbb7257d2f466fa7bdb533/ujson-5.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1a0a9b76a89827a592656fe12e000cf4f12da9692f51a841a4a07aa4c7ecc41c", size = 1037212, upload-time = "2025-08-20T11:56:25.274Z" }, - { url = "https://files.pythonhosted.org/packages/49/44/8e04496acb3d5a1cbee3a54828d9652f67a37523efa3d3b18a347339680a/ujson-5.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:b16930f6a0753cdc7d637b33b4e8f10d5e351e1fb83872ba6375f1e87be39746", size = 1196500, upload-time = "2025-08-20T11:56:27.517Z" }, - { url = "https://files.pythonhosted.org/packages/64/ae/4bc825860d679a0f208a19af2f39206dfd804ace2403330fdc3170334a2f/ujson-5.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:04c41afc195fd477a59db3a84d5b83a871bd648ef371cf8c6f43072d89144eef", size = 1089487, upload-time = "2025-08-20T11:56:29.07Z" }, - { url = "https://files.pythonhosted.org/packages/30/ed/5a057199fb0a5deabe0957073a1c1c1c02a3e99476cd03daee98ea21fa57/ujson-5.11.0-cp314-cp314t-win32.whl", hash = "sha256:aa6d7a5e09217ff93234e050e3e380da62b084e26b9f2e277d2606406a2fc2e5", size = 41859, upload-time = "2025-08-20T11:56:30.495Z" }, - { url = "https://files.pythonhosted.org/packages/aa/03/b19c6176bdf1dc13ed84b886e99677a52764861b6cc023d5e7b6ebda249d/ujson-5.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:48055e1061c1bb1f79e75b4ac39e821f3f35a9b82de17fce92c3140149009bec", size = 46183, upload-time = "2025-08-20T11:56:31.574Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ca/a0413a3874b2dc1708b8796ca895bf363292f9c70b2e8ca482b7dbc0259d/ujson-5.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1194b943e951092db611011cb8dbdb6cf94a3b816ed07906e14d3bc6ce0e90ab", size = 40264, upload-time = "2025-08-20T11:56:32.773Z" }, -] - [[package]] name = "urllib3" version = "2.6.3" @@ -1729,20 +1774,19 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.41.0" +version = "0.52.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/32/ce/eeb58ae4ac36fe09e3842eb02e0eb676bf2c53ae062b98f1b2531673efdd/uvicorn-0.41.0.tar.gz", hash = "sha256:09d11cf7008da33113824ee5a1c6422d89fbc2ff476540d69a34c87fab8b571a", size = 82633, upload-time = "2026-02-16T23:07:24.1Z" } +sdist = { url = "https://files.pythonhosted.org/packages/03/18/ccce41535dee1be77735592bd19965f3972c82e07ee703d324709496b716/uvicorn-0.52.1.tar.gz", hash = "sha256:112ec661814189acbccd3f7b86460147cc065fc92c0821afa78918780e4354dd", size = 100571, upload-time = "2026-08-01T18:19:30.732Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/83/e4/d04a086285c20886c0daad0e026f250869201013d18f81d9ff5eada73a88/uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187", size = 68783, upload-time = "2026-02-16T23:07:22.357Z" }, + { url = "https://files.pythonhosted.org/packages/c7/d5/68e6e9bca63c0badf67002890a46d3784c958de45b65e1275ec583ca1f06/uvicorn-0.52.1-py3-none-any.whl", hash = "sha256:e4403f9d93188cf9d1088e9f40e3acd12630e2df8675316704379a7fc20fff6a", size = 79859, upload-time = "2026-08-01T18:19:29.294Z" }, ] [package.optional-dependencies] standard = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "httptools" }, { name = "python-dotenv" }, { name = "pyyaml" }, diff --git a/bookie/package.json b/bookie/package.json index 9ea4523..2c1ede2 100644 --- a/bookie/package.json +++ b/bookie/package.json @@ -11,36 +11,36 @@ }, "private": true, "dependencies": { - "@angular/cdk": "^21.1.1", - "@angular/common": "^21.1.1", - "@angular/compiler": "^21.1.1", - "@angular/core": "^21.1.1", - "@angular/forms": "^21.1.1", - "@angular/material": "^21.1.1", - "@angular/material-moment-adapter": "^21.1.1", - "@angular/platform-browser": "^21.1.1", - "@angular/platform-browser-dynamic": "^21.1.1", - "@angular/router": "^21.1.1", + "@angular/cdk": "^22.1.1", + "@angular/common": "^22.1.1", + "@angular/compiler": "^22.1.1", + "@angular/core": "^22.1.1", + "@angular/forms": "^22.1.1", + "@angular/material": "^22.1.1", + "@angular/material-moment-adapter": "^22.1.1", + "@angular/platform-browser": "^22.1.1", + "@angular/router": "^22.1.1", "mathjs": "^15.1.0", "moment": "^2.30.1", "rxjs": "~7.8.0", "tslib": "^2.6.0" }, "devDependencies": { - "@angular/build": "^21.1.1", - "@angular/cli": "^21.1.1", - "@angular/compiler-cli": "^21.1.1", - "angular-eslint": "^21.1.0", - "eslint": "^9.28.0", + "@angular/build": "^22.1.3", + "@angular/cli": "^22.1.3", + "@angular/compiler-cli": "^22.1.1", + "@eslint/js": "^10.0.1", + "angular-eslint": "^22.1.0", + "eslint": "^10.8.1", "eslint-config-prettier": "^10.1.5", "eslint-plugin-import": "^2.31.0", "eslint-plugin-perfectionist": "^5.4.0", "eslint-plugin-unused-imports": "^4.1.4", "husky": "^9.1.7", - "lint-staged": "^16.1.2", + "lint-staged": "^17.3.0", "prettier": "^3.4.2", "standard-version": "^9.5.0", - "typescript": "~5.9.3", + "typescript": "~6.0.3", "typescript-eslint": "^8.33.1", "vitest": "^4.0.8" }, diff --git a/bookie/src/app/app.config.ts b/bookie/src/app/app.config.ts index c915ca4..7f83b19 100644 --- a/bookie/src/app/app.config.ts +++ b/bookie/src/app/app.config.ts @@ -18,7 +18,7 @@ import { MatSortModule } from '@angular/material/sort'; import { MatTableModule } from '@angular/material/table'; import { MatToolbarModule } from '@angular/material/toolbar'; import { BrowserModule } from '@angular/platform-browser'; -import { provideRouter, withRouterConfig } from '@angular/router'; +import { provideRouter, withComponentInputBinding, withRouterConfig } from '@angular/router'; import { dateFormat } from './app.environment'; import { routes } from './app.routes'; @@ -55,6 +55,7 @@ export const appConfig: ApplicationConfig = { withRouterConfig({ onSameUrlNavigation: 'reload', }), + withComponentInputBinding(), ), { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] }, { provide: MAT_DATE_FORMATS, useValue: dateFormat }, diff --git a/bookie/src/app/app.environment.ts b/bookie/src/app/app.environment.ts index 83d6876..96913ab 100644 --- a/bookie/src/app/app.environment.ts +++ b/bookie/src/app/app.environment.ts @@ -7,9 +7,12 @@ export const environment = { export const dateFormat = { parse: { dateInput: 'DD-MMM-YYYY', + timeInput: 'hh:mm A', }, display: { dateInput: 'DD-MMM-YYYY', + timeInput: 'hh:mm A', + timeOptionLabel: 'hh:mm A', monthYearLabel: 'MMM YYYY', dateA11yLabel: 'DD-MMM-YYYY', monthYearA11yLabel: 'MMM YYYY', diff --git a/bookie/src/app/auth/login/login.component.html b/bookie/src/app/auth/login/login.component.html index 1683602..57d3aa7 100644 --- a/bookie/src/app/auth/login/login.component.html +++ b/bookie/src/app/auth/login/login.component.html @@ -1,23 +1,23 @@

Login

-
+
Username - +
Password - + {{ hide ? 'visibility' : 'visibility_off' }}
- @if (unregisteredDevice) { + @if (unregisteredDevice()) { -

Sorry, device {{ deviceName }} is not enabled.

+

Sorry, device {{ deviceName() }} is not enabled.

}
- +
diff --git a/bookie/src/app/auth/login/login.component.ts b/bookie/src/app/auth/login/login.component.ts index 16d85a5..31c9f66 100644 --- a/bookie/src/app/auth/login/login.component.ts +++ b/bookie/src/app/auth/login/login.component.ts @@ -1,5 +1,14 @@ -import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ElementRef, + OnInit, + ViewChild, + inject, + signal, +} from '@angular/core'; +import { form, FormField, required } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDividerModule } from '@angular/material/divider'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -11,13 +20,19 @@ import { ActivatedRoute, Router } from '@angular/router'; import { CookieService } from '../../shared/cookie.service'; import { AuthService } from '../auth.service'; +export interface LoginFormData { + username: string; + password: string; +} + @Component({ selector: 'app-login', templateUrl: './login.component.html', styleUrls: ['./login.component.css'], - imports: [MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatInputModule, FormField], }) export class LoginComponent implements OnInit, AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private auth = inject(AuthService); private router = inject(Router); @@ -25,28 +40,26 @@ export class LoginComponent implements OnInit, AfterViewInit { private cs = inject(CookieService); private cd = inject(ChangeDetectorRef); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - username: FormControl; - password: FormControl; - }>; + formModel = signal({ + username: '', + password: '', + }); + + form = form(this.formModel, (schemaPath) => { + required(schemaPath.username); + required(schemaPath.password); + }); hide: boolean; - unregisteredDevice: boolean; - deviceName: string; + unregisteredDevice = signal(undefined); + deviceName = signal(undefined); private returnUrl: string; constructor() { this.hide = true; - this.unregisteredDevice = false; - this.deviceName = ''; + this.unregisteredDevice.set(false); + this.deviceName.set(''); this.returnUrl = ''; - - // Create form - this.form = new FormGroup({ - username: new FormControl('', { validators: Validators.required, nonNullable: true }), - password: new FormControl('', { validators: Validators.required, nonNullable: true }), - }); } ngOnInit() { @@ -62,7 +75,7 @@ export class LoginComponent implements OnInit, AfterViewInit { } login(): void { - const formModel = this.form.value; + const formModel = this.formModel(); const username = formModel.username ?? ''; const password = formModel.password ?? ''; this.auth.login(username.trim(), password.trim()).subscribe({ @@ -71,8 +84,8 @@ export class LoginComponent implements OnInit, AfterViewInit { }, error: (error) => { if (error.status === 401 && error.error.detail === 'Device is not registered') { - this.unregisteredDevice = true; - this.deviceName = this.cs.getCookie('device'); + this.unregisteredDevice.set(true); + this.deviceName.set(this.cs.getCookie('device')); this.cd.detectChanges(); } this.snackBar.open(error.error.detail, 'Error'); diff --git a/bookie/src/app/beer-sale-report/beer-sale-report-datasource.ts b/bookie/src/app/beer-sale-report/beer-sale-report-datasource.ts deleted file mode 100644 index 9da8b48..0000000 --- a/bookie/src/app/beer-sale-report/beer-sale-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { BeerSaleReportItem } from './beer-sale-report-item'; - -export class BeerSaleReportDataSource extends DataSource { - constructor(public data: BeerSaleReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.component.html b/bookie/src/app/beer-sale-report/beer-sale-report.component.html index 7254bee..afeb842 100644 --- a/bookie/src/app/beer-sale-report/beer-sale-report.component.html +++ b/bookie/src/app/beer-sale-report/beer-sale-report.component.html @@ -1,70 +1,86 @@

Beer Sale Report -

-
-
- - Start Date - - - - - - Finish Date - - - - - - Sale Category - - @for (sc of saleCategories; track sc) { - - {{ sc.name }} - +@if (!infoResource.value() || !saleCategoriesResource.value()) { +

Loading...

+} @else { + +
+ + Start Date + + + + + + Finish Date + + + + + + Sale Category + + @for (sc of saleCategories(); track sc) { + + {{ sc.name }} + + } + + @for (error of form.saleCategory().errors(); track error) { + {{ error.message }} } - - - -
-
- Regular - Happy Hour - Staff Consumption - No Charge -
- - - - - Time - {{ row.date }} - - - - @for (col of info.headers; track col) { - - {{ col }} - {{ row[col] | number: '1.2-2' }} +
+ +
+
+ Regular + Happy Hour + Staff Consumption + No Charge +
+ + + + + Time + {{ row.date }} - } - - - + + @for (col of info()?.headers ?? []; track col) { + + {{ col }} + {{ row[col] | number: '1.2-2' }} + + } + + + + +} diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.component.ts b/bookie/src/app/beer-sale-report/beer-sale-report.component.ts index 2681be9..52b784d 100644 --- a/bookie/src/app/beer-sale-report/beer-sale-report.component.ts +++ b/bookie/src/app/beer-sale-report/beer-sale-report.component.ts @@ -1,6 +1,6 @@ import { CommonModule } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField, required } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -13,10 +13,21 @@ import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; import { SaleCategory } from '../core/sale-category'; +import { SaleCategoryService } from '../sale-category/sale-category.service'; import { ToCsvService } from '../shared/to-csv.service'; import { BeerSaleExportHeaderInterface } from './beer-sale-export-header-interface'; import { BeerSaleReport } from './beer-sale-report'; -import { BeerSaleReportDataSource } from './beer-sale-report-datasource'; +import { BeerSaleReportService } from './beer-sale-report.service'; + +export interface BeerSaleReportFormData { + startDate: Date; + finishDate: Date; + saleCategory: string; + regular: boolean; + happy: boolean; + staff: boolean; + nc: boolean; +} @Component({ selector: 'app-beer-sale-report', @@ -32,61 +43,72 @@ import { BeerSaleReportDataSource } from './beer-sale-report-datasource'; MatInputModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class BeerSaleReportComponent implements OnInit { - private route = inject(ActivatedRoute); +export class BeerSaleReportComponent { private router = inject(Router); + private route = inject(ActivatedRoute); private toCsv = inject(ToCsvService); + private ser = inject(BeerSaleReportService); + private saleCategoryService = inject(SaleCategoryService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + saleCategory = input(null, { transform: (v: string | null | undefined) => v ?? null }); + regular = input(true, { transform: (v: string | null | undefined) => v !== 'false' }); + happy = input(true, { transform: (v: string | null | undefined) => v !== 'false' }); + staff = input(true, { transform: (v: string | null | undefined) => v !== 'false' }); + nc = input(true, { transform: (v: string | null | undefined) => v !== 'false' }); - saleCategories: SaleCategory[] = []; - info: BeerSaleReport = new BeerSaleReport(); - dataSource: BeerSaleReportDataSource = new BeerSaleReportDataSource(this.info.data); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - saleCategory: FormControl; - regular: FormControl; - happy: FormControl; - staff: FormControl; - nc: FormControl; - }>; + saleCategoriesResource = this.saleCategoryService.list(); + infoResource = this.ser.get( + this.startDate, + this.finishDate, + this.saleCategory, + this.regular, + this.happy, + this.staff, + this.nc, + ); + + saleCategories = computed(() => this.saleCategoriesResource.value() ?? []); + info = computed(() => this.infoResource.value()); + dataSource = computed(() => this.info()?.data ?? []); + formModel = linkedSignal({ + source: () => this.info(), + computation: (info): BeerSaleReportFormData => { + if (info) { + return { + startDate: moment(info.startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(info.finishDate, 'DD-MMM-YYYY').toDate(), + saleCategory: info.saleCategory?.id ?? '', + regular: info.regular, + happy: info.happy, + staff: info.staff, + nc: info.nc, + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + saleCategory: '', + regular: true, + happy: true, + staff: true, + nc: true, + }; + }, + }); + + form = form(this.formModel, (schemaPath) => { + required(schemaPath.saleCategory, { message: 'Sale Category is required' }); + }); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ - displayedColumns: string[] = ['date']; - - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - saleCategory: new FormControl('', { nonNullable: true }), - regular: new FormControl(true, { nonNullable: true }), - happy: new FormControl(true, { nonNullable: true }), - staff: new FormControl(true, { nonNullable: true }), - nc: new FormControl(true, { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: BeerSaleReport; saleCategories: SaleCategory[] }; - this.info = data.info; - this.saleCategories = data.saleCategories; - this.displayedColumns = ['date'].concat(this.info.headers); - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - saleCategory: this.info.saleCategory?.id ?? '', - regular: this.info.regular, - happy: this.info.happy, - staff: this.info.staff, - nc: this.info.nc, - }); - this.dataSource = new BeerSaleReportDataSource(this.info.data); - }); - } + displayedColumns = computed(() => { + const headers = this.info()?.headers ?? []; + return ['date'].concat(headers); + }); show() { const info = this.getInfo(); @@ -104,17 +126,21 @@ export class BeerSaleReportComponent implements OnInit { } filterOn(id: string) { - const sc = this.saleCategories.find((x) => x.id === id); - this.info.saleCategory = sc ? sc : new SaleCategory({ id }); + const sc = this.saleCategories().find((x: SaleCategory) => x.id === id); + const currentInfo = this.info(); + if (currentInfo) { + currentInfo.saleCategory = sc ? sc : new SaleCategory({ id }); + } } getInfo(): BeerSaleReport { - const formModel = this.form.value; + const formModel = this.formModel(); + const currentInfo = this.info(); return new BeerSaleReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), - saleCategory: this.info.saleCategory, + saleCategory: currentInfo?.saleCategory, regular: formModel.regular, happy: formModel.happy, staff: formModel.staff, @@ -123,12 +149,18 @@ export class BeerSaleReportComponent implements OnInit { } exportCsv() { + const currentInfo = this.info(); + if (!currentInfo) return; + const init: BeerSaleExportHeaderInterface = { Date: 'date' }; - const headers = this.info.headers.reduce((a, c) => { - a[c] = c; - return a; - }, init); - const csvData = new Blob([this.toCsv.toCsv(headers, this.info.data)], { + const headers = currentInfo.headers.reduce( + (a: Record, c: string) => { + a[c] = c; + return a; + }, + init as Record, + ); + const csvData = new Blob([this.toCsv.toCsv(headers, currentInfo.data)], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.resolver.spec.ts b/bookie/src/app/beer-sale-report/beer-sale-report.resolver.spec.ts deleted file mode 100644 index 0440cf5..0000000 --- a/bookie/src/app/beer-sale-report/beer-sale-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { BeerSaleReportResolver } from './beer-sale-report-resolver.service'; - -describe('BeerSaleReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [BeerSaleReportResolver], - }); - }); - - it('should be created', inject([BeerSaleReportResolver], (service: BeerSaleReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.resolver.ts b/bookie/src/app/beer-sale-report/beer-sale-report.resolver.ts deleted file mode 100644 index 9efaf54..0000000 --- a/bookie/src/app/beer-sale-report/beer-sale-report.resolver.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { BeerSaleReport } from './beer-sale-report'; -import { BeerSaleReportService } from './beer-sale-report.service'; - -export const beerSaleReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - const saleCategory = route.queryParamMap.get('saleCategory') ?? null; - const regular = route.queryParamMap.get('regular') !== 'false'; - const happy = route.queryParamMap.get('happy') !== 'false'; - const staff = route.queryParamMap.get('staff') !== 'false'; - const nc = route.queryParamMap.get('nc') !== 'false'; - return inject(BeerSaleReportService).get(startDate, finishDate, saleCategory, regular, happy, staff, nc); -}; diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.routes.ts b/bookie/src/app/beer-sale-report/beer-sale-report.routes.ts index 885b001..91b9a87 100644 --- a/bookie/src/app/beer-sale-report/beer-sale-report.routes.ts +++ b/bookie/src/app/beer-sale-report/beer-sale-report.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { saleCategoryListResolver } from '../sale-category/sale-category-list.resolver'; import { BeerSaleReportComponent } from './beer-sale-report.component'; -import { beerSaleReportResolver } from './beer-sale-report.resolver'; export const routes: Routes = [ { @@ -13,10 +11,6 @@ export const routes: Routes = [ data: { permission: 'Beer Sale Report', }, - resolve: { - info: beerSaleReportResolver, - saleCategories: saleCategoryListResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/beer-sale-report/beer-sale-report.service.ts b/bookie/src/app/beer-sale-report/beer-sale-report.service.ts index f1e1df3..ca0c9d0 100644 --- a/bookie/src/app/beer-sale-report/beer-sale-report.service.ts +++ b/bookie/src/app/beer-sale-report/beer-sale-report.service.ts @@ -1,46 +1,42 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; -import { Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal } from '@angular/core'; -import { ErrorLoggerService } from '../core/error-logger.service'; import { BeerSaleReport } from './beer-sale-report'; const url = '/api/beer-sale-report'; -const serviceName = 'BeerSaleReportService'; @Injectable({ providedIn: 'root', }) export class BeerSaleReportService { - private http = inject(HttpClient); - private log = inject(ErrorLoggerService); - get( - startDate: string | null, - finishDate: string | null, - saleCategory: string | null, - regular: boolean, - happy: boolean, - staff: boolean, - nc: boolean, - ): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - if (saleCategory != null) { - options.params = options.params.set('sc', saleCategory); - } - options.params = options.params.set('r', regular); - options.params = options.params.set('h', happy); - options.params = options.params.set('st', staff); - options.params = options.params.set('n', nc); - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + startDate: Signal, + finishDate: Signal, + saleCategory: Signal, + regular: Signal, + happy: Signal, + staff: Signal, + nc: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + const sc = saleCategory(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + if (sc !== null) { + params = params.set('sc', sc); + } + params = params.set('r', regular()); + params = params.set('h', happy()); + params = params.set('st', staff()); + params = params.set('n', nc()); + return { url, params }; + }); } } diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report-datasource.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report-datasource.ts deleted file mode 100644 index 9e8a5b2..0000000 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { BillSettlementReportItem } from './bill-settlement-report-item'; - -export class BillSettlementReportDataSource extends DataSource { - constructor(public data: BillSettlementReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.component.html b/bookie/src/app/bill-settlement-report/bill-settlement-report.component.html index 838bc0d..4fff145 100644 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.component.html +++ b/bookie/src/app/bill-settlement-report/bill-settlement-report.component.html @@ -1,11 +1,11 @@

Bill Settlement Report -

-
+
Start Date @@ -13,7 +13,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -25,16 +25,16 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> - +
- + Time diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.component.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report.component.ts index b000a7f..8bd32d5 100644 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.component.ts +++ b/bookie/src/app/bill-settlement-report/bill-settlement-report.component.ts @@ -1,6 +1,6 @@ import { DecimalPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -13,7 +13,12 @@ import moment from 'moment'; import { LocalTimePipe } from '../shared/local-time.pipe'; import { ToCsvService } from '../shared/to-csv.service'; import { BillSettlementReport } from './bill-settlement-report'; -import { BillSettlementReportDataSource } from './bill-settlement-report-datasource'; +import { BillSettlementReportService } from './bill-settlement-report.service'; + +export interface BillSettlementReportFormData { + startDate: Date; + finishDate: Date; +} @Component({ selector: 'app-bill-settlement-report', @@ -23,51 +28,47 @@ import { BillSettlementReportDataSource } from './bill-settlement-report-datasou DecimalPipe, LocalTimePipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class BillSettlementReportComponent implements OnInit { +export class BillSettlementReportComponent { + private billSettlementReportService = inject(BillSettlementReportService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - info: BillSettlementReport = new BillSettlementReport(); - dataSource: BillSettlementReportDataSource = new BillSettlementReportDataSource(this.info.amounts); + infoResource = this.billSettlementReportService.get(this.startDate, this.finishDate); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - }>; + info = computed(() => this.infoResource.value() ?? new BillSettlementReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): BillSettlementReportFormData => { + if (infoVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['date', 'billId', 'amount', 'settlement']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: BillSettlementReport }; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - }); - this.dataSource = new BillSettlementReportDataSource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); this.router.navigate(['bill-settlement-report'], { @@ -79,7 +80,7 @@ export class BillSettlementReportComponent implements OnInit { } getInfo(): BillSettlementReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new BillSettlementReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -94,7 +95,7 @@ export class BillSettlementReportComponent implements OnInit { Amount: 'amount', Settlement: 'settlement', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.spec.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.spec.ts deleted file mode 100644 index de7da3d..0000000 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { BillSettlementReportResolver } from './bill-settlement-report-resolver.service'; - -describe('BillSettlementReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [BillSettlementReportResolver], - }); - }); - - it('should be created', inject([BillSettlementReportResolver], (service: BillSettlementReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.ts deleted file mode 100644 index 4577f6c..0000000 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { BillSettlementReport } from './bill-settlement-report'; -import { BillSettlementReportService } from './bill-settlement-report.service'; - -export const billSettlementReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(BillSettlementReportService).get(startDate, finishDate); -}; diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.routes.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report.routes.ts index 1d0e3b4..14e7411 100644 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.routes.ts +++ b/bookie/src/app/bill-settlement-report/bill-settlement-report.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { BillSettlementReportComponent } from './bill-settlement-report.component'; -import { billSettlementReportResolver } from './bill-settlement-report.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Bill Settlement Report', }, - resolve: { - info: billSettlementReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/bill-settlement-report/bill-settlement-report.service.ts b/bookie/src/app/bill-settlement-report/bill-settlement-report.service.ts index a64f0ac..69b04b4 100644 --- a/bookie/src/app/bill-settlement-report/bill-settlement-report.service.ts +++ b/bookie/src/app/bill-settlement-report/bill-settlement-report.service.ts @@ -1,31 +1,29 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; -import { Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal } from '@angular/core'; -import { ErrorLoggerService } from '../core/error-logger.service'; import { BillSettlementReport } from './bill-settlement-report'; const url = '/api/bill-settlement-report'; -const serviceName = 'BillSettlementReportService'; @Injectable({ providedIn: 'root', }) export class BillSettlementReportService { - private http = inject(HttpClient); - private log = inject(ErrorLoggerService); - - get(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url, params }; + }); } } diff --git a/bookie/src/app/bundles/bundle-detail/bundle-detail-datasource.ts b/bookie/src/app/bundles/bundle-detail/bundle-detail-datasource.ts deleted file mode 100644 index a1f78bd..0000000 --- a/bookie/src/app/bundles/bundle-detail/bundle-detail-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -import { BundleItem } from '../bundle'; - -export class BundleDetailDatasource extends DataSource { - constructor(private data: Observable) { - super(); - } - - connect(): Observable { - return this.data; - } - - disconnect() {} -} diff --git a/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.html b/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.html index f056aa1..d8337ca 100644 --- a/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.html +++ b/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.html @@ -1,12 +1,12 @@

Edit Bundle Item

-
+ Item - + - @for (p of products$ | async; track p) { + @for (p of products(); track p) { {{ p.name }} } @@ -15,19 +15,19 @@
Quantity - + Sale Price - + - Print in Bill? + Print in Bill?
- +
diff --git a/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.ts b/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.ts index 3c078c3..aaf7198 100644 --- a/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.ts +++ b/bookie/src/app/bundles/bundle-detail/bundle-detail-dialog.component.ts @@ -1,18 +1,24 @@ import { CommonModule } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, OnInit, inject, signal, computed, effect, debounced } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; -import { debounceTime, distinctUntilChanged, Observable, of as observableOf, switchMap } from 'rxjs'; import { ProductQuery } from '../../core/product-query'; import { ProductService } from '../../product/product.service'; import { BundleItem } from '../bundle'; +export interface BundleDetailDialogFormData { + product: ProductQuery | string; + quantity: number; + salePrice: number; + printInBill: boolean; +} + @Component({ selector: 'app-bundle-detail-dialog', templateUrl: './bundle-detail-dialog.component.html', @@ -26,7 +32,7 @@ import { BundleItem } from '../bundle'; MatDialogModule, MatFormFieldModule, MatInputModule, - ReactiveFormsModule, + FormField, ], }) export class BundleDetailDialogComponent implements OnInit { @@ -35,49 +41,48 @@ export class BundleDetailDialogComponent implements OnInit { data = inject<{ item: BundleItem }>(MAT_DIALOG_DATA); - selectedProduct: ProductQuery | null = null; - products$: Observable; + selectedProduct = signal(null); - form: FormGroup<{ - product: FormControl; - quantity: FormControl; - salePrice: FormControl; - printInBill: FormControl; - }>; + formModel = signal({ + product: '', + quantity: 1, + salePrice: 0, + printInBill: true, + }); + + form = form(this.formModel); + + productSignal = computed(() => { + const p = this.formModel().product; + return typeof p === 'string' ? p.trim() : ''; + }); + + debouncedProduct = debounced(this.productSignal, 150); + + productsResource = this.productSer.query(computed(() => this.debouncedProduct.value())); + products = computed(() => { + if (!this.debouncedProduct.value()) return []; + return this.productsResource.value() ?? []; + }); constructor() { - this.form = new FormGroup({ - product: new FormControl('', { nonNullable: true }), - quantity: new FormControl(1, { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - printInBill: new FormControl(true, { nonNullable: true }), - }); - - this.products$ = this.form.controls.product.valueChanges.pipe( - debounceTime(150), - distinctUntilChanged(), - switchMap((x) => { - if (typeof x !== 'string') return observableOf([]); - return x.trim() === '' ? observableOf([]) : this.productSer.query(x); - }), - ); - // typing after selecting invalidates prior selection - this.form.controls.product.valueChanges.subscribe((x) => { - if (typeof x === 'string') this.selectedProduct = null; + effect(() => { + const x = this.formModel().product; + if (typeof x === 'string') this.selectedProduct.set(null); }); } ngOnInit(): void { // preload display text using existing name - this.form.setValue({ + this.formModel.set({ product: this.data.item.name ?? '', quantity: Number(this.data.item.quantity ?? 1), salePrice: Number(this.data.item.salePrice ?? 0), printInBill: this.data.item.printInBill, }); - this.selectedProduct = null; + this.selectedProduct.set(null); } displayFn(product?: ProductQuery | string): string { @@ -86,11 +91,11 @@ export class BundleDetailDialogComponent implements OnInit { productSelected(event: MatAutocompleteSelectedEvent): void { const p = event.option.value as ProductQuery; - this.selectedProduct = p; + this.selectedProduct.set(p); } accept(): void { - const v = this.form.value; + const v = this.formModel(); const quantity = Number(v.quantity ?? 0); if (Number.isNaN(quantity) || quantity <= 0) return; @@ -99,9 +104,9 @@ export class BundleDetailDialogComponent implements OnInit { if (Number.isNaN(salePrice) || salePrice < 0) return; // If a new product was selected, update itemId + name - if (this.selectedProduct?.id) { - this.data.item.itemId = this.selectedProduct.id; - this.data.item.name = this.selectedProduct.name ?? ''; + if (this.selectedProduct()?.id) { + this.data.item.itemId = this.selectedProduct()?.id ?? ''; + this.data.item.name = this.selectedProduct()?.name ?? ''; } else { // If no selection, don't allow changing SKU silently // but still allow quantity/price edit diff --git a/bookie/src/app/bundles/bundle-detail/bundle-detail.component.html b/bookie/src/app/bundles/bundle-detail/bundle-detail.component.html index edfad6a..7d47054 100644 --- a/bookie/src/app/bundles/bundle-detail/bundle-detail.component.html +++ b/bookie/src/app/bundles/bundle-detail/bundle-detail.component.html @@ -1,29 +1,29 @@

Bundle

-
+
Name - + Units - +
Sale Price - + Computed from bundle items Menu Category - - @for (mc of menuCategories; track mc) { + + @for (mc of menuCategories(); track mc) { {{ mc.name }} @@ -33,8 +33,8 @@ Sale Category - - @for (sc of saleCategories; track sc) { + + @for (sc of saleCategories(); track sc) { {{ sc.name }} @@ -49,24 +49,24 @@ >
- Has Happy Hour? - Not Available? + Has Happy Hour? + Not Available?

Items

-
+
Product - @for (p of itemProducts | async; track p) { + @for (p of itemProducts(); track p) { {{ p.name }} } @@ -74,21 +74,21 @@ Quantity - + Sale Price - + - Print in Bill? + Print in Bill? - +
- + Item @@ -127,10 +127,10 @@ Action - - @@ -142,8 +142,8 @@
- + @if (!!item.id) { - + }
diff --git a/bookie/src/app/bundles/bundle-detail/bundle-detail.component.ts b/bookie/src/app/bundles/bundle-detail/bundle-detail.component.ts index 6b5a60d..05834c2 100644 --- a/bookie/src/app/bundles/bundle-detail/bundle-detail.component.ts +++ b/bookie/src/app/bundles/bundle-detail/bundle-detail.component.ts @@ -1,6 +1,18 @@ -import { AsyncPipe, CurrencyPipe } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { CurrencyPipe } from '@angular/common'; +import { + AfterViewInit, + Component, + ElementRef, + ViewChild, + inject, + computed, + signal, + effect, + debounced, + linkedSignal, + input, +} from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatAutocompleteModule, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -13,24 +25,39 @@ import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; -import { of as observableOf, BehaviorSubject, debounceTime, distinctUntilChanged, Observable, switchMap } from 'rxjs'; import { MenuCategory } from '../../core/menu-category'; import { ProductQuery } from '../../core/product-query'; import { SaleCategory } from '../../core/sale-category'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; import { ProductService } from '../../product/product.service'; +import { SaleCategoryService } from '../../sale-category/sale-category.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { Bundle, BundleItem } from '../bundle'; import { BundleService } from '../bundle.service'; -import { BundleDetailDatasource } from './bundle-detail-datasource'; import { BundleDetailDialogComponent } from './bundle-detail-dialog.component'; +export interface BundleDetailFormData { + name: string; + units: string; + salePrice: number; + menuCategory: string; + saleCategory: string; + hasHappyHour: boolean; + isNotAvailable: boolean; + addRow: { + itemId: ProductQuery | string; + quantity: number; + salePrice: number; + printInBill: boolean; + }; +} + @Component({ selector: 'app-bundle-detail', templateUrl: './bundle-detail.component.html', styleUrls: ['./bundle-detail.component.css'], imports: [ - AsyncPipe, CurrencyPipe, MatAutocompleteModule, MatButtonModule, @@ -41,95 +68,113 @@ import { BundleDetailDialogComponent } from './bundle-detail-dialog.component'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class BundleDetailComponent implements OnInit, AfterViewInit { +export class BundleDetailComponent implements AfterViewInit { + @ViewChild('name', { static: true }) nameElement?: ElementRef; + private menuCategoryService = inject(MenuCategoryService); + private saleCategoryService = inject(SaleCategoryService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(BundleService); private productSer = inject(ProductService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('name', { static: true }) nameElement?: ElementRef; + saleCategoriesResource = this.saleCategoryService.list(); - form: FormGroup<{ - // Bundle header fields - name: FormControl; - units: FormControl; - salePrice: FormControl; - menuCategory: FormControl; - saleCategory: FormControl; - hasHappyHour: FormControl; - isNotAvailable: FormControl; + menuCategoriesResource = this.menuCategoryService.list(undefined); - // Item add row - addRow: FormGroup<{ - itemId: FormControl; - quantity: FormControl; - salePrice: FormControl; - printInBill: FormControl; - }>; - }>; + itemResource = this.ser.get(this.id); - menuCategories: MenuCategory[] = []; - saleCategories: SaleCategory[] = []; - public items$ = new BehaviorSubject([]); - dataSource: BundleDetailDatasource = new BundleDetailDatasource(this.items$); + formModel = linkedSignal({ + source: () => this.menuCategoriesResource.value(), + computation: (menuCategoriesVal): BundleDetailFormData => { + if (menuCategoriesVal) { + return { + name: this.item.name ?? '', + units: this.item.units ?? '', + salePrice: Number(this.item.salePrice ?? 0), + menuCategory: this.item.menuCategory?.id ?? '', + saleCategory: this.item.saleCategory?.id ?? '', + hasHappyHour: this.item.hasHappyHour ?? false, + isNotAvailable: this.item.isNotAvailable ?? false, + + addRow: { + itemId: '', + quantity: 1, + salePrice: 0, + printInBill: true, + }, + }; + } + return { + name: '', + units: '', + salePrice: 0, + menuCategory: '', + saleCategory: '', + hasHappyHour: false, + isNotAvailable: false, + addRow: { + itemId: '', + quantity: 1, + salePrice: 0, + printInBill: true, + }, + }; + }, + }); + + form = form(this.formModel); + + menuCategories = signal([]); + saleCategories = signal([]); + items = signal([]); + dataSource = computed(() => this.items()); item: Bundle = new Bundle(); - itemProduct: ProductQuery | null = null; - itemProducts: Observable; + itemProduct = signal(null); + + itemIdSignal = computed(() => { + const x = this.formModel().addRow?.itemId; + return typeof x === 'string' ? x.trim() : ''; + }); + + debouncedItemId = debounced(this.itemIdSignal, 150); + + itemProductsResource = this.productSer.query(computed(() => this.debouncedItemId.value())); + itemProducts = computed(() => { + if (!this.debouncedItemId.value()) return []; + return this.itemProductsResource.value() ?? []; + }); displayedColumns = ['name', 'quantity', 'salePrice', 'printInBill', 'action']; constructor() { - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - units: new FormControl('', { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - menuCategory: new FormControl('', { nonNullable: true }), - saleCategory: new FormControl('', { nonNullable: true }), - hasHappyHour: new FormControl(false, { nonNullable: true }), - isNotAvailable: new FormControl(false, { nonNullable: true }), - - addRow: new FormGroup({ - itemId: new FormControl('', { nonNullable: true }), - quantity: new FormControl(1, { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - printInBill: new FormControl(true, { nonNullable: true }), - }), - }); - this.itemProducts = this.form.controls.addRow.controls.itemId.valueChanges.pipe( - debounceTime(150), - distinctUntilChanged(), - switchMap((x) => { - // if user types, x is string; if user selects, x is Product - if (typeof x !== 'string') { - return observableOf([]); - } - return x.trim() === '' ? observableOf([]) : this.productSer.query(x); - }), - ); - this.form.controls.addRow.controls.itemId.valueChanges.subscribe((x) => { + effect(() => { + const x = this.formModel().addRow?.itemId; if (typeof x === 'string') { - this.itemProduct = null; + this.itemProduct.set(null); } }); - } + effect(() => { + const menuCategoriesVal = this.menuCategoriesResource.value(); + if (menuCategoriesVal) this.menuCategories.set(menuCategoriesVal); + const saleCategoriesVal = this.saleCategoriesResource.value(); + if (saleCategoriesVal) this.saleCategories.set(saleCategoriesVal); + const itemVal = this.itemResource.value(); + if (itemVal) { + this.item = itemVal; - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { - item: Bundle; - menuCategories: MenuCategory[]; - saleCategories: SaleCategory[]; - }; - this.menuCategories = data.menuCategories; - this.saleCategories = data.saleCategories; - this.showItem(data.item); + this.itemProduct.set(null); + + this.items.set(this.item.items ?? []); + this.recalcBundleSalePrice(); + } }); } @@ -139,8 +184,14 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { bundleSelected(event: MatAutocompleteSelectedEvent): void { const product = event.option.value as ProductQuery; - this.itemProduct = product; - this.form.controls.addRow.controls.salePrice.setValue(product.price ?? 0); + this.itemProduct.set(product); + this.formModel.update((f) => ({ + ...f, + addRow: { + ...f.addRow, + salePrice: product.price ?? 0, + }, + })); } private recalcBundleSalePrice(): void { @@ -154,34 +205,7 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { // keep model + form in sync this.item.salePrice = Number(total.toFixed(2)); - // if the control is disabled, use patchValue - this.form.controls.salePrice.patchValue(this.item.salePrice); - } - - showItem(item: Bundle) { - this.item = item; - - this.form.setValue({ - name: this.item.name ?? '', - units: this.item.units ?? '', - salePrice: Number(this.item.salePrice ?? 0), - menuCategory: this.item.menuCategory?.id ?? '', - saleCategory: this.item.saleCategory?.id ?? '', - hasHappyHour: this.item.hasHappyHour ?? false, - isNotAvailable: this.item.isNotAvailable ?? false, - - addRow: { - itemId: '', - quantity: 1, - salePrice: 0, - printInBill: true, - }, - }); - this.itemProduct = null; - this.form.controls.salePrice.disable({ emitEvent: false }); - - this.items$.next(this.item.items ?? []); - this.recalcBundleSalePrice(); + this.formModel.update((f) => ({ ...f, salePrice: this.item.salePrice })); } ngAfterViewInit() { @@ -193,17 +217,25 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { } resetAddRow() { - this.form.controls.addRow.reset(); - this.itemProduct = null; + this.formModel.update((f) => ({ + ...f, + addRow: { + itemId: '', + quantity: 1, + salePrice: 0, + printInBill: true, + }, + })); + this.itemProduct.set(null); } addRow() { - const v = this.form.value.addRow; + const v = this.formModel().addRow; if (!v) { return; } - if (!this.itemProduct?.id) { + if (!this.itemProduct()?.id) { this.snackBar.open('Please select a product', 'Error'); return; } @@ -223,15 +255,15 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { // name is expected from backend as "name (units)" on GET; // for new rows we keep it blank (or you can set placeholder) const bi = new BundleItem({ - itemId: this.itemProduct?.id, - name: this.itemProduct?.name ?? '', + itemId: this.itemProduct()?.id, + name: this.itemProduct()?.name ?? '', quantity, salePrice, printInBill: v.printInBill || false, }); this.item.items.push(bi); - this.items$.next(this.item.items); + this.items.set(this.item.items); this.resetAddRow(); this.recalcBundleSalePrice(); @@ -250,7 +282,7 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { return; } Object.assign(row, result as BundleItem); - this.items$.next(this.item.items); + this.items.set(this.item.items); this.resetAddRow(); this.recalcBundleSalePrice(); }); @@ -258,7 +290,7 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { deleteRow(row: BundleItem) { this.item.items.splice(this.item.items.indexOf(row), 1); - this.items$.next(this.item.items); + this.items.set(this.item.items); this.recalcBundleSalePrice(); } @@ -272,8 +304,8 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/bundles'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -284,8 +316,8 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/bundles'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -304,7 +336,7 @@ export class BundleDetailComponent implements OnInit, AfterViewInit { } getItem(): Bundle { - const v = this.form.value; + const v = this.formModel(); this.item.name = v.name ?? ''; this.item.units = v.units ?? ''; diff --git a/bookie/src/app/bundles/bundle-list.resolver.spec.ts b/bookie/src/app/bundles/bundle-list.resolver.spec.ts deleted file mode 100644 index ce1ad04..0000000 --- a/bookie/src/app/bundles/bundle-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { BundleListResolver } from './bundle-list-resolver.service'; - -describe('BundleListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [BundleListResolver], - }); - }); - - it('should be created', inject([BundleListResolver], (service: BundleListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/bundles/bundle-list.resolver.ts b/bookie/src/app/bundles/bundle-list.resolver.ts deleted file mode 100644 index a79a399..0000000 --- a/bookie/src/app/bundles/bundle-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Bundle } from './bundle'; -import { BundleService } from './bundle.service'; - -export const bundleListResolver: ResolveFn = () => { - return inject(BundleService).list(); -}; diff --git a/bookie/src/app/bundles/bundle-list/bundle-list-datasource.ts b/bookie/src/app/bundles/bundle-list/bundle-list-datasource.ts deleted file mode 100644 index 3cc39af..0000000 --- a/bookie/src/app/bundles/bundle-list/bundle-list-datasource.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { merge, Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { Bundle } from '../bundle'; - -export class BundleListDataSource extends DataSource { - public data: Bundle[]; - public filteredData: Bundle[]; - public search: string; - public menuCategory: string; - - constructor( - private readonly searchFilter: Observable, - private readonly menuCategoryFilter: Observable, - private readonly dataObs: Observable, - ) { - super(); - this.data = []; - this.filteredData = []; - this.search = ''; - this.menuCategory = ''; - } - - connect(): Observable { - const dataMutations = [ - this.dataObs.pipe( - tap((x) => { - this.data = x; - }), - ), - this.searchFilter.pipe( - tap((x) => { - this.search = x; - }), - ), - this.menuCategoryFilter.pipe( - tap((x) => { - this.menuCategory = x; - }), - ), - ]; - - return merge(...dataMutations).pipe( - map(() => this.getFilteredData(this.data, this.search, this.menuCategory)), - tap((x) => { - this.filteredData = x; - }), - ); - } - - disconnect() {} - - private getFilteredData(data: Bundle[], search: string, menuCategory: string): Bundle[] { - const tokens = (search ?? '').toLowerCase().split(/\s+/).filter(Boolean); - - return data.filter((b: Bundle) => { - const mcName = b.menuCategory?.name ?? ''; - const hay = `${b.name ?? ''} ${b.units ?? ''} ${mcName}`.toLowerCase(); - - const matchesSearch = tokens.length === 0 || tokens.every((t) => hay.includes(t)); - const matchesMenuCategory = menuCategory === '' || (b.menuCategory?.id ?? '') === menuCategory; - - return matchesSearch && matchesMenuCategory; - }); - } -} diff --git a/bookie/src/app/bundles/bundle-list/bundle-list.component.html b/bookie/src/app/bundles/bundle-list/bundle-list.component.html index 8eceec2..7e97d00 100644 --- a/bookie/src/app/bundles/bundle-list/bundle-list.component.html +++ b/bookie/src/app/bundles/bundle-list/bundle-list.component.html @@ -1,6 +1,6 @@

Bundles - @@ -9,18 +9,18 @@

-
+
Filter - + Menu Category - + -- All Bundles -- - @for (mc of menuCategories; track mc) { + @for (mc of menuCategoriesResource.value(); track mc) { {{ mc.name }} @@ -30,7 +30,7 @@
- + Name diff --git a/bookie/src/app/bundles/bundle-list/bundle-list.component.ts b/bookie/src/app/bundles/bundle-list/bundle-list.component.ts index a09ff96..5b58072 100644 --- a/bookie/src/app/bundles/bundle-list/bundle-list.component.ts +++ b/bookie/src/app/bundles/bundle-list/bundle-list.component.ts @@ -1,6 +1,6 @@ -import { AsyncPipe, CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { CurrencyPipe } from '@angular/common'; +import { Component, inject, computed, signal, debounced } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -8,21 +8,23 @@ import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; -import { ActivatedRoute, RouterModule } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; +import { RouterModule } from '@angular/router'; -import { MenuCategory } from '../../core/menu-category'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; import { ToCsvService } from '../../shared/to-csv.service'; import { Bundle } from '../bundle'; -import { BundleListDataSource } from './bundle-list-datasource'; +import { BundleService } from '../bundle.service'; + +export interface BundleListFormData { + menuCategory: string | null; + filter: string; +} @Component({ selector: 'app-bundle-list', templateUrl: './bundle-list.component.html', styleUrls: ['./bundle-list.component.css'], imports: [ - AsyncPipe, CurrencyPipe, MatButtonModule, MatFormFieldModule, @@ -31,58 +33,44 @@ import { BundleListDataSource } from './bundle-list-datasource'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, RouterModule, ], }) -export class BundleListComponent implements OnInit { - private route = inject(ActivatedRoute); +export class BundleListComponent { + private menuCategoryService = inject(MenuCategoryService); + private bundleService = inject(BundleService); private toCsv = inject(ToCsvService); - searchFilter = new BehaviorSubject(''); - menuCategoryFilter = new BehaviorSubject(''); - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: BundleListDataSource = new BundleListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); + menuCategoriesResource = this.menuCategoryService.list(undefined); + listResource = this.bundleService.list(); - form: FormGroup<{ - menuCategory: FormControl; - filter: FormControl; - }>; + menuCategoryFilter = signal(''); + + formModel = signal({ + menuCategory: '', + filter: '', + }); + + form = form(this.formModel); + + filterSignal = computed(() => this.formModel().filter); + debouncedFilter = debounced(this.filterSignal, 150); + + dataSource = computed(() => { + let items = this.listResource.value() ?? []; + const search = this.debouncedFilter.value()?.toLowerCase() ?? ''; + const cat = this.menuCategoryFilter(); + + if (search) items = items.filter((x: Bundle) => x.name.toLowerCase().includes(search)); + if (cat) items = items.filter((x: Bundle) => x.menuCategory?.id === cat); + return items; + }); - list: Bundle[] = []; - menuCategories: MenuCategory[] = []; displayedColumns: string[] = ['name', 'price', 'menuCategory', 'saleCategory', 'info', 'items']; - constructor() { - this.form = new FormGroup({ - menuCategory: new FormControl(''), - filter: new FormControl('', { nonNullable: true }), - }); - - this.data.subscribe((data: Bundle[]) => { - this.list = data; - }); - - this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()).subscribe((value) => { - this.searchFilter.next(value ?? ''); - }); - } - filterOn(val: string) { - this.menuCategoryFilter.next(val); - } - - ngOnInit() { - this.dataSource = new BundleListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); - this.route.data.subscribe((value) => { - const data = value as { list: Bundle[]; menuCategories: MenuCategory[] }; - this.loadData(data.list, data.menuCategories); - }); - } - - loadData(list: Bundle[], menuCategories: MenuCategory[]) { - this.menuCategories = menuCategories; - this.data.next(list); + this.menuCategoryFilter.set(val); } exportCsv() { @@ -96,7 +84,7 @@ export class BundleListComponent implements OnInit { }; // Map items to count for csv (simple) - const csvList = this.dataSource.filteredData.map((b) => ({ + const csvList = this.dataSource().map((b: Bundle) => ({ ...b, menuCategory: b.menuCategory?.name ?? '', items: (b.items ?? []) diff --git a/bookie/src/app/bundles/bundle.resolver.spec.ts b/bookie/src/app/bundles/bundle.resolver.spec.ts deleted file mode 100644 index ff6bd4c..0000000 --- a/bookie/src/app/bundles/bundle.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { BundleResolver } from './bundle-resolver.service'; - -describe('BundleResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [BundleResolver], - }); - }); - - it('should be created', inject([BundleResolver], (service: BundleResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/bundles/bundle.resolver.ts b/bookie/src/app/bundles/bundle.resolver.ts deleted file mode 100644 index f555809..0000000 --- a/bookie/src/app/bundles/bundle.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ActivatedRouteSnapshot, ResolveFn } from '@angular/router'; - -import { Bundle } from './bundle'; -import { BundleService } from './bundle.service'; - -export const bundleResolver: ResolveFn = (route: ActivatedRouteSnapshot) => { - const id = route.paramMap.get('id'); - return inject(BundleService).get(id); -}; diff --git a/bookie/src/app/bundles/bundle.service.ts b/bookie/src/app/bundles/bundle.service.ts index 79dcae9..8ff2660 100644 --- a/bookie/src/app/bundles/bundle.service.ts +++ b/bookie/src/app/bundles/bundle.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -18,17 +18,15 @@ export class BundleService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal): HttpResourceRef { + return httpResource(() => { + const idVal = id(); + return idVal === null ? url : `${url}/${idVal}`; + }); } save(bundle: Bundle): Observable { diff --git a/bookie/src/app/bundles/bundles.routes.ts b/bookie/src/app/bundles/bundles.routes.ts index 3e8c316..f91c4d7 100644 --- a/bookie/src/app/bundles/bundles.routes.ts +++ b/bookie/src/app/bundles/bundles.routes.ts @@ -1,12 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { menuCategoryListResolver } from '../menu-category/menu-category-list.resolver'; -import { saleCategoryListResolver } from '../sale-category/sale-category-list.resolver'; import { BundleDetailComponent } from './bundle-detail/bundle-detail.component'; -import { bundleListResolver } from './bundle-list.resolver'; import { BundleListComponent } from './bundle-list/bundle-list.component'; -import { bundleResolver } from './bundle.resolver'; export const routes: Routes = [ { @@ -14,31 +10,17 @@ export const routes: Routes = [ component: BundleListComponent, canActivate: [authGuard], data: { permission: 'Products' }, // change if you have a separate permission - resolve: { - list: bundleListResolver, - menuCategories: menuCategoryListResolver, - }, }, { path: 'new', component: BundleDetailComponent, canActivate: [authGuard], data: { permission: 'Products' }, - resolve: { - item: bundleResolver, // returns new Bundle() because id === null (no param here) - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, { path: ':id', component: BundleDetailComponent, canActivate: [authGuard], data: { permission: 'Products' }, - resolve: { - item: bundleResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, ]; diff --git a/bookie/src/app/cashier-report/active-cashiers.resolver.spec.ts b/bookie/src/app/cashier-report/active-cashiers.resolver.spec.ts deleted file mode 100644 index f34e996..0000000 --- a/bookie/src/app/cashier-report/active-cashiers.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ActiveCashiersResolver } from './active-cashiers-resolver.service'; - -describe('ActiveCashiersResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ActiveCashiersResolver], - }); - }); - - it('should be created', inject([ActiveCashiersResolver], (service: ActiveCashiersResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/cashier-report/active-cashiers.resolver.ts b/bookie/src/app/cashier-report/active-cashiers.resolver.ts deleted file mode 100644 index e9aad23..0000000 --- a/bookie/src/app/cashier-report/active-cashiers.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { User } from '../core/user'; -import { CashierReportService } from './cashier-report.service'; - -export const activeCashiersResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(CashierReportService).activeCashiers(startDate, finishDate); -}; diff --git a/bookie/src/app/cashier-report/cashier-report-datasource.ts b/bookie/src/app/cashier-report/cashier-report-datasource.ts deleted file mode 100644 index f87c5c8..0000000 --- a/bookie/src/app/cashier-report/cashier-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { CashierReportDisplayItem } from './cashier-report-display-item'; - -export class CashierReportDataSource extends DataSource { - constructor(public data: CashierReportDisplayItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/cashier-report/cashier-report.component.html b/bookie/src/app/cashier-report/cashier-report.component.html index 4617a8d..0f335d3 100644 --- a/bookie/src/app/cashier-report/cashier-report.component.html +++ b/bookie/src/app/cashier-report/cashier-report.component.html @@ -1,15 +1,15 @@

Cashier Report - -

-
+
Start Date @@ -17,7 +17,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -29,7 +29,7 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> @@ -39,19 +39,19 @@
Cashier - + -- Cashier -- - @for (ac of activeCashiers; track ac) { + @for (ac of cashiers(); track ac) { {{ ac.name }} } - +
- + Name diff --git a/bookie/src/app/cashier-report/cashier-report.component.ts b/bookie/src/app/cashier-report/cashier-report.component.ts index d48e7a3..368aa87 100644 --- a/bookie/src/app/cashier-report/cashier-report.component.ts +++ b/bookie/src/app/cashier-report/cashier-report.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -16,9 +16,14 @@ import moment from 'moment'; import { User } from '../core/user'; import { ToCsvService } from '../shared/to-csv.service'; import { CashierReport } from './cashier-report'; -import { CashierReportDataSource } from './cashier-report-datasource'; import { CashierReportService } from './cashier-report.service'; +export interface CashierReportFormData { + startDate: Date; + finishDate: Date; + cashier: string | null; +} + @Component({ selector: 'app-cashier-report', templateUrl: './cashier-report.component.html', @@ -26,7 +31,6 @@ import { CashierReportService } from './cashier-report.service'; imports: [ CurrencyPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, @@ -34,51 +38,49 @@ import { CashierReportService } from './cashier-report.service'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class CashierReportComponent implements OnInit { +export class CashierReportComponent { private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); private snackBar = inject(MatSnackBar); private ser = inject(CashierReportService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - activeCashiers: User[] = []; - info: CashierReport = new CashierReport(); - dataSource: CashierReportDataSource = new CashierReportDataSource(this.info.amounts); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - cashier: FormControl; - }>; + infoResource = this.ser.list(this.id, this.startDate, this.finishDate); + cashiersResource = this.ser.activeCashiers(this.startDate, this.finishDate); + + cashiers = computed(() => (this.cashiersResource.value() ?? []) as User[]); + + info = computed(() => this.infoResource.value() ?? new CashierReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): CashierReportFormData => { + if (infoVal) { + return { + cashier: this.info().cashier.id ?? '', + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + cashier: null, + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'amount']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - cashier: new FormControl(null), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { cashiers: User[]; info: CashierReport }; - this.activeCashiers = data.cashiers; - this.info = data.info; - this.form.setValue({ - cashier: this.info.cashier.id ?? '', - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - }); - this.dataSource = new CashierReportDataSource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); const url = ['cashier-report']; @@ -94,22 +96,22 @@ export class CashierReportComponent implements OnInit { } print() { - this.ser.print(this.info.cashier.id as string, this.info.startDate, this.info.finishDate).subscribe({ + this.ser.print(this.info().cashier.id as string, this.info().startDate, this.info().finishDate).subscribe({ next: () => { this.snackBar.open('Successfully Printed', ''); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } getInfo(): CashierReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new CashierReport({ cashier: new User({ id: formModel.cashier ?? undefined }), - cashiers: this.info.cashiers, + cashiers: this.info().cashiers, startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), }); @@ -120,7 +122,7 @@ export class CashierReportComponent implements OnInit { Name: 'name', Amount: 'amount', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/cashier-report/cashier-report.resolver.spec.ts b/bookie/src/app/cashier-report/cashier-report.resolver.spec.ts deleted file mode 100644 index a36be18..0000000 --- a/bookie/src/app/cashier-report/cashier-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { CashierReportResolver } from './cashier-report-resolver.service'; - -describe('CashierReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [CashierReportResolver], - }); - }); - - it('should be created', inject([CashierReportResolver], (service: CashierReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/cashier-report/cashier-report.resolver.ts b/bookie/src/app/cashier-report/cashier-report.resolver.ts deleted file mode 100644 index a80e711..0000000 --- a/bookie/src/app/cashier-report/cashier-report.resolver.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { CashierReport } from './cashier-report'; -import { CashierReportService } from './cashier-report.service'; - -export const cashierReportResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(CashierReportService).list(id, startDate, finishDate); -}; diff --git a/bookie/src/app/cashier-report/cashier-report.routes.ts b/bookie/src/app/cashier-report/cashier-report.routes.ts index 6a5eac2..7b8530c 100644 --- a/bookie/src/app/cashier-report/cashier-report.routes.ts +++ b/bookie/src/app/cashier-report/cashier-report.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { activeCashiersResolver } from './active-cashiers.resolver'; import { CashierReportComponent } from './cashier-report.component'; -import { cashierReportResolver } from './cashier-report.resolver'; export const routes: Routes = [ { @@ -13,10 +11,6 @@ export const routes: Routes = [ data: { permission: 'Cashier Report', }, - resolve: { - info: cashierReportResolver, - cashiers: activeCashiersResolver, - }, runGuardsAndResolvers: 'always', }, { @@ -26,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Cashier Report', }, - resolve: { - info: cashierReportResolver, - cashiers: activeCashiersResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/cashier-report/cashier-report.service.ts b/bookie/src/app/cashier-report/cashier-report.service.ts index b9c4451..c785ca9 100644 --- a/bookie/src/app/cashier-report/cashier-report.service.ts +++ b/bookie/src/app/cashier-report/cashier-report.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -17,32 +17,43 @@ export class CashierReportService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - list(id: string | null, startDate: string | null, finishDate: string | null): Observable { - const listUrl = id === null ? url : `${url}/${id}`; - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(listUrl, options) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list( + id: Signal, + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + const idVal = id(); + const listUrl = idVal === null ? url : `${url}/${idVal}`; + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url: listUrl, params }; + }); } - activeCashiers(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(`${url}/active`, options) - - .pipe(catchError(this.log.handleError(serviceName, 'activeCashiers'))) as Observable; + activeCashiers( + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url: `${url}/active`, params }; + }); } print(id: string, startDate: string | null, finishDate: string | null): Observable { diff --git a/bookie/src/app/core/user-role.ts b/bookie/src/app/core/user-role.ts new file mode 100644 index 0000000..21054e8 --- /dev/null +++ b/bookie/src/app/core/user-role.ts @@ -0,0 +1,12 @@ +export class UserRole { + id: string | undefined; + name: string; + enabled: boolean; + + public constructor(init?: Partial) { + this.id = undefined; + this.name = ''; + this.enabled = false; + Object.assign(this, init); + } +} diff --git a/bookie/src/app/customers/customer-detail/customer-detail.component.html b/bookie/src/app/customers/customer-detail/customer-detail.component.html index 72db9ed..32c34d8 100644 --- a/bookie/src/app/customers/customer-detail/customer-detail.component.html +++ b/bookie/src/app/customers/customer-detail/customer-detail.component.html @@ -1,39 +1,41 @@

Customer

-
+
Name - +
Phone - +
Address - +
- Print in Bill? + Print in Bill?
-
- @for (r of item.discounts; track r; let i = $index) { - - Discount on {{ r.name }} - - % - Max {{ r.limit | percent: '1.2-2' }} - +
+ @for (r of item().discounts; track r; let i = $index) { +
+ + Discount on {{ r.name }} + + % + Max {{ r.limit | percent: '1.2-2' }} + +
}
- - + +
diff --git a/bookie/src/app/customers/customer-detail/customer-detail.component.ts b/bookie/src/app/customers/customer-detail/customer-detail.component.ts index 79b8702..6626737 100644 --- a/bookie/src/app/customers/customer-detail/customer-detail.component.ts +++ b/bookie/src/app/customers/customer-detail/customer-detail.component.ts @@ -1,6 +1,6 @@ import { PercentPipe } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -15,6 +15,16 @@ import { Customer } from '../../core/customer'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { CustomerService } from '../customer.service'; +export interface CustomerDetailFormData { + name: string; + phone: string; + address: string; + printInBill: boolean; + discounts: { + discount: number | null; + }[]; +} + @Component({ selector: 'app-customer-detail', templateUrl: './customer-detail.component.html', @@ -26,66 +36,37 @@ import { CustomerService } from '../customer.service'; MatFormFieldModule, MatInputModule, PercentPipe, - ReactiveFormsModule, + FormField, ], }) -export class CustomerDetailComponent implements OnInit, AfterViewInit { +export class CustomerDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(CustomerService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - phone: FormControl; - address: FormControl; - printInBill: FormControl; - discounts: FormArray< - FormGroup<{ - discount: FormControl; - }> - >; - }>; + itemResource = this.ser.get(this.id); - item: Customer = new Customer(); - hide: boolean; + item = computed(() => this.itemResource.value() ?? new Customer()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): CustomerDetailFormData => { + return { + name: itemVal.name ?? '', + phone: itemVal.phone ?? '', + address: itemVal.address ?? '', + printInBill: itemVal.printInBill ?? false, + discounts: itemVal.discounts.map((x) => ({ discount: x.discount ? x.discount * 100 : null })), + }; + }, + }); - constructor() { - this.hide = true; - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - phone: new FormControl('', { nonNullable: true }), - address: new FormControl(null), - printInBill: new FormControl(false, { nonNullable: true }), - discounts: new FormArray }>>([]), - }); - } + form = form(this.formModel); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Customer }; - this.showItem(data.item); - }); - } - - showItem(item: Customer) { - this.item = item; - this.form.controls.name.setValue(item.name); - this.form.controls.phone.setValue(item.phone); - this.form.controls.address.setValue(item.address); - this.form.controls.printInBill.setValue(item.printInBill); - this.form.controls.discounts.clear(); - this.item.discounts.forEach((x) => - this.form.controls.discounts.push( - new FormGroup({ - discount: new FormControl(x.discount ? x.discount * 100 : null), - }), - ), - ); - } + hide = true; ngAfterViewInit() { setTimeout(() => { @@ -101,20 +82,20 @@ export class CustomerDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/customers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/customers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -133,23 +114,20 @@ export class CustomerDetailComponent implements OnInit, AfterViewInit { } getItem(): Customer { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.phone = formModel.phone ?? ''; - this.item.address = formModel.address ?? null; - this.item.printInBill = formModel.printInBill ?? false; - - const array = formModel.discounts; - if (array) { - this.item.discounts.forEach((item, index) => { - const array_item = array.at(index); - if (array_item && array_item?.discount) { - item.discount = Math.max(Math.min(round(array_item.discount / 100, 5), 100), 0); - } else { - item.discount = 0; - } - }); - } - return this.item; + const formModel = this.formModel(); + return new Customer({ + ...this.item(), + name: formModel.name ?? '', + phone: formModel.phone ?? '', + address: formModel.address ?? null, + printInBill: formModel.printInBill ?? false, + discounts: this.item().discounts.map((item, index) => { + const discount = formModel.discounts[index]?.discount; + return { + ...item, + discount: discount ? Math.max(Math.min(round(discount / 100, 5), 100), 0) : 0, + }; + }), + }); } } diff --git a/bookie/src/app/customers/customer-list.resolver.spec.ts b/bookie/src/app/customers/customer-list.resolver.spec.ts deleted file mode 100644 index 677c015..0000000 --- a/bookie/src/app/customers/customer-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { CustomerListResolver } from './customer-list-resolver.service'; - -describe('CustomerListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [CustomerListResolver], - }); - }); - - it('should be created', inject([CustomerListResolver], (service: CustomerListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/customers/customer-list.resolver.ts b/bookie/src/app/customers/customer-list.resolver.ts deleted file mode 100644 index 3bf4d20..0000000 --- a/bookie/src/app/customers/customer-list.resolver.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Customer } from '../core/customer'; -import { PagedResult } from '../core/paged-result'; -import { CustomerService } from './customer.service'; - -export const customerListResolver: ResolveFn> = (route) => { - const q = route.queryParamMap.get('q'); - const page = Number(route.queryParamMap.get('p') ?? 0); - const size = Number(route.queryParamMap.get('s') ?? 50); - const field = route.queryParamMap.get('f') ?? 'name'; - const direction = route.queryParamMap.get('d') ?? 'asc'; - return inject(CustomerService).list(q, page, size, field, direction); -}; diff --git a/bookie/src/app/customers/customer-list/customer-list-datasource.ts b/bookie/src/app/customers/customer-list/customer-list-datasource.ts deleted file mode 100644 index 26e5777..0000000 --- a/bookie/src/app/customers/customer-list/customer-list-datasource.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { MatPaginator } from '@angular/material/paginator'; -import { MatSort } from '@angular/material/sort'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Customer } from '../../core/customer'; -import { PagedResult } from '../../core/paged-result'; - -export class CustomerListDatasource extends DataSource { - constructor( - public data: PagedResult, - private paginator?: MatPaginator, - private sort?: MatSort, - ) { - super(); - } - - connect(): Observable { - if (this.paginator) { - this.paginator.length = this.data.total; - if (this.data.pageSize !== undefined) { - this.paginator.pageSize = this.data.pageSize; - } - if (this.data.page !== undefined) { - this.paginator.pageIndex = this.data.page; - } - } - if (this.sort) { - if (this.data.field !== undefined) { - this.sort.active = this.data.field; - } - if (this.data.sortDirection !== undefined) { - this.sort.direction = this.data.sortDirection; - } - } - return observableOf(this.data.items); - } - - disconnect() {} -} - -// import { DataSource } from '@angular/cdk/collections'; -// import { map, merge, Observable, of as observableOf, tap } from 'rxjs'; - -// import { Customer } from '../../core/customer'; -// import { MatPaginator, PageEvent } from '@angular/material/paginator'; -// import { MatSort, Sort } from '@angular/material/sort'; -// import { EventEmitter } from '@angular/core'; - -// export class CustomerListDatasource extends DataSource { -// private filterValue = ''; -// constructor(public data: Customer[], -// private readonly filter: Observable, -// private paginator?: MatPaginator, -// private sort?: MatSort, - -// ) { -// super(); -// this.filter = filter.pipe( -// tap((x) => { -// this.filterValue = x; -// }), -// ); -// } - -// connect(): Observable { -// const dataMutations: (EventEmitter | EventEmitter)[] = []; -// if (this.paginator) { -// dataMutations.push((this.paginator as MatPaginator).page); -// } -// if (this.sort) { -// dataMutations.push((this.sort as MatSort).sortChange); -// } - -// return merge(observableOf(this.data), this.filter, ...dataMutations).pipe( -// map(() => this.getFilteredData([...this.data])), -// tap((x: Customer[]) => { -// if (this.paginator) { -// this.paginator.length = x.length; -// } -// }), -// map((x: Customer[]) => this.getPagedData(this.getSortedData(x))), -// ); -// } - -// disconnect() {} -// private getFilteredData(data: Customer[]): Customer[] { -// return this.filterValue.toLowerCase().split(' ').reduce( -// (p: Customer[], c: string) => -// p.filter((x) => { -// const productString = `${x.name} ${x.phone}${x.address}`.toLowerCase(); -// return productString.indexOf(c) !== -1; -// }), -// Object.assign([], data), -// ); -// } -// private getPagedData(data: Customer[]) { -// if (this.paginator === undefined) { -// return data; -// } -// const startIndex = this.paginator.pageIndex * this.paginator.pageSize; -// return data.splice(startIndex, this.paginator.pageSize); -// } - -// private getSortedData(data: Customer[]) { -// if (this.sort === undefined) { -// return data; -// } -// if (!this.sort.active || this.sort.direction === '') { -// return data; -// } - -// const sort = this.sort as MatSort; -// console.log('Sorting by', sort.active, sort.direction); -// return data.sort(sortBy(sort.active as keyof Customer, sort.direction === 'asc')); -// } - -// } - -// function compareValues(a: T, b: T, isAsc: boolean): number { -// if (a === b) return 0; -// if (a == null) return isAsc ? -1 : 1; -// if (b == null) return isAsc ? 1 : -1; - -// if (typeof a === "string" && typeof b === "string") { -// return isAsc ? a.localeCompare(b) : b.localeCompare(a); -// } -// if (typeof a === "number" && typeof b === "number") { -// return isAsc ? a - b : b - a; -// } -// if (typeof a === "boolean" && typeof b === "boolean") { -// return isAsc ? (Number(a) - Number(b)) : (Number(b) - Number(a)); -// } -// // Fallback -// const aStr = String(a); -// const bStr = String(b); -// return isAsc ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr); -// } - -// function sortBy( -// key: K, -// isAsc = true -// ): (a: T, b: T) => number { -// return (a, b) => compareValues(a[key], b[key], isAsc); -// } - -// // function getNestedValue(obj: T, path: string | string[]): any { -// // const keys = Array.isArray(path) ? path : path.split("."); -// // return keys.reduce((acc, key) => (acc == null ? undefined : acc[key]), obj); -// // } - -// // function sortByNested( -// // path: string | string[], -// // isAsc = true -// // ): (a: T, b: T) => number { -// // return (a, b) => { -// // const aValue = getNestedValue(a, path); -// // const bValue = getNestedValue(b, path); -// // return compareValues(aValue, bValue, isAsc); -// // }; -// // } diff --git a/bookie/src/app/customers/customer-list/customer-list.component.html b/bookie/src/app/customers/customer-list/customer-list.component.html index dcaea6d..b45111d 100644 --- a/bookie/src/app/customers/customer-list/customer-list.component.html +++ b/bookie/src/app/customers/customer-list/customer-list.component.html @@ -5,15 +5,15 @@ Add -
+
Filter - +
- + Name @@ -57,7 +57,7 @@ ; @ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator; @ViewChild(MatSort, { static: true }) sort!: MatSort; + private route = inject(ActivatedRoute); + private router = inject(Router); + private customerService = inject(CustomerService); - data: PagedResult = new PagedResult([], 0, 0, 0); - filter: Observable; - dataSource: CustomerListDatasource; - form: FormGroup<{ - filter: FormControl; - }>; + formModel = signal({ + filter: this.route.snapshot.queryParamMap.get('q') ?? '', + }); + + form = form(this.formModel); + + filterSignal = computed(() => this.formModel().filter); + debouncedFilter = debounced(this.filterSignal, 150); + + pageIndex = signal(+(this.route.snapshot.queryParamMap.get('p') ?? '0')); + pageSize = signal(+(this.route.snapshot.queryParamMap.get('s') ?? '50')); + sortField = signal(this.route.snapshot.queryParamMap.get('f') ?? 'name'); + sortDirection = signal(this.route.snapshot.queryParamMap.get('d') ?? 'asc'); + + queryParams = computed(() => ({ + q: this.debouncedFilter.value() ?? '', + p: this.pageIndex(), + s: this.pageSize(), + f: this.sortField(), + d: this.sortDirection(), + })); + + listResource = this.customerService.query(this.queryParams); + + dataSource = computed(() => { + const data = this.listResource.value(); + if (!data) return { items: [], total: 0 }; + data.items.forEach((c: Customer) => (c.discounts = c.discounts.filter((d) => d.discount !== 0))); + return data; + }); - /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'phone', 'address', 'printInBill', 'discounts']; constructor() { - this.form = new FormGroup({ - filter: new FormControl('', { nonNullable: true }), - }); - this.filter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()); - this.dataSource = new CustomerListDatasource(this.data, this.paginator, this.sort); - } - - ngOnInit() { - const q = this.route.snapshot.queryParamMap.get('q'); - if (q) { - this.form.controls.filter.setValue(q, { emitEvent: false }); // Prevent infinite loop - } - this.route.data.subscribe((value) => { - const data = value as { data: PagedResult }; - data.data.items.forEach((c: Customer) => (c.discounts = c.discounts.filter((d) => d.discount !== 0))); - this.data = data.data; - this.dataSource = new CustomerListDatasource(this.data, this.paginator, this.sort); - this.cdr.detectChanges(); - }); - this.sort.sortChange.subscribe({ - next: () => - this.router.navigate([], { - relativeTo: this.route, - queryParams: { f: this.sort?.active ?? 'name', d: this.sort?.direction }, - queryParamsHandling: 'merge', - }), - }); - this.paginator.page.subscribe({ - next: () => - this.router.navigate([], { - relativeTo: this.route, - queryParams: { s: this.paginator.pageSize, p: this.paginator.pageIndex }, - queryParamsHandling: 'merge', - }), - }); - this.filter.subscribe({ - next: (value) => { - this.router.navigate([], { - relativeTo: this.route, - queryParams: { q: value }, - queryParamsHandling: 'merge', - }); - }, + // Sync query string whenever params change + effect(() => { + const p = this.queryParams(); + this.router.navigate([], { + relativeTo: this.route, + queryParams: { q: p.q, p: p.p, s: p.s, f: p.f, d: p.d }, + queryParamsHandling: 'merge', + replaceUrl: true, + }); }); } ngAfterViewInit() { + this.sort.sortChange.subscribe(() => { + this.sortField.set(this.sort.active); + this.sortDirection.set(this.sort.direction); + this.pageIndex.set(0); + }); + + this.paginator.page.subscribe(() => { + this.pageSize.set(this.paginator.pageSize); + this.pageIndex.set(this.paginator.pageIndex); + }); + setTimeout(() => { this.filterElement.nativeElement.focus(); }, 0); diff --git a/bookie/src/app/customers/customer.resolver.spec.ts b/bookie/src/app/customers/customer.resolver.spec.ts deleted file mode 100644 index ad34cd2..0000000 --- a/bookie/src/app/customers/customer.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { CustomerResolver } from './customer-resolver.service'; - -describe('CustomerResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [CustomerResolver], - }); - }); - - it('should be created', inject([CustomerResolver], (service: CustomerResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/customers/customer.resolver.ts b/bookie/src/app/customers/customer.resolver.ts deleted file mode 100644 index 79d649e..0000000 --- a/bookie/src/app/customers/customer.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Customer } from '../core/customer'; -import { CustomerService } from './customer.service'; - -export const customerResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(CustomerService).get(id); -}; diff --git a/bookie/src/app/customers/customer.routes.ts b/bookie/src/app/customers/customer.routes.ts index 09a1dfe..b453320 100644 --- a/bookie/src/app/customers/customer.routes.ts +++ b/bookie/src/app/customers/customer.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { CustomerDetailComponent } from './customer-detail/customer-detail.component'; -import { customerListResolver } from './customer-list.resolver'; import { CustomerListComponent } from './customer-list/customer-list.component'; -import { customerResolver } from './customer.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Customers', }, - resolve: { - data: customerListResolver, - }, runGuardsAndResolvers: 'always', }, { @@ -26,16 +21,10 @@ export const routes: Routes = [ data: { permission: 'Customers', }, - resolve: { - item: customerResolver, - }, }, { path: ':id', component: CustomerDetailComponent, canActivate: [authGuard], - resolve: { - item: customerResolver, - }, }, ]; diff --git a/bookie/src/app/customers/customer.service.ts b/bookie/src/app/customers/customer.service.ts index b3e98dd..36e7138 100644 --- a/bookie/src/app/customers/customer.service.ts +++ b/bookie/src/app/customers/customer.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -20,11 +20,11 @@ export class CustomerService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } list(q: string | null, page = 0, size = 50, field = 'name', direction = 'asc'): Observable> { @@ -35,12 +35,29 @@ export class CustomerService { f: field, d: direction, }; - console.log('CustomerService.list', params); return this.http .get>(`${url}/list`, { params }) .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable>; } + query( + params: Signal<{ q: string; p: number; s: number; f: string; d: string }>, + ): HttpResourceRef | undefined> { + return httpResource>(() => { + const p = params(); + return { + url: `${url}/list`, + params: { + ...(p.q ? { q: p.q } : {}), + p: p.p, + s: p.s, + f: p.f, + d: p.d, + }, + }; + }); + } + save(customer: Customer): Observable { return this.http .post(`${url}`, customer, httpOptions) @@ -66,10 +83,10 @@ export class CustomerService { .pipe(catchError(this.log.handleError(serviceName, 'delete'))) as Observable; } - autocomplete(query: string): Observable { - const options = { params: new HttpParams().set('q', query) }; - return this.http - .get(`${url}/query`, options) - .pipe(catchError(this.log.handleError(serviceName, 'autocomplete'))) as Observable; + autocomplete(query: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const qVal = typeof query === 'function' ? query() : query; + return `${url}/query?q=${qVal ?? ''}`; + }); } } diff --git a/bookie/src/app/devices/device-detail/device-detail.component.html b/bookie/src/app/devices/device-detail/device-detail.component.html index 2d2086f..75512c7 100644 --- a/bookie/src/app/devices/device-detail/device-detail.component.html +++ b/bookie/src/app/devices/device-detail/device-detail.component.html @@ -1,16 +1,16 @@

Device

-
+
Name - +
Section - - @for (s of sections; track s) { + + @for (s of sections(); track s) { {{ s.name }} @@ -19,16 +19,16 @@
- Enabled? + Enabled?
- - @if (!!item.id) { - + + @if (!!item().id) { + }
Created on {{ item.creationDate | localTime }}Created on {{ item().creationDate | localTime }}
diff --git a/bookie/src/app/devices/device-detail/device-detail.component.ts b/bookie/src/app/devices/device-detail/device-detail.component.ts index bf4aaba..e2caf7b 100644 --- a/bookie/src/app/devices/device-detail/device-detail.component.ts +++ b/bookie/src/app/devices/device-detail/device-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; @@ -12,10 +12,17 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Device } from '../../core/device'; import { Section } from '../../core/section'; +import { SectionService } from '../../sections/section.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { LocalTimePipe } from '../../shared/local-time.pipe'; import { DeviceService } from '../device.service'; +export interface DeviceDetailFormData { + name: string; + section: string | null; + enabled: boolean; +} + @Component({ selector: 'app-device-detail', templateUrl: './device-detail.component.html', @@ -23,58 +30,43 @@ import { DeviceService } from '../device.service'; imports: [ LocalTimePipe, MatButtonModule, - MatCheckboxModule, MatFormFieldModule, MatInputModule, - MatOptionModule, MatSelectModule, - ReactiveFormsModule, + FormField, ], }) -export class DeviceDetailComponent implements OnInit, AfterViewInit { +export class DeviceDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(DeviceService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - section: FormControl; - enabled: FormControl; - }>; + sectionsResource = this.sectionService.list(); - sections: Section[] = []; - item: Device = new Device(); + itemResource = this.ser.get(this.id); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - section: new FormControl(null), - enabled: new FormControl(false, { nonNullable: true }), - }); - } + item = computed(() => this.itemResource.value() ?? new Device()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): DeviceDetailFormData => { + return { + name: itemVal.name ?? '', + section: itemVal.section.id ? itemVal.section.id : '', + enabled: itemVal.enabled, + }; + }, + }); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Device; sections: Section[] }; - this.showItem(data.item); - this.sections = data.sections; - }); - } + form = form(this.formModel); - showItem(item: Device) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - section: this.item.section.id ? this.item.section.id : '', - enabled: this.item.enabled, - }); - } + sections = computed(() => this.sectionsResource.value() ?? []); ngAfterViewInit() { setTimeout(() => { @@ -90,20 +82,20 @@ export class DeviceDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/devices'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/devices'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -122,10 +114,12 @@ export class DeviceDetailComponent implements OnInit, AfterViewInit { } getItem(): Device { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.section.id = formModel.section ?? ''; - this.item.enabled = formModel.enabled ?? true; - return this.item; + const formModel = this.formModel(); + return new Device({ + ...this.item(), + name: formModel.name ?? '', + section: new Section({ id: formModel.section ?? '' }), + enabled: formModel.enabled ?? true, + }); } } diff --git a/bookie/src/app/devices/device-list.resolver.spec.ts b/bookie/src/app/devices/device-list.resolver.spec.ts deleted file mode 100644 index 0880b05..0000000 --- a/bookie/src/app/devices/device-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { DeviceListResolver } from './device-list-resolver.service'; - -describe('DeviceListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [DeviceListResolver], - }); - }); - - it('should be created', inject([DeviceListResolver], (service: DeviceListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/devices/device-list.resolver.ts b/bookie/src/app/devices/device-list.resolver.ts deleted file mode 100644 index 8fdc936..0000000 --- a/bookie/src/app/devices/device-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Device } from '../core/device'; -import { DeviceService } from './device.service'; - -export const deviceListResolver: ResolveFn = () => { - return inject(DeviceService).list(); -}; diff --git a/bookie/src/app/devices/device-list/device-list-datasource.ts b/bookie/src/app/devices/device-list/device-list-datasource.ts deleted file mode 100644 index 19aec8b..0000000 --- a/bookie/src/app/devices/device-list/device-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Device } from '../../core/device'; - -export class DeviceListDataSource extends DataSource { - constructor(public data: Device[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/devices/device-list/device-list.component.html b/bookie/src/app/devices/device-list/device-list.component.html index 2455214..82ccd6a 100644 --- a/bookie/src/app/devices/device-list/device-list.component.html +++ b/bookie/src/app/devices/device-list/device-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/devices/device-list/device-list.component.ts b/bookie/src/app/devices/device-list/device-list.component.ts index 5dd73f8..5cd0636 100644 --- a/bookie/src/app/devices/device-list/device-list.component.ts +++ b/bookie/src/app/devices/device-list/device-list.component.ts @@ -1,32 +1,23 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Device } from '../../core/device'; import { LocalTimePipe } from '../../shared/local-time.pipe'; -import { DeviceListDataSource } from './device-list-datasource'; - +import { DeviceService } from '../device.service'; @Component({ selector: 'app-device-list', templateUrl: './device-list.component.html', styleUrls: ['./device-list.component.css'], imports: [LocalTimePipe, MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class DeviceListComponent implements OnInit { +export class DeviceListComponent { + private deviceService = inject(DeviceService); private route = inject(ActivatedRoute); + listResource = this.deviceService.list(); - list: Device[] = []; - dataSource: DeviceListDataSource = new DeviceListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'section', 'enabled', 'creationDate', 'last']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Device[] }; - this.list = data.list; - }); - this.dataSource = new DeviceListDataSource(this.list); - } } diff --git a/bookie/src/app/devices/device.resolver.spec.ts b/bookie/src/app/devices/device.resolver.spec.ts deleted file mode 100644 index 6bcb9b6..0000000 --- a/bookie/src/app/devices/device.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { DeviceResolver } from './device-resolver.service'; - -describe('DeviceResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [DeviceResolver], - }); - }); - - it('should be created', inject([DeviceResolver], (service: DeviceResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/devices/device.resolver.ts b/bookie/src/app/devices/device.resolver.ts deleted file mode 100644 index b529b73..0000000 --- a/bookie/src/app/devices/device.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Device } from '../core/device'; -import { DeviceService } from './device.service'; - -export const deviceResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(DeviceService).get(id); -}; diff --git a/bookie/src/app/devices/device.service.ts b/bookie/src/app/devices/device.service.ts index 2536354..18e881c 100644 --- a/bookie/src/app/devices/device.service.ts +++ b/bookie/src/app/devices/device.service.ts @@ -1,5 +1,5 @@ -import { HttpClient } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,17 +16,15 @@ export class DeviceService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(device: Device): Observable { diff --git a/bookie/src/app/devices/devices.routes.ts b/bookie/src/app/devices/devices.routes.ts index e597ead..d8eedc6 100644 --- a/bookie/src/app/devices/devices.routes.ts +++ b/bookie/src/app/devices/devices.routes.ts @@ -1,11 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { sectionListResolver } from '../sections/section-list.resolver'; import { DeviceDetailComponent } from './device-detail/device-detail.component'; -import { deviceListResolver } from './device-list.resolver'; import { DeviceListComponent } from './device-list/device-list.component'; -import { deviceResolver } from './device.resolver'; export const routes: Routes = [ { @@ -15,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Devices', }, - resolve: { - list: deviceListResolver, - }, }, { path: 'new', @@ -26,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Devices', }, - resolve: { - item: deviceResolver, - sections: sectionListResolver, - }, }, { path: ':id', @@ -38,9 +28,5 @@ export const routes: Routes = [ data: { permission: 'Devices', }, - resolve: { - item: deviceResolver, - sections: sectionListResolver, - }, }, ]; diff --git a/bookie/src/app/discount-report/discount-report-datasource.ts b/bookie/src/app/discount-report/discount-report-datasource.ts deleted file mode 100644 index b23b46c..0000000 --- a/bookie/src/app/discount-report/discount-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { DiscountReportItem } from './discount-report-item'; - -export class DiscountReportDataSource extends DataSource { - constructor(public data: DiscountReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/discount-report/discount-report.component.html b/bookie/src/app/discount-report/discount-report.component.html index 54297c8..30b91db 100644 --- a/bookie/src/app/discount-report/discount-report.component.html +++ b/bookie/src/app/discount-report/discount-report.component.html @@ -1,14 +1,14 @@

Discount Report - -

-
+
Start Date @@ -16,7 +16,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -28,16 +28,16 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> - +
- + Name diff --git a/bookie/src/app/discount-report/discount-report.component.ts b/bookie/src/app/discount-report/discount-report.component.ts index 2828ab3..471b8e8 100644 --- a/bookie/src/app/discount-report/discount-report.component.ts +++ b/bookie/src/app/discount-report/discount-report.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -13,9 +13,13 @@ import moment from 'moment'; import { ToCsvService } from '../shared/to-csv.service'; import { DiscountReport } from './discount-report'; -import { DiscountReportDataSource } from './discount-report-datasource'; import { DiscountReportService } from './discount-report.service'; +export interface DiscountReportFormData { + startDate: Date; + finishDate: Date; +} + @Component({ selector: 'app-discount-report', templateUrl: './discount-report.component.html', @@ -23,52 +27,48 @@ import { DiscountReportService } from './discount-report.service'; imports: [ CurrencyPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class DiscountReportComponent implements OnInit { +export class DiscountReportComponent { private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); private snackBar = inject(MatSnackBar); private ser = inject(DiscountReportService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - info: DiscountReport = new DiscountReport(); - dataSource: DiscountReportDataSource = new DiscountReportDataSource(this.info.amounts); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - }>; + infoResource = this.ser.get(this.startDate, this.finishDate); + + info = computed(() => this.infoResource.value() ?? new DiscountReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): DiscountReportFormData => { + if (infoVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'amount']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: DiscountReport }; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - }); - this.dataSource = new DiscountReportDataSource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); this.router.navigate(['discount-report'], { @@ -80,7 +80,7 @@ export class DiscountReportComponent implements OnInit { } getInfo(): DiscountReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new DiscountReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -89,12 +89,12 @@ export class DiscountReportComponent implements OnInit { } print() { - this.ser.print(this.info.startDate, this.info.finishDate).subscribe({ + this.ser.print(this.info().startDate, this.info().finishDate).subscribe({ next: () => { this.snackBar.open('Successfully Printed', ''); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -104,7 +104,7 @@ export class DiscountReportComponent implements OnInit { Name: 'name', Amount: 'amount', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/discount-report/discount-report.resolver.spec.ts b/bookie/src/app/discount-report/discount-report.resolver.spec.ts deleted file mode 100644 index 4b6e25d..0000000 --- a/bookie/src/app/discount-report/discount-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { DiscountReportResolver } from './discount-report-resolver.service'; - -describe('DiscountReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [DiscountReportResolver], - }); - }); - - it('should be created', inject([DiscountReportResolver], (service: DiscountReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/discount-report/discount-report.resolver.ts b/bookie/src/app/discount-report/discount-report.resolver.ts deleted file mode 100644 index 59b0469..0000000 --- a/bookie/src/app/discount-report/discount-report.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { DiscountReport } from './discount-report'; -import { DiscountReportService } from './discount-report.service'; - -export const discountReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(DiscountReportService).get(startDate, finishDate); -}; diff --git a/bookie/src/app/discount-report/discount-report.routes.ts b/bookie/src/app/discount-report/discount-report.routes.ts index 12f9a97..397a033 100644 --- a/bookie/src/app/discount-report/discount-report.routes.ts +++ b/bookie/src/app/discount-report/discount-report.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { DiscountReportComponent } from './discount-report.component'; -import { discountReportResolver } from './discount-report.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Discount Report', }, - resolve: { - info: discountReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/discount-report/discount-report.service.ts b/bookie/src/app/discount-report/discount-report.service.ts index a1816ef..4406684 100644 --- a/bookie/src/app/discount-report/discount-report.service.ts +++ b/bookie/src/app/discount-report/discount-report.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,17 +16,22 @@ export class DiscountReportService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url, params }; + }); } print(startDate: string | null, finishDate: string | null): Observable { diff --git a/bookie/src/app/guest-book/guest-book-detail.resolver.ts b/bookie/src/app/guest-book/guest-book-detail.resolver.ts deleted file mode 100644 index ec58890..0000000 --- a/bookie/src/app/guest-book/guest-book-detail.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { GuestBook } from './guest-book'; -import { GuestBookService } from './guest-book.service'; - -export const guestBookDetailResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - const account = route.queryParamMap.get('t') || 'walk_in'; - return inject(GuestBookService).get(id, account); -}; diff --git a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html index 872d544..54798e6 100644 --- a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html +++ b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.html @@ -1,18 +1,15 @@

Guest Details

-
+
Name - - @if (form.controls['name'].hasError('required')) { - Name is required - } +
Phone - + - @for (customer of customers | async; track customer) { + @for (customer of customers(); track customer) { {{ customer.name }} - {{ customer.phone }} } @@ -28,42 +25,46 @@
Pax - +
Address - +
Notes - +
Date - + - - Hours - - - - Minutes - + + Time + + +
- - @if (!!item.id) { - + + @if (!!item().id) { + }
diff --git a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts index 4c882ed..cbe21a3 100644 --- a/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts +++ b/bookie/src/app/guest-book/guest-book-detail/guest-book-detail.component.ts @@ -1,6 +1,15 @@ -import { AsyncPipe } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; +import { + AfterViewInit, + Component, + ElementRef, + ViewChild, + computed, + inject, + debounced, + linkedSignal, + input, +} from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatAutocompleteSelectedEvent, MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; @@ -9,88 +18,98 @@ import { MatDialog } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { MatTimepickerModule } from '@angular/material/timepicker'; import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; -import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; import { Customer } from '../../core/customer'; import { CustomerService } from '../../customers/customer.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; -import { GuestBook } from '../guest-book'; +import { GuestBook, GuestBookType } from '../guest-book'; import { GuestBookService } from '../guest-book.service'; +export interface GuestBookDetailFormData { + name: string; + phone: string | Customer; + pax: number; + address: string; + notes: string; + date: Date; + time: Date; +} + @Component({ selector: 'app-guest-book-detail', templateUrl: './guest-book-detail.component.html', styleUrls: ['./guest-book-detail.component.css'], imports: [ - AsyncPipe, MatAutocompleteModule, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, - MatInputModule, MatOptionModule, - ReactiveFormsModule, + MatTimepickerModule, + FormField, ], }) -export class GuestBookDetailComponent implements OnInit, AfterViewInit { +export class GuestBookDetailComponent implements AfterViewInit { + @ViewChild('phone', { static: true }) phoneElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(GuestBookService); private customerService = inject(CustomerService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + t = input('walk_in', { + transform: (v: string | null | undefined) => (v as GuestBookType) ?? 'walk_in', + }); - @ViewChild('phone', { static: true }) phoneElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - phone: FormControl; - pax: FormControl; - address: FormControl; - notes: FormControl; - date: FormControl; - hours: FormControl; - minutes: FormControl; - }>; + itemResource = this.ser.get(this.id, this.t); - item: GuestBook = new GuestBook(); - customers: Observable; + item = computed(() => this.itemResource.value() ?? new GuestBook()); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { validators: Validators.required, nonNullable: true }), - phone: new FormControl('', { - validators: Validators.required, - nonNullable: true, - }), - pax: new FormControl(0, { validators: Validators.required, nonNullable: true }), - address: new FormControl(null), - notes: new FormControl(null), - date: new FormControl({ value: new Date(), disabled: false }, { nonNullable: true }), - hours: new FormControl(0, { validators: [Validators.min(0), Validators.max(23)], nonNullable: true }), - minutes: new FormControl(0, { validators: [Validators.min(0), Validators.max(59)], nonNullable: true }), - }); - // Setup Account Autocomplete - this.customers = this.form.controls.phone.valueChanges.pipe( - startWith(null), - map((x) => (x !== null && (x as string).length >= 1 ? x : null)), - debounceTime(150), - distinctUntilChanged(), - switchMap((x) => (x === null ? observableOf([]) : this.customerService.autocomplete(x as string))), - ); - } + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): GuestBookDetailFormData => { + if (itemVal && itemVal.id) { + const dt = (itemVal.arrivalDate || itemVal.bookingDate) as string; + return { + name: itemVal.name, + phone: itemVal.phone, + pax: itemVal.pax, + address: itemVal.address ?? '', + notes: itemVal.notes ?? '', + date: dt ? new Date(dt) : new Date(), + time: dt ? new Date(dt) : new Date(), + }; + } + return { + name: '', + phone: '', + pax: 0, + address: '', + notes: '', + date: new Date(), + time: new Date(), + }; + }, + }); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: GuestBook }; - this.showItem(data.item); - }); - } + form = form(this.formModel); + phoneSignal = computed(() => { + const p = this.formModel().phone; + return typeof p === 'string' ? p.trim() : (p as Customer).phone; + }); + + debouncedPhone = debounced(this.phoneSignal, 150); + + customersResource = this.customerService.autocomplete(computed(() => this.debouncedPhone.value())); + customers = computed(() => { + if (!this.debouncedPhone.value()) return []; + return this.customersResource.value() ?? []; + }); ngAfterViewInit() { setTimeout(() => { @@ -100,35 +119,14 @@ export class GuestBookDetailComponent implements OnInit, AfterViewInit { }, 0); } - showItem(item: GuestBook) { - this.item = item; - const dt = (this.item.arrivalDate || this.item.bookingDate) as string; - if (item.type === 'booking') { - this.form.controls.date.enable(); - } else { - this.form.controls.date.disable(); - } - - this.form.setValue({ - name: item.name, - phone: item.phone, - pax: item.pax, - address: item.address, - notes: item.notes, - date: new Date(dt), - hours: +dt.substring(12, 14), - minutes: +dt.substring(15, 17), - }); - } - save() { this.ser.saveOrUpdate(this.getItem()).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/guest-book'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -139,11 +137,12 @@ export class GuestBookDetailComponent implements OnInit, AfterViewInit { selected(event: MatAutocompleteSelectedEvent): void { const customer = event.option.value; - this.form.patchValue({ + this.formModel.update((f) => ({ + ...f, name: customer.name, // phone: customer.phone, address: customer.address, - }); + })); } confirmDelete(): void { @@ -154,7 +153,7 @@ export class GuestBookDetailComponent implements OnInit, AfterViewInit { dialogRef.afterClosed().subscribe((result: boolean) => { if (result) { - this.delete(this.item.id ?? ''); + this.delete(this.item().id ?? ''); } }); } @@ -165,32 +164,36 @@ export class GuestBookDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/guest-book'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } getItem(): GuestBook { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; + const formModel = this.formModel(); + const item = Object.assign(new GuestBook(), this.item()); + item.name = formModel.name ?? ''; if (typeof formModel.phone === 'string') { - this.item.phone = formModel.phone; + item.phone = formModel.phone; } else { - this.item.phone = (formModel.phone as Customer).phone; + item.phone = (formModel.phone as Customer).phone; } - this.item.pax = formModel.pax ?? 0; - this.item.address = formModel.address ?? null; - this.item.notes = formModel.notes ?? null; - const hours = ('' + (formModel.hours as number)).padStart(2, '0'); - const minutes = ('' + (formModel.minutes as number)).padStart(2, '0'); - if (this.item.type === 'booking') { - console.log(formModel.date); - this.item.bookingDate = moment(formModel.date).format('DD-MMM-YYYY') + ' ' + hours + ':' + minutes; + item.pax = formModel.pax ?? 0; + item.address = formModel.address; + item.notes = formModel.notes; + const timeStr = formModel.time ? moment(formModel.time).format('HH:mm') : '00:00'; + item.type = item.type || this.t() || 'walk_in'; + + if (item.type === 'booking') { + item.bookingDate = moment(formModel.date).format('DD-MMM-YYYY') + ' ' + timeStr; } else { - this.item.arrivalDate = (this.item.arrivalDate as string).substring(0, 12) + hours + ':' + minutes; + const existingDate = item.arrivalDate + ? (item.arrivalDate as string).substring(0, 12) + : moment(formModel.date).format('DD-MMM-YYYY '); + item.arrivalDate = existingDate + timeStr; } - return this.item; + return item; } } diff --git a/bookie/src/app/guest-book/guest-book-list.resolver.ts b/bookie/src/app/guest-book/guest-book-list.resolver.ts deleted file mode 100644 index 0445394..0000000 --- a/bookie/src/app/guest-book/guest-book-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { GuestBookList } from './guest-book-list'; -import { GuestBookService } from './guest-book.service'; - -export const guestBookListResolver: ResolveFn = () => { - return inject(GuestBookService).list(null); -}; diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts b/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts deleted file mode 100644 index aa32a12..0000000 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list-datasource.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -import { GuestBook } from '../guest-book'; - -export class GuestBookListDataSource extends DataSource { - constructor(private readonly dataObs: Observable) { - super(); - } - - connect(): Observable { - return this.dataObs; - } - - /** - * Called when the table is being destroyed. Use this function, to clean up - * any open connections or free any held resources that were set up during connect. - */ - disconnect() {} -} diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html index 456f83d..c2b2a86 100644 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html +++ b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.html @@ -10,17 +10,17 @@ -
+
Date - +
- + S. No / Total diff --git a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts index cd68605..b03edbf 100644 --- a/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts +++ b/bookie/src/app/guest-book/guest-book-list/guest-book-list.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, effect, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -9,14 +9,13 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import moment from 'moment'; -import { BehaviorSubject } from 'rxjs'; -import { map } from 'rxjs/operators'; import { LocalTimePipe } from '../../shared/local-time.pipe'; -import { GuestBook } from '../guest-book'; -import { GuestBookList } from '../guest-book-list'; import { GuestBookService } from '../guest-book.service'; -import { GuestBookListDataSource } from './guest-book-list-datasource'; + +export interface GuestBookListFormData { + date: Date; +} @Component({ selector: 'app-guest-book-list', @@ -26,53 +25,53 @@ import { GuestBookListDataSource } from './guest-book-list-datasource'; LocalTimePipe, MatButtonModule, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, RouterLink, ], }) -export class GuestBookListComponent implements OnInit { +export class GuestBookListComponent { private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private ser = inject(GuestBookService); - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: GuestBookListDataSource = new GuestBookListDataSource(this.data); - form: FormGroup<{ - date: FormControl; - }>; + formModel = signal({ + date: this.initialDate(), + }); + + form = form(this.formModel); - /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['sno', 'name', 'phone', 'pax', 'date', 'action']; + dateSignal = computed(() => moment(this.formModel().date).format('DD-MMM-YYYY')); + listResource = this.ser.list(this.dateSignal); + + dataSource = computed(() => this.listResource.value()?.list ?? []); + constructor() { - // Create form - this.form = new FormGroup({ - date: new FormControl(new Date(), { nonNullable: true }), + // Keep the query string in sync with the form date + effect(() => { + const date = this.dateSignal(); + this.router.navigate([], { + relativeTo: this.route, + queryParams: { date }, + queryParamsHandling: 'merge', + replaceUrl: true, + }); }); - this.listenToDateChange(); } - listenToDateChange(): void { - this.form.controls.date.valueChanges.pipe(map((x) => moment(x).format('DD-MMM-YYYY'))).subscribe((x) => - this.ser.list(x).subscribe((list: GuestBookList) => { - this.data.next(list.list); - }), - ); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: GuestBookList }; - this.data.next(data.list.list); - this.form.setValue({ date: moment(data.list.date, 'DD-MMM-YYYY').toDate() }); - }); - this.dataSource = new GuestBookListDataSource(this.data); + private initialDate(): Date { + const qp = this.route.snapshot.queryParamMap.get('date'); + if (qp) { + const parsed = moment(qp, 'DD-MMM-YYYY', true); + if (parsed.isValid()) return parsed.toDate(); + } + return new Date(); } } diff --git a/bookie/src/app/guest-book/guest-book.routes.ts b/bookie/src/app/guest-book/guest-book.routes.ts index ec35b22..83d13b5 100644 --- a/bookie/src/app/guest-book/guest-book.routes.ts +++ b/bookie/src/app/guest-book/guest-book.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { guestBookDetailResolver } from './guest-book-detail.resolver'; import { GuestBookDetailComponent } from './guest-book-detail/guest-book-detail.component'; -import { guestBookListResolver } from './guest-book-list.resolver'; import { GuestBookListComponent } from './guest-book-list/guest-book-list.component'; export const routes: Routes = [ @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Customers', }, - resolve: { - list: guestBookListResolver, - }, runGuardsAndResolvers: 'always', }, { @@ -26,9 +21,6 @@ export const routes: Routes = [ data: { permission: 'Customers', }, - resolve: { - item: guestBookDetailResolver, - }, }, { path: ':id', @@ -37,8 +29,5 @@ export const routes: Routes = [ data: { permission: 'Customers', }, - resolve: { - item: guestBookDetailResolver, - }, }, ]; diff --git a/bookie/src/app/guest-book/guest-book.service.ts b/bookie/src/app/guest-book/guest-book.service.ts index d2a8b83..98f56e0 100644 --- a/bookie/src/app/guest-book/guest-book.service.ts +++ b/bookie/src/app/guest-book/guest-book.service.ts @@ -1,10 +1,10 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { ErrorLoggerService } from '../core/error-logger.service'; -import { GuestBook } from './guest-book'; +import { GuestBook, GuestBookType } from './guest-book'; import { GuestBookList } from './guest-book-list'; const httpOptions = { @@ -19,19 +19,25 @@ export class GuestBookService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null, type: string): Observable { - const options = { params: new HttpParams().set('t', type) }; - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl, options) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get( + id: Signal | string | null, + type: Signal | GuestBookType | string = '', + ): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + const typeVal = typeof type === 'function' ? type() : type; + const options = { params: new HttpParams().set('t', typeVal) }; + const getUrl: string = idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + return { url: getUrl, ...options }; + }); } - list(date: string | null): Observable { - const options = { params: new HttpParams().set('q', date === null ? '' : date) }; - return this.http - .get(`${url}/list`, options) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(date: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const dateVal = typeof date === 'function' ? date() : date; + const options = { params: new HttpParams().set('q', dateVal === null ? '' : dateVal) }; + return { url: `${url}/list`, ...options }; + }); } save(guestBook: GuestBook): Observable { diff --git a/bookie/src/app/guest-book/guest-book.ts b/bookie/src/app/guest-book/guest-book.ts index 0b2d4a8..e9cc6e0 100644 --- a/bookie/src/app/guest-book/guest-book.ts +++ b/bookie/src/app/guest-book/guest-book.ts @@ -1,3 +1,5 @@ +export type GuestBookType = 'walk_in' | 'booking'; + export class GuestBook { id: string | undefined; serial: number; @@ -9,7 +11,7 @@ export class GuestBook { notes: string | null; bookingDate: string | null; arrivalDate: string | null; - type: string | undefined; + type: GuestBookType | undefined; lastEditDate: string | undefined; status?: string; tableId?: string; diff --git a/bookie/src/app/header-footer/header-footer.component.html b/bookie/src/app/header-footer/header-footer.component.html index b571c5c..d0f8138 100644 --- a/bookie/src/app/header-footer/header-footer.component.html +++ b/bookie/src/app/header-footer/header-footer.component.html @@ -1,9 +1,9 @@ -
+
Header / Footer - - @for (s of list; track s) { + + @for (s of list(); track s) { {{ s.name }} @@ -14,10 +14,10 @@
Text - +
- +
diff --git a/bookie/src/app/header-footer/header-footer.component.ts b/bookie/src/app/header-footer/header-footer.component.ts index aed906c..a096df4 100644 --- a/bookie/src/app/header-footer/header-footer.component.ts +++ b/bookie/src/app/header-footer/header-footer.component.ts @@ -1,5 +1,5 @@ -import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; @@ -9,92 +9,82 @@ import { MatInputModule } from '@angular/material/input'; import { MatSelectChange, MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Router } from '@angular/router'; -import { map } from 'rxjs/operators'; import { HeaderFooter } from './header-footer'; import { HeaderFooterService } from './header-footer.service'; +export interface HeaderFooterFormData { + id: string; + text: string; +} + @Component({ selector: 'app-section-printer', templateUrl: './header-footer.component.html', styleUrls: ['./header-footer.component.css'], imports: [ MatButtonModule, - MatDividerModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, - ReactiveFormsModule, + FormField, ], }) -export class HeaderFooterComponent implements OnInit { +export class HeaderFooterComponent { + @ViewChild('section', { static: true }) sectionElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(HeaderFooterService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + listResource = this.ser.list(); - @ViewChild('section', { static: true }) sectionElement?: ElementRef; - form: FormGroup<{ - id: FormControl; - text: FormControl; - }>; + list = computed(() => this.listResource.value() ?? []); - list: HeaderFooter[] = []; - id = ''; + formModel = linkedSignal({ + source: () => { + const list = this.list(); + let currentId = this.id(); + if (!currentId && list.length > 0) { + currentId = list[0].id; + } + return { list, id: currentId }; + }, + computation: ({ list, id }): HeaderFooterFormData => { + const val = list.find((v) => v.id === id); + return { + id: id ?? '', + text: val?.text ?? '', + }; + }, + }); - constructor() { - const route = this.route; - - // Create form - this.form = new FormGroup({ - id: new FormControl('', { nonNullable: true }), - text: new FormControl('', { nonNullable: true }), - }); - route.params.pipe(map((p) => p['id'])).subscribe((x) => { - this.id = x; - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: HeaderFooter[] }; - this.showItem(data.list); - }); - } - - showItem(list: HeaderFooter[]) { - this.list = list; - this.id = this.id ?? this.list[0].id; - const val = this.list.find((v) => v.id === this.id) as HeaderFooter; - this.form.setValue({ - id: this.id, - text: val.text, - }); - } + form = form(this.formModel); save() { this.ser.save(this.getItem()).subscribe({ next: (result: HeaderFooter[]) => { this.snackBar.open('', 'Success'); - this.showItem(result); + this.listResource.value.set(result); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } getItem(): HeaderFooter { - const formModel = this.form.value; - const item = this.list.find((v) => v.id === this.id); + const formModel = this.formModel(); + const item = this.list().find((v) => v.id === formModel.id); if (item === undefined) { return new HeaderFooter(); } - item.text = formModel.text ?? ''; - return item; + const clonedItem = Object.assign(new HeaderFooter(), item); + clonedItem.text = formModel.text ?? ''; + return clonedItem; } show(val: MatSelectChange) { diff --git a/bookie/src/app/header-footer/header-footer.resolver.spec.ts b/bookie/src/app/header-footer/header-footer.resolver.spec.ts deleted file mode 100644 index 9b93d4d..0000000 --- a/bookie/src/app/header-footer/header-footer.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { HeaderFooterResolver } from './header-footer-resolver.service'; - -describe('HeaderFooterResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [HeaderFooterResolver], - }); - }); - - it('should be created', inject([HeaderFooterResolver], (service: HeaderFooterResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/header-footer/header-footer.resolver.ts b/bookie/src/app/header-footer/header-footer.resolver.ts deleted file mode 100644 index 6c90f11..0000000 --- a/bookie/src/app/header-footer/header-footer.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { HeaderFooter } from './header-footer'; -import { HeaderFooterService } from './header-footer.service'; - -export const headerFooterResolver: ResolveFn = () => { - return inject(HeaderFooterService).list(); -}; diff --git a/bookie/src/app/header-footer/header-footer.routes.ts b/bookie/src/app/header-footer/header-footer.routes.ts index c21be34..dc34e86 100644 --- a/bookie/src/app/header-footer/header-footer.routes.ts +++ b/bookie/src/app/header-footer/header-footer.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { HeaderFooterComponent } from './header-footer.component'; -import { headerFooterResolver } from './header-footer.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Owner', }, - resolve: { - list: headerFooterResolver, - }, }, { path: ':id', @@ -23,8 +19,5 @@ export const routes: Routes = [ data: { permission: 'Owner', }, - resolve: { - list: headerFooterResolver, - }, }, ]; diff --git a/bookie/src/app/header-footer/header-footer.service.ts b/bookie/src/app/header-footer/header-footer.service.ts index 952630c..727beea 100644 --- a/bookie/src/app/header-footer/header-footer.service.ts +++ b/bookie/src/app/header-footer/header-footer.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,10 +19,8 @@ export class HeaderFooterService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - list(): Observable { - return this.http.get(url).pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable< - HeaderFooter[] - >; + list(): HttpResourceRef { + return httpResource(() => url); } save(item: HeaderFooter): Observable { diff --git a/bookie/src/app/menu-category/menu-categories.routes.ts b/bookie/src/app/menu-category/menu-categories.routes.ts index 47e55f6..19f258d 100644 --- a/bookie/src/app/menu-category/menu-categories.routes.ts +++ b/bookie/src/app/menu-category/menu-categories.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { MenuCategoryDetailComponent } from './menu-category-detail/menu-category-detail.component'; -import { menuCategoryListResolver } from './menu-category-list.resolver'; import { MenuCategoryListComponent } from './menu-category-list/menu-category-list.component'; -import { menuCategoryResolver } from './menu-category.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - list: menuCategoryListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: menuCategoryResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: menuCategoryResolver, - }, }, ]; diff --git a/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html index 731b01f..34a668f 100644 --- a/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html +++ b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.html @@ -1,19 +1,23 @@

Menu Category

-
+
Name - +
- Is Active? + Is Active?
- - @if (!!item.id) { - + + @if (!!item().id) { + }
diff --git a/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts index 06d000d..59d754a 100644 --- a/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts +++ b/bookie/src/app/menu-category/menu-category-detail/menu-category-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -12,49 +12,40 @@ import { MenuCategory } from '../../core/menu-category'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { MenuCategoryService } from '../menu-category.service'; +export interface MenuCategoryDetailFormData { + name: string; + isActive: boolean; +} + @Component({ selector: 'app-menu-category-detail', templateUrl: './menu-category-detail.component.html', styleUrls: ['./menu-category-detail.component.css'], - imports: [MatButtonModule, MatCheckboxModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatCheckboxModule, MatFormFieldModule, MatInputModule, FormField], }) -export class MenuCategoryDetailComponent implements OnInit, AfterViewInit { +export class MenuCategoryDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(MenuCategoryService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - isActive: FormControl; - }>; + itemResource = this.ser.get(this.id); - item: MenuCategory = new MenuCategory(); + item = computed(() => this.itemResource.value() ?? new MenuCategory()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): MenuCategoryDetailFormData => { + return { + name: itemVal.name, + isActive: itemVal.isActive, + }; + }, + }); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - isActive: new FormControl(true, { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: MenuCategory }; - this.showItem(data.item); - }); - } - - showItem(item: MenuCategory) { - this.item = item; - this.form.setValue({ - name: this.item.name, - isActive: this.item.isActive, - }); - } + form = form(this.formModel); ngAfterViewInit() { setTimeout(() => { @@ -70,20 +61,20 @@ export class MenuCategoryDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/menu-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/menu-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -102,9 +93,11 @@ export class MenuCategoryDetailComponent implements OnInit, AfterViewInit { } getItem(): MenuCategory { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.isActive = formModel.isActive ?? true; - return this.item; + const formModel = this.formModel(); + return new MenuCategory({ + ...this.item(), + name: formModel.name ?? '', + isActive: formModel.isActive ?? true, + }); } } diff --git a/bookie/src/app/menu-category/menu-category-list.resolver.spec.ts b/bookie/src/app/menu-category/menu-category-list.resolver.spec.ts deleted file mode 100644 index 1309cbc..0000000 --- a/bookie/src/app/menu-category/menu-category-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { MenuCategoryListResolver } from './menu-category-list-resolver.service'; - -describe('MenuCategoryListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [MenuCategoryListResolver], - }); - }); - - it('should be created', inject([MenuCategoryListResolver], (service: MenuCategoryListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/menu-category/menu-category-list.resolver.ts b/bookie/src/app/menu-category/menu-category-list.resolver.ts deleted file mode 100644 index e90afbf..0000000 --- a/bookie/src/app/menu-category/menu-category-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { MenuCategory } from '../core/menu-category'; -import { MenuCategoryService } from './menu-category.service'; - -export const menuCategoryListResolver: ResolveFn = () => { - return inject(MenuCategoryService).list(false); -}; diff --git a/bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts b/bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts deleted file mode 100644 index 3cae71c..0000000 --- a/bookie/src/app/menu-category/menu-category-list/menu-category-list-datasource.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; - -import { MenuCategory } from '../../core/menu-category'; - -export class MenuCategoryListDatasource extends DataSource { - private data: MenuCategory[] = []; - - constructor(private readonly dataObs: Observable) { - super(); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - return this.dataObs; - } - - disconnect() {} -} diff --git a/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html index a6206dc..7461994 100644 --- a/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.html @@ -1,6 +1,6 @@

Menu Categories - + add_box Add @@ -9,8 +9,8 @@ diff --git a/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts index d65c4bd..c1cd85b 100644 --- a/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts +++ b/bookie/src/app/menu-category/menu-category-list/menu-category-list.component.ts @@ -1,63 +1,46 @@ import { CdkDragDrop, moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop'; -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; +import { firstValueFrom } from 'rxjs'; import { MenuCategory } from '../../core/menu-category'; import { MenuCategoryService } from '../menu-category.service'; -import { MenuCategoryListDatasource } from './menu-category-list-datasource'; - @Component({ selector: 'app-menu-category-list', templateUrl: './menu-category-list.component.html', styleUrls: ['./menu-category-list.component.css'], imports: [DragDropModule, MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class MenuCategoryListComponent implements OnInit { +export class MenuCategoryListComponent { private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private ser = inject(MenuCategoryService); + listResource = this.ser.list(undefined); + + dataSource = computed(() => this.listResource.value() ?? []); - // @ViewChild('table', { static: true }) table?: MatTable; - list: MenuCategory[] = []; - data: BehaviorSubject = new BehaviorSubject(this.list); - dataSource: MenuCategoryListDatasource = new MenuCategoryListDatasource(this.data); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'isActive', 'isFixture']; - constructor() { - this.data.subscribe((data: MenuCategory[]) => { - this.list = data; - }); + async updateSortOrder() { + try { + await firstValueFrom(this.ser.updateSortOrder(this.dataSource())); + this.snackBar.open('', 'Success'); + this.listResource.reload(); + } catch (error) { + this.snackBar.open(error as string, 'Error'); + } } - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: MenuCategory[] }; - this.data.next(data.list); - }); - this.dataSource = new MenuCategoryListDatasource(this.data); - } - - updateSortOrder() { - this.ser.updateSortOrder(this.list).subscribe({ - next: () => { - this.snackBar.open('', 'Success'); - }, - error: (error) => { - this.snackBar.open(error, 'Error'); - }, - }); - } - - dropTable(event: CdkDragDrop) { - const prevIndex = this.list.indexOf(event.item.data); - moveItemInArray(this.list, prevIndex, event.currentIndex); - this.data.next(this.list); + dropTable(event: CdkDragDrop) { + const arr = [...this.dataSource()]; + const prevIndex = arr.findIndex((d) => d === event.item.data); + moveItemInArray(arr, prevIndex, event.currentIndex); + this.listResource.set(arr); } } diff --git a/bookie/src/app/menu-category/menu-category.resolver.spec.ts b/bookie/src/app/menu-category/menu-category.resolver.spec.ts deleted file mode 100644 index 32c4642..0000000 --- a/bookie/src/app/menu-category/menu-category.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { MenuCategoryResolver } from './menu-category-resolver.service'; - -describe('MenuCategoriesResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [MenuCategoryResolver], - }); - }); - - it('should be created', inject([MenuCategoryResolver], (service: MenuCategoryResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/menu-category/menu-category.resolver.ts b/bookie/src/app/menu-category/menu-category.resolver.ts deleted file mode 100644 index ec7fc76..0000000 --- a/bookie/src/app/menu-category/menu-category.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { MenuCategory } from '../core/menu-category'; -import { MenuCategoryService } from './menu-category.service'; - -export const menuCategoryResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(MenuCategoryService).get(id); -}; diff --git a/bookie/src/app/menu-category/menu-category.service.ts b/bookie/src/app/menu-category/menu-category.service.ts index 4623d15..f1d9350 100644 --- a/bookie/src/app/menu-category/menu-category.service.ts +++ b/bookie/src/app/menu-category/menu-category.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,21 +19,21 @@ export class MenuCategoryService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(shouldHaveActiveProducts: boolean | undefined): Observable { - const options = { params: new HttpParams() }; - if (shouldHaveActiveProducts) { - options.params = options.params.set('p', 'true'); - } - return this.http - .get(`${url}/list`, options) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(shouldHaveActiveProducts: boolean | undefined): HttpResourceRef { + return httpResource(() => { + const options = { params: new HttpParams() }; + if (shouldHaveActiveProducts) { + options.params = options.params.set('p', 'true'); + } + return { url: `${url}/list`, ...options }; + }); } save(menuCategory: MenuCategory): Observable { diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report-datasource.ts b/bookie/src/app/menu-engineering-report/menu-engineering-report-datasource.ts deleted file mode 100644 index b8b0cc2..0000000 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report-datasource.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { EventEmitter } from '@angular/core'; -import { MatPaginator, PageEvent } from '@angular/material/paginator'; -import { MatSort, Sort } from '@angular/material/sort'; -import { merge, Observable, of as observableOf } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { MenuEngineeringReportItem } from './menu-engineering-report-item'; - -/** Simple sort comparator for example ID/Name columns (for client-side sorting). */ -const compare = (a: string | number | boolean, b: string | number | boolean, isAsc: boolean) => - (a < b ? -1 : 1) * (isAsc ? 1 : -1); -export class MenuEngineeringReportDataSource extends DataSource { - private filterValue = ''; - constructor( - public data: MenuEngineeringReportItem[], - private filter: Observable, - private paginator?: MatPaginator, - private sort?: MatSort, - ) { - super(); - this.filter = filter.pipe( - tap((x) => { - this.filterValue = x; - }), - ); - } - - connect(): Observable { - const dataMutations: (EventEmitter | EventEmitter)[] = []; - if (this.paginator) { - dataMutations.push((this.paginator as MatPaginator).page); - } - if (this.sort) { - dataMutations.push((this.sort as MatSort).sortChange); - } - return merge(observableOf(this.data), this.filter, ...dataMutations) - .pipe( - map(() => this.getFilteredData([...this.data])), - map((x) => this.recalculate(x)), - tap((x: MenuEngineeringReportItem[]) => { - if (this.paginator) { - this.paginator.length = x.length; - } - }), - ) - .pipe(map((x: MenuEngineeringReportItem[]) => this.getPagedData(this.getSortedData(x)))); - } - - disconnect() {} - - private getFilteredData(data: MenuEngineeringReportItem[]): MenuEngineeringReportItem[] { - return this.filterValue.split(' ').reduce( - (p: MenuEngineeringReportItem[], c: string) => - p.filter((x) => { - if (c.startsWith('n:')) { - return x.name.toLowerCase().indexOf(c.substring(2)) !== -1; - } - if (c.startsWith('sc:')) { - return x.saleCategory.toLowerCase().indexOf(c.substring(3)) !== -1; - } - if (c.startsWith('mc:')) { - return x.menuCategory.toLowerCase().indexOf(c.substring(3)) !== -1; - } - if (c.startsWith('q:')) { - const result = c.match(/^q:(?=|<=|>=|<|>)(?\d*)$/); - if (result && result.groups) { - return math_it_up(result.groups['sign'])(x.quantity, +result.groups['amount']); - } - } - if (c.startsWith('s:')) { - const result = c.match(/^s:(?=|<=|>=|<|>)(?\d*)$/); - if (result && result.groups) { - return math_it_up(result.groups['sign'])(x.sales, +result.groups['amount']); - } - } - const itemString = `${x.name} ${x.saleCategory} ${x.menuCategory}`.toLowerCase(); - return itemString.indexOf(c) !== -1; - }), - Object.assign([], data), - ); - } - - private recalculate(data: MenuEngineeringReportItem[]): MenuEngineeringReportItem[] { - const gr = data.reduce(function (res: Record, value: MenuEngineeringReportItem) { - if (!res[value['saleCategory']]) { - res[value['saleCategory']] = { q: 0, s: 0 }; - } - res[value['saleCategory']].q += value.quantity; - res[value['saleCategory']].s += value.sales; - return res; - }, {}); - data.forEach((v) => { - v.quantityPercent = v.quantity / gr[v.saleCategory].q; - v.salesPercent = v.sales / gr[v.saleCategory].s; - }); - return data; - } - - private getPagedData(data: MenuEngineeringReportItem[]) { - if (this.paginator === undefined) { - return data; - } - const startIndex = this.paginator.pageIndex * this.paginator.pageSize; - return data.splice(startIndex, this.paginator.pageSize); - } - - private getSortedData(data: MenuEngineeringReportItem[]): MenuEngineeringReportItem[] { - if (this.sort === undefined) { - return data; - } - if (!this.sort.active || this.sort.direction === '') { - return data; - } - - const sort = this.sort as MatSort; - return data.sort((a, b) => { - const isAsc = sort.direction === 'asc'; - switch (sort.active) { - case 'name': - return compare(a.name, b.name, isAsc); - case 'price': - return compare(a.price, b.price, isAsc); - case 'saleCategory': - return compare(a.saleCategory, b.saleCategory, isAsc); - case 'menuCategory': - return compare(a.menuCategory, b.menuCategory, isAsc); - case 'quantity': - return compare(a.quantity, b.quantity, isAsc); - case 'sales': - return compare(a.sales, b.sales, isAsc); - default: - return 0; - } - }); - } -} - -function eq(x: number, y: number) { - return x === y; -} -function gt(x: number, y: number) { - return x > y; -} -function lt(x: number, y: number) { - return x < y; -} -function gte(x: number, y: number) { - return x >= y; -} -function lte(x: number, y: number) { - return x <= y; -} - -function math_it_up(sign: string) { - if (sign == '=') { - return eq; - } - if (sign == '>') { - return gt; - } - if (sign == '<') { - return lt; - } - if (sign == '>=') { - return gte; - } - if (sign == '<=') { - return lte; - } - return eq; -} diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report.component.html b/bookie/src/app/menu-engineering-report/menu-engineering-report.component.html index d372507..62e25fb 100644 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report.component.html +++ b/bookie/src/app/menu-engineering-report/menu-engineering-report.component.html @@ -1,15 +1,15 @@

Menu Engineering Report - -

-
+
Start Date @@ -17,7 +17,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -29,18 +29,18 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> - +
Filter - + n: Name, sc: Sale Category, mc: Menu Category, q:(=/<=/>=/</>)Quantity, s:(=/<=/>=/</>)Sales
- + Name @@ -95,7 +95,7 @@ v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('filterElement', { static: true }) filterElement?: ElementRef; - @ViewChild(MatPaginator, { static: true }) paginator?: MatPaginator; - @ViewChild(MatSort, { static: true }) sort?: MatSort; - info: MenuEngineeringReport = new MenuEngineeringReport(); + infoResource = this.ser.get(this.startDate, this.finishDate); + + info = computed(() => this.infoResource.value() ?? new MenuEngineeringReport()); filter: Observable; - dataSource: MenuEngineeringReportDataSource; - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - filter: FormControl; - }>; + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): MenuEngineeringReportFormData => { + if (infoVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + filter: '', + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + filter: '', + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'price', 'saleCategory', 'menuCategory', 'quantity', 'sales']; constructor() { // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - filter: new FormControl('', { nonNullable: true }), - }); // Listen to Filter Change - this.filter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()); - this.dataSource = new MenuEngineeringReportDataSource(this.info.amounts, this.filter); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: MenuEngineeringReport }; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - filter: '', - }); - this.dataSource = new MenuEngineeringReportDataSource(this.info.amounts, this.filter, this.paginator, this.sort); - }); + const filterSignal = computed(() => this.formModel().filter); + this.filter = toObservable(filterSignal).pipe(debounceTime(150), distinctUntilChanged()); } show() { @@ -97,7 +102,7 @@ export class MenuEngineeringReportComponent implements OnInit { } getInfo(): MenuEngineeringReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new MenuEngineeringReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -106,12 +111,12 @@ export class MenuEngineeringReportComponent implements OnInit { } print() { - this.ser.print(this.info.startDate, this.info.finishDate).subscribe({ + this.ser.print(this.info().startDate, this.info().finishDate).subscribe({ next: () => { this.snackBar.open('Successfully Printed', ''); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -126,7 +131,7 @@ export class MenuEngineeringReportComponent implements OnInit { Quantity: 'quantity', Sales: 'sales', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.spec.ts b/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.spec.ts deleted file mode 100644 index 66d2c2d..0000000 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { MenuEngineeringReportResolver } from './menu-engineering-report-resolver.service'; - -describe('MenuEngineeringReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [MenuEngineeringReportResolver], - }); - }); - - it('should be created', inject([MenuEngineeringReportResolver], (service: MenuEngineeringReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.ts b/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.ts deleted file mode 100644 index d479230..0000000 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { MenuEngineeringReport } from './menu-engineering-report'; -import { MenuEngineeringReportService } from './menu-engineering-report.service'; - -export const menuEngineeringReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(MenuEngineeringReportService).get(startDate, finishDate); -}; diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report.routes.ts b/bookie/src/app/menu-engineering-report/menu-engineering-report.routes.ts index eafb4b8..07544f5 100644 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report.routes.ts +++ b/bookie/src/app/menu-engineering-report/menu-engineering-report.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { MenuEngineeringReportComponent } from './menu-engineering-report.component'; -import { menuEngineeringReportResolver } from './menu-engineering-report.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Product Sale Report', }, - resolve: { - info: menuEngineeringReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/menu-engineering-report/menu-engineering-report.service.ts b/bookie/src/app/menu-engineering-report/menu-engineering-report.service.ts index 0b4f295..5436ee7 100644 --- a/bookie/src/app/menu-engineering-report/menu-engineering-report.service.ts +++ b/bookie/src/app/menu-engineering-report/menu-engineering-report.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,17 +16,22 @@ export class MenuEngineeringReportService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url, params }; + }); } print(startDate: string | null, finishDate: string | null): Observable { diff --git a/bookie/src/app/modifier-categories/modifier-categories.routes.ts b/bookie/src/app/modifier-categories/modifier-categories.routes.ts index a9c5d79..cd48d33 100644 --- a/bookie/src/app/modifier-categories/modifier-categories.routes.ts +++ b/bookie/src/app/modifier-categories/modifier-categories.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { ModifierCategoryDetailComponent } from './modifier-category-detail/modifier-category-detail.component'; -import { modifierCategoryListResolver } from './modifier-category-list.resolver'; import { ModifierCategoryListComponent } from './modifier-category-list/modifier-category-list.component'; -import { modifierCategoryResolver } from './modifier-category.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - list: modifierCategoryListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - item: modifierCategoryResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - item: modifierCategoryResolver, - }, }, ]; diff --git a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.html b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.html index e9fd634..dfd9a69 100644 --- a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.html +++ b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.html @@ -1,23 +1,23 @@

Modifier Category

-
+
Name - +
Minimum - + Maximum - +
- Is Active? + Is Active?
@@ -26,7 +26,7 @@
  • - +
  • - - + +
    diff --git a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts index bb1c30e..2ab79e9 100644 --- a/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts +++ b/bookie/src/app/modifier-categories/modifier-category-detail/modifier-category-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, effect, inject, input, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -10,7 +10,6 @@ import { MatInputModule } from '@angular/material/input'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTreeModule, MatTreeNestedDataSource } from '@angular/material/tree'; import { ActivatedRoute, Router } from '@angular/router'; -import { map } from 'rxjs/operators'; import { ModifierCategory, MenuCategory, StockKeepingUnitLink } from '../../core/modifier-category'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; @@ -27,6 +26,13 @@ interface ModifierCategoryNode { children?: ModifierCategoryNode[]; } +export interface ModifierCategoryDetailFormData { + name: string; + minimum: number; + maximum: number | null; + isActive: boolean; +} + @Component({ selector: 'app-role-detail', templateUrl: './modifier-category-detail.component.html', @@ -39,23 +45,28 @@ interface ModifierCategoryNode { MatIconModule, MatInputModule, MatTreeModule, - ReactiveFormsModule, + FormField, ], }) -export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { +export class ModifierCategoryDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(ModifierCategoryService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - minimum: FormControl; - maximum: FormControl; - isActive: FormControl; - }>; + itemResource = this.ser.get(this.id); + + formModel = signal({ + name: '', + minimum: 0, + maximum: null, + isActive: true, + }); + + form = form(this.formModel); childrenAccessor = (node: ModifierCategoryNode) => node.children ?? []; hasChild = (_: number, node: ModifierCategoryNode) => !!node.children && node.children.length > 0; @@ -66,55 +77,37 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { productsOfMenuCategory: Map = new Map(); constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - minimum: new FormControl(0, { nonNullable: true }), - maximum: new FormControl(null), - isActive: new FormControl(true, { nonNullable: true }), - }); this.dataSource.data = []; - } - - ngOnInit() { - this.route.data - .pipe( - map((value) => { - const data = value as { item: ModifierCategory }; - const tree: NodeItem[] = data.item.menuCategories.map((x: MenuCategory) => ({ - id: x.id as string, - name: x.name, - children: x.skus.map((y: StockKeepingUnitLink) => ({ id: y.id as string, name: y.name })), - })); - return { item: data.item, tree }; - }), - ) - .subscribe((data) => { - this.showItem(data.item, data.tree); - }); - } - - showItem(item: ModifierCategory, tree: NodeItem[]) { - this.item = item; - this.dataSource.data = tree; - this.form.patchValue({ - name: this.item.name ?? '', - minimum: this.item.minimum, - maximum: this.item.maximum, - isActive: this.item.isActive, + effect(() => { + const itemVal = this.itemResource.value(); + if (itemVal) { + this.item = itemVal; + const tree: NodeItem[] = this.item.menuCategories.map((x: MenuCategory) => ({ + id: x.id as string, + name: x.name, + children: x.skus.map((y: StockKeepingUnitLink) => ({ id: y.id as string, name: y.name })), + })); + this.dataSource.data = tree; + this.formModel.update((f) => ({ + ...f, + name: this.item.name ?? '', + minimum: this.item.minimum, + maximum: this.item.maximum, + isActive: this.item.isActive, + })); + this.products = new Map(); + this.productsOfMenuCategory = new Map(); + this.item.menuCategories.forEach((mc: MenuCategory) => { + mc.skus.forEach((p: StockKeepingUnitLink) => { + this.products.set(p.id as string, p); + if (!this.productsOfMenuCategory.has(mc.id as string)) { + this.productsOfMenuCategory.set(mc.id as string, []); + } + (this.productsOfMenuCategory.get(mc.id as string) as StockKeepingUnitLink[]).push(p); + }); + }); + } }); - this.products = new Map(); - this.productsOfMenuCategory = new Map(); - this.item.menuCategories.forEach((mc: MenuCategory) => { - mc.skus.forEach((p: StockKeepingUnitLink) => { - this.products.set(p.id as string, p); - if (!this.productsOfMenuCategory.has(mc.id as string)) { - this.productsOfMenuCategory.set(mc.id as string, []); - } - (this.productsOfMenuCategory.get(mc.id as string) as StockKeepingUnitLink[]).push(p); - }); - }); - // this.setMenuCategories(); } ngAfterViewInit() { @@ -136,8 +129,8 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/modifier-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -148,8 +141,8 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/modifier-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -168,7 +161,7 @@ export class ModifierCategoryDetailComponent implements OnInit, AfterViewInit { } getItem(): ModifierCategory { - const formModel = this.form.value; + const formModel = this.formModel(); this.item.name = formModel.name ?? ''; this.item.minimum = formModel.minimum ?? 0; this.item.maximum = formModel.maximum ?? null; diff --git a/bookie/src/app/modifier-categories/modifier-category-list.resolver.spec.ts b/bookie/src/app/modifier-categories/modifier-category-list.resolver.spec.ts deleted file mode 100644 index df515c9..0000000 --- a/bookie/src/app/modifier-categories/modifier-category-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ModifierCategoryListResolver } from './modifier-category-list-resolver.service'; - -describe('ModifierCategoryListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ModifierCategoryListResolver], - }); - }); - - it('should be created', inject([ModifierCategoryListResolver], (service: ModifierCategoryListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/modifier-categories/modifier-category-list.resolver.ts b/bookie/src/app/modifier-categories/modifier-category-list.resolver.ts deleted file mode 100644 index 47fc2d4..0000000 --- a/bookie/src/app/modifier-categories/modifier-category-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { ModifierCategory } from '../core/modifier-category'; -import { ModifierCategoryService } from './modifier-category.service'; - -export const modifierCategoryListResolver: ResolveFn = () => { - return inject(ModifierCategoryService).list(); -}; diff --git a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list-datasource.ts b/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list-datasource.ts deleted file mode 100644 index 91b73e4..0000000 --- a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { ModifierCategory } from '../../core/modifier-category'; - -export class ModifierCategoryListDatasource extends DataSource { - constructor(public data: ModifierCategory[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.html b/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.html index 17606d0..d43dade 100644 --- a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.html +++ b/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.html @@ -5,7 +5,7 @@ Add
  • - + Name diff --git a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.ts b/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.ts index 238a366..4614140 100644 --- a/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.ts +++ b/bookie/src/app/modifier-categories/modifier-category-list/modifier-category-list.component.ts @@ -1,31 +1,21 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { ModifierCategory } from '../../core/modifier-category'; -import { ModifierCategoryListDatasource } from './modifier-category-list-datasource'; - +import { ModifierCategoryService } from '../modifier-category.service'; @Component({ selector: 'app-modifier-category-list', templateUrl: './modifier-category-list.component.html', styleUrls: ['./modifier-category-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class ModifierCategoryListComponent implements OnInit { +export class ModifierCategoryListComponent { + private modifierCategoryService = inject(ModifierCategoryService); private route = inject(ActivatedRoute); + listResource = this.modifierCategoryService.list(); - list: ModifierCategory[] = []; - dataSource: ModifierCategoryListDatasource = new ModifierCategoryListDatasource(this.list); - /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ + dataSource = computed(() => this.listResource.value() ?? []); displayedColumns = ['name', 'minimum', 'maximum', 'products', 'isActive']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: ModifierCategory[] }; - this.list = data.list; - }); - this.dataSource = new ModifierCategoryListDatasource(this.list); - } } diff --git a/bookie/src/app/modifier-categories/modifier-category.resolver.spec.ts b/bookie/src/app/modifier-categories/modifier-category.resolver.spec.ts deleted file mode 100644 index b2073cf..0000000 --- a/bookie/src/app/modifier-categories/modifier-category.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ModifierCategoryResolver } from './modifier-category-resolver.service'; - -describe('ModifierCategoryResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ModifierCategoryResolver], - }); - }); - - it('should be created', inject([ModifierCategoryResolver], (service: ModifierCategoryResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/modifier-categories/modifier-category.resolver.ts b/bookie/src/app/modifier-categories/modifier-category.resolver.ts deleted file mode 100644 index 69aacdc..0000000 --- a/bookie/src/app/modifier-categories/modifier-category.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { ModifierCategory } from '../core/modifier-category'; -import { ModifierCategoryService } from './modifier-category.service'; - -export const modifierCategoryResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(ModifierCategoryService).get(id); -}; diff --git a/bookie/src/app/modifier-categories/modifier-category.service.ts b/bookie/src/app/modifier-categories/modifier-category.service.ts index 199dab0..d527c5d 100644 --- a/bookie/src/app/modifier-categories/modifier-category.service.ts +++ b/bookie/src/app/modifier-categories/modifier-category.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class ModifierCategoryService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } listForSku(sku_id: string): Observable { diff --git a/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.html b/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.html index b4a5979..5916bfc 100644 --- a/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.html +++ b/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.html @@ -1,40 +1,43 @@

    Modifier

    -
    +
    Name - +
    - Show In Bill? + Show In Bill?
    Price - +
    Category - - @for (mc of modifierCategories; track mc) { + + @for (mc of modifierCategories(); track mc) { {{ mc.name }} } + @for (error of form.modifierCategory().errors(); track error) { + {{ error.message }} + }
    - Is Active? + Is Active?
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.ts b/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.ts index ba4edaf..9487636 100644 --- a/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.ts +++ b/bookie/src/app/modifiers/modifier-detail/modifier-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField, required } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; @@ -12,73 +12,64 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Modifier } from '../../core/modifier'; import { ModifierCategory } from '../../core/modifier-category'; +import { ModifierCategoryService } from '../../modifier-categories/modifier-category.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { ModifierService } from '../modifier.service'; +export interface ModifierDetailFormData { + name: string; + showInBill: boolean; + price: number; + modifierCategory: string; + isActive: boolean; +} + @Component({ selector: 'app-modifier-detail', templateUrl: './modifier-detail.component.html', styleUrls: ['./modifier-detail.component.css'], imports: [ MatButtonModule, - MatCheckboxModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, - - ReactiveFormsModule, + FormField, ], }) -export class ModifierDetailComponent implements OnInit, AfterViewInit { +export class ModifierDetailComponent implements AfterViewInit { + @ViewChild('name', { static: true }) nameElement?: ElementRef; + private modifierCategoryService = inject(ModifierCategoryService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(ModifierService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('name', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - showInBill: FormControl; - price: FormControl; - modifierCategory: FormControl; - isActive: FormControl; - }>; + modifierCategoriesResource = this.modifierCategoryService.list(); + modifierCategories = computed(() => this.modifierCategoriesResource.value() ?? []); - modifierCategories: ModifierCategory[] = []; - item: Modifier = new Modifier(); + itemResource = this.ser.get(this.id); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - showInBill: new FormControl(true, { nonNullable: true }), - price: new FormControl(0, { nonNullable: true }), - modifierCategory: new FormControl('', { nonNullable: true }), - isActive: new FormControl(true, { nonNullable: true }), - }); - } + item = computed(() => this.itemResource.value() ?? new Modifier()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): ModifierDetailFormData => { + return { + name: itemVal.name ?? '', + showInBill: itemVal.showInBill, + price: itemVal.price ?? 0, + isActive: itemVal.isActive, + modifierCategory: itemVal.modifierCategory ? (itemVal.modifierCategory.id as string) : '', + }; + }, + }); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Modifier; modifierCategories: ModifierCategory[] }; - this.modifierCategories = data.modifierCategories; - this.showItem(data.item); - }); - } - - showItem(item: Modifier) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - showInBill: this.item.showInBill, - price: this.item.price ?? 0, - isActive: this.item.isActive, - modifierCategory: this.item.modifierCategory ? (this.item.modifierCategory.id as string) : '', - }); - } + form = form(this.formModel, (schema) => { + required(schema.modifierCategory, { message: 'Modifier Category is required' }); + }); ngAfterViewInit() { setTimeout(() => { @@ -94,20 +85,20 @@ export class ModifierDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/modifiers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/modifiers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -126,12 +117,14 @@ export class ModifierDetailComponent implements OnInit, AfterViewInit { } getItem(): Modifier { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.showInBill = formModel.showInBill ?? false; - this.item.price = formModel.price ?? 0; - this.item.isActive = formModel.isActive ?? true; - this.item.modifierCategory = new ModifierCategory({ id: formModel.modifierCategory }); - return this.item; + const formModel = this.formModel(); + return new Modifier({ + ...this.item(), + name: formModel.name ?? '', + showInBill: formModel.showInBill ?? false, + price: formModel.price ?? 0, + isActive: formModel.isActive ?? true, + modifierCategory: new ModifierCategory({ id: formModel.modifierCategory }), + }); } } diff --git a/bookie/src/app/modifiers/modifier-list.resolver.spec.ts b/bookie/src/app/modifiers/modifier-list.resolver.spec.ts deleted file mode 100644 index 881c9de..0000000 --- a/bookie/src/app/modifiers/modifier-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ModifierListResolver } from './modifier-list-resolver.service'; - -describe('ModifierListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ModifierListResolver], - }); - }); - - it('should be created', inject([ModifierListResolver], (service: ModifierListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/modifiers/modifier-list.resolver.ts b/bookie/src/app/modifiers/modifier-list.resolver.ts deleted file mode 100644 index d0eaf75..0000000 --- a/bookie/src/app/modifiers/modifier-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Modifier } from '../core/modifier'; -import { ModifierService } from './modifier.service'; - -export const modifierListResolver: ResolveFn = () => { - return inject(ModifierService).list(); -}; diff --git a/bookie/src/app/modifiers/modifier-list/modifier-list-datasource.ts b/bookie/src/app/modifiers/modifier-list/modifier-list-datasource.ts deleted file mode 100644 index cf11f73..0000000 --- a/bookie/src/app/modifiers/modifier-list/modifier-list-datasource.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { merge, Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { Modifier } from '../../core/modifier'; -import { ModifierCategory } from '../../core/modifier-category'; - -export class ModifierListDataSource extends DataSource { - public data: Modifier[]; - public viewData: Modifier[]; - private filterValue: string; - - constructor( - private readonly filter: Observable, - private readonly dataObs: Observable, - ) { - super(); - this.data = []; - this.viewData = []; - this.filterValue = ''; - this.filter = filter.pipe( - tap((x) => { - this.filterValue = x; - }), - ); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - const dataMutations = [this.dataObs, this.filter]; - - return merge(...dataMutations).pipe( - map(() => { - this.viewData = this.getFilteredData([...this.data]); - return this.viewData; - }), - ); - } - - disconnect() {} - - private getFilteredData(data: Modifier[]): Modifier[] { - const filter = this.filterValue === undefined ? '' : this.filterValue; - return data.filter((x) => (x.modifierCategory as ModifierCategory).id === filter || filter === ''); - } -} diff --git a/bookie/src/app/modifiers/modifier-list/modifier-list.component.html b/bookie/src/app/modifiers/modifier-list/modifier-list.component.html index 62fce67..4d877a8 100644 --- a/bookie/src/app/modifiers/modifier-list/modifier-list.component.html +++ b/bookie/src/app/modifiers/modifier-list/modifier-list.component.html @@ -5,13 +5,13 @@ Add -
    +
    Modifier Category - + -- All Categories -- - @for (mc of modifierCategories; track mc) { + @for (mc of modifierCategories(); track mc.id) { {{ mc.name }} @@ -20,7 +20,7 @@
    - + Name diff --git a/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts b/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts index e1f2726..26049fe 100644 --- a/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts +++ b/bookie/src/app/modifiers/modifier-list/modifier-list.component.ts @@ -1,18 +1,15 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, signal } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatSelectChange, MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; -import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; +import { RouterLink } from '@angular/router'; -import { Modifier } from '../../core/modifier'; -import { ModifierCategory } from '../../core/modifier-category'; -import { ModifierListDataSource } from './modifier-list-datasource'; +import { ModifierCategoryService } from '../../modifier-categories/modifier-category.service'; +import { ModifierService } from '../modifier.service'; @Component({ selector: 'app-modifier-list', @@ -21,52 +18,37 @@ import { ModifierListDataSource } from './modifier-list-datasource'; imports: [ CurrencyPipe, MatButtonModule, - MatFormFieldModule, MatIconModule, MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, RouterLink, ], }) -export class ModifierListComponent implements OnInit { - private route = inject(ActivatedRoute); - private router = inject(Router); +export class ModifierListComponent { + private modifierService = inject(ModifierService); + private modifierCategoryService = inject(ModifierCategoryService); - // @ViewChild('table', { static: true }) table?: MatTable; - filter = new BehaviorSubject(''); - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: ModifierListDataSource = new ModifierListDataSource(this.filter, this.data); - form: FormGroup<{ - modifierCategory: FormControl; - }>; + modifierCategoriesResource = this.modifierCategoryService.list(); + listResource = this.modifierService.list(); + + modifierCategories = computed(() => this.modifierCategoriesResource.value() ?? []); + filter = signal(''); + + dataSource = computed(() => { + const items = this.listResource.value() ?? []; + const cat = this.filter(); + if (cat) { + return items.filter((x) => x.modifierCategory?.id === cat); + } + return items; + }); - list: Modifier[] = []; - modifierCategories: ModifierCategory[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns: string[] = ['name', 'showInBill', 'price', 'isActive', 'modifierCategory']; - constructor() { - this.form = new FormGroup({ - modifierCategory: new FormControl(''), - }); - this.data.subscribe((data: Modifier[]) => { - this.list = data; - }); - } - - filterOn(val: MatSelectChange) { - this.filter.next(val.value); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Modifier[]; modifierCategories: ModifierCategory[] }; - this.data.next(data.list); - this.modifierCategories = data.modifierCategories; - }); - this.dataSource = new ModifierListDataSource(this.filter, this.data); + filterOn(val: MatSelectChange): void { + this.filter.set(val.value); } } diff --git a/bookie/src/app/modifiers/modifier.resolver.spec.ts b/bookie/src/app/modifiers/modifier.resolver.spec.ts deleted file mode 100644 index 78f27fa..0000000 --- a/bookie/src/app/modifiers/modifier.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ModifierResolver } from './modifier-resolver.service'; - -describe('ModifierResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ModifierResolver], - }); - }); - - it('should be created', inject([ModifierResolver], (service: ModifierResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/modifiers/modifier.resolver.ts b/bookie/src/app/modifiers/modifier.resolver.ts deleted file mode 100644 index 69bf86e..0000000 --- a/bookie/src/app/modifiers/modifier.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Modifier } from '../core/modifier'; -import { ModifierService } from './modifier.service'; - -export const modifierResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(ModifierService).get(id); -}; diff --git a/bookie/src/app/modifiers/modifier.service.ts b/bookie/src/app/modifiers/modifier.service.ts index 77d905f..5be4b9e 100644 --- a/bookie/src/app/modifiers/modifier.service.ts +++ b/bookie/src/app/modifiers/modifier.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -18,17 +18,15 @@ export class ModifierService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'getList'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(modifier: Modifier): Observable { diff --git a/bookie/src/app/modifiers/modifiers.routes.ts b/bookie/src/app/modifiers/modifiers.routes.ts index 05ac01e..8458eff 100644 --- a/bookie/src/app/modifiers/modifiers.routes.ts +++ b/bookie/src/app/modifiers/modifiers.routes.ts @@ -1,11 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { modifierCategoryListResolver } from '../modifier-categories/modifier-category-list.resolver'; import { ModifierDetailComponent } from './modifier-detail/modifier-detail.component'; -import { modifierListResolver } from './modifier-list.resolver'; import { ModifierListComponent } from './modifier-list/modifier-list.component'; -import { modifierResolver } from './modifier.resolver'; export const routes: Routes = [ { @@ -15,10 +12,6 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - list: modifierListResolver, - modifierCategories: modifierCategoryListResolver, - }, }, { path: 'new', @@ -27,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - item: modifierResolver, - modifierCategories: modifierCategoryListResolver, - }, }, { path: ':id', @@ -39,9 +28,5 @@ export const routes: Routes = [ data: { permission: 'Modifiers', }, - resolve: { - item: modifierResolver, - modifierCategories: modifierCategoryListResolver, - }, }, ]; diff --git a/bookie/src/app/printers/printer-detail/printer-detail.component.html b/bookie/src/app/printers/printer-detail/printer-detail.component.html index 208cd71..c77beb3 100644 --- a/bookie/src/app/printers/printer-detail/printer-detail.component.html +++ b/bookie/src/app/printers/printer-detail/printer-detail.component.html @@ -1,26 +1,26 @@

    Printer

    -
    +
    Name - +
    Address - + Cut Code - +
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/printers/printer-detail/printer-detail.component.ts b/bookie/src/app/printers/printer-detail/printer-detail.component.ts index 966b91a..d236ce1 100644 --- a/bookie/src/app/printers/printer-detail/printer-detail.component.ts +++ b/bookie/src/app/printers/printer-detail/printer-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -11,52 +11,42 @@ import { Printer } from '../../core/printer'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { PrinterService } from '../printer.service'; +export interface PrinterDetailFormData { + name: string; + address: string; + cutCode: string; +} + @Component({ selector: 'app-printer-detail', templateUrl: './printer-detail.component.html', styleUrls: ['./printer-detail.component.css'], - imports: [MatButtonModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatFormFieldModule, MatInputModule, FormField], }) -export class PrinterDetailComponent implements OnInit, AfterViewInit { +export class PrinterDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(PrinterService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - address: FormControl; - cutCode: FormControl; - }>; + itemResource = this.ser.get(this.id); - item: Printer = new Printer(); + item = computed(() => this.itemResource.value() ?? new Printer()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): PrinterDetailFormData => { + return { + name: itemVal.name ?? '', + address: itemVal.address ?? '', + cutCode: itemVal.cutCode ?? '', + }; + }, + }); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - address: new FormControl('', { nonNullable: true }), - cutCode: new FormControl('', { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Printer }; - this.showItem(data.item); - }); - } - - showItem(item: Printer) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - address: this.item.address ?? '', - cutCode: this.item.cutCode ?? '', - }); - } + form = form(this.formModel); ngAfterViewInit() { setTimeout(() => { @@ -72,20 +62,20 @@ export class PrinterDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/printers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/printers'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -104,10 +94,12 @@ export class PrinterDetailComponent implements OnInit, AfterViewInit { } getItem(): Printer { - const formModel = this.form.value; - this.item.name = formModel.name; - this.item.address = formModel.address; - this.item.cutCode = formModel.cutCode; - return this.item; + const formModel = this.formModel(); + return new Printer({ + ...this.item(), + name: formModel.name ?? '', + address: formModel.address ?? '', + cutCode: formModel.cutCode ?? '', + }); } } diff --git a/bookie/src/app/printers/printer-list.resolver.spec.ts b/bookie/src/app/printers/printer-list.resolver.spec.ts deleted file mode 100644 index c7a0993..0000000 --- a/bookie/src/app/printers/printer-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { PrinterListResolver } from './printer-list-resolver.service'; - -describe('PrinterListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [PrinterListResolver], - }); - }); - - it('should be created', inject([PrinterListResolver], (service: PrinterListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/printers/printer-list.resolver.ts b/bookie/src/app/printers/printer-list.resolver.ts deleted file mode 100644 index efae83e..0000000 --- a/bookie/src/app/printers/printer-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Printer } from '../core/printer'; -import { PrinterService } from './printer.service'; - -export const printerListResolver: ResolveFn = () => { - return inject(PrinterService).list(); -}; diff --git a/bookie/src/app/printers/printer-list/printer-list-datasource.ts b/bookie/src/app/printers/printer-list/printer-list-datasource.ts deleted file mode 100644 index 9d464a8..0000000 --- a/bookie/src/app/printers/printer-list/printer-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Printer } from '../../core/printer'; - -export class PrinterListDataSource extends DataSource { - constructor(public data: Printer[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/printers/printer-list/printer-list.component.html b/bookie/src/app/printers/printer-list/printer-list.component.html index af559b1..b2fc556 100644 --- a/bookie/src/app/printers/printer-list/printer-list.component.html +++ b/bookie/src/app/printers/printer-list/printer-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/printers/printer-list/printer-list.component.ts b/bookie/src/app/printers/printer-list/printer-list.component.ts index 7daaab7..32f5135 100644 --- a/bookie/src/app/printers/printer-list/printer-list.component.ts +++ b/bookie/src/app/printers/printer-list/printer-list.component.ts @@ -1,31 +1,22 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Printer } from '../../core/printer'; -import { PrinterListDataSource } from './printer-list-datasource'; - +import { PrinterService } from '../printer.service'; @Component({ selector: 'app-printer-list', templateUrl: './printer-list.component.html', styleUrls: ['./printer-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class PrinterListComponent implements OnInit { +export class PrinterListComponent { + private printerService = inject(PrinterService); private route = inject(ActivatedRoute); + listResource = this.printerService.list(); - list: Printer[] = []; - dataSource: PrinterListDataSource = new PrinterListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'address', 'cutCode']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Printer[] }; - this.list = data.list; - }); - this.dataSource = new PrinterListDataSource(this.list); - } } diff --git a/bookie/src/app/printers/printer.resolver.spec.ts b/bookie/src/app/printers/printer.resolver.spec.ts deleted file mode 100644 index 73b0731..0000000 --- a/bookie/src/app/printers/printer.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { PrinterResolver } from './printer-resolver.service'; - -describe('PrinterResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [PrinterResolver], - }); - }); - - it('should be created', inject([PrinterResolver], (service: PrinterResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/printers/printer.resolver.ts b/bookie/src/app/printers/printer.resolver.ts deleted file mode 100644 index cef2fa1..0000000 --- a/bookie/src/app/printers/printer.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Printer } from '../core/printer'; -import { PrinterService } from './printer.service'; - -export const printerResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(PrinterService).get(id); -}; diff --git a/bookie/src/app/printers/printer.service.ts b/bookie/src/app/printers/printer.service.ts index 6c6d2b7..7aa4023 100644 --- a/bookie/src/app/printers/printer.service.ts +++ b/bookie/src/app/printers/printer.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class PrinterService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(printer: Printer): Observable { diff --git a/bookie/src/app/printers/printers.routes.ts b/bookie/src/app/printers/printers.routes.ts index bb0daba..e0b54b8 100644 --- a/bookie/src/app/printers/printers.routes.ts +++ b/bookie/src/app/printers/printers.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { PrinterDetailComponent } from './printer-detail/printer-detail.component'; -import { printerListResolver } from './printer-list.resolver'; import { PrinterListComponent } from './printer-list/printer-list.component'; -import { printerResolver } from './printer.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Printers', }, - resolve: { - list: printerListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Printers', }, - resolve: { - item: printerResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Printers', }, - resolve: { - item: printerResolver, - }, }, ]; diff --git a/bookie/src/app/product-sale-report/product-sale-report-datasource.ts b/bookie/src/app/product-sale-report/product-sale-report-datasource.ts deleted file mode 100644 index 09c93ca..0000000 --- a/bookie/src/app/product-sale-report/product-sale-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { ProductSaleReportItem } from './product-sale-report-item'; - -export class ProductSaleReportDataSource extends DataSource { - constructor(public data: ProductSaleReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/product-sale-report/product-sale-report.component.html b/bookie/src/app/product-sale-report/product-sale-report.component.html index 575b3f8..c6b1721 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.component.html +++ b/bookie/src/app/product-sale-report/product-sale-report.component.html @@ -1,15 +1,15 @@

    Product Sale Report - -

    -
    +
    Start Date @@ -17,7 +17,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -29,7 +29,7 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> @@ -37,19 +37,19 @@ Section - + -- All -- - @for (p of sections; track p.id) { + @for (p of sections(); track p.id) { {{ p.name }} } - +
    - + Name diff --git a/bookie/src/app/product-sale-report/product-sale-report.component.ts b/bookie/src/app/product-sale-report/product-sale-report.component.ts index 5c411e7..303f208 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.component.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.component.ts @@ -1,6 +1,6 @@ import { DecimalPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -12,12 +12,17 @@ import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; -import { Section } from '../core/section'; +import { SectionService } from '../sections/section.service'; import { ToCsvService } from '../shared/to-csv.service'; import { ProductSaleReport } from './product-sale-report'; -import { ProductSaleReportDataSource } from './product-sale-report-datasource'; import { ProductSaleReportService } from './product-sale-report.service'; +export interface ProductSaleReportFormData { + startDate: Date; + finishDate: Date; + section: string | null; +} + @Component({ selector: 'app-product-sale-report', templateUrl: './product-sale-report.component.html', @@ -25,58 +30,56 @@ import { ProductSaleReportService } from './product-sale-report.service'; imports: [ DecimalPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class ProductSaleReportComponent implements OnInit { +export class ProductSaleReportComponent { + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); private snackBar = inject(MatSnackBar); private ser = inject(ProductSaleReportService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + section = input(null, { transform: (v: string | null | undefined) => v ?? null }); - sections: Section[] = []; - info: ProductSaleReport = new ProductSaleReport(); - dataSource: ProductSaleReportDataSource = new ProductSaleReportDataSource(this.info.amounts); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - section: FormControl; - }>; + infoResource = this.ser.get(this.startDate, this.finishDate, this.section); + + sectionsResource = this.sectionService.list(); + + sections = computed(() => this.sectionsResource.value() ?? []); + info = computed(() => this.infoResource.value() ?? new ProductSaleReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: () => this.sectionsResource.value(), + computation: (sectionsVal): ProductSaleReportFormData => { + if (sectionsVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + section: this.info().sectionId || null, + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + section: null, + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'unbilled', 'sale', 'noCharge', 'staff', 'cancel']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - section: new FormControl(null), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { sections: Section[]; info: ProductSaleReport }; - this.sections = data.sections; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - section: this.info.sectionId || null, - }); - this.dataSource = new ProductSaleReportDataSource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); const params = { @@ -92,7 +95,7 @@ export class ProductSaleReportComponent implements OnInit { } getInfo(): ProductSaleReport { - const formModel = this.form.value; + const formModel = this.formModel(); const data = new ProductSaleReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -105,12 +108,12 @@ export class ProductSaleReportComponent implements OnInit { } print() { - this.ser.print(this.info.startDate, this.info.finishDate, this.info.sectionId).subscribe({ + this.ser.print(this.info().startDate, this.info().finishDate, this.info().sectionId).subscribe({ next: () => { this.snackBar.open('Successfully Printed', ''); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -124,7 +127,7 @@ export class ProductSaleReportComponent implements OnInit { Staff: 'staff', Void: 'void', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/product-sale-report/product-sale-report.resolver.spec.ts b/bookie/src/app/product-sale-report/product-sale-report.resolver.spec.ts deleted file mode 100644 index 2734b2f..0000000 --- a/bookie/src/app/product-sale-report/product-sale-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ProductSaleReportResolver } from './product-sale-report-resolver.service'; - -describe('ProductSaleReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductSaleReportResolver], - }); - }); - - it('should be created', inject([ProductSaleReportResolver], (service: ProductSaleReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product-sale-report/product-sale-report.resolver.ts b/bookie/src/app/product-sale-report/product-sale-report.resolver.ts deleted file mode 100644 index eb80f52..0000000 --- a/bookie/src/app/product-sale-report/product-sale-report.resolver.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { ProductSaleReport } from './product-sale-report'; -import { ProductSaleReportService } from './product-sale-report.service'; - -export const productSaleReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - const section = route.queryParamMap.get('section') ?? null; - return inject(ProductSaleReportService).get(startDate, finishDate, section); -}; diff --git a/bookie/src/app/product-sale-report/product-sale-report.routes.ts b/bookie/src/app/product-sale-report/product-sale-report.routes.ts index 85e65ff..2031caf 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.routes.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { sectionListResolver } from '../sections/section-list.resolver'; import { ProductSaleReportComponent } from './product-sale-report.component'; -import { productSaleReportResolver } from './product-sale-report.resolver'; export const routes: Routes = [ { @@ -13,10 +11,6 @@ export const routes: Routes = [ data: { permission: 'Product Sale Report', }, - resolve: { - sections: sectionListResolver, - info: productSaleReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/product-sale-report/product-sale-report.service.ts b/bookie/src/app/product-sale-report/product-sale-report.service.ts index 13f4034..4483288 100644 --- a/bookie/src/app/product-sale-report/product-sale-report.service.ts +++ b/bookie/src/app/product-sale-report/product-sale-report.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,20 +16,27 @@ export class ProductSaleReportService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(startDate: string | null, finishDate: string | null, section: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - if (section !== null) { - options.params = options.params.set('section', section); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + section: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + const sec = section(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + if (sec !== null) { + params = params.set('section', sec); + } + return { url, params }; + }); } print(startDate: string | null, finishDate: string | null, section: string | null): Observable { diff --git a/bookie/src/app/product-updates-report/product-updates-report-datasource.ts b/bookie/src/app/product-updates-report/product-updates-report-datasource.ts deleted file mode 100644 index 42bd083..0000000 --- a/bookie/src/app/product-updates-report/product-updates-report-datasource.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -export class ProductUpdatesReportDataSource extends DataSource { - constructor(public data: string[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/product-updates-report/product-updates-report.component.html b/bookie/src/app/product-updates-report/product-updates-report.component.html index ff3aabc..e5e416a 100644 --- a/bookie/src/app/product-updates-report/product-updates-report.component.html +++ b/bookie/src/app/product-updates-report/product-updates-report.component.html @@ -1,11 +1,11 @@

    Product Update Report -

    -
    +
    Start Date @@ -13,7 +13,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -25,16 +25,16 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> - +
    - + Details diff --git a/bookie/src/app/product-updates-report/product-updates-report.component.ts b/bookie/src/app/product-updates-report/product-updates-report.component.ts index 8cc5304..de78d5e 100644 --- a/bookie/src/app/product-updates-report/product-updates-report.component.ts +++ b/bookie/src/app/product-updates-report/product-updates-report.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -11,7 +11,12 @@ import moment from 'moment'; import { ToCsvService } from '../shared/to-csv.service'; import { ProductUpdatesReport } from './product-updates-report'; -import { ProductUpdatesReportDataSource } from './product-updates-report-datasource'; +import { ProductUpdatesReportService } from './product-updates-report.service'; + +export interface ProductUpdatesReportFormData { + startDate: Date; + finishDate: Date; +} @Component({ selector: 'app-product-updates-report', @@ -19,50 +24,47 @@ import { ProductUpdatesReportDataSource } from './product-updates-report-datasou styleUrls: ['./product-updates-report.component.css'], imports: [ MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class ProductUpdatesReportComponent implements OnInit { +export class ProductUpdatesReportComponent { + private productUpdatesReportService = inject(ProductUpdatesReportService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - info: ProductUpdatesReport = new ProductUpdatesReport(); - dataSource: ProductUpdatesReportDataSource = new ProductUpdatesReportDataSource(this.info.report); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - }>; + infoResource = this.productUpdatesReportService.get(this.startDate, this.finishDate); + + info = computed(() => this.infoResource.value() ?? new ProductUpdatesReport()); + dataSource = computed(() => this.info().report); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): ProductUpdatesReportFormData => { + if (infoVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['details']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: ProductUpdatesReport }; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - }); - this.dataSource = new ProductUpdatesReportDataSource(this.info.report); - }); - } - show() { const info = this.getInfo(); this.router.navigate(['product-updates-report'], { @@ -74,7 +76,7 @@ export class ProductUpdatesReportComponent implements OnInit { } getInfo(): ProductUpdatesReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new ProductUpdatesReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -86,7 +88,7 @@ export class ProductUpdatesReportComponent implements OnInit { const headers = { Details: 'details', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/product-updates-report/product-updates-report.resolver.spec.ts b/bookie/src/app/product-updates-report/product-updates-report.resolver.spec.ts deleted file mode 100644 index feabd81..0000000 --- a/bookie/src/app/product-updates-report/product-updates-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ProductUpdatesReportResolver } from './product-updates-report-resolver.service'; - -describe('ProductUpdatesReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductUpdatesReportResolver], - }); - }); - - it('should be created', inject([ProductUpdatesReportResolver], (service: ProductUpdatesReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product-updates-report/product-updates-report.resolver.ts b/bookie/src/app/product-updates-report/product-updates-report.resolver.ts deleted file mode 100644 index d502e32..0000000 --- a/bookie/src/app/product-updates-report/product-updates-report.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { ProductUpdatesReport } from './product-updates-report'; -import { ProductUpdatesReportService } from './product-updates-report.service'; - -export const productUpdatesReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(ProductUpdatesReportService).get(startDate, finishDate); -}; diff --git a/bookie/src/app/product-updates-report/product-updates-report.routes.ts b/bookie/src/app/product-updates-report/product-updates-report.routes.ts index 4a0769f..f7580cd 100644 --- a/bookie/src/app/product-updates-report/product-updates-report.routes.ts +++ b/bookie/src/app/product-updates-report/product-updates-report.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { ProductUpdatesReportComponent } from './product-updates-report.component'; -import { productUpdatesReportResolver } from './product-updates-report.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - info: productUpdatesReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/product-updates-report/product-updates-report.service.ts b/bookie/src/app/product-updates-report/product-updates-report.service.ts index 843e162..a3868e5 100644 --- a/bookie/src/app/product-updates-report/product-updates-report.service.ts +++ b/bookie/src/app/product-updates-report/product-updates-report.service.ts @@ -1,31 +1,29 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; -import { Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal } from '@angular/core'; -import { ErrorLoggerService } from '../core/error-logger.service'; import { ProductUpdatesReport } from './product-updates-report'; const url = '/api/product-updates-report'; -const serviceName = 'ProductUpdatesReportService'; @Injectable({ providedIn: 'root', }) export class ProductUpdatesReportService { - private http = inject(HttpClient); - private log = inject(ErrorLoggerService); - - get(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url, params }; + }); } } diff --git a/bookie/src/app/product/product-detail/product-detail-datasource.ts b/bookie/src/app/product/product-detail/product-detail-datasource.ts deleted file mode 100644 index fbaafeb..0000000 --- a/bookie/src/app/product/product-detail/product-detail-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -import { StockKeepingUnit } from '../../core/product'; - -export class ProductDetailDatasource extends DataSource { - constructor(private data: Observable) { - super(); - } - - connect(): Observable { - return this.data; - } - - disconnect() {} -} diff --git a/bookie/src/app/product/product-detail/product-detail-dialog.component.html b/bookie/src/app/product/product-detail/product-detail-dialog.component.html index 3efa9c2..a4ca500 100644 --- a/bookie/src/app/product/product-detail/product-detail-dialog.component.html +++ b/bookie/src/app/product/product-detail/product-detail-dialog.component.html @@ -1,35 +1,50 @@

    Edit Product SKU

    -
    +
    Units - + + @for (error of form.units().errors(); track error) { + {{ error.message }} + } Fraction - + + @for (error of form.fraction().errors(); track error) { + {{ error.message }} + } Yield - + + @for (error of form.productYield().errors(); track error) { + {{ error.message }} + } Cost Price - + + @for (error of form.costPrice().errors(); track error) { + {{ error.message }} + } Sale Price - + + @for (error of form.salePrice().errors(); track error) { + {{ error.message }} + } Menu Category - + @for (mc of menuCategories; track mc) { {{ mc.name }} @@ -38,13 +53,13 @@ - Has Happy Hour? - Not Available? + Has Happy Hour? + Not Available?
    - +
    diff --git a/bookie/src/app/product/product-detail/product-detail-dialog.component.ts b/bookie/src/app/product/product-detail/product-detail-dialog.component.ts index aec8679..79a285b 100644 --- a/bookie/src/app/product/product-detail/product-detail-dialog.component.ts +++ b/bookie/src/app/product/product-detail/product-detail-dialog.component.ts @@ -1,6 +1,6 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { Component, inject, OnInit } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, OnInit, signal } from '@angular/core'; +import { form, FormField, required, min, max } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; @@ -11,6 +11,17 @@ import { MatSelectModule } from '@angular/material/select'; import { MenuCategory } from '../../core/menu-category'; import { StockKeepingUnit } from '../../core/product'; +export interface ProductDetailDialogFormData { + units: string; + fraction: number; + productYield: number; + costPrice: number; + salePrice: number; + menuCategory: string; + hasHappyHour: boolean; + isNotAvailable: boolean; +} + @Component({ selector: 'app-product-detail-dialog', templateUrl: './product-detail-dialog.component.html', @@ -24,7 +35,7 @@ import { StockKeepingUnit } from '../../core/product'; MatFormFieldModule, MatInputModule, MatSelectModule, - ReactiveFormsModule, + FormField, ], }) export class ProductDetailDialogComponent implements OnInit { @@ -43,33 +54,29 @@ export class ProductDetailDialogComponent implements OnInit { menuCategories: MenuCategory[]; }>(MAT_DIALOG_DATA); - form: FormGroup<{ - units: FormControl; - fraction: FormControl; - productYield: FormControl; - costPrice: FormControl; - salePrice: FormControl; - menuCategory: FormControl; - hasHappyHour: FormControl; - isNotAvailable: FormControl; - }>; + formModel = signal({ + units: '', + fraction: 1, + productYield: 1, + costPrice: 0, + salePrice: 0, + menuCategory: '', + hasHappyHour: false, + isNotAvailable: false, + }); - constructor() { - this.form = new FormGroup({ - units: new FormControl('', { nonNullable: true }), - fraction: new FormControl(1, { nonNullable: true }), - productYield: new FormControl(1, { nonNullable: true }), - costPrice: new FormControl(0, { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - menuCategory: new FormControl('', { nonNullable: true }), - hasHappyHour: new FormControl(false, { nonNullable: true }), - isNotAvailable: new FormControl(false, { nonNullable: true }), - }); - } + form = form(this.formModel, (schemaPath) => { + required(schemaPath.units, { message: 'Units cannot be blank' }); + min(schemaPath.fraction, 1, { message: 'Fraction cannot be less than 1' }); + min(schemaPath.productYield, 0.0001, { message: 'Yield must be greater than 0' }); + max(schemaPath.productYield, 1, { message: 'Yield must be less than or equal to 1' }); + min(schemaPath.costPrice, 0, { message: 'Cost price cannot be negative' }); + min(schemaPath.salePrice, 0, { message: 'Sale price cannot be negative' }); + }); ngOnInit(): void { // Populate from the row being edited - this.form.setValue({ + this.formModel.set({ units: this.data.item.units ?? '', fraction: this.data.item.fraction ?? 1, productYield: this.data.item.productYield ?? 1, @@ -83,28 +90,13 @@ export class ProductDetailDialogComponent implements OnInit { } accept(): void { - const formValue = this.form.value; - const fraction = formValue.fraction ?? 0; - if (fraction < 1) { - return; - } - const productYield = formValue.productYield ?? 0; - if (productYield < 0 || productYield > 1) { - return; - } - const costPrice = formValue.costPrice ?? 0; - if (costPrice < 0) { - return; - } - const salePrice = formValue.salePrice ?? 0; - if (salePrice < 0) { - return; - } + if (this.form().invalid()) return; + const formValue = this.formModel(); this.data.item.units = (formValue.units ?? '').trim(); - this.data.item.fraction = fraction; - this.data.item.productYield = productYield; - this.data.item.costPrice = costPrice; - this.data.item.salePrice = salePrice; + this.data.item.fraction = formValue.fraction ?? 1; + this.data.item.productYield = formValue.productYield ?? 1; + this.data.item.costPrice = formValue.costPrice ?? 0; + this.data.item.salePrice = formValue.salePrice ?? 0; this.data.item.hasHappyHour = formValue.hasHappyHour ?? false; this.data.item.isNotAvailable = formValue.isNotAvailable ?? false; if (this.data.item.menuCategory === null || this.data.item.menuCategory === undefined) { diff --git a/bookie/src/app/product/product-detail/product-detail.component.html b/bookie/src/app/product/product-detail/product-detail.component.html index d4c9696..4bcd12a 100644 --- a/bookie/src/app/product/product-detail/product-detail.component.html +++ b/bookie/src/app/product/product-detail/product-detail.component.html @@ -1,77 +1,104 @@

    Product

    -
    +
    Name - + Fraction Units - +
    Sale Category - - @for (sc of saleCategories; track sc) { + + @for (sc of saleCategories(); track sc) { {{ sc.name }} } - Enabled? + Enabled?

    Stock Keeping Units

    -
    +
    Units - + + @for (error of form.addRow.units().errors(); track error) { + {{ error.message }} + } Fraction - + + @for (error of form.addRow.fraction().errors(); track error) { + {{ error.message }} + } Yield - + + @for (error of form.addRow.productYield().errors(); track error) { + {{ error.message }} + } Cost Price - + + @for (error of form.addRow.costPrice().errors(); track error) { + {{ error.message }} + } Sale Price - + + @for (error of form.addRow.salePrice().errors(); track error) { + {{ error.message }} + } Menu Category - - @for (mc of menuCategories; track mc) { + + @for (mc of menuCategories(); track mc) { {{ mc.name }} } + @for (error of form.addRow.menuCategory().errors(); track error) { + {{ error.message }} + } - Has Happy Hour? - Not Available? + Has Happy Hour? + Not Available? - +
    - + Units @@ -130,10 +157,10 @@ Action - - @@ -144,8 +171,8 @@
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/product/product-detail/product-detail.component.ts b/bookie/src/app/product/product-detail/product-detail.component.ts index aafefa0..225b3e4 100644 --- a/bookie/src/app/product/product-detail/product-detail.component.ts +++ b/bookie/src/app/product/product-detail/product-detail.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField, required, min, max } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; @@ -12,16 +12,34 @@ import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; import { MenuCategory } from '../../core/menu-category'; import { Product, StockKeepingUnit } from '../../core/product'; import { SaleCategory } from '../../core/sale-category'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; +import { SaleCategoryService } from '../../sale-category/sale-category.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { ProductService } from '../product.service'; -import { ProductDetailDatasource } from './product-detail-datasource'; import { ProductDetailDialogComponent } from './product-detail-dialog.component'; +export interface ProductDetailFormData { + name: string; + fractionUnits: string; + saleCategory: string; + enabled: boolean; + addRow: { + units: string; + fraction: number; + productYield: number; + costPrice: number; + salePrice: number; + menuCategory: string; + hasHappyHour: boolean; + isNotAvailable: boolean; + }; + skus: StockKeepingUnit[]; +} + @Component({ selector: 'app-product-detail', templateUrl: './product-detail.component.html', @@ -36,42 +54,62 @@ import { ProductDetailDialogComponent } from './product-detail-dialog.component' MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class ProductDetailComponent implements OnInit, AfterViewInit { +export class ProductDetailComponent implements AfterViewInit { + @ViewChild('name', { static: true }) nameElement?: ElementRef; + private menuCategoryService = inject(MenuCategoryService); + private saleCategoryService = inject(SaleCategoryService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(ProductService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('name', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - // Product fields - name: FormControl; - fractionUnits: FormControl; - saleCategory: FormControl; - enabled: FormControl; + saleCategoriesResource = this.saleCategoryService.list(); - // SKU add/edit row - addRow: FormGroup<{ - units: FormControl; - fraction: FormControl; - productYield: FormControl; - costPrice: FormControl; - salePrice: FormControl; - menuCategory: FormControl; - hasHappyHour: FormControl; - isNotAvailable: FormControl; - }>; - }>; + menuCategoriesResource = this.menuCategoryService.list(undefined); - menuCategories: MenuCategory[] = []; - saleCategories: SaleCategory[] = []; - public skus = new BehaviorSubject([]); - dataSource: ProductDetailDatasource = new ProductDetailDatasource(this.skus); - item: Product = new Product(); + itemResource = this.ser.get(this.id); + + item = computed(() => this.itemResource.value() ?? new Product()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): ProductDetailFormData => { + return { + name: itemVal.name ?? '', + fractionUnits: itemVal.fractionUnits ?? '', + saleCategory: itemVal.saleCategory?.id ?? '', + enabled: itemVal.enabled ?? true, + addRow: { + units: '', + fraction: 1, + productYield: 1, + costPrice: 0, + salePrice: 0, + menuCategory: '', + hasHappyHour: false, + isNotAvailable: false, + }, + skus: [...(itemVal.skus ?? [])], + }; + }, + }); + + form = form(this.formModel, (schemaPath) => { + required(schemaPath.addRow.units, { message: 'Units cannot be blank' }); + min(schemaPath.addRow.fraction, 1, { message: 'Fraction cannot be less than 1' }); + min(schemaPath.addRow.productYield, 0.0001, { message: 'Yield must be greater than 0' }); + max(schemaPath.addRow.productYield, 1, { message: 'Yield must be less than or equal to 1' }); + min(schemaPath.addRow.costPrice, 0, { message: 'Cost price cannot be negative' }); + min(schemaPath.addRow.salePrice, 0, { message: 'Sale price cannot be negative' }); + required(schemaPath.addRow.menuCategory, { message: 'Menu category is required' }); + }); + + menuCategories = computed(() => this.menuCategoriesResource.value() ?? []); + saleCategories = computed(() => this.saleCategoriesResource.value() ?? []); displayedColumns = [ 'units', @@ -85,48 +123,47 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { 'action', ]; - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - fractionUnits: new FormControl('', { nonNullable: true }), - saleCategory: new FormControl('', { nonNullable: true }), - enabled: new FormControl(true, { nonNullable: true }), + ngAfterViewInit() { + setTimeout(() => { + if (this.nameElement !== undefined) { + this.nameElement.nativeElement.focus(); + } + }, 0); + } - addRow: new FormGroup({ - units: new FormControl('', { nonNullable: true }), - fraction: new FormControl(1, { nonNullable: true }), - productYield: new FormControl(1, { nonNullable: true }), - costPrice: new FormControl(0, { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - menuCategory: new FormControl('', { nonNullable: true }), - hasHappyHour: new FormControl(false, { nonNullable: true }), - isNotAvailable: new FormControl(false, { nonNullable: true }), + addRow() { + if (this.form.addRow().invalid()) return; + const formValue = this.formModel().addRow; + if (formValue === undefined) { + return; + } + const units = (formValue.units ?? '').trim(); + const fraction = Number(formValue.fraction ?? 1); + const productYield = Number(formValue.productYield ?? 1); + const costPrice = Number(formValue.costPrice ?? 0); + const salePrice = Number(formValue.salePrice ?? 0); + const menuCategoryId = formValue.menuCategory ?? ''; + const sku = new StockKeepingUnit({ + units, + fraction, + productYield, + costPrice, + salePrice, + menuCategory: new MenuCategory({ + id: menuCategoryId, + name: this.menuCategories().find((x) => x.id === menuCategoryId)?.name ?? '', }), + hasHappyHour: formValue.hasHappyHour ?? false, + isNotAvailable: formValue.isNotAvailable ?? false, }); + this.formModel.update((m) => ({ ...m, skus: [...m.skus, sku] })); + this.resetAddRow(); + // console.log('Added SKU', sku, this.item().skus); } - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { - item: Product; - menuCategories: MenuCategory[]; - saleCategories: SaleCategory[]; - }; - this.menuCategories = data.menuCategories; - this.saleCategories = data.saleCategories; - this.showItem(data.item); - }); - } - - showItem(item: Product) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - fractionUnits: this.item.fractionUnits ?? '', - saleCategory: this.item.saleCategory?.id ?? '', - enabled: this.item.enabled ?? true, - + resetAddRow() { + this.formModel.update((m) => ({ + ...m, addRow: { units: '', fraction: 1, @@ -137,74 +174,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { hasHappyHour: false, isNotAvailable: false, }, - }); - this.skus.next(this.item.skus); - } - - ngAfterViewInit() { - setTimeout(() => { - if (this.nameElement !== undefined) { - this.nameElement.nativeElement.focus(); - } - }, 0); - } - - addRow() { - const formValue = this.form.value.addRow; - if (formValue === undefined) { - return; - } - const units = (formValue.units ?? '').trim(); - if (units.length < 1) { - this.snackBar.open('Units cannot be blank', 'Error'); - return; - } - const fraction = Number(formValue.fraction ?? 1); - if (Number.isNaN(fraction) || fraction < 1) { - this.snackBar.open('Fraction has to be >= 1', 'Error'); - return; - } - const productYield = Number(formValue.productYield ?? 1); - if (Number.isNaN(productYield) || productYield <= 0 || productYield > 1) { - this.snackBar.open('Product Yield has to be > 0 and <= 1', 'Error'); - return; - } - const costPrice = Number(formValue.costPrice ?? 0); - if (Number.isNaN(costPrice) || costPrice < 0) { - this.snackBar.open('Cost Price has to be >= 0', 'Error'); - return; - } - const salePrice = Number(formValue.salePrice ?? 0); - if (Number.isNaN(salePrice) || salePrice < 0) { - this.snackBar.open('Sale Price has to be >= 0', 'Error'); - return; - } - const menuCategoryId = formValue.menuCategory ?? ''; - if (!menuCategoryId) { - this.snackBar.open('Menu Category is required', 'Error'); - return; - } - const sku = new StockKeepingUnit({ - units, - fraction, - productYield, - costPrice, - salePrice, - menuCategory: new MenuCategory({ - id: menuCategoryId, - name: this.menuCategories.find((x) => x.id === menuCategoryId)?.name ?? '', - }), - hasHappyHour: formValue.hasHappyHour ?? false, - isNotAvailable: formValue.isNotAvailable ?? false, - }); - this.item.skus.push(sku); - this.skus.next(this.item.skus); - this.resetAddRow(); - // console.log('Added SKU', sku, this.item.skus); - } - - resetAddRow() { - this.form.controls.addRow.reset(); + })); } editRow(row: StockKeepingUnit) { @@ -220,7 +190,7 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { menuCategory: row.menuCategory?.id ?? '', hasHappyHour: row.hasHappyHour, isNotAvailable: row.isNotAvailable, - menuCategories: this.menuCategories, + menuCategories: this.menuCategories(), }, }); dialogRef.afterClosed().subscribe((result: boolean | StockKeepingUnit) => { @@ -228,15 +198,16 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { return; } const j = result as StockKeepingUnit; - Object.assign(row, j); - this.skus.next(this.item.skus); + this.formModel.update((m) => ({ + ...m, + skus: m.skus.map((s) => (s === row ? Object.assign(new StockKeepingUnit(s), j) : s)), + })); this.resetAddRow(); }); } deleteRow(row: StockKeepingUnit) { - this.item.skus.splice(this.item.skus.indexOf(row), 1); - this.skus.next(this.item.skus); + this.formModel.update((m) => ({ ...m, skus: m.skus.filter((s) => s !== row) })); } save() { @@ -245,20 +216,20 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/products'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/products'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -277,34 +248,26 @@ export class ProductDetailComponent implements OnInit, AfterViewInit { } getItem(): Product { - const formModel = this.form.value; + const formModel = this.formModel(); - this.item.name = formModel.name ?? ''; - this.item.fractionUnits = formModel.fractionUnits ?? ''; - this.item.sortOrder = this.item.sortOrder ?? 0; - this.item.enabled = formModel.enabled ?? true; - - // Sale Category (by id) - if (this.item.saleCategory === null || this.item.saleCategory === undefined) { - this.item.saleCategory = new SaleCategory(); - } - this.item.saleCategory.id = formModel.saleCategory ?? ''; - - // Ensure skus list exists - if (!this.item.skus) { - this.item.skus = []; - } - - return this.item; + return new Product({ + ...this.item(), + name: formModel.name ?? '', + fractionUnits: formModel.fractionUnits ?? '', + sortOrder: this.item().sortOrder ?? 0, + enabled: formModel.enabled ?? true, + saleCategory: new SaleCategory({ id: formModel.saleCategory ?? '' }), + skus: formModel.skus, + }); } } -// if (this.item.menuCategory === null || this.item.menuCategory === undefined) { -// this.item.menuCategory = new MenuCategory(); +// if (this.item().menuCategory === null || this.item().menuCategory === undefined) { +// this.item().menuCategory = new MenuCategory(); // } -// this.item.menuCategory.id = formModel.menuCategory; +// this.item().menuCategory.id = formModel.menuCategory; -// this.item.price = formModel.price ?? 0; -// this.item.hasHappyHour = formModel.hasHappyHour ?? false; -// this.item.isNotAvailable = formModel.isNotAvailable ?? false; -// this.item.quantity = formModel.quantity ?? 0; +// this.item().price = formModel.price ?? 0; +// this.item().hasHappyHour = formModel.hasHappyHour ?? false; +// this.item().isNotAvailable = formModel.isNotAvailable ?? false; +// this.item().quantity = formModel.quantity ?? 0; diff --git a/bookie/src/app/product/product-list.resolver.spec.ts b/bookie/src/app/product/product-list.resolver.spec.ts deleted file mode 100644 index 4c2e796..0000000 --- a/bookie/src/app/product/product-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ProductListResolver } from './product-list-resolver.service'; - -describe('ProductListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductListResolver], - }); - }); - - it('should be created', inject([ProductListResolver], (service: ProductListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product/product-list.resolver.ts b/bookie/src/app/product/product-list.resolver.ts deleted file mode 100644 index 6746a82..0000000 --- a/bookie/src/app/product/product-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Product } from '../core/product'; -import { ProductService } from './product.service'; - -export const productListResolver: ResolveFn = () => { - return inject(ProductService).list(); -}; diff --git a/bookie/src/app/product/product-list/product-list-datasource.ts b/bookie/src/app/product/product-list/product-list-datasource.ts deleted file mode 100644 index 46a3fa3..0000000 --- a/bookie/src/app/product/product-list/product-list-datasource.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { merge, Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { Product } from '../../core/product'; - -export class ProductListDataSource extends DataSource { - public data: Product[]; - public filteredData: Product[]; - public search: string; - public menuCategory: string; - - constructor( - private readonly searchFilter: Observable, - private readonly menuCategoryFilter: Observable, - private readonly dataObs: Observable, - ) { - super(); - this.data = []; - this.filteredData = []; - this.search = ''; - this.menuCategory = ''; - } - - connect(): Observable { - const dataMutations = [ - this.dataObs.pipe( - tap((x) => { - this.data = x; - }), - ), - this.searchFilter.pipe( - tap((x) => { - this.search = x; - }), - ), - this.menuCategoryFilter.pipe( - tap((x) => { - this.menuCategory = x; - }), - ), - ]; - return merge(...dataMutations).pipe( - map(() => this.getFilteredData(this.data, this.search, this.menuCategory)), - tap((x) => { - this.filteredData = x; - }), - ); - } - - disconnect() {} - - private getFilteredData(data: Product[], search: string, menuCategory: string): Product[] { - const tokens = (search ?? '').toLowerCase().split(/\s+/).filter(Boolean); - return data.filter((product: Product) => { - search = search.toLowerCase(); - - const skus = product.skus ?? []; - - // 1) Search: match ANY product/sku fields - const matchesSearch = - tokens.length === 0 || - tokens.every( - (token) => - `${product.name ?? ''} ${product.fractionUnits ?? ''} ${product.saleCategory?.name ?? ''}` - .toLowerCase() - .includes(token) || - skus.some((k) => { - const hay = `${k.units ?? ''} ${k.menuCategory?.name ?? ''}`.toLowerCase(); - return hay.includes(token); - }), - ); - - const matchesMenuCategory = !menuCategory || skus.some((k) => (k.menuCategory?.id ?? '') === menuCategory); - return matchesSearch && matchesMenuCategory; - }); - } -} diff --git a/bookie/src/app/product/product-list/product-list.component.html b/bookie/src/app/product/product-list/product-list.component.html index bfbafa3..859e1aa 100644 --- a/bookie/src/app/product/product-list/product-list.component.html +++ b/bookie/src/app/product/product-list/product-list.component.html @@ -1,14 +1,15 @@

    Products - @@ -16,17 +17,17 @@ Add

    -
    +
    Filter - + Menu Category - + -- All Products -- - @for (mc of menuCategories; track mc) { + @for (mc of menuCategoriesResource.value(); track mc) { {{ mc.name }} @@ -38,8 +39,8 @@ diff --git a/bookie/src/app/product/product-list/product-list.component.ts b/bookie/src/app/product/product-list/product-list.component.ts index 39d5acd..627624b 100644 --- a/bookie/src/app/product/product-list/product-list.component.ts +++ b/bookie/src/app/product/product-list/product-list.component.ts @@ -1,7 +1,7 @@ import { CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop'; -import { AsyncPipe, DecimalPipe, CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { DecimalPipe, CurrencyPipe } from '@angular/common'; +import { Component, inject, computed, signal, debounced } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -10,22 +10,24 @@ import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; -import { ActivatedRoute, RouterModule } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; +import { RouterModule } from '@angular/router'; +import { firstValueFrom } from 'rxjs'; -import { MenuCategory } from '../../core/menu-category'; import { Product } from '../../core/product'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; import { ToCsvService } from '../../shared/to-csv.service'; import { ProductService } from '../product.service'; -import { ProductListDataSource } from './product-list-datasource'; + +export interface ProductListFormData { + menuCategory: string | null; + filter: string; +} @Component({ selector: 'app-product-list', templateUrl: './product-list.component.html', styleUrls: ['./product-list.component.css'], imports: [ - AsyncPipe, CurrencyPipe, DecimalPipe, DragDropModule, @@ -36,87 +38,75 @@ import { ProductListDataSource } from './product-list-datasource'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, RouterModule, ], }) -export class ProductListComponent implements OnInit { - private route = inject(ActivatedRoute); +export class ProductListComponent { + private menuCategoryService = inject(MenuCategoryService); private snackBar = inject(MatSnackBar); private toCsv = inject(ToCsvService); private ser = inject(ProductService); - searchFilter = new BehaviorSubject(''); - menuCategoryFilter = new BehaviorSubject(''); - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: ProductListDataSource = new ProductListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); + menuCategoriesResource = this.menuCategoryService.list(undefined); - form: FormGroup<{ - menuCategory: FormControl; - filter: FormControl; - }>; + listResource = this.ser.list(); + + menuCategoryFilter = signal(''); + + formModel = signal({ + menuCategory: '', + filter: '', + }); + + form = form(this.formModel); + + filterSignal = computed(() => this.formModel().filter); + debouncedFilter = debounced(this.filterSignal, 150); + + dataSource = computed(() => { + let items = this.listResource.value() ?? []; + const cat = this.menuCategoryFilter(); + const search = this.debouncedFilter.value()?.toLowerCase() ?? ''; + + if (cat) { + items = items.filter((x) => x.skus.some((k) => k.menuCategory?.id === cat)); + } + if (search) { + items = items.filter((x) => x.name.toLowerCase().includes(search)); + } + return items; + }); - list: Product[] = []; - menuCategories: MenuCategory[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns: string[] = ['name', 'price', 'menuCategory', 'saleCategory', 'info', 'quantity']; - constructor() { - this.form = new FormGroup({ - menuCategory: new FormControl(''), - filter: new FormControl('', { nonNullable: true }), - }); - this.data.subscribe((data: Product[]) => { - this.list = data; - }); - this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()).subscribe((value) => { - this.searchFilter.next(value ?? ''); - }); - this.menuCategoryFilter.subscribe((val) => { - console.log('Menu category filter changed to ', val); - }); + filterOn(val: string): void { + this.menuCategoryFilter.set(val); } - filterOn(val: string) { - this.menuCategoryFilter.next(val); + async updateSortOrder() { + try { + await firstValueFrom(this.ser.updateSortOrder(this.menuCategoryFilter(), this.dataSource())); + this.snackBar.open('', 'Success'); + this.listResource.reload(); + } catch (error) { + this.snackBar.open(error as string, 'Error'); + } } - ngOnInit() { - this.dataSource = new ProductListDataSource(this.searchFilter, this.menuCategoryFilter, this.data); - this.route.data.subscribe((value) => { - const data = value as { list: Product[]; menuCategories: MenuCategory[] }; - this.loadData(data.list, data.menuCategories); - }); - } - - loadData(list: Product[], menuCategories: MenuCategory[]) { - this.menuCategories = menuCategories; - this.data.next(list); - } - - updateSortOrder() { - this.ser.updateSortOrder(this.menuCategoryFilter.value, this.dataSource.filteredData).subscribe({ - next: (result: Product[]) => { - this.snackBar.open('', 'Success'); - this.loadData(result, this.menuCategories); - }, - error: (error) => { - this.snackBar.open(error, 'Error'); - }, - }); - } + dropTable(event: CdkDragDrop) { + const arr = [...this.dataSource()]; + const prevIndex = arr.indexOf(event.item.data); + moveItemInArray(arr, prevIndex, event.currentIndex); - dropTable(event: CdkDragDrop) { - const prevIndex = this.dataSource.filteredData.indexOf(event.item.data); - moveItemInArray(this.dataSource.filteredData, prevIndex, event.currentIndex); - if (this.dataSource.menuCategory === undefined) { - this.list = this.dataSource.filteredData; + const cat = this.menuCategoryFilter(); + const currentItems = this.listResource.value() ?? []; + if (!cat) { + this.listResource.set(arr); } else { - this.list = this.list - .filter((x) => !x.skus.some((k) => k.menuCategory?.id === this.dataSource.menuCategory)) - .concat(this.dataSource.filteredData); + this.listResource.set(currentItems.filter((x) => !x.skus.some((k) => k.menuCategory?.id === cat)).concat(arr)); } - this.data.next(this.list); } exportCsv() { @@ -128,7 +118,7 @@ export class ProductListComponent implements OnInit { SaleCategory: 'saleCategory', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.filteredData)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/product/product.resolver.spec.ts b/bookie/src/app/product/product.resolver.spec.ts deleted file mode 100644 index 0bceccf..0000000 --- a/bookie/src/app/product/product.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { ProductResolver } from './product-resolver.service'; - -describe('ProductResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ProductResolver], - }); - }); - - it('should be created', inject([ProductResolver], (service: ProductResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/product/product.resolver.ts b/bookie/src/app/product/product.resolver.ts deleted file mode 100644 index ef91630..0000000 --- a/bookie/src/app/product/product.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Product } from '../core/product'; -import { ProductService } from './product.service'; - -export const productResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(ProductService).get(id); -}; diff --git a/bookie/src/app/product/product.service.ts b/bookie/src/app/product/product.service.ts index a3aa8e1..a160247 100644 --- a/bookie/src/app/product/product.service.ts +++ b/bookie/src/app/product/product.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,38 +19,36 @@ export class ProductService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } - listOfSaleCategory(id: string): Observable { - const options = { params: new HttpParams().set('sc', id) }; - return this.http - .get(`${url}/query`, options) - .pipe(catchError(this.log.handleError(serviceName, 'listOfSaleCategory'))) as Observable; + listOfSaleCategory(id: Signal | string): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return `${url}/query?sc=${idVal ?? ''}`; + }); } - listIsActiveOfCategory(id: string): Observable { - const options = { params: new HttpParams().set('mc', id) }; - return this.http - .get(`${url}/query`, options) - .pipe(catchError(this.log.handleError(serviceName, 'listIsActiveOfCategory'))) as Observable; + listIsActiveOfCategory(id: Signal | string): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return `${url}/query?mc=${idVal ?? ''}`; + }); } - query(query: string): Observable { - const options = { params: new HttpParams().set('q', query) }; - return this.http - .get(`${url}/query`, options) - .pipe(catchError(this.log.handleError(serviceName, 'query'))) as Observable; + query(query: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const qVal = typeof query === 'function' ? query() : query; + return `${url}/query?q=${qVal ?? ''}`; + }); } save(product: Product): Observable { diff --git a/bookie/src/app/product/products.routes.ts b/bookie/src/app/product/products.routes.ts index fbf7693..5522d24 100644 --- a/bookie/src/app/product/products.routes.ts +++ b/bookie/src/app/product/products.routes.ts @@ -1,12 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { menuCategoryListResolver } from '../menu-category/menu-category-list.resolver'; -import { saleCategoryListResolver } from '../sale-category/sale-category-list.resolver'; import { ProductDetailComponent } from './product-detail/product-detail.component'; -import { productListResolver } from './product-list.resolver'; import { ProductListComponent } from './product-list/product-list.component'; -import { productResolver } from './product.resolver'; export const routes: Routes = [ { @@ -16,10 +12,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - list: productListResolver, - menuCategories: menuCategoryListResolver, - }, }, { path: 'new', @@ -28,11 +20,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: productResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, { path: ':id', @@ -41,10 +28,5 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: productResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, ]; diff --git a/bookie/src/app/regimes/regime-detail/regime-detail.component.html b/bookie/src/app/regimes/regime-detail/regime-detail.component.html index 303efff..99c81c5 100644 --- a/bookie/src/app/regimes/regime-detail/regime-detail.component.html +++ b/bookie/src/app/regimes/regime-detail/regime-detail.component.html @@ -1,28 +1,32 @@

    Regime

    - +
    Name - +
    Header - +
    Prefix - +
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/regimes/regime-detail/regime-detail.component.ts b/bookie/src/app/regimes/regime-detail/regime-detail.component.ts index 370a701..1f9689e 100644 --- a/bookie/src/app/regimes/regime-detail/regime-detail.component.ts +++ b/bookie/src/app/regimes/regime-detail/regime-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -11,52 +11,42 @@ import { Regime } from '../../core/regime'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { RegimeService } from '../regime.service'; +export interface RegimeDetailFormData { + name: string; + header: string; + prefix: string; +} + @Component({ selector: 'app-regime-detail', templateUrl: './regime-detail.component.html', styleUrls: ['./regime-detail.component.css'], - imports: [MatButtonModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatFormFieldModule, MatInputModule, FormField], }) -export class RegimeDetailComponent implements OnInit, AfterViewInit { +export class RegimeDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(RegimeService); + id = input(null, { transform: (v: string | null | undefined) => (v ? +v : null) }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - header: FormControl; - prefix: FormControl; - }>; + itemResource = this.ser.get(this.id); - item: Regime = new Regime(); + item = computed(() => this.itemResource.value() ?? new Regime()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): RegimeDetailFormData => { + return { + name: itemVal.name ?? '', + header: itemVal.header ?? '', + prefix: itemVal.prefix ?? '', + }; + }, + }); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - header: new FormControl('', { nonNullable: true }), - prefix: new FormControl('', { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Regime }; - this.showItem(data.item); - }); - } - - showItem(item: Regime) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - header: this.item.header ?? '', - prefix: this.item.prefix ?? '', - }); - } + form = form(this.formModel); ngAfterViewInit() { setTimeout(() => { @@ -72,20 +62,20 @@ export class RegimeDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/regimes'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as number).subscribe({ + this.ser.delete(this.item().id as number).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/regimes'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -104,10 +94,12 @@ export class RegimeDetailComponent implements OnInit, AfterViewInit { } getItem(): Regime { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.header = formModel.header ?? ''; - this.item.prefix = formModel.prefix ?? ''; - return this.item; + const formModel = this.formModel(); + return new Regime({ + ...this.item(), + name: formModel.name ?? '', + header: formModel.header ?? '', + prefix: formModel.prefix ?? '', + }); } } diff --git a/bookie/src/app/regimes/regime-list.resolver.spec.ts b/bookie/src/app/regimes/regime-list.resolver.spec.ts deleted file mode 100644 index f8a9cdc..0000000 --- a/bookie/src/app/regimes/regime-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { RegimeListResolver } from './regime-list-resolver.service'; - -describe('RegimeListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [RegimeListResolver], - }); - }); - - it('should be created', inject([RegimeListResolver], (service: RegimeListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/regimes/regime-list.resolver.ts b/bookie/src/app/regimes/regime-list.resolver.ts deleted file mode 100644 index 3a0cdc2..0000000 --- a/bookie/src/app/regimes/regime-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Regime } from '../core/regime'; -import { RegimeService } from './regime.service'; - -export const regimeListResolver: ResolveFn = () => { - return inject(RegimeService).list(); -}; diff --git a/bookie/src/app/regimes/regime-list/regime-list-datasource.ts b/bookie/src/app/regimes/regime-list/regime-list-datasource.ts deleted file mode 100644 index 5129d63..0000000 --- a/bookie/src/app/regimes/regime-list/regime-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Regime } from '../../core/regime'; - -export class RegimeListDataSource extends DataSource { - constructor(public data: Regime[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/regimes/regime-list/regime-list.component.html b/bookie/src/app/regimes/regime-list/regime-list.component.html index 5f21ddb..09ed2b7 100644 --- a/bookie/src/app/regimes/regime-list/regime-list.component.html +++ b/bookie/src/app/regimes/regime-list/regime-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/regimes/regime-list/regime-list.component.ts b/bookie/src/app/regimes/regime-list/regime-list.component.ts index 603c933..c1d3293 100644 --- a/bookie/src/app/regimes/regime-list/regime-list.component.ts +++ b/bookie/src/app/regimes/regime-list/regime-list.component.ts @@ -1,31 +1,22 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Regime } from '../../core/regime'; -import { RegimeListDataSource } from './regime-list-datasource'; - +import { RegimeService } from '../regime.service'; @Component({ selector: 'app-regime-list', templateUrl: './regime-list.component.html', styleUrls: ['./regime-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class RegimeListComponent implements OnInit { +export class RegimeListComponent { + private regimeService = inject(RegimeService); private route = inject(ActivatedRoute); + listResource = this.regimeService.list(); - list: Regime[] = []; - dataSource: RegimeListDataSource = new RegimeListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'header', 'prefix', 'isFixture']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Regime[] }; - this.list = data.list; - }); - this.dataSource = new RegimeListDataSource(this.list); - } } diff --git a/bookie/src/app/regimes/regime.resolver.spec.ts b/bookie/src/app/regimes/regime.resolver.spec.ts deleted file mode 100644 index afedf49..0000000 --- a/bookie/src/app/regimes/regime.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { RegimeResolver } from './regime-resolver.service'; - -describe('RegimeResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [RegimeResolver], - }); - }); - - it('should be created', inject([RegimeResolver], (service: RegimeResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/regimes/regime.resolver.ts b/bookie/src/app/regimes/regime.resolver.ts deleted file mode 100644 index 7ad6f95..0000000 --- a/bookie/src/app/regimes/regime.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Regime } from '../core/regime'; -import { RegimeService } from './regime.service'; - -export const regimeResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(RegimeService).get(id ? +id : null); -}; diff --git a/bookie/src/app/regimes/regime.service.ts b/bookie/src/app/regimes/regime.service.ts index 4bd035c..06652bd 100644 --- a/bookie/src/app/regimes/regime.service.ts +++ b/bookie/src/app/regimes/regime.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class RegimeService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: number | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | number | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined || isNaN(idVal) ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(regime: Regime): Observable { diff --git a/bookie/src/app/regimes/regimes.routes.ts b/bookie/src/app/regimes/regimes.routes.ts index 1c63a95..aa4b670 100644 --- a/bookie/src/app/regimes/regimes.routes.ts +++ b/bookie/src/app/regimes/regimes.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { RegimeDetailComponent } from './regime-detail/regime-detail.component'; -import { regimeListResolver } from './regime-list.resolver'; import { RegimeListComponent } from './regime-list/regime-list.component'; -import { regimeResolver } from './regime.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Regimes', }, - resolve: { - list: regimeListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Regimes', }, - resolve: { - item: regimeResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Regimes', }, - resolve: { - item: regimeResolver, - }, }, ]; diff --git a/bookie/src/app/roles/role-detail/role-detail.component.html b/bookie/src/app/roles/role-detail/role-detail.component.html index fb53e2e..4784fa9 100644 --- a/bookie/src/app/roles/role-detail/role-detail.component.html +++ b/bookie/src/app/roles/role-detail/role-detail.component.html @@ -1,27 +1,32 @@

    Role

    -
    +
    Name - +
    -
    +

    Permissions

    - @for (p of item.permissions; track p; let i = $index) { -
    - {{ p.name }} + @for (p of form.permissions; track p; let i = $index) { +
    + {{ p.name().value() }}
    }
    -
    +

    Includes Roles

    - @for (r of item.includedRoles; track r; let i = $index) { -
    - {{ r.name }} + @for (r of form.includedRoles; track r; let i = $index) { +
    + {{ r.name().value() }}
    }
    @@ -29,6 +34,6 @@
    - - + +
    diff --git a/bookie/src/app/roles/role-detail/role-detail.component.ts b/bookie/src/app/roles/role-detail/role-detail.component.ts index efa4f2f..045757b 100644 --- a/bookie/src/app/roles/role-detail/role-detail.component.ts +++ b/bookie/src/app/roles/role-detail/role-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -7,89 +7,58 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatSnackBar } from '@angular/material/snack-bar'; import { ActivatedRoute, Router } from '@angular/router'; -import { Subject, takeUntil } from 'rxjs'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { Role } from '../role'; import { RoleService } from '../role.service'; +export interface RoleDetailFormData { + name: string; + permissions: { id: string; name: string; enabled: boolean }[]; + includedRoles: { id: string; name: string; enabled: boolean }[]; +} + @Component({ selector: 'app-role-detail', templateUrl: './role-detail.component.html', styleUrls: ['./role-detail.component.css'], - imports: [MatButtonModule, MatCheckboxModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatCheckboxModule, MatFormFieldModule, MatInputModule, FormField], }) -export class RoleDetailComponent implements OnInit, AfterViewInit, OnDestroy { +export class RoleDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(RoleService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - private destroyed$ = new Subject(); + itemResource = this.ser.get(this.id); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - permissions: FormArray< - FormGroup<{ - permission: FormControl; - }> - >; - includedRoles: FormArray< - FormGroup<{ - role: FormControl; - }> - >; - }>; + item = computed(() => this.itemResource.value() ?? new Role()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): RoleDetailFormData => { + return { + name: itemVal.name, + permissions: itemVal.permissions.map((x) => ({ id: x.id ?? '', name: x.name, enabled: x.enabled })), + includedRoles: itemVal.includedRoles.map((x) => ({ id: x.id ?? '', name: x.name, enabled: x.enabled })), + }; + }, + }); - item: Role = new Role(); + form = form(this.formModel); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - permissions: new FormArray }>>([]), - includedRoles: new FormArray }>>([]), + impliedPermissions = computed(() => { + const implied = new Set(); + const includedRoles = this.formModel().includedRoles; + this.item().includedRoles.forEach((roleOpt, idx) => { + if (includedRoles[idx]?.enabled) { + (roleOpt.permissionIds || []).forEach((pid) => implied.add(pid)); + } }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Role }; - this.item = data.item; - - this.form.controls.name.setValue(this.item.name); - this.form.controls.permissions.clear(); - this.item.permissions.forEach((x) => - this.form.controls.permissions.push( - new FormGroup({ - permission: new FormControl(x.enabled, { nonNullable: true }), - }), - ), - ); - - this.form.controls.includedRoles.clear(); - this.item.includedRoles.forEach((x) => - this.form.controls.includedRoles.push( - new FormGroup({ - role: new FormControl(x.enabled, { nonNullable: true }), - }), - ), - ); - - // Rebind listeners (important when route data changes) - this.destroyed$.next(); - - // When included roles change, recompute locks - this.form.controls.includedRoles.valueChanges.pipe(takeUntil(this.destroyed$)).subscribe(() => { - this.applyIncludedRolePermissionLocks(); - }); - - // Apply initial locks immediately - this.applyIncludedRolePermissionLocks(); - }); - } + return implied; + }); ngAfterViewInit() { setTimeout(() => { @@ -99,63 +68,26 @@ export class RoleDetailComponent implements OnInit, AfterViewInit, OnDestroy { }, 0); } - ngOnDestroy(): void { - this.destroyed$.next(); - this.destroyed$.complete(); - } - - private applyIncludedRolePermissionLocks(): void { - // 1) collect all permission IDs implied by enabled included roles - const implied = new Set(); - - this.item.includedRoles.forEach((roleOpt, idx) => { - const checked = this.form.controls.includedRoles.at(idx).controls.role.value; - if (checked) { - (roleOpt.permissionIds || []).forEach((pid) => implied.add(pid)); - } - }); - - // 2) apply to permission checkboxes - this.item.permissions.forEach((perm, idx) => { - const ctrl = this.form.controls.permissions.at(idx).controls.permission; - - const isImplied = implied.has(perm.id as string); - const isDirect = perm.enabled === true; // from backend: direct assignment - - if (isImplied) { - // must be checked + disabled - ctrl.setValue(true, { emitEvent: false }); - ctrl.disable({ emitEvent: false }); - } else { - // not implied -> enable checkbox - ctrl.enable({ emitEvent: false }); - - // restore to direct-enabled state (so user sees what is explicitly on the role) - ctrl.setValue(isDirect, { emitEvent: false }); - } - }); - } - save() { this.ser.saveOrUpdate(this.getItem()).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/roles'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/roles'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -174,24 +106,20 @@ export class RoleDetailComponent implements OnInit, AfterViewInit, OnDestroy { } getItem(): Role { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - const permArray = this.form.controls.permissions; - this.item.permissions.forEach((p, index) => { - // If disabled, keep p.enabled as it was originally direct (don’t accidentally mark direct) - if (permArray.at(index).controls.permission.disabled) { - // leave p.enabled unchanged - return; - } - p.enabled = permArray.at(index).controls.permission.value; + const formModel = this.formModel(); + const implied = this.impliedPermissions(); + const currentItem = this.item(); + return new Role({ + ...currentItem, + name: formModel.name ?? '', + permissions: currentItem.permissions.map((p, index) => ({ + ...p, + enabled: implied.has(p.id as string) ? p.enabled : (formModel.permissions[index]?.enabled ?? false), + })), + includedRoles: currentItem.includedRoles.map((r, index) => ({ + ...r, + enabled: formModel.includedRoles[index]?.enabled ?? false, + })), }); - // this.item.permissions.forEach((item, index) => { - // item.enabled = permArray.controls[index].value.permission ?? false; - // }); - const includeArray = this.form.controls.includedRoles; - this.item.includedRoles.forEach((r, index) => { - r.enabled = includeArray.controls[index]?.value.role ?? false; - }); - return this.item; } } diff --git a/bookie/src/app/roles/role-list.resolver.spec.ts b/bookie/src/app/roles/role-list.resolver.spec.ts deleted file mode 100644 index cb3edaa..0000000 --- a/bookie/src/app/roles/role-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { RoleListResolver } from './role-list-resolver.service'; - -describe('RoleListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [RoleListResolver], - }); - }); - - it('should be created', inject([RoleListResolver], (service: RoleListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/roles/role-list.resolver.ts b/bookie/src/app/roles/role-list.resolver.ts deleted file mode 100644 index 3f67066..0000000 --- a/bookie/src/app/roles/role-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Role } from './role'; -import { RoleService } from './role.service'; - -export const roleListResolver: ResolveFn = () => { - return inject(RoleService).list(); -}; diff --git a/bookie/src/app/roles/role-list/role-list-datasource.ts b/bookie/src/app/roles/role-list/role-list-datasource.ts deleted file mode 100644 index fc15f3b..0000000 --- a/bookie/src/app/roles/role-list/role-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Role } from '../role'; - -export class RoleListDataSource extends DataSource { - constructor(public data: Role[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/roles/role-list/role-list.component.html b/bookie/src/app/roles/role-list/role-list.component.html index b5ca6f3..e68a46e 100644 --- a/bookie/src/app/roles/role-list/role-list.component.html +++ b/bookie/src/app/roles/role-list/role-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/roles/role-list/role-list.component.ts b/bookie/src/app/roles/role-list/role-list.component.ts index 541342d..51f7946 100644 --- a/bookie/src/app/roles/role-list/role-list.component.ts +++ b/bookie/src/app/roles/role-list/role-list.component.ts @@ -1,31 +1,22 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Role } from '../role'; -import { RoleListDataSource } from './role-list-datasource'; - +import { RoleService } from '../role.service'; @Component({ selector: 'app-role-list', templateUrl: './role-list.component.html', styleUrls: ['./role-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class RoleListComponent implements OnInit { +export class RoleListComponent { + private roleService = inject(RoleService); private route = inject(ActivatedRoute); + listResource = this.roleService.list(); - list: Role[] = []; - dataSource: RoleListDataSource = new RoleListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'includedRoles', 'permissions']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Role[] }; - this.list = data.list; - }); - this.dataSource = new RoleListDataSource(this.list); - } } diff --git a/bookie/src/app/roles/role.resolver.spec.ts b/bookie/src/app/roles/role.resolver.spec.ts deleted file mode 100644 index 9206b24..0000000 --- a/bookie/src/app/roles/role.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { RoleResolver } from './role-resolver.service'; - -describe('RoleResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [RoleResolver], - }); - }); - - it('should be created', inject([RoleResolver], (service: RoleResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/roles/role.resolver.ts b/bookie/src/app/roles/role.resolver.ts deleted file mode 100644 index fc621d8..0000000 --- a/bookie/src/app/roles/role.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Role } from './role'; -import { RoleService } from './role.service'; - -export const roleResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(RoleService).get(id); -}; diff --git a/bookie/src/app/roles/role.service.ts b/bookie/src/app/roles/role.service.ts index e92a0a0..f52d9fa 100644 --- a/bookie/src/app/roles/role.service.ts +++ b/bookie/src/app/roles/role.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class RoleService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(role: Role): Observable { diff --git a/bookie/src/app/roles/roles.routes.ts b/bookie/src/app/roles/roles.routes.ts index 7b34ab7..f2ff585 100644 --- a/bookie/src/app/roles/roles.routes.ts +++ b/bookie/src/app/roles/roles.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { RoleDetailComponent } from './role-detail/role-detail.component'; -import { roleListResolver } from './role-list.resolver'; import { RoleListComponent } from './role-list/role-list.component'; -import { roleResolver } from './role.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Users', }, - resolve: { - list: roleListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Users', }, - resolve: { - item: roleResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Users', }, - resolve: { - item: roleResolver, - }, }, ]; diff --git a/bookie/src/app/sale-category/product-list.resolver.ts b/bookie/src/app/sale-category/product-list.resolver.ts deleted file mode 100644 index 015cd0d..0000000 --- a/bookie/src/app/sale-category/product-list.resolver.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; -import { of as observableOf } from 'rxjs'; - -import { ProductQuery } from '../core/product-query'; -import { ProductService } from '../product/product.service'; - -export const productListResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - if (id === null) { - return observableOf([]); - } - return inject(ProductService).listOfSaleCategory(id); -}; diff --git a/bookie/src/app/sale-category/sale-categories.routes.ts b/bookie/src/app/sale-category/sale-categories.routes.ts index 41ba9d3..94096f5 100644 --- a/bookie/src/app/sale-category/sale-categories.routes.ts +++ b/bookie/src/app/sale-category/sale-categories.routes.ts @@ -1,12 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { taxListResolver } from '../taxes/tax-list.resolver'; -import { productListResolver } from './product-list.resolver'; import { SaleCategoryDetailComponent } from './sale-category-detail/sale-category-detail.component'; -import { saleCategoryListResolver } from './sale-category-list.resolver'; import { SaleCategoryListComponent } from './sale-category-list/sale-category-list.component'; -import { saleCategoryResolver } from './sale-category.resolver'; export const routes: Routes = [ { @@ -16,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - list: saleCategoryListResolver, - }, }, { path: 'new', @@ -27,11 +20,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: saleCategoryResolver, - taxes: taxListResolver, - products: productListResolver, - }, }, { path: ':id', @@ -40,10 +28,5 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - item: saleCategoryResolver, - taxes: taxListResolver, - products: productListResolver, - }, }, ]; diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts deleted file mode 100644 index 217a32d..0000000 --- a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail-datasource.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; - -import { ProductQuery } from '../../core/product-query'; - -export class SaleCategoryDetailDatasource extends DataSource { - private data: ProductQuery[] = []; - - constructor(private readonly dataObs: Observable) { - super(); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - return this.dataObs; - } - - disconnect() {} -} diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html index ae5911c..99bb478 100644 --- a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.html @@ -1,23 +1,23 @@

    Sale Category

    -
    +
    Name - +
    Discount Limit - + %
    Tax - - @for (t of taxes; track t) { + + @for (t of taxes(); track t) { {{ t.name }} @@ -28,14 +28,14 @@
    - - @if (!!item.id) { - + + @if (!!item().id) { + }

    Products

    - + Name diff --git a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts index 5311933..0a8796b 100644 --- a/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts +++ b/bookie/src/app/sale-category/sale-category-detail/sale-category-detail.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; @@ -12,14 +12,19 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; import { round } from 'mathjs'; -import { BehaviorSubject } from 'rxjs'; -import { ProductQuery } from '../../core/product-query'; import { SaleCategory } from '../../core/sale-category'; import { Tax } from '../../core/tax'; +import { ProductService } from '../../product/product.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; +import { TaxService } from '../../taxes/tax.service'; import { SaleCategoryService } from '../sale-category.service'; -import { SaleCategoryDetailDatasource } from './sale-category-detail-datasource'; + +export interface SaleCategoryDetailFormData { + name: string; + discountLimit: number; + tax: string; +} @Component({ selector: 'app-sale-category-detail', @@ -28,64 +33,53 @@ import { SaleCategoryDetailDatasource } from './sale-category-detail-datasource' imports: [ CurrencyPipe, MatButtonModule, - MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, MatDividerModule, MatTableModule, - ReactiveFormsModule, + FormField, RouterLink, ], }) -export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { +export class SaleCategoryDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; + private taxService = inject(TaxService); + private productService = inject(ProductService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(SaleCategoryService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - discountLimit: FormControl; - tax: FormControl; - }>; + productsResource = this.productService.listOfSaleCategory(this.id); - taxes: Tax[] = []; - item: SaleCategory = new SaleCategory(); - products: BehaviorSubject = new BehaviorSubject([]); - dataSource: SaleCategoryDetailDatasource = new SaleCategoryDetailDatasource(this.products); + taxesResource = this.taxService.list(); + + itemResource = this.ser.get(this.id); + + item = computed(() => this.itemResource.value() ?? new SaleCategory()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): SaleCategoryDetailFormData => { + return { + name: itemVal.name, + discountLimit: itemVal.discountLimit * 100, + tax: itemVal.tax?.id ?? '', + }; + }, + }); + + form = form(this.formModel); + + taxes = computed(() => this.taxesResource.value() ?? []); + + products = computed(() => this.productsResource.value() ?? []); + dataSource = computed(() => this.products()); displayedColumns = ['name', 'price', 'menuCategory']; - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - discountLimit: new FormControl(100, { nonNullable: true }), - tax: new FormControl('', { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: SaleCategory; taxes: Tax[]; products: ProductQuery[] }; - this.showItem(data.item); - this.taxes = data.taxes; - this.products.next(data.products); - }); - } - - showItem(item: SaleCategory) { - this.item = item; - this.form.setValue({ - name: this.item.name, - discountLimit: this.item.discountLimit * 100, - tax: this.item.tax?.id ?? '', - }); - } - ngAfterViewInit() { setTimeout(() => { if (this.nameElement !== undefined) { @@ -100,20 +94,20 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/sale-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/sale-categories'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -132,13 +126,12 @@ export class SaleCategoryDetailComponent implements OnInit, AfterViewInit { } getItem(): SaleCategory { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.discountLimit = round((formModel.discountLimit ?? 100) / 100, 5); - if (this.item.tax === null || this.item.tax === undefined) { - this.item.tax = new Tax(); - } - this.item.tax.id = formModel.tax; - return this.item; + const formModel = this.formModel(); + return new SaleCategory({ + ...this.item(), + name: formModel.name ?? '', + discountLimit: round((formModel.discountLimit ?? 100) / 100, 5), + tax: new Tax({ id: formModel.tax }), + }); } } diff --git a/bookie/src/app/sale-category/sale-category-list.resolver.spec.ts b/bookie/src/app/sale-category/sale-category-list.resolver.spec.ts deleted file mode 100644 index 6aed21d..0000000 --- a/bookie/src/app/sale-category/sale-category-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SaleCategoryListResolver } from './sale-category-list-resolver.service'; - -describe('SaleCategoryListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SaleCategoryListResolver], - }); - }); - - it('should be created', inject([SaleCategoryListResolver], (service: SaleCategoryListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sale-category/sale-category-list.resolver.ts b/bookie/src/app/sale-category/sale-category-list.resolver.ts deleted file mode 100644 index 435c384..0000000 --- a/bookie/src/app/sale-category/sale-category-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SaleCategory } from '../core/sale-category'; -import { SaleCategoryService } from './sale-category.service'; - -export const saleCategoryListResolver: ResolveFn = () => { - return inject(SaleCategoryService).list(); -}; diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts deleted file mode 100644 index e640461..0000000 --- a/bookie/src/app/sale-category/sale-category-list/sale-category-list-datasource.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; - -import { SaleCategory } from '../../core/sale-category'; - -export class SaleCategoryListDatasource extends DataSource { - private data: SaleCategory[] = []; - - constructor(private readonly dataObs: Observable) { - super(); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - return this.dataObs; - } - - disconnect() {} -} diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html index 3692ca7..5b06da4 100644 --- a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts index f5c94c8..97417d0 100644 --- a/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts +++ b/bookie/src/app/sale-category/sale-category-list/sale-category-list.component.ts @@ -1,46 +1,28 @@ import { PercentPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { SaleCategory } from '../../core/sale-category'; import { SaleCategoryService } from '../sale-category.service'; -import { SaleCategoryListDatasource } from './sale-category-list-datasource'; - @Component({ selector: 'app-sale-category-list', templateUrl: './sale-category-list.component.html', styleUrls: ['./sale-category-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, PercentPipe, RouterLink], }) -export class SaleCategoryListComponent implements OnInit { +export class SaleCategoryListComponent { private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private ser = inject(SaleCategoryService); + listResource = this.ser.list(); // @ViewChild('table', { static: true }) table?: MatTable; - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: SaleCategoryListDatasource = new SaleCategoryListDatasource(this.data); - list: SaleCategory[] = []; + dataSource = computed(() => this.listResource.value() ?? []); + /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'discountLimit', 'tax']; - - constructor() { - this.data.subscribe((data: SaleCategory[]) => { - this.list = data; - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: SaleCategory[] }; - this.data.next(data.list); - }); - this.dataSource = new SaleCategoryListDatasource(this.data); - } } diff --git a/bookie/src/app/sale-category/sale-category.resolver.spec.ts b/bookie/src/app/sale-category/sale-category.resolver.spec.ts deleted file mode 100644 index 732207a..0000000 --- a/bookie/src/app/sale-category/sale-category.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SaleCategoryResolver } from './sale-category-resolver.service'; - -describe('SaleCategoryResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SaleCategoryResolver], - }); - }); - - it('should be created', inject([SaleCategoryResolver], (service: SaleCategoryResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sale-category/sale-category.resolver.ts b/bookie/src/app/sale-category/sale-category.resolver.ts deleted file mode 100644 index 62c0414..0000000 --- a/bookie/src/app/sale-category/sale-category.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SaleCategory } from '../core/sale-category'; -import { SaleCategoryService } from './sale-category.service'; - -export const saleCategoryResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(SaleCategoryService).get(id); -}; diff --git a/bookie/src/app/sale-category/sale-category.service.ts b/bookie/src/app/sale-category/sale-category.service.ts index 79abb95..2bc4b16 100644 --- a/bookie/src/app/sale-category/sale-category.service.ts +++ b/bookie/src/app/sale-category/sale-category.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class SaleCategoryService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(saleCategory: SaleCategory): Observable { diff --git a/bookie/src/app/sale-report/sale-report-datasource.ts b/bookie/src/app/sale-report/sale-report-datasource.ts deleted file mode 100644 index 25c8dcb..0000000 --- a/bookie/src/app/sale-report/sale-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { SaleReportItem } from './sale-report-item'; - -export class SaleReportDatasource extends DataSource { - constructor(public data: SaleReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/sale-report/sale-report.component.html b/bookie/src/app/sale-report/sale-report.component.html index 929b0e3..353434f 100644 --- a/bookie/src/app/sale-report/sale-report.component.html +++ b/bookie/src/app/sale-report/sale-report.component.html @@ -1,15 +1,15 @@

    Sale Report - -

    -
    +
    Start Date @@ -17,7 +17,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -29,7 +29,7 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> @@ -37,19 +37,19 @@ Section - + -- All -- - @for (p of sections; track p.id) { + @for (p of sections(); track p.id) { {{ p.name }} } - +
    - + Name diff --git a/bookie/src/app/sale-report/sale-report.component.ts b/bookie/src/app/sale-report/sale-report.component.ts index 6bc6163..5e7e30c 100644 --- a/bookie/src/app/sale-report/sale-report.component.ts +++ b/bookie/src/app/sale-report/sale-report.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -13,12 +13,17 @@ import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; -import { Section } from '../core/section'; +import { SectionService } from '../sections/section.service'; import { ToCsvService } from '../shared/to-csv.service'; import { SaleReport } from './sale-report'; -import { SaleReportDatasource } from './sale-report-datasource'; import { SaleReportService } from './sale-report.service'; +export interface SaleReportFormData { + startDate: Date; + finishDate: Date; + section: string | null; +} + @Component({ selector: 'app-sale-report', templateUrl: './sale-report.component.html', @@ -26,7 +31,6 @@ import { SaleReportService } from './sale-report.service'; imports: [ CurrencyPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, @@ -34,51 +38,50 @@ import { SaleReportService } from './sale-report.service'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class SaleReportComponent implements OnInit { +export class SaleReportComponent { + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); private snackBar = inject(MatSnackBar); private ser = inject(SaleReportService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + section = input(null, { transform: (v: string | null | undefined) => v ?? null }); - sections: Section[] = []; - info: SaleReport = new SaleReport(); - dataSource: SaleReportDatasource = new SaleReportDatasource(this.info.amounts); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - section: FormControl; - }>; + infoResource = this.ser.get(this.startDate, this.finishDate, this.section); + + sectionsResource = this.sectionService.list(); + + sections = computed(() => this.sectionsResource.value() ?? []); + info = computed(() => this.infoResource.value() ?? new SaleReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: () => this.sectionsResource.value(), + computation: (sectionsVal): SaleReportFormData => { + if (sectionsVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + section: this.info().sectionId || null, + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + section: null, + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'amount']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - section: new FormControl(null), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { sections: Section[]; info: SaleReport }; - this.sections = data.sections; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - section: this.info.sectionId || null, - }); - this.dataSource = new SaleReportDatasource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); const params = { @@ -94,7 +97,7 @@ export class SaleReportComponent implements OnInit { } getInfo(): SaleReport { - const formModel = this.form.value; + const formModel = this.formModel(); const data = new SaleReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), finishDate: moment(formModel.finishDate).format('DD-MMM-YYYY'), @@ -106,12 +109,12 @@ export class SaleReportComponent implements OnInit { } print() { - this.ser.print(this.info.startDate, this.info.finishDate, this.info.sectionId).subscribe({ + this.ser.print(this.info().startDate, this.info().finishDate, this.info().sectionId).subscribe({ next: () => { this.snackBar.open('Successfully Printed', ''); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -121,7 +124,7 @@ export class SaleReportComponent implements OnInit { Name: 'name', Amount: 'amount', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/sale-report/sale-report.resolver.spec.ts b/bookie/src/app/sale-report/sale-report.resolver.spec.ts deleted file mode 100644 index fe33db4..0000000 --- a/bookie/src/app/sale-report/sale-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SaleReportResolver } from './sale-report-resolver.service'; - -describe('SaleReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SaleReportResolver], - }); - }); - - it('should be created', inject([SaleReportResolver], (service: SaleReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sale-report/sale-report.resolver.ts b/bookie/src/app/sale-report/sale-report.resolver.ts deleted file mode 100644 index 9f9555e..0000000 --- a/bookie/src/app/sale-report/sale-report.resolver.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SaleReport } from './sale-report'; -import { SaleReportService } from './sale-report.service'; - -export const saleReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - const section = route.queryParamMap.get('section') ?? null; - return inject(SaleReportService).get(startDate, finishDate, section); -}; diff --git a/bookie/src/app/sale-report/sale-report.routes.ts b/bookie/src/app/sale-report/sale-report.routes.ts index 57961ca..36ec466 100644 --- a/bookie/src/app/sale-report/sale-report.routes.ts +++ b/bookie/src/app/sale-report/sale-report.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { sectionListResolver } from '../sections/section-list.resolver'; import { SaleReportComponent } from './sale-report.component'; -import { saleReportResolver } from './sale-report.resolver'; export const routes: Routes = [ { @@ -13,10 +11,6 @@ export const routes: Routes = [ data: { permission: 'Sale Report', }, - resolve: { - sections: sectionListResolver, - info: saleReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/sale-report/sale-report.service.ts b/bookie/src/app/sale-report/sale-report.service.ts index ed111c5..0e83cbf 100644 --- a/bookie/src/app/sale-report/sale-report.service.ts +++ b/bookie/src/app/sale-report/sale-report.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,20 +16,27 @@ export class SaleReportService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(startDate: string | null, finishDate: string | null, section: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - if (section !== null) { - options.params = options.params.set('section', section); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get( + startDate: Signal, + finishDate: Signal, + section: Signal, + ): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + const sec = section(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + if (sec !== null) { + params = params.set('section', sec); + } + return { url, params }; + }); } print(startDate: string | null, finishDate: string | null, section: string | null): Observable { diff --git a/bookie/src/app/sales/bill-number/bill-number.component.html b/bookie/src/app/sales/bill-number/bill-number.component.html index 2bfa629..6a5405d 100644 --- a/bookie/src/app/sales/bill-number/bill-number.component.html +++ b/bookie/src/app/sales/bill-number/bill-number.component.html @@ -1,9 +1,9 @@ -
    +
    Regime - + @for (r of regimes; track r) { {{ r.name }} @@ -17,7 +17,7 @@ type="text" matInput #billNumber - formControlName="billNumber" + [formField]="form.billNumber" autocomplete="off" (focus)="billNumber.select()" cdkFocusInitial @@ -28,5 +28,5 @@ - + diff --git a/bookie/src/app/sales/bill-number/bill-number.component.ts b/bookie/src/app/sales/bill-number/bill-number.component.ts index 3a7ed66..31e4e34 100644 --- a/bookie/src/app/sales/bill-number/bill-number.component.ts +++ b/bookie/src/app/sales/bill-number/bill-number.component.ts @@ -1,6 +1,6 @@ import { ScrollingModule } from '@angular/cdk/scrolling'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, OnInit, inject, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; @@ -10,6 +10,11 @@ import { MatSelectModule } from '@angular/material/select'; import { Regime } from '../../core/regime'; +export interface BillNumberFormData { + regime: Regime | null; + billNumber: number | null; +} + @Component({ selector: 'app-bill-number', templateUrl: './bill-number.component.html', @@ -21,18 +26,19 @@ import { Regime } from '../../core/regime'; MatInputModule, MatOptionModule, MatSelectModule, - ReactiveFormsModule, + FormField, ScrollingModule, ], }) export class BillNumberComponent implements OnInit { - dialogRef = inject>(MatDialogRef); data = inject(MAT_DIALOG_DATA); + dialogRef = inject>(MatDialogRef); + formModel = signal({ + regime: null, + billNumber: null, + }); - form: FormGroup<{ - regime: FormControl; - billNumber: FormControl; - }>; + form = form(this.formModel); regimes: Regime[] = []; @@ -41,21 +47,17 @@ export class BillNumberComponent implements OnInit { this.regimes = data; // Create form - this.form = new FormGroup({ - regime: new FormControl(null), - billNumber: new FormControl(0, { nonNullable: true }), - }); } ngOnInit() { - this.form.setValue({ + this.formModel.set({ regime: null, billNumber: 0, }); } accept(): void { - const formValue = this.form.value; + const formValue = this.formModel(); const billNumber = formValue.billNumber ?? 0; const regime = formValue.regime ?? null; if (regime == null) { diff --git a/bookie/src/app/sales/bills/bill.resolver.ts b/bookie/src/app/sales/bills/bill.resolver.ts deleted file mode 100644 index 9d04c08..0000000 --- a/bookie/src/app/sales/bills/bill.resolver.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Bill } from './bill'; -import { VoucherService } from './voucher.service'; - -export const billResolver: ResolveFn = (route) => { - const tableId = route.queryParamMap.get('table'); - const guestId = route.queryParamMap.get('guest'); - const voucherId = route.queryParamMap.get('voucher'); - const billId = route.queryParamMap.get('bill'); - if (billId !== null) { - return inject(VoucherService).getFromBill(billId); - } - if (tableId !== null) { - return inject(VoucherService).getFromTable(tableId as string, voucherId, guestId); - } - if (voucherId !== null) { - return inject(VoucherService).getFromId(voucherId); - } - throw new Error('Unable to get bill'); -}; diff --git a/bookie/src/app/sales/bills/bills-datasource.ts b/bookie/src/app/sales/bills/bills-datasource.ts deleted file mode 100644 index dd418a2..0000000 --- a/bookie/src/app/sales/bills/bills-datasource.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { map, Observable, tap } from 'rxjs'; - -import { BillRow } from './bill-row'; -import { Kot } from './kot'; - -export class BillsDataSource extends DataSource { - private data: Kot[] = []; - constructor(private readonly dataObs: Observable) { - super(); - } - - connect(): Observable { - return this.dataObs.pipe( - tap((x) => { - this.data = x; - }), - map((d) => - d.flatMap((k) => { - const kotRow: BillRow = new BillRow({ kind: 'kot', kot: k, id: k.id! }); - const rows: BillRow[] = []; - for (const inv of k.inventories) { - if (!inv.id) { - inv.clientId = inv.clientId || crypto.randomUUID(); - } - rows.push(new BillRow({ kind: 'inv', kot: k, inv, id: `${k.id}-${inv.id || inv.clientId}` })); - if (inv.type === 'bundle') { - for (const child of inv.children) { - if (!child.id) { - child.clientId = child.clientId || crypto.randomUUID(); - } - child.parentId = inv.id || inv.clientId; - rows.push( - new BillRow({ - kind: 'child', - kot: k, - parent: inv, - inv: child, - id: `${k.id}-${child.id || child.clientId}`, - }), - ); - } - } - } - return [kotRow, ...rows]; - }), - ), - ); - } - - disconnect() {} -} diff --git a/bookie/src/app/sales/bills/bills.component.html b/bookie/src/app/sales/bills/bills.component.html index 8533305..564bd5a 100644 --- a/bookie/src/app/sales/bills/bills.component.html +++ b/bookie/src/app/sales/bills/bills.component.html @@ -26,8 +26,8 @@ / - / - / + @@ -90,7 +90,7 @@ Quantity - @@ -98,16 +98,28 @@ Quantity - - - - @@ -116,11 +128,11 @@ Quantity - - diff --git a/bookie/src/app/sales/bills/bills.component.ts b/bookie/src/app/sales/bills/bills.component.ts index 686322d..4a81686 100644 --- a/bookie/src/app/sales/bills/bills.component.ts +++ b/bookie/src/app/sales/bills/bills.component.ts @@ -1,5 +1,5 @@ import { CommonModule, CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; +import { Component, OnInit, inject, input, effect } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -24,7 +24,6 @@ import { QuantityComponent } from '../quantity/quantity.component'; import { TablesDialogComponent } from '../tables-dialog/tables-dialog.component'; import { Bill } from './bill'; import { BillRow } from './bill-row'; -import { BillsDataSource } from './bills-datasource'; import { Inventory } from './inventory'; import { Kot } from './kot'; import { VoucherType } from './voucher-type'; @@ -53,18 +52,16 @@ export class BillsComponent implements OnInit { private auth = inject(AuthService); bs = inject(BillService); private tSer = inject(TableService); + updateTable = input.required(); + item = input.required(); - dataSource: BillsDataSource = new BillsDataSource(this.bs.dataObs); + dataSource = this.bs.dataObs; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ kotColumns: string[] = ['selectKot', 'infoKot', 'kotActions']; displayedColumns: string[] = ['selectInv', 'infoInv', 'quantity']; childColumns: string[] = ['selectChild', 'infoChild', 'childQuantity']; ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Bill; updateTable: boolean }; - this.bs.loadData(data.item, data.updateTable); - }); this.getPax(); } @@ -148,7 +145,7 @@ export class BillsComponent implements OnInit { } } - trackByRow = (_: number, row: BillRow) => { + trackByRow = (_: number, row: { id?: string }) => { return row.id; }; @@ -266,4 +263,10 @@ export class BillsComponent implements OnInit { } return false; } + + constructor() { + effect(() => { + this.bs.loadData(this.item(), this.updateTable()); + }); + } } diff --git a/bookie/src/app/sales/bills/update-table.resolver.ts b/bookie/src/app/sales/bills/update-table.resolver.ts deleted file mode 100644 index b81a6d7..0000000 --- a/bookie/src/app/sales/bills/update-table.resolver.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ResolveFn } from '@angular/router'; -import { of as observableOf } from 'rxjs'; - -export const updateTableResolver: ResolveFn = (route) => { - return route.queryParamMap.get('bill') !== null ? observableOf(false) : observableOf(true); -}; diff --git a/bookie/src/app/sales/bills/voucher.service.ts b/bookie/src/app/sales/bills/voucher.service.ts index 08737fc..081a364 100644 --- a/bookie/src/app/sales/bills/voucher.service.ts +++ b/bookie/src/app/sales/bills/voucher.service.ts @@ -1,4 +1,4 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; +import { HttpParams, HttpClient, httpResource, HttpResourceRef } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,10 +19,8 @@ export class VoucherService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string): Observable { - return this.http - .get(`${url}/from-id/${id}`) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: string): HttpResourceRef { + return httpResource(() => `${url}/from-id/${id}`); } getFromTable(tableId: string, voucherId: string | null, guestId: string | null): Observable { diff --git a/bookie/src/app/sales/choose-customer/choose-customer.component.html b/bookie/src/app/sales/choose-customer/choose-customer.component.html index 819455d..a01fa30 100644 --- a/bookie/src/app/sales/choose-customer/choose-customer.component.html +++ b/bookie/src/app/sales/choose-customer/choose-customer.component.html @@ -1,13 +1,13 @@

    Customer

    - +
    Phone - @for (customer of customers | async; track customer) { + @for (customer of customers(); track customer) { {{ customer.name }} - {{ customer.phone }} } @@ -27,25 +27,25 @@
    Name - +
    Address - +
    - Print in Bill? + Print in Bill?

    -
    +
    @for (r of item.discounts; track r; let i = $index) { -
    +
    Discount on {{ r.name }} - + %
    @@ -55,5 +55,5 @@ - + diff --git a/bookie/src/app/sales/choose-customer/choose-customer.component.ts b/bookie/src/app/sales/choose-customer/choose-customer.component.ts index a2e00c2..26680f1 100644 --- a/bookie/src/app/sales/choose-customer/choose-customer.component.ts +++ b/bookie/src/app/sales/choose-customer/choose-customer.component.ts @@ -1,7 +1,6 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { AsyncPipe } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, signal, computed, effect, debounced } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatAutocompleteSelectedEvent, MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; @@ -10,18 +9,25 @@ import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/materia import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { round } from 'mathjs'; -import { Observable, of as observableOf } from 'rxjs'; -import { debounceTime, distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators'; import { Customer } from '../../core/customer'; import { CustomerService } from '../../customers/customer.service'; +export interface ChooseCustomerFormData { + name: string; + phone: string; + address: string; + printInBill: boolean; + discounts: { + discount: number | null; + }[]; +} + @Component({ selector: 'app-choose-customer', templateUrl: './choose-customer.component.html', styleUrls: ['./choose-customer.component.css'], imports: [ - AsyncPipe, CdkScrollableModule, MatAutocompleteModule, MatButtonModule, @@ -30,74 +36,67 @@ import { CustomerService } from '../../customers/customer.service'; MatFormFieldModule, MatInputModule, MatOptionModule, - ReactiveFormsModule, + FormField, ], }) export class ChooseCustomerComponent { - dialogRef = inject>(MatDialogRef); data = inject(MAT_DIALOG_DATA); private ser = inject(CustomerService); + dialogRef = inject>(MatDialogRef); + formModel = signal({ + name: '', + phone: '', + address: '', + printInBill: false, + discounts: [], + }); - form: FormGroup<{ - name: FormControl; - phone: FormControl; - address: FormControl; - printInBill: FormControl; - discounts: FormArray< - FormGroup<{ - discount: FormControl; - }> - >; - }>; + form = form(this.formModel); item: Customer = new Customer(); - customers: Observable; + phoneSignal = computed(() => { + const p = this.formModel().phone; + return p === this.item.phone ? '' : p; + }); + + debouncedPhone = debounced(this.phoneSignal, 150); + + customersResource = this.ser.autocomplete(computed(() => this.debouncedPhone.value())); + customers = computed(() => { + if (!this.debouncedPhone.value()) return []; + return this.customersResource.value() ?? []; + }); constructor() { const data = this.data; - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - phone: new FormControl('', { nonNullable: true }), - address: new FormControl(null), - printInBill: new FormControl(false, { nonNullable: true }), - discounts: new FormArray }>>([]), - }); - // Setup Account Autocomplete - this.customers = this.form.controls.phone.valueChanges.pipe( - startWith(null), - map((x) => (x === this.item.phone ? '' : x)), - map((x) => (x !== null && x.length >= 1 ? x : null)), - debounceTime(150), - distinctUntilChanged(), - switchMap((x) => (x === null ? observableOf([]) : this.ser.autocomplete(x))), - ); if (data) { - this.ser.get(data).subscribe((x) => this.showItem(x)); + const res = this.ser.get(data); + effect(() => { + const x = res.value(); + if (x) { + this.showItem(x); + } + }); } } showItem(item: Customer) { this.item = item; - this.form.controls.name.setValue(item.name); - this.form.controls.phone.setValue(item.phone); - this.form.controls.address.setValue(item.address); - this.form.controls.printInBill.setValue(item.printInBill); - this.form.controls.discounts.clear(); - this.item.discounts.forEach((x) => - this.form.controls.discounts.push( - new FormGroup({ - discount: new FormControl(x.discount ? x.discount * 100 : null), - }), - ), - ); - this.form.markAsPristine(); + this.formModel.set({ + name: item.name, + phone: item.phone, + address: item.address ?? '', + printInBill: item.printInBill, + discounts: item.discounts.map((x) => ({ + discount: x.discount ? x.discount * 100 : null, + })), + }); } save() { const customer = this.getItem(); - const promise = this.form.pristine ? observableOf(customer) : this.ser.saveOrUpdate(customer); + const promise = this.ser.saveOrUpdate(customer); promise.subscribe((x) => this.dialogRef.close(x)); } @@ -114,23 +113,24 @@ export class ChooseCustomerComponent { } getItem(): Customer { - const formModel = this.form.value; - this.item.id = this.item.phone.trim() !== formModel.phone?.trim() ? '' : this.item.id; - this.item.name = formModel.name ?? ''; - this.item.phone = formModel.phone ?? ''; - this.item.address = formModel.address ?? ''; - this.item.printInBill = formModel.printInBill ?? false; + const formModel = this.formModel(); const array = formModel.discounts; - if (array) { - this.item.discounts.forEach((item, index) => { - const array_item = array.at(index); - if (array_item && array_item?.discount) { - item.discount = Math.max(Math.min(round(array_item.discount / 100, 5), 100), 0); - } else { - item.discount = 0; - } - }); - } - return this.item; + + return new Customer({ + ...this.item, + id: this.item.phone.trim() !== formModel.phone?.trim() ? '' : this.item.id, + name: formModel.name ?? '', + phone: formModel.phone ?? '', + address: formModel.address ?? '', + printInBill: formModel.printInBill ?? false, + discounts: this.item.discounts.map((item, index) => { + const array_item = array?.[index]; + return { + ...item, + discount: + array_item && array_item?.discount ? Math.max(Math.min(round(array_item.discount / 100, 5), 100), 0) : 0, + }; + }), + }); } } diff --git a/bookie/src/app/sales/discount/customer-discounts.service.ts b/bookie/src/app/sales/discount/customer-discounts.service.ts index d1484c1..963ded8 100644 --- a/bookie/src/app/sales/discount/customer-discounts.service.ts +++ b/bookie/src/app/sales/discount/customer-discounts.service.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, httpResource, HttpResourceRef } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,11 +16,8 @@ export class CustomerDiscountsService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - list(id: string | undefined): Observable { - const getUrl: string = id === undefined ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + list(id: string | undefined): HttpResourceRef { + return httpResource(() => (id === undefined ? url : `${url}/${id}`)); } listForDiscount(): Observable<{ name: string; discount: number; discountLimit: number }[]> { diff --git a/bookie/src/app/sales/discount/discount-datasource.ts b/bookie/src/app/sales/discount/discount-datasource.ts deleted file mode 100644 index c22be27..0000000 --- a/bookie/src/app/sales/discount/discount-datasource.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -export class DiscountDataSource extends DataSource<{ name: string; discount: number }> { - constructor(private data: Observable<{ name: string; discount: number }[]>) { - super(); - } - - connect(): Observable<{ name: string; discount: number }[]> { - return this.data; - } - - disconnect() {} -} diff --git a/bookie/src/app/sales/discount/discount.component.html b/bookie/src/app/sales/discount/discount.component.html index 5b697e8..7bd684e 100644 --- a/bookie/src/app/sales/discount/discount.component.html +++ b/bookie/src/app/sales/discount/discount.component.html @@ -1,7 +1,7 @@

    Discount

    - - + + Name @@ -11,9 +11,9 @@ Discount - + - + % Cust: {{ row.customer | percent: '1.2-2' }} Max: {{ row.limit | percent: '1.2-2' }} @@ -28,5 +28,5 @@ - + diff --git a/bookie/src/app/sales/discount/discount.component.ts b/bookie/src/app/sales/discount/discount.component.ts index 1345345..a8bb9fe 100644 --- a/bookie/src/app/sales/discount/discount.component.ts +++ b/bookie/src/app/sales/discount/discount.component.ts @@ -1,18 +1,24 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; import { PercentPipe } from '@angular/common'; -import { Component, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, signal, computed } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatTableModule } from '@angular/material/table'; import { round } from 'mathjs'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; -import { DiscountDataSource } from './discount-datasource'; import { DiscountItem } from './discount-item'; +export interface DiscountFormData { + discounts: { + name: string; + discount: number; + }[]; +} + @Component({ selector: 'app-modifiers', templateUrl: './discount.component.html', @@ -25,68 +31,48 @@ import { DiscountItem } from './discount-item'; MatInputModule, MatTableModule, PercentPipe, - ReactiveFormsModule, + FormField, ], }) export class DiscountComponent { dialogRef = inject>(MatDialogRef); data = inject>(MAT_DIALOG_DATA); - list: DiscountItem[] = []; - form: FormGroup<{ - discounts: FormArray< - FormGroup<{ - name: FormControl; - discount: FormControl; - }> - >; - }>; + list = signal([]); + formModel = signal({ + discounts: [], + }); - public listObservable = new BehaviorSubject([]); - dataSource: DiscountDataSource = new DiscountDataSource(this.listObservable); + form = form(this.formModel); + + dataSource = computed(() => this.list()); displayedColumns = ['name', 'discount']; constructor() { - this.form = new FormGroup({ - discounts: new FormArray< - FormGroup<{ - name: FormControl; - discount: FormControl; - }> - >([]), - }); - this.data.subscribe((list: DiscountItem[]) => { - this.list = list; - this.form.controls.discounts.clear(); - - this.list.forEach((x) => { - this.form.controls.discounts.push( - new FormGroup({ - name: new FormControl(x.name, { nonNullable: true }), - discount: new FormControl(x.discount * 100, { - validators: [Validators.min(0), Validators.max(x.limit * 100)], - nonNullable: true, - }), - }), - ); - }); - this.listObservable.next(this.list); + this.list.set(list); + this.formModel.update((f) => ({ + ...f, + discounts: list.map((x) => ({ + name: x.name, + discount: x.discount * 100, + })), + })); }); } accept(): void { - const array = this.form.controls.discounts; - for (let i = this.list.length - 1; i >= 0; i--) { - const item = this.list[i]; - const control = array.controls[i].controls.discount; - if (control.pristine && control.value === 0) { - this.list.splice(i, 1); + const formModel = this.formModel(); + for (let i = this.list().length - 1; i >= 0; i--) { + const item = this.list()[i]; + const val = formModel.discounts[i]?.discount ?? 0; + if (val === 0) { + this.list().splice(i, 1); } else { - item.discount = Math.max(Math.min(round(control.value / 100, 5), item.limit), 0); + item.discount = Math.max(Math.min(round(val / 100, 5), item.limit), 0); } } - this.dialogRef.close(this.list); + this.dialogRef.close(this.list()); } } diff --git a/bookie/src/app/sales/home/sales-home.component.ts b/bookie/src/app/sales/home/sales-home.component.ts index b6b2f8e..99f0374 100644 --- a/bookie/src/app/sales/home/sales-home.component.ts +++ b/bookie/src/app/sales/home/sales-home.component.ts @@ -1,4 +1,4 @@ -import { Component, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatCardModule } from '@angular/material/card'; import { MatRippleModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; @@ -9,6 +9,7 @@ import { map, switchMap, tap } from 'rxjs/operators'; import { AuthService } from '../../auth/auth.service'; import { ReceivePaymentItem } from '../../core/receive-payment-item'; +import { SaleCategory } from '../../core/sale-category'; import { Table } from '../../core/table'; import { SaleCategoryService } from '../../sale-category/sale-category.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; @@ -40,6 +41,12 @@ export class SalesHomeComponent { private customerDiscountsService = inject(CustomerDiscountsService); private bs = inject(BillService); + saleCategoriesResource = this.saleCategoryService.list(); + splitBillCategories = computed(() => { + const x = this.saleCategoriesResource.value(); + return (x || []).map((y: SaleCategory) => ({ id: y.id, name: y.name, selected: false })); + }); + printKotAllowed(): boolean { if (!this.auth.allowed('print-kot')) { return false; @@ -336,9 +343,7 @@ export class SalesHomeComponent { showBillSplitChoices(): Observable<{ id: string; name: string; selected: boolean }[] | undefined | false> { return this.dialog .open(SplitBillComponent, { - data: this.saleCategoryService - .list() - .pipe(map((x) => x.map((y) => ({ id: y.id, name: y.name, selected: false })))), + data: this.splitBillCategories, }) .afterClosed(); } diff --git a/bookie/src/app/sales/menu-categories/menu-categories.component.html b/bookie/src/app/sales/menu-categories/menu-categories.component.html index ebc0f6a..df76f80 100644 --- a/bookie/src/app/sales/menu-categories/menu-categories.component.html +++ b/bookie/src/app/sales/menu-categories/menu-categories.component.html @@ -2,7 +2,7 @@

    Back

    - @for (item of list; track item) { + @for (item of list(); track item) { { - const data = value as { list: MenuCategory[] }; - this.list = data.list; - }); - } + list = computed(() => this.listResource.value() ?? []); } diff --git a/bookie/src/app/sales/menu-categories/menu-categories.resolver.spec.ts b/bookie/src/app/sales/menu-categories/menu-categories.resolver.spec.ts deleted file mode 100644 index f3c3619..0000000 --- a/bookie/src/app/sales/menu-categories/menu-categories.resolver.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; -import { inject, TestBed } from '@angular/core/testing'; - -import { MenuCategoriesResolver } from './menu-categories-resolver.service'; - -describe('MenuCategoriesResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [], - providers: [MenuCategoriesResolver, provideHttpClient(withInterceptorsFromDi())], - }); - }); - - it('should be created', inject([MenuCategoriesResolver], (service: MenuCategoriesResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sales/menu-categories/menu-categories.resolver.ts b/bookie/src/app/sales/menu-categories/menu-categories.resolver.ts deleted file mode 100644 index d6e65a5..0000000 --- a/bookie/src/app/sales/menu-categories/menu-categories.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { MenuCategory } from '../../core/menu-category'; -import { MenuCategoryService } from '../../menu-category/menu-category.service'; - -export const menuCategoriesResolver: ResolveFn = () => { - return inject(MenuCategoryService).list(true); -}; diff --git a/bookie/src/app/sales/pax/pax.component.html b/bookie/src/app/sales/pax/pax.component.html index 26b2389..37455d8 100644 --- a/bookie/src/app/sales/pax/pax.component.html +++ b/bookie/src/app/sales/pax/pax.component.html @@ -1,6 +1,6 @@

    Pax

    - +
    Pax @@ -8,7 +8,7 @@ type="text" matInput #quantity - formControlName="pax" + [formField]="form.pax" autocomplete="off" (focus)="quantity.select()" cdkFocusInitial @@ -19,5 +19,5 @@ - + diff --git a/bookie/src/app/sales/pax/pax.component.ts b/bookie/src/app/sales/pax/pax.component.ts index 76900ec..4a4667e 100644 --- a/bookie/src/app/sales/pax/pax.component.ts +++ b/bookie/src/app/sales/pax/pax.component.ts @@ -1,47 +1,42 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, OnInit, inject, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; +export interface PaxFormData { + pax: number | null; +} + @Component({ selector: 'app-pax', templateUrl: './pax.component.html', styleUrls: ['./pax.component.css'], - imports: [ - CdkScrollableModule, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - ], + imports: [CdkScrollableModule, MatButtonModule, MatDialogModule, MatFormFieldModule, MatInputModule, FormField], }) export class PaxComponent implements OnInit { - dialogRef = inject>(MatDialogRef); data = inject(MAT_DIALOG_DATA); + dialogRef = inject>(MatDialogRef); + formModel = signal({ + pax: null, + }); - form: FormGroup<{ - pax: FormControl; - }>; + form = form(this.formModel); constructor() { // Create form - this.form = new FormGroup({ - pax: new FormControl(0, { nonNullable: true }), - }); } ngOnInit() { - this.form.setValue({ + this.formModel.set({ pax: this.data, }); } accept(): void { - const pax = this.form.value.pax ?? 0; + const pax = this.formModel().pax ?? 0; this.dialogRef.close(pax); } } diff --git a/bookie/src/app/sales/products/products.component.html b/bookie/src/app/sales/products/products.component.html index 547fd08..2957a8b 100644 --- a/bookie/src/app/sales/products/products.component.html +++ b/bookie/src/app/sales/products/products.component.html @@ -7,7 +7,7 @@ >

    Back

    - @for (item of list; track item) { + @for (item of list(); track item) { v ?? null }); - list: ProductQuery[] = []; + listResource = this.productService.listIsActiveOfCategory(this.id); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: ProductQuery[] }; - this.list = data.list; - }); - } + list = computed(() => this.listResource.value() ?? []); addSku(product: ProductQuery): void { if (product.isNotAvailable) { diff --git a/bookie/src/app/sales/products/products.resolver.spec.ts b/bookie/src/app/sales/products/products.resolver.spec.ts deleted file mode 100644 index 51efc55..0000000 --- a/bookie/src/app/sales/products/products.resolver.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http'; -import { inject, TestBed } from '@angular/core/testing'; - -import { ProductsResolver } from './products-resolver.service'; - -describe('ProductsResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [], - providers: [ProductsResolver, provideHttpClient(withInterceptorsFromDi())], - }); - }); - - it('should be created', inject([ProductsResolver], (service: ProductsResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sales/products/products.resolver.ts b/bookie/src/app/sales/products/products.resolver.ts deleted file mode 100644 index 91e941b..0000000 --- a/bookie/src/app/sales/products/products.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { ProductQuery } from '../../core/product-query'; -import { ProductService } from '../../product/product.service'; - -export const productsResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id') as string; - return inject(ProductService).listIsActiveOfCategory(id); -}; diff --git a/bookie/src/app/sales/quantity/quantity.component.html b/bookie/src/app/sales/quantity/quantity.component.html index 02c7e69..539c991 100644 --- a/bookie/src/app/sales/quantity/quantity.component.html +++ b/bookie/src/app/sales/quantity/quantity.component.html @@ -1,5 +1,5 @@ - +
    Quantity @@ -7,7 +7,7 @@ type="text" matInput #quantity - formControlName="quantity" + [formField]="form.quantity" autocomplete="off" (focus)="quantity.select()" cdkFocusInitial @@ -18,5 +18,5 @@ - + diff --git a/bookie/src/app/sales/quantity/quantity.component.ts b/bookie/src/app/sales/quantity/quantity.component.ts index 91ae355..9428ea5 100644 --- a/bookie/src/app/sales/quantity/quantity.component.ts +++ b/bookie/src/app/sales/quantity/quantity.component.ts @@ -1,6 +1,6 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, OnInit, inject, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -8,43 +8,38 @@ import { MatInputModule } from '@angular/material/input'; import { MathService } from '../../shared/math.service'; +export interface QuantityFormData { + quantity: string; +} + @Component({ selector: 'app-quantity', templateUrl: './quantity.component.html', styleUrls: ['./quantity.component.css'], - imports: [ - CdkScrollableModule, - MatButtonModule, - MatDialogModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - ], + imports: [CdkScrollableModule, MatButtonModule, MatDialogModule, MatFormFieldModule, MatInputModule, FormField], }) export class QuantityComponent implements OnInit { - dialogRef = inject>(MatDialogRef); data = inject(MAT_DIALOG_DATA); private math = inject(MathService); + dialogRef = inject>(MatDialogRef); + formModel = signal({ + quantity: '', + }); - form: FormGroup<{ - quantity: FormControl; - }>; + form = form(this.formModel); constructor() { // Create form - this.form = new FormGroup({ - quantity: new FormControl('', { nonNullable: true }), - }); } ngOnInit() { - this.form.setValue({ + this.formModel.set({ quantity: `${this.data}`, }); } accept(): void { - const quantity = this.math.parseAmount(this.form.value.quantity ?? ''); + const quantity = this.math.parseAmount(this.formModel().quantity ?? ''); this.dialogRef.close(quantity); } } diff --git a/bookie/src/app/sales/reason/reason-datasource.ts b/bookie/src/app/sales/reason/reason-datasource.ts deleted file mode 100644 index 80737ae..0000000 --- a/bookie/src/app/sales/reason/reason-datasource.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -export class ReasonDatasource extends DataSource { - constructor(private data: string[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/sales/reason/reason.component.html b/bookie/src/app/sales/reason/reason.component.html index 8a886c8..023dfb7 100644 --- a/bookie/src/app/sales/reason/reason.component.html +++ b/bookie/src/app/sales/reason/reason.component.html @@ -1,7 +1,7 @@

    {{ title }}

    - - + + {{ row }} @@ -12,7 +12,7 @@ type="text" matInput #son - formControlName="son" + [formField]="form.son" autocomplete="off" (focus)="select(son.value) && son.select()" (input)="select(son.value)" @@ -28,5 +28,5 @@ - + diff --git a/bookie/src/app/sales/reason/reason.component.ts b/bookie/src/app/sales/reason/reason.component.ts index 1dea1b3..b6f5c5d 100644 --- a/bookie/src/app/sales/reason/reason.component.ts +++ b/bookie/src/app/sales/reason/reason.component.ts @@ -1,13 +1,15 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { Component, ElementRef, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, ElementRef, ViewChild, inject, computed, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatTableModule } from '@angular/material/table'; -import { ReasonDatasource } from './reason-datasource'; +export interface ReasonFormData { + son: string; +} @Component({ selector: 'app-reason', @@ -20,22 +22,24 @@ import { ReasonDatasource } from './reason-datasource'; MatFormFieldModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) export class ReasonComponent { + @ViewChild('son', { static: true }) son?: ElementRef; dialogRef = inject>(MatDialogRef); private data = inject<{ title: string; reasons: string[]; }>(MAT_DIALOG_DATA); - @ViewChild('son', { static: true }) son?: ElementRef; - form: FormGroup<{ - son: FormControl; - }>; + formModel = signal({ + son: '', + }); - dataSource: ReasonDatasource; + form = form(this.formModel); + + dataSource = computed(() => this.reasons); title: string; selected = ''; reasons: string[]; @@ -46,10 +50,6 @@ export class ReasonComponent { this.reasons = data.reasons ?? []; this.title = data.title; - this.form = new FormGroup({ - son: new FormControl('', { nonNullable: true }), - }); - this.dataSource = new ReasonDatasource(this.reasons); } select(reason: string) { diff --git a/bookie/src/app/sales/receive-payment/receive-payment-datasource.ts b/bookie/src/app/sales/receive-payment/receive-payment-datasource.ts deleted file mode 100644 index af1f3d5..0000000 --- a/bookie/src/app/sales/receive-payment/receive-payment-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -import { ReceivePaymentItem } from '../../core/receive-payment-item'; - -export class ReceivePaymentDatasource extends DataSource { - constructor(private data: Observable) { - super(); - } - - connect(): Observable { - return this.data; - } - - disconnect() {} -} diff --git a/bookie/src/app/sales/receive-payment/receive-payment.component.html b/bookie/src/app/sales/receive-payment/receive-payment.component.html index 783df61..a86fdca 100644 --- a/bookie/src/app/sales/receive-payment/receive-payment.component.html +++ b/bookie/src/app/sales/receive-payment/receive-payment.component.html @@ -1,12 +1,7 @@

    Receive Payment

    - - + + Amount @@ -18,24 +13,24 @@ {{ amount | currency: 'INR' }} - + - + - {{ balance | currency: 'INR' }} + {{ balance() | currency: 'INR' }} - + Reason - + diff --git a/bookie/src/app/sales/receive-payment/receive-payment.component.ts b/bookie/src/app/sales/receive-payment/receive-payment.component.ts index 46894d1..b54e099 100644 --- a/bookie/src/app/sales/receive-payment/receive-payment.component.ts +++ b/bookie/src/app/sales/receive-payment/receive-payment.component.ts @@ -1,20 +1,26 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; import { CurrencyPipe } from '@angular/common'; -import { Component, ElementRef, ViewChild, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, ElementRef, ViewChild, inject, signal, computed } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatTableModule } from '@angular/material/table'; -import { BehaviorSubject } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { ReceivePaymentItem } from '../../core/receive-payment-item'; import { SettleOption } from '../../core/settle-option'; import { SettleOptionService } from '../../settle-option/settle-option.service'; import { VoucherType } from '../bills/voucher-type'; -import { ReceivePaymentDatasource } from './receive-payment-datasource'; + +export interface ReceivePaymentFormData { + amounts: { + name: string; + amount: number; + }[]; + son: string; +} @Component({ selector: 'app-receive-payment', @@ -28,93 +34,69 @@ import { ReceivePaymentDatasource } from './receive-payment-datasource'; MatFormFieldModule, MatInputModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) export class ReceivePaymentComponent { - dialogRef = inject>(MatDialogRef); + @ViewChild('son', { static: true }) son?: ElementRef; private ser = inject(SettleOptionService); + dialogRef = inject>(MatDialogRef); data = inject<{ type: VoucherType; amount: number; }>(MAT_DIALOG_DATA); - @ViewChild('son', { static: true }) son?: ElementRef; - choices: ReceivePaymentItem[] = []; - choicesSubject = new BehaviorSubject([]); + choices = signal([]); + choicesWithAmount = computed(() => { + const amounts = this.formModel().amounts; + return this.choices().map((c, i) => ({ ...c, amount: amounts[i]?.amount ?? 0 })); + }); type: VoucherType; amount: number; - balance: number; - reason = ''; - displayReason: boolean; - displayTable: boolean; - form: FormGroup<{ - amounts: FormArray< - FormGroup<{ - name: FormControl; - amount: FormControl; - }> - >; - son: FormControl; - }>; + balance = computed(() => { + return this.amount - this.formModel().amounts.reduce((a, c) => a + (c.amount ?? 0), 0); + }); - dataSource: ReceivePaymentDatasource = new ReceivePaymentDatasource(this.choicesSubject); + reason = ''; + displayReason = signal(undefined); + displayTable = signal(undefined); + formModel = signal({ + amounts: [], + son: '', + }); + + form = form(this.formModel); + + dataSource = this.choicesWithAmount; displayedColumns = ['name', 'amount']; constructor() { const data = this.data; - - this.form = new FormGroup({ - amounts: new FormArray< - FormGroup<{ - name: FormControl; - amount: FormControl; - }> - >([]), - son: new FormControl('', { nonNullable: true }), - }); this.type = data.type; this.amount = data.amount; - this.balance = data.amount; - this.displayReason = false; - this.displayTable = false; - this.choicesSubject.subscribe((x) => (this.choices = x)); + this.displayReason.set(false); + this.displayTable.set(false); this.ser .listForType(data.type) .pipe( - tap((x: SettleOption[]) => (this.displayReason = x.reduce((o, n) => o || n.hasReason, this.displayReason))), - tap((x: SettleOption[]) => (this.displayTable = x.length > 1)), + tap((x: SettleOption[]) => this.displayReason.set(x.reduce((o, n) => o || n.hasReason, this.displayReason()))), + tap((x: SettleOption[]) => this.displayTable.set(x.length > 1)), map((x: SettleOption[]) => - x.map((y) => ({ ...y, amount: !this.displayTable ? this.amount : 0 }) as ReceivePaymentItem), + x.map((y) => ({ ...y, amount: !this.displayTable() ? this.amount : 0 }) as ReceivePaymentItem), ), ) .subscribe((x) => { - this.choicesSubject.next(x); - this.form.controls.amounts.clear(); - x.forEach((y: ReceivePaymentItem) => - this.form.controls.amounts.push( - new FormGroup({ - name: new FormControl(y.name, { nonNullable: true }), - amount: new FormControl(y.amount === 0 ? 0 : this.amount, { - nonNullable: true, - }), - }), - ), - ); + this.choices.set(x); + this.formModel.update((f) => ({ + ...f, + amounts: x.map((y) => ({ + name: y.name, + amount: y.amount === 0 ? 0 : this.amount, + })), + })); }); - this.form.valueChanges.subscribe((x) => this.listenToAmountChange(x.amounts)); - } - - listenToAmountChange(amounts?: Partial<{ name: string; amount: number }>[]) { - if (!amounts) { - return; - } - amounts.forEach((z, i) => { - this.choices[i].amount = z.amount ?? 0; - }); - this.balance = this.amount - this.choices.reduce((a, c) => a + c.amount, 0); } select(reason: string) { @@ -123,12 +105,16 @@ export class ReceivePaymentComponent { } accept(): void { - this.dialogRef.close({ choices: this.choices, reason: this.reason }); + this.dialogRef.close({ choices: this.choicesWithAmount(), reason: this.reason }); } maxAmount(row: ReceivePaymentItem, index: number) { - const array = this.form.controls.amounts; - const ctrl = array.controls[index].controls.amount; - ctrl.setValue(row.amount + this.balance); + this.formModel.update((f) => { + const newAmounts = [...f.amounts]; + if (newAmounts[index]) { + newAmounts[index] = { ...newAmounts[index], amount: row.amount + this.balance() }; + } + return { ...f, amounts: newAmounts }; + }); } } diff --git a/bookie/src/app/sales/running-tables/running-tables.component.html b/bookie/src/app/sales/running-tables/running-tables.component.html index 9e7191b..3b5fd73 100644 --- a/bookie/src/app/sales/running-tables/running-tables.component.html +++ b/bookie/src/app/sales/running-tables/running-tables.component.html @@ -1,7 +1,7 @@

    Running Tables

    - @for (table of list; track table) { + @for (table of list(); track table) { { - const data = value as { list: Table[]; regimes: Regime[] }; - this.regimes = data.regimes; - this.list = data.list; - }); - } + regimes = computed(() => this.regimesResource.value() ?? []); + list = computed(() => this.listResource.value() ?? []); navigateToBill(table: Table): void { const qp = { table: table.id }; @@ -49,7 +47,7 @@ export class RunningTablesComponent implements OnInit { openBill() { return this.dialog - .open(BillNumberComponent, { data: this.regimes }) + .open(BillNumberComponent, { data: this.regimes() }) .afterClosed() .pipe( map((x) => { diff --git a/bookie/src/app/sales/running-tables/running-tables.resolver.ts b/bookie/src/app/sales/running-tables/running-tables.resolver.ts deleted file mode 100644 index 6d66fa5..0000000 --- a/bookie/src/app/sales/running-tables/running-tables.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Table } from '../../core/table'; -import { TableService } from '../../tables/table.service'; - -export const runningTablesResolver: ResolveFn = () => { - return inject(TableService).running(); -}; diff --git a/bookie/src/app/sales/sales.routes.ts b/bookie/src/app/sales/sales.routes.ts index c58bcbf..5f2ee58 100644 --- a/bookie/src/app/sales/sales.routes.ts +++ b/bookie/src/app/sales/sales.routes.ts @@ -1,18 +1,12 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { regimeListResolver } from '../regimes/regime-list.resolver'; -import { billResolver } from './bills/bill.resolver'; import { BillsComponent } from './bills/bills.component'; -import { updateTableResolver } from './bills/update-table.resolver'; import { CanDeactivateBillGuard } from './can-deactivate-bill.guard'; import { SalesHomeComponent } from './home/sales-home.component'; import { MenuCategoriesComponent } from './menu-categories/menu-categories.component'; -import { menuCategoriesResolver } from './menu-categories/menu-categories.resolver'; import { ProductsComponent } from './products/products.component'; -import { productsResolver } from './products/products.resolver'; import { RunningTablesComponent } from './running-tables/running-tables.component'; -import { runningTablesResolver } from './running-tables/running-tables.resolver'; export const routes: Routes = [ { @@ -22,10 +16,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - list: runningTablesResolver, - regimes: regimeListResolver, - }, }, { path: 'tables/:id', @@ -34,10 +24,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - item: runningTablesResolver, - regimes: regimeListResolver, - }, }, { path: 'bill', @@ -47,10 +33,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - item: billResolver, - updateTable: updateTableResolver, - }, children: [ { path: '', @@ -59,9 +41,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - list: menuCategoriesResolver, - }, }, { path: 'menu-categories', @@ -70,9 +49,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - list: menuCategoriesResolver, - }, }, { path: 'products/:id', @@ -81,9 +57,6 @@ export const routes: Routes = [ data: { permission: 'Sales', }, - resolve: { - list: productsResolver, - }, }, ], }, diff --git a/bookie/src/app/sales/split-bill/split-bill.component.html b/bookie/src/app/sales/split-bill/split-bill.component.html index 0b0aaf7..bfb43ab 100644 --- a/bookie/src/app/sales/split-bill/split-bill.component.html +++ b/bookie/src/app/sales/split-bill/split-bill.component.html @@ -1,10 +1,10 @@

    Select Sale Categories

    - -
    - @for (sc of list; track sc; let i = $index) { -
    - {{ sc.name }} + +
    + @for (sc of list(); track sc; let i = $index) { +
    + {{ sc.name }}
    }
    @@ -12,5 +12,5 @@ - + diff --git a/bookie/src/app/sales/split-bill/split-bill.component.ts b/bookie/src/app/sales/split-bill/split-bill.component.ts index 7732002..644e861 100644 --- a/bookie/src/app/sales/split-bill/split-bill.component.ts +++ b/bookie/src/app/sales/split-bill/split-bill.component.ts @@ -1,21 +1,26 @@ import { CdkScrollableModule } from '@angular/cdk/scrolling'; -import { Component, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, signal, Signal, effect } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule } from '@angular/material/dialog'; -import { Observable } from 'rxjs'; + +export interface SplitBillFormData { + saleCategories: { + saleCategory: boolean; + }[]; +} @Component({ selector: 'app-split-bill', templateUrl: './split-bill.component.html', styleUrls: ['./split-bill.component.css'], - imports: [CdkScrollableModule, MatButtonModule, MatCheckboxModule, MatDialogModule, ReactiveFormsModule], + imports: [CdkScrollableModule, MatButtonModule, MatCheckboxModule, MatDialogModule, FormField], }) export class SplitBillComponent { dialogRef = inject>(MatDialogRef); data = inject< - Observable< + Signal< { id: string; name: string; @@ -24,42 +29,31 @@ export class SplitBillComponent { > >(MAT_DIALOG_DATA); - list: { id: string; name: string; selected: boolean }[] = []; - form: FormGroup<{ - saleCategories: FormArray< - FormGroup<{ - saleCategory: FormControl; - }> - >; - }>; + list = signal<{ id: string; name: string; selected: boolean }[]>([]); + formModel = signal({ + saleCategories: [], + }); + + form = form(this.formModel); constructor() { - this.form = new FormGroup({ - saleCategories: new FormArray< - FormGroup<{ - saleCategory: FormControl; - }> - >([]), - }); - this.data.subscribe((list: { id: string; name: string; selected: boolean }[]) => { - this.list = list; - this.form.controls.saleCategories.clear(); - - this.list.forEach((x) => - this.form.controls.saleCategories.push( - new FormGroup({ - saleCategory: new FormControl(x.selected, { nonNullable: true }), - }), - ), - ); + effect(() => { + const list = this.data(); + if (list) { + this.list.set(list); + this.formModel.update((f) => ({ + ...f, + saleCategories: list.map((x) => ({ saleCategory: x.selected })), + })); + } }); } accept(): void { - const array = this.form.controls.saleCategories; - this.list.forEach((item, index) => { - item.selected = array.controls[index].value.saleCategory ?? false; + const formModel = this.formModel(); + this.list().forEach((item, index) => { + item.selected = formModel.saleCategories[index]?.saleCategory ?? false; }); - this.dialogRef.close(this.list); + this.dialogRef.close(this.list()); } } diff --git a/bookie/src/app/sales/tables-dialog/tables-dialog.component.html b/bookie/src/app/sales/tables-dialog/tables-dialog.component.html index fc33df0..292fa99 100644 --- a/bookie/src/app/sales/tables-dialog/tables-dialog.component.html +++ b/bookie/src/app/sales/tables-dialog/tables-dialog.component.html @@ -25,5 +25,5 @@ - + diff --git a/bookie/src/app/section-printers/section-printer-datasource.ts b/bookie/src/app/section-printers/section-printer-datasource.ts deleted file mode 100644 index 496a9ef..0000000 --- a/bookie/src/app/section-printers/section-printer-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; - -import { SectionPrinter } from '../core/section-printer'; - -export class SectionPrinterDataSource extends DataSource { - constructor(private data: Observable) { - super(); - } - - connect(): Observable { - return this.data; - } - - disconnect() {} -} diff --git a/bookie/src/app/section-printers/section-printer.component.html b/bookie/src/app/section-printers/section-printer.component.html index 389c13a..0dfbc65 100644 --- a/bookie/src/app/section-printers/section-printer.component.html +++ b/bookie/src/app/section-printers/section-printer.component.html @@ -1,10 +1,10 @@

    Section Printer

    - +
    Section - - @for (s of sections; track s) { + + @for (s of sections(); track s) { {{ s.name }} @@ -13,7 +13,7 @@
    - + Sale Category @@ -23,12 +23,12 @@ Printer - + Printer - - -- Default -- - @for (p of printers; track p) { + + -- Default -- + @for (p of printers(); track p) { {{ p.name }} @@ -41,11 +41,11 @@ Copies - - @if (!!$any(form.get('saleCategories')).at(i).value.printer) { + + @if (form.saleCategories[i].printer().controlValue()) { Copies - + } @@ -56,8 +56,8 @@
    - - @if (sectionId) { - + + @if (id()) { + }
    diff --git a/bookie/src/app/section-printers/section-printer.component.ts b/bookie/src/app/section-printers/section-printer.component.ts index a3aeaf1..0f5b834 100644 --- a/bookie/src/app/section-printers/section-printer.component.ts +++ b/bookie/src/app/section-printers/section-printer.component.ts @@ -1,5 +1,5 @@ -import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; @@ -10,125 +10,92 @@ import { MatSelectChange, MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { map } from 'rxjs/operators'; import { Printer } from '../core/printer'; -import { Section } from '../core/section'; import { SectionPrinter } from '../core/section-printer'; +import { PrinterService } from '../printers/printer.service'; +import { SectionService } from '../sections/section.service'; import { ConfirmDialogComponent } from '../shared/confirm-dialog/confirm-dialog.component'; -import { SectionPrinterDataSource } from './section-printer-datasource'; import { SectionPrinterService } from './section-printer.service'; +export interface SectionPrinterFormData { + section: string; + saleCategories: { + saleCategory: string; + printer: string | null; + copies: number; + }[]; +} + @Component({ selector: 'app-section-printer', templateUrl: './section-printer.component.html', styleUrls: ['./section-printer.component.css'], imports: [ MatButtonModule, - MatDividerModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class SectionPrinterComponent implements OnInit { +export class SectionPrinterComponent { + @ViewChild('section', { static: true }) sectionElement?: ElementRef; + private printerService = inject(PrinterService); + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(SectionPrinterService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + printersResource = this.printerService.list(); + sectionsResource = this.sectionService.list(); + listResource = this.ser.get(this.id); + sections = computed(() => this.sectionsResource.value() ?? []); + printers = computed(() => this.printersResource.value() ?? []); + list = computed(() => this.listResource.value() ?? []); - @ViewChild('section', { static: true }) sectionElement?: ElementRef; - form: FormGroup<{ - section: FormControl; - saleCategories: FormArray< - FormGroup<{ - saleCategory: FormControl; - printer: FormControl; - copies: FormControl; - }> - >; - }>; + formModel = linkedSignal({ + source: this.list, + computation: (listVal) => { + return { + section: this.id() ?? '', + saleCategories: listVal.map((x) => ({ + saleCategory: x.saleCategory?.name ?? 'Default', + printer: x.printer?.id ?? null, + copies: x.copies, + })), + }; + }, + }); + + form = form(this.formModel, () => {}); - public listObservable = new BehaviorSubject([]); - dataSource: SectionPrinterDataSource = new SectionPrinterDataSource(this.listObservable); - list: SectionPrinter[] = []; - sections: Section[] = []; - printers: Printer[] = []; - sectionId = ''; displayedColumns = ['saleCategory', 'printer', 'copies']; - constructor() { - const route = this.route; - - // Create form - this.form = new FormGroup({ - section: new FormControl('', { nonNullable: true }), - saleCategories: new FormArray< - FormGroup<{ - saleCategory: FormControl; - printer: FormControl; - copies: FormControl; - }> - >([]), - }); - route.params.pipe(map((p) => p['id'])).subscribe((x) => { - this.sectionId = x; - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: SectionPrinter[]; sections: Section[]; printers: Printer[] }; - this.sections = data.sections; - this.printers = data.printers; - this.showItem(data.list); - this.dataSource = new SectionPrinterDataSource(this.listObservable); - this.listObservable.next(this.list); - }); - } - - showItem(list: SectionPrinter[]) { - this.list = list; - this.form.controls.section.setValue(this.sectionId); - this.form.controls.saleCategories.clear(); - this.list.forEach((x) => - this.form.controls.saleCategories.push( - new FormGroup({ - saleCategory: new FormControl(x.saleCategory?.name ?? 'Default', { - nonNullable: true, - }), - printer: new FormControl(x.printer?.id ?? null), - copies: new FormControl(x.copies, { nonNullable: true }), - }), - ), - ); - } - save() { - this.ser.save(this.sectionId, this.getItem()).subscribe({ + this.ser.save(this.id() ?? '', this.getItem()).subscribe({ next: (result: SectionPrinter[]) => { this.snackBar.open('', 'Success'); - this.showItem(result); + this.listResource.set(result); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.sectionId).subscribe({ + this.ser.delete(this.id() ?? '').subscribe({ next: () => { this.snackBar.open('', 'Success'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -150,19 +117,13 @@ export class SectionPrinterComponent implements OnInit { } getItem(): SectionPrinter[] { - const formModel = this.form.value; - this.sectionId = formModel.section ?? ''; - const array = this.form.controls.saleCategories; - this.list.forEach((item, index) => { - const cont = array.controls[index].value; - if (cont.printer === null || cont.printer === undefined) { - item.printer = null; - } else { - item.printer = { id: cont.printer }; - } - item.copies = cont.copies ?? 0; + return this.formModel().saleCategories.map((item, index) => { + return new SectionPrinter({ + saleCategory: this.listResource?.value()?.[index].saleCategory ?? null, + printer: item.printer ? new Printer({ id: item.printer }) : null, + copies: item.copies, + }); }); - return this.list; } show(val: MatSelectChange) { diff --git a/bookie/src/app/section-printers/section-printer.resolver.spec.ts b/bookie/src/app/section-printers/section-printer.resolver.spec.ts deleted file mode 100644 index fe5ceac..0000000 --- a/bookie/src/app/section-printers/section-printer.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SectionPrinterResolver } from './section-printer-resolver.service'; - -describe('SectionPrinterResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SectionPrinterResolver], - }); - }); - - it('should be created', inject([SectionPrinterResolver], (service: SectionPrinterResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/section-printers/section-printer.resolver.ts b/bookie/src/app/section-printers/section-printer.resolver.ts deleted file mode 100644 index a1b8462..0000000 --- a/bookie/src/app/section-printers/section-printer.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SectionPrinter } from '../core/section-printer'; -import { SectionPrinterService } from './section-printer.service'; - -export const sectionPrinterResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(SectionPrinterService).get(id); -}; diff --git a/bookie/src/app/section-printers/section-printer.service.ts b/bookie/src/app/section-printers/section-printer.service.ts index 73751e6..354396c 100644 --- a/bookie/src/app/section-printers/section-printer.service.ts +++ b/bookie/src/app/section-printers/section-printer.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,11 +19,11 @@ export class SectionPrinterService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } save(sectionId: string, list: SectionPrinter[]): Observable { diff --git a/bookie/src/app/section-printers/section-printers.routes.ts b/bookie/src/app/section-printers/section-printers.routes.ts index 03dfd8a..08f9bbe 100644 --- a/bookie/src/app/section-printers/section-printers.routes.ts +++ b/bookie/src/app/section-printers/section-printers.routes.ts @@ -1,10 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { printerListResolver } from '../printers/printer-list.resolver'; -import { sectionListResolver } from '../sections/section-list.resolver'; import { SectionPrinterComponent } from './section-printer.component'; -import { sectionPrinterResolver } from './section-printer.resolver'; export const routes: Routes = [ { @@ -14,11 +11,6 @@ export const routes: Routes = [ data: { permission: 'Section Printers', }, - resolve: { - list: sectionPrinterResolver, - sections: sectionListResolver, - printers: printerListResolver, - }, }, { path: ':id', @@ -27,10 +19,5 @@ export const routes: Routes = [ data: { permission: 'Section Printers', }, - resolve: { - list: sectionPrinterResolver, - sections: sectionListResolver, - printers: printerListResolver, - }, }, ]; diff --git a/bookie/src/app/sections/section-detail/section-detail.component.html b/bookie/src/app/sections/section-detail/section-detail.component.html index 43b3a7f..8032256 100644 --- a/bookie/src/app/sections/section-detail/section-detail.component.html +++ b/bookie/src/app/sections/section-detail/section-detail.component.html @@ -1,16 +1,16 @@

    Section

    -
    +
    Name - +
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/sections/section-detail/section-detail.component.ts b/bookie/src/app/sections/section-detail/section-detail.component.ts index 45b8366..9529ca7 100644 --- a/bookie/src/app/sections/section-detail/section-detail.component.ts +++ b/bookie/src/app/sections/section-detail/section-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDialog } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -11,46 +11,38 @@ import { Section } from '../../core/section'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { SectionService } from '../section.service'; +export interface SectionDetailFormData { + name: string; +} + @Component({ selector: 'app-section-detail', templateUrl: './section-detail.component.html', styleUrls: ['./section-detail.component.css'], - imports: [MatButtonModule, MatFormFieldModule, MatInputModule, ReactiveFormsModule], + imports: [MatButtonModule, MatFormFieldModule, MatInputModule, FormField], }) -export class SectionDetailComponent implements OnInit, AfterViewInit { +export class SectionDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(SectionService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - }>; + itemResource = this.ser.get(this.id); - item: Section = new Section(); + item = computed(() => this.itemResource.value() ?? new Section()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): SectionDetailFormData => { + return { + name: itemVal.name ?? '', + }; + }, + }); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Section }; - this.showItem(data.item); - }); - } - - showItem(item: Section) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - }); - } + form = form(this.formModel); ngAfterViewInit() { setTimeout(() => { @@ -66,20 +58,20 @@ export class SectionDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/sections'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/sections'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -98,8 +90,10 @@ export class SectionDetailComponent implements OnInit, AfterViewInit { } getItem(): Section { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - return this.item; + const formModel = this.formModel(); + return new Section({ + ...this.item(), + name: formModel.name ?? '', + }); } } diff --git a/bookie/src/app/sections/section-list.resolver.spec.ts b/bookie/src/app/sections/section-list.resolver.spec.ts deleted file mode 100644 index cfd5b8a..0000000 --- a/bookie/src/app/sections/section-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SectionListResolver } from './section-list-resolver.service'; - -describe('SectionListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SectionListResolver], - }); - }); - - it('should be created', inject([SectionListResolver], (service: SectionListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sections/section-list.resolver.ts b/bookie/src/app/sections/section-list.resolver.ts deleted file mode 100644 index 4bbad4b..0000000 --- a/bookie/src/app/sections/section-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Section } from '../core/section'; -import { SectionService } from './section.service'; - -export const sectionListResolver: ResolveFn = () => { - return inject(SectionService).list(); -}; diff --git a/bookie/src/app/sections/section-list/section-list-datasource.ts b/bookie/src/app/sections/section-list/section-list-datasource.ts deleted file mode 100644 index a00306d..0000000 --- a/bookie/src/app/sections/section-list/section-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Section } from '../../core/section'; - -export class SectionListDataSource extends DataSource
    { - constructor(public data: Section[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/sections/section-list/section-list.component.html b/bookie/src/app/sections/section-list/section-list.component.html index 6de3c5c..00b62ec 100644 --- a/bookie/src/app/sections/section-list/section-list.component.html +++ b/bookie/src/app/sections/section-list/section-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/sections/section-list/section-list.component.ts b/bookie/src/app/sections/section-list/section-list.component.ts index d70a497..2d86cee 100644 --- a/bookie/src/app/sections/section-list/section-list.component.ts +++ b/bookie/src/app/sections/section-list/section-list.component.ts @@ -1,31 +1,22 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Section } from '../../core/section'; -import { SectionListDataSource } from './section-list-datasource'; - +import { SectionService } from '../section.service'; @Component({ selector: 'app-section-list', templateUrl: './section-list.component.html', styleUrls: ['./section-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class SectionListComponent implements OnInit { +export class SectionListComponent { + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); + listResource = this.sectionService.list(); - list: Section[] = []; - dataSource: SectionListDataSource = new SectionListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Section[] }; - this.list = data.list; - }); - this.dataSource = new SectionListDataSource(this.list); - } } diff --git a/bookie/src/app/sections/section.resolver.spec.ts b/bookie/src/app/sections/section.resolver.spec.ts deleted file mode 100644 index 1c60239..0000000 --- a/bookie/src/app/sections/section.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SectionResolver } from './section-resolver.service'; - -describe('SectionResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SectionResolver], - }); - }); - - it('should be created', inject([SectionResolver], (service: SectionResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/sections/section.resolver.ts b/bookie/src/app/sections/section.resolver.ts deleted file mode 100644 index 60bf7d6..0000000 --- a/bookie/src/app/sections/section.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Section } from '../core/section'; -import { SectionService } from './section.service'; - -export const sectionResolver: ResolveFn
    = (route) => { - const id = route.paramMap.get('id'); - return inject(SectionService).get(id); -}; diff --git a/bookie/src/app/sections/section.service.ts b/bookie/src/app/sections/section.service.ts index c882fe2..e6e7588 100644 --- a/bookie/src/app/sections/section.service.ts +++ b/bookie/src/app/sections/section.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class SectionService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable
    { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get
    (getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable
    ; + get(id: Signal | string | null): HttpResourceRef
    { + return httpResource
    (() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(section: Section): Observable
    { diff --git a/bookie/src/app/sections/sections.routes.ts b/bookie/src/app/sections/sections.routes.ts index 5623f31..0548ef7 100644 --- a/bookie/src/app/sections/sections.routes.ts +++ b/bookie/src/app/sections/sections.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { SectionDetailComponent } from './section-detail/section-detail.component'; -import { sectionListResolver } from './section-list.resolver'; import { SectionListComponent } from './section-list/section-list.component'; -import { sectionResolver } from './section.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - list: sectionListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - item: sectionResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - item: sectionResolver, - }, }, ]; diff --git a/bookie/src/app/settings/prefill-customer-discount.resolver.ts b/bookie/src/app/settings/prefill-customer-discount.resolver.ts deleted file mode 100644 index 04ed80c..0000000 --- a/bookie/src/app/settings/prefill-customer-discount.resolver.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SettingsService } from './settings.service'; - -export const prefillCustomerDiscountResolver: ResolveFn = () => { - return inject(SettingsService).getPrefillCustomerDiscount(); -}; diff --git a/bookie/src/app/settings/settings.component.html b/bookie/src/app/settings/settings.component.html index 4d3068d..504831f 100644 --- a/bookie/src/app/settings/settings.component.html +++ b/bookie/src/app/settings/settings.component.html @@ -11,7 +11,7 @@ -
    +
    Start Date @@ -19,7 +19,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="maintenanceForm.startDate" autocomplete="off" /> @@ -31,7 +31,7 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="maintenanceForm.finishDate" autocomplete="off" /> @@ -42,7 +42,7 @@

    Sale

    - + diff --git a/bookie/src/app/settings/settings.component.ts b/bookie/src/app/settings/settings.component.ts index 1c19f10..4c3c4d8 100644 --- a/bookie/src/app/settings/settings.component.ts +++ b/bookie/src/app/settings/settings.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, computed, inject, signal } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -28,49 +28,34 @@ import { SettingsService } from './settings.service'; MatInputModule, MatSlideToggleModule, MatTabsModule, - ReactiveFormsModule, MatCardModule, + FormField, ], }) -export class SettingsComponent implements OnInit { +export class SettingsComponent { private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); auth = inject(AuthService); private ser = inject(SettingsService); + prefillCustomerDiscountResource = this.ser.getPrefillCustomerDiscount(); + prefillCustomerDiscount = computed(() => this.prefillCustomerDiscountResource.value()?.value ?? false); - prefillCustomerDiscount = true; - version: string; - maintenanceForm: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - }>; + version = environment.version; + formModel = signal({ + startDate: new Date(), + finishDate: new Date(), + }); + + maintenanceForm = form(this.formModel); beerFile: File | null = null; saleFile: File | null = null; - constructor() { - this.version = environment.version; - this.maintenanceForm = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { - prefillCustomerDiscount: boolean; - }; - - this.prefillCustomerDiscount = data.prefillCustomerDiscount; - }); - } - togglePrefill() { - this.ser.setPrefillCustomerDiscount(!this.prefillCustomerDiscount).subscribe((x) => { - this.prefillCustomerDiscount = x; + this.ser.setPrefillCustomerDiscount(!this.prefillCustomerDiscount()).subscribe((x) => { + this.prefillCustomerDiscountResource.value.set(x); }); } @@ -83,7 +68,7 @@ export class SettingsComponent implements OnInit { } runMaintenance() { - const formModel = this.maintenanceForm.value; + const formModel = this.formModel(); const startDate = moment(formModel.startDate).format('DD-MMM-YYYY'); const finishDate = moment(formModel.finishDate).format('DD-MMM-YYYY'); @@ -95,8 +80,8 @@ export class SettingsComponent implements OnInit { next: () => { this.snackBar.open('Maintenance done', 'Success'); }, - error: (error) => { - this.snackBar.open(error, 'Danger'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Danger'); }, }); } diff --git a/bookie/src/app/settings/settings.routes.ts b/bookie/src/app/settings/settings.routes.ts index d6435b7..d8140a3 100644 --- a/bookie/src/app/settings/settings.routes.ts +++ b/bookie/src/app/settings/settings.routes.ts @@ -1,7 +1,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { prefillCustomerDiscountResolver } from './prefill-customer-discount.resolver'; import { SettingsComponent } from './settings.component'; export const routes: Routes = [ @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Settings', }, - resolve: { - prefillCustomerDiscount: prefillCustomerDiscountResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/settings/settings.service.ts b/bookie/src/app/settings/settings.service.ts index 0a61bab..74bf532 100644 --- a/bookie/src/app/settings/settings.service.ts +++ b/bookie/src/app/settings/settings.service.ts @@ -1,7 +1,7 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; import { Observable } from 'rxjs'; -import { catchError, map } from 'rxjs/operators'; +import { catchError } from 'rxjs/operators'; import { ErrorLoggerService } from '../core/error-logger.service'; @@ -12,20 +12,18 @@ export class SettingsService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - getPrefillCustomerDiscount(): Observable { + getPrefillCustomerDiscount(): HttpResourceRef<{ value: boolean } | undefined> { const url = '/api/settings/prefill-customer-discount'; - return this.http.get<{ value: boolean }>(url).pipe( - map((x) => x.value), - catchError(this.log.handleError(serviceName, 'getPrefillCustomerDiscount')), - ) as Observable; + return httpResource<{ value: boolean }>(() => url); } - setPrefillCustomerDiscount(value: boolean): Observable { + setPrefillCustomerDiscount(value: boolean): Observable<{ value: boolean }> { const url = '/api/settings/prefill-customer-discount'; - return this.http.post<{ value: boolean }>(url, { value: value }).pipe( - map((x) => x.value), - catchError(this.log.handleError(serviceName, 'setPrefillCustomerDiscount')), - ) as Observable; + return this.http + .post<{ value: boolean }>(url, { value: value }) + .pipe(catchError(this.log.handleError(serviceName, 'setPrefillCustomerDiscount'))) as Observable<{ + value: boolean; + }>; } runMaintenance(startDate: string, finishDate: string, beerFile: File, saleFile: File): Observable { diff --git a/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.html b/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.html index 4f84b67..7c47ad8 100644 --- a/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.html +++ b/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.html @@ -1,15 +1,15 @@

    Settle Option

    -
    +
    Name - +
    Voucher Type - + @for (vt of voucherTypes; track vt) { {{ vt.name }} @@ -19,7 +19,7 @@ Reporting Level - + @for (rl of reportingLevel; track rl) { {{ rl.name }} @@ -27,13 +27,13 @@ } - Has Reason? + Has Reason?
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.ts b/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.ts index a715355..569135e 100644 --- a/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.ts +++ b/bookie/src/app/settle-option/settle-option-detail/settle-option-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; @@ -16,48 +16,57 @@ import { VoucherType } from '../../sales/bills/voucher-type'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { SettleOptionService } from '../settle-option.service'; +export interface SettleOptionDetailFormData { + name: string; + voucherType: number; + reportingLevel: number; + hasReason: boolean; +} + @Component({ selector: 'app-settle-option-detail', templateUrl: './settle-option-detail.component.html', styleUrls: ['./settle-option-detail.component.css'], imports: [ MatButtonModule, - MatCheckboxModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, - ReactiveFormsModule, + FormField, ], }) -export class SettleOptionDetailComponent implements OnInit, AfterViewInit { +export class SettleOptionDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(SettleOptionService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - voucherType: FormControl; - reportingLevel: FormControl; - hasReason: FormControl; - }>; + itemResource = this.ser.get(this.id); + + item = computed(() => this.itemResource.value() ?? new SettleOption()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): SettleOptionDetailFormData => { + return { + name: itemVal.name, + voucherType: itemVal.voucherType, + reportingLevel: itemVal.reportingLevel, + hasReason: itemVal.hasReason, + }; + }, + }); + + form = form(this.formModel); - item: SettleOption = new SettleOption(); voucherTypes: { id: number; name: string }[]; reportingLevel: { id: number; name: string }[]; constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - voucherType: new FormControl(0, { nonNullable: true }), - reportingLevel: new FormControl(0, { nonNullable: true }), - hasReason: new FormControl(false, { nonNullable: true }), - }); this.voucherTypes = Object.keys(VoucherType) .filter((e) => !isNaN(+e)) .map((o) => ({ id: +o, name: VoucherType[+o] as string })); @@ -66,23 +75,6 @@ export class SettleOptionDetailComponent implements OnInit, AfterViewInit { .map((o) => ({ id: +o, name: ReportingLevel[+o] as string })); } - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: SettleOption }; - this.showItem(data.item); - }); - } - - showItem(item: SettleOption) { - this.item = item; - this.form.setValue({ - name: this.item.name, - voucherType: this.item.voucherType, - reportingLevel: this.item.reportingLevel, - hasReason: this.item.hasReason, - }); - } - ngAfterViewInit() { setTimeout(() => { if (this.nameElement !== undefined) { @@ -97,20 +89,20 @@ export class SettleOptionDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/settle-options'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id).subscribe({ + this.ser.delete(this.item().id).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/settle-options'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -129,11 +121,13 @@ export class SettleOptionDetailComponent implements OnInit, AfterViewInit { } getItem(): SettleOption { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.voucherType = formModel.voucherType ?? 0; - this.item.reportingLevel = formModel.reportingLevel ?? 0; - this.item.hasReason = formModel.hasReason ?? false; - return this.item; + const formModel = this.formModel(); + return new SettleOption({ + ...this.item(), + name: formModel.name ?? '', + voucherType: formModel.voucherType ?? 0, + reportingLevel: formModel.reportingLevel ?? 0, + hasReason: formModel.hasReason ?? false, + }); } } diff --git a/bookie/src/app/settle-option/settle-option-list.resolver.spec.ts b/bookie/src/app/settle-option/settle-option-list.resolver.spec.ts deleted file mode 100644 index 83488d8..0000000 --- a/bookie/src/app/settle-option/settle-option-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SettleOptionListResolver } from './settle-option-list-resolver.service'; - -describe('SettleOptionListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SettleOptionListResolver], - }); - }); - - it('should be created', inject([SettleOptionListResolver], (service: SettleOptionListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/settle-option/settle-option-list.resolver.ts b/bookie/src/app/settle-option/settle-option-list.resolver.ts deleted file mode 100644 index 611a7de..0000000 --- a/bookie/src/app/settle-option/settle-option-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SettleOption } from '../core/settle-option'; -import { SettleOptionService } from './settle-option.service'; - -export const settleOptionListResolver: ResolveFn = () => { - return inject(SettleOptionService).list(); -}; diff --git a/bookie/src/app/settle-option/settle-option-list/settle-option-list-datasource.ts b/bookie/src/app/settle-option/settle-option-list/settle-option-list-datasource.ts deleted file mode 100644 index 5ef29a5..0000000 --- a/bookie/src/app/settle-option/settle-option-list/settle-option-list-datasource.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; - -import { SettleOption } from '../../core/settle-option'; - -export class SettleOptionListDatasource extends DataSource { - private data: SettleOption[] = []; - - constructor(private readonly dataObs: Observable) { - super(); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - return this.dataObs; - } - - disconnect() {} -} diff --git a/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.html b/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.html index 5af9852..1528db6 100644 --- a/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.html +++ b/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.ts b/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.ts index a400d53..aec42f0 100644 --- a/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.ts +++ b/bookie/src/app/settle-option/settle-option-list/settle-option-list.component.ts @@ -1,55 +1,31 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; -import { map } from 'rxjs/operators'; import { ReportingLevel } from '../../core/reporting-level'; -import { SettleOption } from '../../core/settle-option'; import { VoucherType } from '../../sales/bills/voucher-type'; import { SettleOptionService } from '../settle-option.service'; -import { SettleOptionListDatasource } from './settle-option-list-datasource'; - @Component({ selector: 'app-settle-option-list', templateUrl: './settle-option-list.component.html', styleUrls: ['./settle-option-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class SettleOptionListComponent implements OnInit { +export class SettleOptionListComponent { private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private ser = inject(SettleOptionService); + listResource = this.ser.list(); + + dataSource = computed(() => this.listResource.value() ?? []); - // @ViewChild('table', { static: true }) table?: MatTable; - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: SettleOptionListDatasource = new SettleOptionListDatasource(this.data); - list: SettleOption[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'voucherType', 'reportingLevel', 'hasReason', 'isFixture']; - constructor() { - this.data.subscribe((data: SettleOption[]) => { - this.list = data; - }); - } - - ngOnInit() { - this.route.data.pipe(map((x) => (x as { list: SettleOption[] }).list)).subscribe((list) => { - this.data.next(list); - }); - - this.route.data.subscribe((value) => { - const data = value as { list: SettleOption[] }; - this.data.next(data.list); - }); - this.dataSource = new SettleOptionListDatasource(this.data); - } - voucherType(input: VoucherType): string { return VoucherType[input]; } diff --git a/bookie/src/app/settle-option/settle-option.resolver.spec.ts b/bookie/src/app/settle-option/settle-option.resolver.spec.ts deleted file mode 100644 index 5cdf4de..0000000 --- a/bookie/src/app/settle-option/settle-option.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { SettleOptionResolver } from './settle-option-resolver.service'; - -describe('SettleOptionResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [SettleOptionResolver], - }); - }); - - it('should be created', inject([SettleOptionResolver], (service: SettleOptionResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/settle-option/settle-option.resolver.ts b/bookie/src/app/settle-option/settle-option.resolver.ts deleted file mode 100644 index a34a496..0000000 --- a/bookie/src/app/settle-option/settle-option.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { SettleOption } from '../core/settle-option'; -import { SettleOptionService } from './settle-option.service'; - -export const settleOptionResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(SettleOptionService).get(id); -}; diff --git a/bookie/src/app/settle-option/settle-option.service.ts b/bookie/src/app/settle-option/settle-option.service.ts index a49044a..f2d3a52 100644 --- a/bookie/src/app/settle-option/settle-option.service.ts +++ b/bookie/src/app/settle-option/settle-option.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -20,17 +20,15 @@ export class SettleOptionService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } listForType(voucherType: VoucherType): Observable { diff --git a/bookie/src/app/settle-option/settle-options.routes.ts b/bookie/src/app/settle-option/settle-options.routes.ts index fbb7a8e..73bf852 100644 --- a/bookie/src/app/settle-option/settle-options.routes.ts +++ b/bookie/src/app/settle-option/settle-options.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { SettleOptionDetailComponent } from './settle-option-detail/settle-option-detail.component'; -import { settleOptionListResolver } from './settle-option-list.resolver'; import { SettleOptionListComponent } from './settle-option-list/settle-option-list.component'; -import { settleOptionResolver } from './settle-option.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Owner', }, - resolve: { - list: settleOptionListResolver, - }, }, { path: 'new', @@ -25,9 +20,6 @@ export const routes: Routes = [ data: { permission: 'Owner', }, - resolve: { - item: settleOptionResolver, - }, }, { path: ':id', @@ -36,8 +28,5 @@ export const routes: Routes = [ data: { permission: 'Owner', }, - resolve: { - item: settleOptionResolver, - }, }, ]; diff --git a/bookie/src/app/tables/table-detail/table-detail.component.html b/bookie/src/app/tables/table-detail/table-detail.component.html index cde68af..b93f337 100644 --- a/bookie/src/app/tables/table-detail/table-detail.component.html +++ b/bookie/src/app/tables/table-detail/table-detail.component.html @@ -1,22 +1,22 @@

    Table

    -
    +
    Name - +
    Seats - +
    Section - - @for (s of sections; track s) { + + @for (s of sections(); track s) { {{ s.name }} @@ -25,13 +25,13 @@
    - Is Active? + Is Active?
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/tables/table-detail/table-detail.component.ts b/bookie/src/app/tables/table-detail/table-detail.component.ts index f1d986c..95abafb 100644 --- a/bookie/src/app/tables/table-detail/table-detail.component.ts +++ b/bookie/src/app/tables/table-detail/table-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; @@ -12,69 +12,61 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Section } from '../../core/section'; import { Table } from '../../core/table'; +import { SectionService } from '../../sections/section.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { TableService } from '../table.service'; +export interface TableDetailFormData { + name: string; + seats: number; + section: string; + isActive: boolean; +} + @Component({ selector: 'app-table-detail', templateUrl: './table-detail.component.html', styleUrls: ['./table-detail.component.css'], imports: [ MatButtonModule, - MatCheckboxModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, - ReactiveFormsModule, + FormField, ], }) -export class TableDetailComponent implements OnInit, AfterViewInit { +export class TableDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; + private sectionService = inject(SectionService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(TableService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - seats: FormControl; - section: FormControl; - isActive: FormControl; - }>; + sectionsResource = this.sectionService.list(); - sections: Section[] = []; - item: Table = new Table(); + itemResource = this.ser.get(this.id); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - seats: new FormControl(0, { nonNullable: true }), - section: new FormControl('', { nonNullable: true }), - isActive: new FormControl(true, { nonNullable: true }), - }); - } + item = computed(() => this.itemResource.value() ?? new Table()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): TableDetailFormData => { + return { + name: itemVal.name, + seats: itemVal.seats, + section: itemVal.section?.id ?? '', + isActive: itemVal.isActive, + }; + }, + }); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Table; sections: Section[] }; - this.showItem(data.item); - this.sections = data.sections; - }); - } + form = form(this.formModel); - showItem(item: Table) { - this.item = item; - this.form.setValue({ - name: this.item.name, - seats: this.item.seats, - section: this.item.section?.id ?? '', - isActive: this.item.isActive, - }); - } + sections = computed(() => this.sectionsResource.value() ?? []); ngAfterViewInit() { setTimeout(() => { @@ -90,20 +82,20 @@ export class TableDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/tables'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/tables'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -122,14 +114,13 @@ export class TableDetailComponent implements OnInit, AfterViewInit { } getItem(): Table { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.seats = formModel.seats ?? 0; - if (this.item.section === null || this.item.section === undefined) { - this.item.section = new Section(); - } - this.item.section.id = formModel.section; - this.item.isActive = formModel.isActive ?? true; - return this.item; + const formModel = this.formModel(); + return new Table({ + ...this.item(), + name: formModel.name ?? '', + seats: formModel.seats ?? 0, + section: new Section({ id: formModel.section }), + isActive: formModel.isActive ?? true, + }); } } diff --git a/bookie/src/app/tables/table-list.resolver.spec.ts b/bookie/src/app/tables/table-list.resolver.spec.ts deleted file mode 100644 index bbc4619..0000000 --- a/bookie/src/app/tables/table-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TableListResolver } from './table-list-resolver.service'; - -describe('TableListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TableListResolver], - }); - }); - - it('should be created', inject([TableListResolver], (service: TableListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/tables/table-list.resolver.ts b/bookie/src/app/tables/table-list.resolver.ts deleted file mode 100644 index ec186db..0000000 --- a/bookie/src/app/tables/table-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Table } from '../core/table'; -import { TableService } from './table.service'; - -export const tableListResolver: ResolveFn = () => { - return inject(TableService).list(); -}; diff --git a/bookie/src/app/tables/table-list/table-list-datasource.ts b/bookie/src/app/tables/table-list/table-list-datasource.ts deleted file mode 100644 index 4b50cd8..0000000 --- a/bookie/src/app/tables/table-list/table-list-datasource.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable } from 'rxjs'; -import { tap } from 'rxjs/operators'; - -import { Table } from '../../core/table'; - -export class TableListDataSource extends DataSource { - private data: Table[] = []; - - constructor(private readonly dataObs: Observable) { - super(); - this.dataObs = dataObs.pipe( - tap((x) => { - this.data = x; - }), - ); - } - - connect(): Observable { - return this.dataObs; - } - - disconnect() {} -} diff --git a/bookie/src/app/tables/table-list/table-list.component.html b/bookie/src/app/tables/table-list/table-list.component.html index 77d133e..75ecdcf 100644 --- a/bookie/src/app/tables/table-list/table-list.component.html +++ b/bookie/src/app/tables/table-list/table-list.component.html @@ -1,6 +1,6 @@

    Tables - + add_box Add @@ -10,8 +10,8 @@ diff --git a/bookie/src/app/tables/table-list/table-list.component.ts b/bookie/src/app/tables/table-list/table-list.component.ts index 2cd8a11..511a052 100644 --- a/bookie/src/app/tables/table-list/table-list.component.ts +++ b/bookie/src/app/tables/table-list/table-list.component.ts @@ -1,64 +1,47 @@ import { CdkDragDrop, moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop'; -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { MatToolbarModule } from '@angular/material/toolbar'; import { ActivatedRoute, Router, RouterLink } from '@angular/router'; -import { BehaviorSubject } from 'rxjs'; +import { firstValueFrom } from 'rxjs'; import { Table } from '../../core/table'; import { TableService } from '../table.service'; -import { TableListDataSource } from './table-list-datasource'; - @Component({ selector: 'app-table-list', templateUrl: './table-list.component.html', styleUrls: ['./table-list.component.sass'], imports: [DragDropModule, MatButtonModule, MatIconModule, MatTableModule, RouterLink, MatToolbarModule], }) -export class TableListComponent implements OnInit { +export class TableListComponent { private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private ser = inject(TableService); + listResource = this.ser.list(); + + dataSource = computed(() => this.listResource.value() ?? []); - // @ViewChild('table', { static: true }) table?: MatTable

    ; - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: TableListDataSource = new TableListDataSource(this.data); - list: Table[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'seats', 'section', 'isActive']; - constructor() { - this.data.subscribe((data: Table[]) => { - this.list = data; - }); + async updateSortOrder() { + try { + await firstValueFrom(this.ser.updateSortOrder(this.dataSource())); + this.snackBar.open('', 'Success'); + this.listResource.reload(); + } catch (error) { + this.snackBar.open(error as string, 'Error'); + } } - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Table[] }; - this.data.next(data.list); - }); - this.dataSource = new TableListDataSource(this.data); - } - - updateSortOrder() { - this.ser.updateSortOrder(this.list).subscribe({ - next: () => { - this.snackBar.open('', 'Success'); - }, - error: (error) => { - this.snackBar.open(error, 'Error'); - }, - }); - } - - dropTable(event: CdkDragDrop) { - const prevIndex = this.list.indexOf(event.item.data); - moveItemInArray(this.list, prevIndex, event.currentIndex); - this.data.next(this.list); + dropTable(event: CdkDragDrop) { + const arr = [...this.dataSource()]; + const prevIndex = arr.indexOf(event.item.data); + moveItemInArray(arr, prevIndex, event.currentIndex); + this.listResource.set(arr); } } diff --git a/bookie/src/app/tables/table.resolver.spec.ts b/bookie/src/app/tables/table.resolver.spec.ts deleted file mode 100644 index 0c1152b..0000000 --- a/bookie/src/app/tables/table.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TableResolver } from './table-resolver.service'; - -describe('TableResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TableResolver], - }); - }); - - it('should be created', inject([TableResolver], (service: TableResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/tables/table.resolver.ts b/bookie/src/app/tables/table.resolver.ts deleted file mode 100644 index 372e3df..0000000 --- a/bookie/src/app/tables/table.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Table } from '../core/table'; -import { TableService } from './table.service'; - -export const tableResolver: ResolveFn
    = (route) => { - const id = route.paramMap.get('id'); - return inject(TableService).get(id); -}; diff --git a/bookie/src/app/tables/table.service.ts b/bookie/src/app/tables/table.service.ts index 4c86506..26d03f0 100644 --- a/bookie/src/app/tables/table.service.ts +++ b/bookie/src/app/tables/table.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,23 +19,19 @@ export class TableService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable
    { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get
    (getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable
    ; + get(id: Signal | string | null): HttpResourceRef
    { + return httpResource
    (() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } - running(): Observable { - return this.http - .get(`${url}/running`) - .pipe(catchError(this.log.handleError(serviceName, 'running'))) as Observable; + running(): HttpResourceRef { + return httpResource(() => `${url}/running`); } save(tables: Table): Observable
    { diff --git a/bookie/src/app/tables/tables.routes.ts b/bookie/src/app/tables/tables.routes.ts index 275527a..0e39d7c 100644 --- a/bookie/src/app/tables/tables.routes.ts +++ b/bookie/src/app/tables/tables.routes.ts @@ -1,11 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { sectionListResolver } from '../sections/section-list.resolver'; import { TableDetailComponent } from './table-detail/table-detail.component'; -import { tableListResolver } from './table-list.resolver'; import { TableListComponent } from './table-list/table-list.component'; -import { tableResolver } from './table.resolver'; export const routes: Routes = [ { @@ -15,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - list: tableListResolver, - }, }, { path: 'new', @@ -26,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - item: tableResolver, - sections: sectionListResolver, - }, }, { path: ':id', @@ -38,9 +28,5 @@ export const routes: Routes = [ data: { permission: 'Sections', }, - resolve: { - item: tableResolver, - sections: sectionListResolver, - }, }, ]; diff --git a/bookie/src/app/tax-report/tax-report-datasource.ts b/bookie/src/app/tax-report/tax-report-datasource.ts deleted file mode 100644 index 1baae2a..0000000 --- a/bookie/src/app/tax-report/tax-report-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { TaxReportItem } from './tax-report-item'; - -export class TaxReportDatasource extends DataSource { - constructor(public data: TaxReportItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/tax-report/tax-report.component.html b/bookie/src/app/tax-report/tax-report.component.html index f76730b..62b374a 100644 --- a/bookie/src/app/tax-report/tax-report.component.html +++ b/bookie/src/app/tax-report/tax-report.component.html @@ -1,11 +1,11 @@

    Tax Report -

    -
    +
    Start Date @@ -13,7 +13,7 @@ matInput [matDatepicker]="startDate" (focus)="startDate.open()" - formControlName="startDate" + [formField]="form.startDate" autocomplete="off" /> @@ -25,16 +25,16 @@ matInput [matDatepicker]="finishDate" (focus)="finishDate.open()" - formControlName="finishDate" + [formField]="form.finishDate" autocomplete="off" /> - +
    - + Name diff --git a/bookie/src/app/tax-report/tax-report.component.ts b/bookie/src/app/tax-report/tax-report.component.ts index 4475288..5e66653 100644 --- a/bookie/src/app/tax-report/tax-report.component.ts +++ b/bookie/src/app/tax-report/tax-report.component.ts @@ -1,6 +1,6 @@ import { PercentPipe, CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -12,7 +12,12 @@ import moment from 'moment'; import { ToCsvService } from '../shared/to-csv.service'; import { TaxReport } from './tax-report'; -import { TaxReportDatasource } from './tax-report-datasource'; +import { TaxReportService } from './tax-report.service'; + +export interface TaxReportFormData { + startDate: Date; + finishDate: Date; +} @Component({ selector: 'app-tax-report', @@ -21,51 +26,48 @@ import { TaxReportDatasource } from './tax-report-datasource'; imports: [ CurrencyPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, MatInputModule, MatTableModule, PercentPipe, - ReactiveFormsModule, + FormField, ], }) -export class TaxReportComponent implements OnInit { +export class TaxReportComponent { + private taxReportService = inject(TaxReportService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); + startDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); + finishDate = input(null, { transform: (v: string | null | undefined) => v ?? null }); - info: TaxReport = new TaxReport(); - dataSource: TaxReportDatasource = new TaxReportDatasource(this.info.amounts); - form: FormGroup<{ - startDate: FormControl; - finishDate: FormControl; - }>; + infoResource = this.taxReportService.get(this.startDate, this.finishDate); + + info = computed(() => this.infoResource.value() ?? new TaxReport()); + dataSource = computed(() => this.info().amounts); + formModel = linkedSignal({ + source: this.info, + computation: (infoVal): TaxReportFormData => { + if (infoVal) { + return { + startDate: moment(this.info().startDate, 'DD-MMM-YYYY').toDate(), + finishDate: moment(this.info().finishDate, 'DD-MMM-YYYY').toDate(), + }; + } + return { + startDate: new Date(), + finishDate: new Date(), + }; + }, + }); + + form = form(this.formModel); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'taxRate', 'saleAmount', 'taxAmount']; - constructor() { - // Create form - this.form = new FormGroup({ - startDate: new FormControl(new Date(), { nonNullable: true }), - finishDate: new FormControl(new Date(), { nonNullable: true }), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { info: TaxReport }; - this.info = data.info; - this.form.setValue({ - startDate: moment(this.info.startDate, 'DD-MMM-YYYY').toDate(), - finishDate: moment(this.info.finishDate, 'DD-MMM-YYYY').toDate(), - }); - this.dataSource = new TaxReportDatasource(this.info.amounts); - }); - } - show() { const info = this.getInfo(); this.router.navigate(['tax-report'], { @@ -77,7 +79,7 @@ export class TaxReportComponent implements OnInit { } getInfo(): TaxReport { - const formModel = this.form.value; + const formModel = this.formModel(); return new TaxReport({ startDate: moment(formModel.startDate).format('DD-MMM-YYYY'), @@ -90,7 +92,7 @@ export class TaxReportComponent implements OnInit { Name: 'name', Amount: 'amount', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); diff --git a/bookie/src/app/tax-report/tax-report.resolver.spec.ts b/bookie/src/app/tax-report/tax-report.resolver.spec.ts deleted file mode 100644 index 6d5b8b0..0000000 --- a/bookie/src/app/tax-report/tax-report.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TaxReportResolver } from './tax-report-resolver.service'; - -describe('TaxReportResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TaxReportResolver], - }); - }); - - it('should be created', inject([TaxReportResolver], (service: TaxReportResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/tax-report/tax-report.resolver.ts b/bookie/src/app/tax-report/tax-report.resolver.ts deleted file mode 100644 index 0ba357b..0000000 --- a/bookie/src/app/tax-report/tax-report.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { TaxReport } from './tax-report'; -import { TaxReportService } from './tax-report.service'; - -export const taxReportResolver: ResolveFn = (route) => { - const startDate = route.queryParamMap.get('startDate') ?? null; - const finishDate = route.queryParamMap.get('finishDate') ?? null; - return inject(TaxReportService).get(startDate, finishDate); -}; diff --git a/bookie/src/app/tax-report/tax-report.routes.ts b/bookie/src/app/tax-report/tax-report.routes.ts index 52b553c..cc57327 100644 --- a/bookie/src/app/tax-report/tax-report.routes.ts +++ b/bookie/src/app/tax-report/tax-report.routes.ts @@ -2,7 +2,6 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { TaxReportComponent } from './tax-report.component'; -import { taxReportResolver } from './tax-report.resolver'; export const routes: Routes = [ { @@ -12,9 +11,6 @@ export const routes: Routes = [ data: { permission: 'Tax Report', }, - resolve: { - info: taxReportResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/tax-report/tax-report.service.ts b/bookie/src/app/tax-report/tax-report.service.ts index d0e675a..dc82379 100644 --- a/bookie/src/app/tax-report/tax-report.service.ts +++ b/bookie/src/app/tax-report/tax-report.service.ts @@ -1,31 +1,26 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; -import { Observable } from 'rxjs'; -import { catchError } from 'rxjs/operators'; +import { HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal } from '@angular/core'; -import { ErrorLoggerService } from '../core/error-logger.service'; import { TaxReport } from './tax-report'; const url = '/api/tax-report'; -const serviceName = 'TaxReportService'; @Injectable({ providedIn: 'root', }) export class TaxReportService { - private http = inject(HttpClient); - private log = inject(ErrorLoggerService); - - get(startDate: string | null, finishDate: string | null): Observable { - const options = { params: new HttpParams() }; - if (startDate !== null) { - options.params = options.params.set('s', startDate); - } - if (finishDate !== null) { - options.params = options.params.set('f', finishDate); - } - return this.http - .get(url, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get(startDate: Signal, finishDate: Signal): HttpResourceRef { + return httpResource(() => { + let params = new HttpParams(); + const s = startDate(); + const f = finishDate(); + if (s !== null) { + params = params.set('s', s); + } + if (f !== null) { + params = params.set('f', f); + } + return { url, params }; + }); } } diff --git a/bookie/src/app/taxes/tax-detail/tax-detail.component.html b/bookie/src/app/taxes/tax-detail/tax-detail.component.html index 2c9455e..74f92ec 100644 --- a/bookie/src/app/taxes/tax-detail/tax-detail.component.html +++ b/bookie/src/app/taxes/tax-detail/tax-detail.component.html @@ -1,24 +1,24 @@

    Tax

    -
    +
    Name - + Format for GST: ST GST @ x% (1/2) ; CGST @ x% (1/2)
    Rate - + %
    Regime - - @for (reg of regimes; track reg) { + + @for (reg of regimes(); track reg) { {{ reg.name }} @@ -29,8 +29,12 @@
    - - @if (!!item.id) { - + + @if (!!item().id) { + }
    diff --git a/bookie/src/app/taxes/tax-detail/tax-detail.component.ts b/bookie/src/app/taxes/tax-detail/tax-detail.component.ts index c4fe79b..fae8b77 100644 --- a/bookie/src/app/taxes/tax-detail/tax-detail.component.ts +++ b/bookie/src/app/taxes/tax-detail/tax-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDialog } from '@angular/material/dialog'; @@ -12,57 +12,51 @@ import { round } from 'mathjs'; import { Regime } from '../../core/regime'; import { Tax } from '../../core/tax'; +import { RegimeService } from '../../regimes/regime.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { TaxService } from '../tax.service'; +export interface TaxDetailFormData { + name: string; + rate: number; + regime: number; +} + @Component({ selector: 'app-tax-detail', templateUrl: './tax-detail.component.html', styleUrls: ['./tax-detail.component.css'], - imports: [MatButtonModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, ReactiveFormsModule], + imports: [MatButtonModule, MatFormFieldModule, MatInputModule, MatOptionModule, MatSelectModule, FormField], }) -export class TaxDetailComponent implements OnInit, AfterViewInit { +export class TaxDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; + private regimeService = inject(RegimeService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(TaxService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - rate: FormControl; - regime: FormControl; - }>; + regimesResource = this.regimeService.list(); - item: Tax = new Tax(); - regimes: Regime[] = []; + itemResource = this.ser.get(this.id); - constructor() { - // Create form - this.form = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - rate: new FormControl(100, { nonNullable: true }), - regime: new FormControl(0, { nonNullable: true }), - }); - } + item = computed(() => this.itemResource.value() ?? new Tax()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): TaxDetailFormData => { + return { + name: itemVal.name ?? '', + rate: itemVal.rate * 100, + regime: itemVal.regime?.id ?? 0, + }; + }, + }); - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: Tax; regimes: Regime[] }; - this.regimes = data.regimes; - this.showItem(data.item); - }); - } + form = form(this.formModel); - showItem(item: Tax) { - this.item = item; - this.form.setValue({ - name: this.item.name ?? '', - rate: this.item.rate * 100, - regime: this.item.regime?.id ?? 0, - }); - } + regimes = computed(() => this.regimesResource.value() ?? []); ngAfterViewInit() { setTimeout(() => { @@ -78,20 +72,20 @@ export class TaxDetailComponent implements OnInit, AfterViewInit { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/taxes'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/taxes'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -110,13 +104,12 @@ export class TaxDetailComponent implements OnInit, AfterViewInit { } getItem(): Tax { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.rate = round((formModel.rate ?? 0) / 100, 5); - if (this.item.regime === null || this.item.regime === undefined) { - this.item.regime = new Regime(); - } - this.item.regime.id = formModel.regime; - return this.item; + const formModel = this.formModel(); + return new Tax({ + ...this.item(), + name: formModel.name ?? '', + rate: round((formModel.rate ?? 0) / 100, 5), + regime: new Regime({ id: formModel.regime }), + }); } } diff --git a/bookie/src/app/taxes/tax-list.resolver.spec.ts b/bookie/src/app/taxes/tax-list.resolver.spec.ts deleted file mode 100644 index 89e2993..0000000 --- a/bookie/src/app/taxes/tax-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TaxListResolver } from './tax-list-resolver.service'; - -describe('TaxListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TaxListResolver], - }); - }); - - it('should be created', inject([TaxListResolver], (service: TaxListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/taxes/tax-list.resolver.ts b/bookie/src/app/taxes/tax-list.resolver.ts deleted file mode 100644 index ef64818..0000000 --- a/bookie/src/app/taxes/tax-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Tax } from '../core/tax'; -import { TaxService } from './tax.service'; - -export const taxListResolver: ResolveFn = () => { - return inject(TaxService).list(); -}; diff --git a/bookie/src/app/taxes/tax-list/tax-list-datasource.ts b/bookie/src/app/taxes/tax-list/tax-list-datasource.ts deleted file mode 100644 index 54c8662..0000000 --- a/bookie/src/app/taxes/tax-list/tax-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { Tax } from '../../core/tax'; - -export class TaxListDataSource extends DataSource { - constructor(public data: Tax[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/taxes/tax-list/tax-list.component.html b/bookie/src/app/taxes/tax-list/tax-list.component.html index 745dfc6..7a9a14d 100644 --- a/bookie/src/app/taxes/tax-list/tax-list.component.html +++ b/bookie/src/app/taxes/tax-list/tax-list.component.html @@ -5,7 +5,7 @@ Add
    - + Name diff --git a/bookie/src/app/taxes/tax-list/tax-list.component.ts b/bookie/src/app/taxes/tax-list/tax-list.component.ts index 6a2adf3..98c859c 100644 --- a/bookie/src/app/taxes/tax-list/tax-list.component.ts +++ b/bookie/src/app/taxes/tax-list/tax-list.component.ts @@ -1,32 +1,23 @@ import { PercentPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; +import { Component, inject, computed } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { Tax } from '../../core/tax'; -import { TaxListDataSource } from './tax-list-datasource'; - +import { TaxService } from '../tax.service'; @Component({ selector: 'app-tax-list', templateUrl: './tax-list.component.html', styleUrls: ['./tax-list.component.css'], imports: [MatButtonModule, MatIconModule, MatTableModule, PercentPipe, RouterLink], }) -export class TaxListComponent implements OnInit { +export class TaxListComponent { + private taxService = inject(TaxService); private route = inject(ActivatedRoute); + listResource = this.taxService.list(); - list: Tax[] = []; - dataSource: TaxListDataSource = new TaxListDataSource(this.list); + dataSource = computed(() => this.listResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'rate', 'regime', 'isFixture']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: Tax[] }; - this.list = data.list; - }); - this.dataSource = new TaxListDataSource(this.list); - } } diff --git a/bookie/src/app/taxes/tax.resolver.spec.ts b/bookie/src/app/taxes/tax.resolver.spec.ts deleted file mode 100644 index 417e52a..0000000 --- a/bookie/src/app/taxes/tax.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TaxResolver } from './tax-resolver.service'; - -describe('TaxResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TaxResolver], - }); - }); - - it('should be created', inject([TaxResolver], (service: TaxResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/taxes/tax.resolver.ts b/bookie/src/app/taxes/tax.resolver.ts deleted file mode 100644 index 9c5fb22..0000000 --- a/bookie/src/app/taxes/tax.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { Tax } from '../core/tax'; -import { TaxService } from './tax.service'; - -export const taxResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(TaxService).get(id); -}; diff --git a/bookie/src/app/taxes/tax.service.ts b/bookie/src/app/taxes/tax.service.ts index 424b882..d41644d 100644 --- a/bookie/src/app/taxes/tax.service.ts +++ b/bookie/src/app/taxes/tax.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class TaxService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(tax: Tax): Observable { diff --git a/bookie/src/app/taxes/taxes.routes.ts b/bookie/src/app/taxes/taxes.routes.ts index 8b24aa4..0404fca 100644 --- a/bookie/src/app/taxes/taxes.routes.ts +++ b/bookie/src/app/taxes/taxes.routes.ts @@ -1,11 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { regimeListResolver } from '../regimes/regime-list.resolver'; import { TaxDetailComponent } from './tax-detail/tax-detail.component'; -import { taxListResolver } from './tax-list.resolver'; import { TaxListComponent } from './tax-list/tax-list.component'; -import { taxResolver } from './tax.resolver'; export const routes: Routes = [ { @@ -15,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Taxes', }, - resolve: { - list: taxListResolver, - }, }, { path: 'new', @@ -26,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Taxes', }, - resolve: { - item: taxResolver, - regimes: regimeListResolver, - }, }, { path: ':id', @@ -38,9 +28,5 @@ export const routes: Routes = [ data: { permission: 'Taxes', }, - resolve: { - item: taxResolver, - regimes: regimeListResolver, - }, }, ]; diff --git a/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.html b/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.html index 9ee2d2e..f94fdbc 100644 --- a/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.html +++ b/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.html @@ -2,22 +2,22 @@

    Product Versions

    -
    +
    Name - + Fraction Units - +
    Sale Category - - @for (sc of saleCategories; track sc) { + + @for (sc of saleCategories(); track sc) { {{ sc.name }} @@ -28,13 +28,23 @@
    Valid From - + Valid Till - + @@ -44,7 +54,7 @@
    -
    +
    @@ -83,40 +93,40 @@

    SKU Versions

    -
    +
    Units - + Fraction - +
    Yield - + Cost Price - + Sale Price - +
    Menu Category - - @for (mc of menuCategories; track mc) { + + @for (mc of menuCategories(); track mc) { {{ mc.name }} @@ -125,19 +135,19 @@
    - Has Happy Hour? - Is Not Available? + Has Happy Hour? + Is Not Available?
    Valid From - + Valid Till - + @@ -147,7 +157,7 @@
    -
    Name {{ p.name }}
    +
    @@ -186,6 +196,6 @@
    - - + +
    diff --git a/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.ts b/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.ts index 10dcf56..7d35b4e 100644 --- a/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.ts +++ b/bookie/src/app/temporal-product/temporal-product-detail/temporal-product-detail.component.ts @@ -1,11 +1,24 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { + AfterViewInit, + Component, + ElementRef, + ViewChild, + computed, + inject, + signal, + linkedSignal, + input, +} from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatOptionModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatDialog } from '@angular/material/dialog'; +import { MatDividerModule } from '@angular/material/divider'; import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -15,105 +28,136 @@ import moment from 'moment'; import { MenuCategory } from '../../core/menu-category'; import { SaleCategory } from '../../core/sale-category'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; +import { SaleCategoryService } from '../../sale-category/sale-category.service'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { Product, StockKeepingUnit, TemporalProduct } from '../temporal-product'; import { TemporalProductService } from '../temporal-product.service'; +export interface TemporalProductFormData { + name: string; + fractionUnits: string; + saleCategory: string; + validFrom: Date | null; + validTill: Date | null; +} + +export interface TemporalSkuFormData { + units: string; + fraction: number; + productYield: number; + costPrice: number; + salePrice: number; + menuCategory: string; + hasHappyHour: boolean; + isNotAvailable: boolean; + validFrom: Date | null; + validTill: Date | null; +} + @Component({ - selector: 'app-product-detail', + selector: 'app-temporal-product-detail', templateUrl: './temporal-product-detail.component.html', styleUrls: ['./temporal-product-detail.component.css'], imports: [ MatButtonModule, + MatCardModule, MatCheckboxModule, MatDatepickerModule, + MatDividerModule, MatFormFieldModule, + MatIconModule, MatInputModule, MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class TemporalProductDetailComponent implements OnInit, AfterViewInit { +export class TemporalProductDetailComponent implements AfterViewInit { + @ViewChild('name', { static: true }) nameElement?: ElementRef; + private menuCategoryService = inject(MenuCategoryService); + private saleCategoryService = inject(SaleCategoryService); private route = inject(ActivatedRoute); private router = inject(Router); private dialog = inject(MatDialog); private snackBar = inject(MatSnackBar); private ser = inject(TemporalProductService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + + saleCategoriesResource = this.saleCategoryService.list(); + + menuCategoriesResource = this.menuCategoryService.list(undefined); + + itemResource = this.ser.get(this.id); productDisplayedColumns = ['name', 'fractionUnits', 'saleCategory', 'validFrom', 'validTill', 'actions']; skuDisplayedColumns = ['units', 'salePrice', 'menuCategory', 'validFrom', 'validTill', 'actions']; - @ViewChild('name', { static: true }) nameElement?: ElementRef; + private selectedProduct = signal(null); + private selectedSku = signal(null); - private selectedProduct: Product | null; - private selectedSku: StockKeepingUnit | null; + menuCategories = computed(() => this.menuCategoriesResource.value() ?? []); + saleCategories = computed(() => this.saleCategoriesResource.value() ?? []); + item = computed(() => this.itemResource.value() ?? new TemporalProduct()); - productForm: FormGroup<{ - name: FormControl; - fractionUnits: FormControl; - saleCategory: FormControl; - validFrom: FormControl; - validTill: FormControl; - }>; - - skuForm: FormGroup<{ - units: FormControl; - fraction: FormControl; - productYield: FormControl; - costPrice: FormControl; - salePrice: FormControl; - menuCategory: FormControl; - hasHappyHour: FormControl; - isNotAvailable: FormControl; - validFrom: FormControl; - validTill: FormControl; - }>; - - menuCategories: MenuCategory[] = []; - saleCategories: SaleCategory[] = []; - item: TemporalProduct = new TemporalProduct(); - - constructor() { - // Create form - this.productForm = new FormGroup({ - name: new FormControl('', { nonNullable: true }), - fractionUnits: new FormControl('', { nonNullable: true }), - saleCategory: new FormControl('', { nonNullable: true }), - validFrom: new FormControl(null), - validTill: new FormControl(null), - }); - this.skuForm = new FormGroup({ - units: new FormControl('', { nonNullable: true }), - fraction: new FormControl(1, { nonNullable: true }), - productYield: new FormControl(1, { nonNullable: true }), - costPrice: new FormControl(0, { nonNullable: true }), - salePrice: new FormControl(0, { nonNullable: true }), - - menuCategory: new FormControl('', { nonNullable: true }), - hasHappyHour: new FormControl(false, { nonNullable: true }), - isNotAvailable: new FormControl(false, { nonNullable: true }), - validFrom: new FormControl(null), - validTill: new FormControl(null), - }); - this.selectedProduct = null; - this.selectedSku = null; - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { - item: TemporalProduct; - menuCategories: MenuCategory[]; - saleCategories: SaleCategory[]; + productFormModel = linkedSignal({ + source: this.selectedProduct, + computation: (p: Product | null): TemporalProductFormData => { + if (!p) { + return { + name: '', + fractionUnits: '', + saleCategory: '', + validFrom: null as Date | null, + validTill: null as Date | null, + }; + } + return { + name: p.name ?? '', + fractionUnits: p.fraction_units ?? '', + saleCategory: p.saleCategory?.id ?? '', + validFrom: this.parseDateOrNull(p.validFrom), + validTill: this.parseDateOrNull(p.validTill), }; - this.menuCategories = data.menuCategories; - this.saleCategories = data.saleCategories; - this.item = data.item; - // this.showItem(data.item); - }); - } + }, + }); + + productForm = form(this.productFormModel); + + skuFormModel = linkedSignal({ + source: this.selectedSku, + computation: (s: StockKeepingUnit | null): TemporalSkuFormData => { + if (!s) { + return { + units: '', + fraction: 1, + productYield: 1, + costPrice: 0, + salePrice: 0, + menuCategory: '', + hasHappyHour: false, + isNotAvailable: false, + validFrom: null as Date | null, + validTill: null as Date | null, + }; + } + return { + units: s.units ?? '', + fraction: s.fraction ?? 1, + productYield: s.productYield ?? 1, + costPrice: s.costPrice ?? 0, + salePrice: s.salePrice ?? 0, + menuCategory: s.menuCategory?.id ?? '', + hasHappyHour: s.hasHappyHour ?? false, + isNotAvailable: s.isNotAvailable ?? false, + validFrom: this.parseDateOrNull(s.validFrom), + validTill: this.parseDateOrNull(s.validTill), + }; + }, + }); + + skuForm = form(this.skuFormModel); private parseDateOrNull(d: string | null | undefined): Date | null { return !d ? null : moment(d, 'DD-MMM-YYYY').toDate(); @@ -128,30 +172,8 @@ export class TemporalProductDetailComponent implements OnInit, AfterViewInit { // this.selectedProduct = this.item.products[0]; // this.selectedSku = this.item.skus[0]; - // this.productForm.setValue({ - // // product - // name: this.selectedProduct.name ?? '', - // fractionUnits: this.selectedProduct.fraction_units ?? '', - // saleCategory: this.selectedProduct.saleCategory?.id ?? '', - // validFrom: this.parseDateOrNull(this.selectedProduct.validFrom), - // validTill: this.parseDateOrNull(this.selectedProduct.validTill), - // }); - - // this.skuForm.setValue({ - // // sku - // units: this.selectedSku.units ?? '', - // fraction: this.selectedSku.fraction ?? 1, - // productYield: this.selectedSku.productYield ?? 1, - // costPrice: this.selectedSku.costPrice ?? 0, - // salePrice: this.selectedSku.salePrice ?? 0, - - // menuCategory: this.selectedSku.menuCategory?.id ?? '', - // hasHappyHour: this.selectedSku.hasHappyHour ?? false, - // isNotAvailable: this.selectedSku.isNotAvailable ?? false, - // validFrom: this.parseDateOrNull(this.selectedSku.validFrom), - // validTill: this.parseDateOrNull(this.selectedSku.validTill), - // }); - // } + // + // // } ngAfterViewInit() { setTimeout(() => { @@ -162,25 +184,18 @@ export class TemporalProductDetailComponent implements OnInit, AfterViewInit { } editProduct(p: Product) { - this.selectedProduct = p; + this.selectedProduct.set(p); console.log(p); - this.productForm.setValue({ - name: p.name ?? '', - fractionUnits: p.fraction_units ?? '', - saleCategory: p.saleCategory?.id ?? '', - validFrom: this.parseDateOrNull(p.validFrom), - validTill: this.parseDateOrNull(p.validTill), - }); setTimeout(() => this.nameElement?.nativeElement?.focus?.(), 0); } updateProduct() { - if (!this.selectedProduct) return; - const formModel = this.productForm.value; + if (!this.selectedProduct()) return; + const formModel = this.productFormModel(); - const p = this.selectedProduct; + const p = this.selectedProduct() as Product; p.name = formModel.name ?? ''; p.fraction_units = formModel.fractionUnits ?? ''; @@ -197,48 +212,25 @@ export class TemporalProductDetailComponent implements OnInit, AfterViewInit { } deleteProduct() { - if (!this.selectedProduct) return; + if (!this.selectedProduct()) return; - const idx = (this.item.products ?? []).indexOf(this.selectedProduct); + const idx = (this.item().products ?? []).indexOf(this.selectedProduct() as Product); if (idx >= 0) { - this.item.products.splice(idx, 1); + this.item().products.splice(idx, 1); } - this.selectedProduct = null; - - // Reset form - this.productForm.reset({ - name: '', - fractionUnits: '', - saleCategory: '', - validFrom: null, - validTill: null, - }); + this.selectedProduct.set(null); } editSku(s: StockKeepingUnit) { - this.selectedSku = s; - - this.skuForm.setValue({ - units: s.units ?? '', - fraction: s.fraction ?? 1, - productYield: s.productYield ?? 1, - costPrice: s.costPrice ?? 0, - salePrice: s.salePrice ?? 0, - menuCategory: s.menuCategory?.id ?? '', - - hasHappyHour: s.hasHappyHour ?? false, - isNotAvailable: s.isNotAvailable ?? false, - validFrom: this.parseDateOrNull(s.validFrom), - validTill: this.parseDateOrNull(s.validTill), - }); + this.selectedSku.set(s); } updateSku() { - if (!this.selectedSku) return; - const formModel = this.skuForm.value; + if (!this.selectedSku()) return; + const formModel = this.skuFormModel(); - const s = this.selectedSku; + const s = this.selectedSku() as StockKeepingUnit; s.units = formModel.units ?? ''; s.fraction = formModel.fraction ?? 1; s.productYield = formModel.productYield ?? 1; @@ -260,50 +252,36 @@ export class TemporalProductDetailComponent implements OnInit, AfterViewInit { } deleteSku() { - if (!this.selectedSku) return; + if (!this.selectedSku()) return; - const idx = (this.item.skus ?? []).indexOf(this.selectedSku); + const idx = (this.item().skus ?? []).indexOf(this.selectedSku() as StockKeepingUnit); if (idx >= 0) { - this.item.skus.splice(idx, 1); + this.item().skus.splice(idx, 1); } - this.selectedSku = null; - - // Reset form - this.skuForm.reset({ - units: '', - fraction: 1, - productYield: 1, - costPrice: 0, - salePrice: 0, - menuCategory: '', - hasHappyHour: false, - isNotAvailable: false, - validFrom: null, - validTill: null, - }); + this.selectedSku.set(null); } update() { - this.ser.update(this.item).subscribe({ + this.ser.update(this.item()).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/temporal-products'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.products[0].id as string).subscribe({ + this.ser.delete(this.item().products[0].id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/temporal-products'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } diff --git a/bookie/src/app/temporal-product/temporal-product-list.resolver.spec.ts b/bookie/src/app/temporal-product/temporal-product-list.resolver.spec.ts deleted file mode 100644 index 250290a..0000000 --- a/bookie/src/app/temporal-product/temporal-product-list.resolver.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TemporalProductListResolverService } from './temporal-product-list-resolver.service'; - -describe('TemporalProductListResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TemporalProductListResolverService], - }); - }); - - it('should be created', inject( - [TemporalProductListResolverService], - (service: TemporalProductListResolverService) => { - expect(service).toBeTruthy(); - }, - )); -}); diff --git a/bookie/src/app/temporal-product/temporal-product-list.resolver.ts b/bookie/src/app/temporal-product/temporal-product-list.resolver.ts deleted file mode 100644 index 52e43ed..0000000 --- a/bookie/src/app/temporal-product/temporal-product-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { TemporalProduct } from './temporal-product'; -import { TemporalProductService } from './temporal-product.service'; - -export const temporalProductListResolver: ResolveFn = () => { - return inject(TemporalProductService).list(); -}; diff --git a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list-datasource.ts b/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list-datasource.ts deleted file mode 100644 index 7f27c51..0000000 --- a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list-datasource.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { merge, Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; - -import { TemporalProduct } from '../temporal-product'; - -export class TemporalProductListDatasource extends DataSource { - public data: TemporalProduct[]; - public filteredData: TemporalProduct[]; - public search: string; - public menuCategory: string; - public saleCategory: string; - - constructor( - private readonly searchFilter: Observable, - private readonly menuCategoryFilter: Observable, - private readonly saleCategoryFilter: Observable, - private readonly dataObs: Observable, - ) { - super(); - this.data = []; - this.filteredData = []; - this.search = ''; - this.menuCategory = ''; - this.saleCategory = ''; - } - - connect(): Observable { - const dataMutations = [ - this.dataObs.pipe( - tap((x) => { - this.data = x; - }), - ), - this.searchFilter.pipe( - tap((x) => { - this.search = x; - }), - ), - this.menuCategoryFilter.pipe( - tap((x) => { - this.menuCategory = x; - }), - ), - this.saleCategoryFilter.pipe( - tap((x) => { - this.saleCategory = x; - }), - ), - ]; - return merge(...dataMutations).pipe( - map(() => this.getFilteredData(this.data, this.search, this.menuCategory, this.saleCategory)), - tap((x: TemporalProduct[]) => { - this.filteredData = x; - }), - ); - } - - disconnect() {} - - private getFilteredData( - data: TemporalProduct[], - search: string, - menuCategory: string, - saleCategory: string, - ): TemporalProduct[] { - const tokens = (search ?? '').toLowerCase().split(/\s+/).filter(Boolean); - - return data.filter((tp: TemporalProduct) => { - search = search.toLowerCase(); - - const products = tp.products ?? []; - const skus = tp.skus ?? []; - - // 1) Search: match ANY product/sku fields - const matchesSearch = - tokens.length === 0 || - tokens.every( - (token) => - products.some((p) => { - const hay = `${p.name ?? ''} ${p.fraction_units ?? ''} ${p.saleCategory?.name ?? ''}`.toLowerCase(); - return hay.includes(token); - }) || - skus.some((k) => { - const hay = `${k.units ?? ''} ${k.menuCategory?.name ?? ''}`.toLowerCase(); - return hay.includes(token); - }), - ); - - const matchesMenuCategory = menuCategory === '' || skus.some((k) => (k.menuCategory?.id ?? '') === menuCategory); - - const matchesSaleCategory = - saleCategory === '' || products.some((p) => (p.saleCategory?.id ?? '') === saleCategory); - - return matchesSearch && matchesMenuCategory && matchesSaleCategory; - }); - } -} diff --git a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.html b/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.html index 0ade828..aeb0e1b 100644 --- a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.html +++ b/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.html @@ -1,15 +1,15 @@

    Temporal Products

    -
    +
    Filter - + Menu Category - + -- All Products -- - @for (mc of menuCategories; track mc) { + @for (mc of menuCategoriesResource.value(); track mc) { {{ mc.name }} @@ -18,9 +18,9 @@ Sale Category - + -- All Products -- - @for (mc of saleCategories; track mc) { + @for (mc of saleCategoriesResource.value(); track mc) { {{ mc.name }} @@ -29,7 +29,7 @@
    - + Products diff --git a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.ts b/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.ts index cefa36a..752fb41 100644 --- a/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.ts +++ b/bookie/src/app/temporal-product/temporal-product-list/temporal-product-list.component.ts @@ -1,105 +1,90 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, signal, debounced } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatOptionModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; -import { ActivatedRoute, RouterLink } from '@angular/router'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; +import { RouterLink } from '@angular/router'; -import { MenuCategory } from '../../core/menu-category'; -import { SaleCategory } from '../../core/sale-category'; -import { TemporalProduct } from '../temporal-product'; -import { TemporalProductListDatasource } from './temporal-product-list-datasource'; +import { MenuCategoryService } from '../../menu-category/menu-category.service'; +import { SaleCategoryService } from '../../sale-category/sale-category.service'; +import { TemporalProductService } from '../temporal-product.service'; + +export interface TemporalProductListFormData { + filter: string; + menuCategory: string | null; + saleCategory: string | null; +} @Component({ - selector: 'app-product-list', + selector: 'app-temporal-product-list', templateUrl: './temporal-product-list.component.html', styleUrls: ['./temporal-product-list.component.css'], imports: [ CurrencyPipe, // DecimalPipe, - MatFormFieldModule, MatIconModule, MatInputModule, MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, RouterLink, ], }) -export class TemporalProductListComponent implements OnInit { - private route = inject(ActivatedRoute); +export class TemporalProductListComponent { + private menuCategoryService = inject(MenuCategoryService); + private saleCategoryService = inject(SaleCategoryService); + private temporalProductService = inject(TemporalProductService); - searchFilter = new Observable(); - menuCategoryFilter = new BehaviorSubject(''); - saleCategoryFilter = new BehaviorSubject(''); - data: BehaviorSubject = new BehaviorSubject([]); - dataSource: TemporalProductListDatasource = new TemporalProductListDatasource( - this.searchFilter, - this.menuCategoryFilter, - this.saleCategoryFilter, - this.data, - ); + saleCategoriesResource = this.saleCategoryService.list(); + menuCategoriesResource = this.menuCategoryService.list(undefined); + listResource = this.temporalProductService.list(); - form: FormGroup<{ - filter: FormControl; - menuCategory: FormControl; - saleCategory: FormControl; - }>; + menuCategoryFilter = signal(''); + saleCategoryFilter = signal(''); + + formModel = signal({ + filter: '', + menuCategory: '', + saleCategory: '', + }); + + form = form(this.formModel); + + filterSignal = computed(() => this.formModel().filter); + debouncedFilter = debounced(this.filterSignal, 150); + + dataSource = computed(() => { + let items = this.listResource.value() ?? []; + const search = this.debouncedFilter.value()?.toLowerCase() ?? ''; + const cat = this.menuCategoryFilter(); + const saleCat = this.saleCategoryFilter(); + + if (search) { + items = items.filter((x) => x.products.some((p) => p.name.toLowerCase().includes(search))); + } + if (cat) { + items = items.filter((x) => x.skus.some((s) => s.menuCategory?.id === cat)); + } + if (saleCat) { + items = items.filter((x) => x.products.some((p) => p.saleCategory?.id === saleCat)); + } + return items; + }); - list: TemporalProduct[] = []; - menuCategories: MenuCategory[] = []; - saleCategories: SaleCategory[] = []; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns: string[] = ['product', 'sku', 'price', 'menuCategory', 'saleCategory', 'info']; - constructor() { - this.form = new FormGroup({ - filter: new FormControl('', { nonNullable: true }), - menuCategory: new FormControl(''), - saleCategory: new FormControl(''), - }); - this.data.subscribe((data: TemporalProduct[]) => { - this.list = data; - }); - this.searchFilter = this.form.controls.filter.valueChanges.pipe(debounceTime(150), distinctUntilChanged()); - } - filterMcOn(val: string) { - this.menuCategoryFilter.next(val); + this.menuCategoryFilter.set(val); } filterScOn(val: string) { - this.saleCategoryFilter.next(val); - } - - ngOnInit() { - this.dataSource = new TemporalProductListDatasource( - this.searchFilter, - this.menuCategoryFilter, - this.saleCategoryFilter, - this.data, - ); - this.route.data.subscribe((value) => { - const data = value as { - list: TemporalProduct[]; - menuCategories: MenuCategory[]; - saleCategories: SaleCategory[]; - }; - this.loadData(data.list, data.menuCategories, data.saleCategories); - }); - } - - loadData(list: TemporalProduct[], menuCategories: MenuCategory[], saleCategories: SaleCategory[]) { - this.menuCategories = menuCategories; - this.saleCategories = saleCategories; - this.data.next(list); + this.saleCategoryFilter.set(val); } } diff --git a/bookie/src/app/temporal-product/temporal-product.resolver.spec.ts b/bookie/src/app/temporal-product/temporal-product.resolver.spec.ts deleted file mode 100644 index 129c4dd..0000000 --- a/bookie/src/app/temporal-product/temporal-product.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { TemporalProductResolverService } from './temporal-product-resolver.service'; - -describe('TemporalProductResolverService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [TemporalProductResolverService], - }); - }); - - it('should be created', inject([TemporalProductResolverService], (service: TemporalProductResolverService) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/temporal-product/temporal-product.resolver.ts b/bookie/src/app/temporal-product/temporal-product.resolver.ts deleted file mode 100644 index 7652b7f..0000000 --- a/bookie/src/app/temporal-product/temporal-product.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { TemporalProduct } from './temporal-product'; -import { TemporalProductService } from './temporal-product.service'; - -export const temporalProductResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(TemporalProductService).get(id as string); -}; diff --git a/bookie/src/app/temporal-product/temporal-product.service.ts b/bookie/src/app/temporal-product/temporal-product.service.ts index c20808a..195fe02 100644 --- a/bookie/src/app/temporal-product/temporal-product.service.ts +++ b/bookie/src/app/temporal-product/temporal-product.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -18,16 +18,15 @@ export class TemporalProductService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string): Observable { - return this.http - .get(`${url}/${id}`) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return `${url}/${idVal ?? ''}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } update(product: TemporalProduct): Observable { diff --git a/bookie/src/app/temporal-product/temporal-products.routes.ts b/bookie/src/app/temporal-product/temporal-products.routes.ts index bc66ad1..68e1026 100644 --- a/bookie/src/app/temporal-product/temporal-products.routes.ts +++ b/bookie/src/app/temporal-product/temporal-products.routes.ts @@ -1,12 +1,8 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { menuCategoryListResolver } from '../menu-category/menu-category-list.resolver'; -import { saleCategoryListResolver } from '../sale-category/sale-category-list.resolver'; import { TemporalProductDetailComponent } from './temporal-product-detail/temporal-product-detail.component'; -import { temporalProductListResolver } from './temporal-product-list.resolver'; import { TemporalProductListComponent } from './temporal-product-list/temporal-product-list.component'; -import { temporalProductResolver } from './temporal-product.resolver'; export const routes: Routes = [ { @@ -16,11 +12,6 @@ export const routes: Routes = [ data: { permission: 'Temporal Products', }, - resolve: { - list: temporalProductListResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, { path: 'new', @@ -29,11 +20,6 @@ export const routes: Routes = [ data: { permission: 'Temporal Products', }, - resolve: { - item: temporalProductResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, { path: ':id', @@ -42,10 +28,5 @@ export const routes: Routes = [ data: { permission: 'Temporal Products', }, - resolve: { - item: temporalProductResolver, - menuCategories: menuCategoryListResolver, - saleCategories: saleCategoryListResolver, - }, }, ]; diff --git a/bookie/src/app/update-product-prices/update-product-prices-datasource.ts b/bookie/src/app/update-product-prices/update-product-prices-datasource.ts deleted file mode 100644 index 8d7389b..0000000 --- a/bookie/src/app/update-product-prices/update-product-prices-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { UpdateProductPricesItem } from './update-product-prices-item'; - -export class UpdateProductPricesDataSource extends DataSource { - constructor(public data: UpdateProductPricesItem[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/update-product-prices/update-product-prices.component.html b/bookie/src/app/update-product-prices/update-product-prices.component.html index ceb4b9a..de33a86 100644 --- a/bookie/src/app/update-product-prices/update-product-prices.component.html +++ b/bookie/src/app/update-product-prices/update-product-prices.component.html @@ -1,31 +1,31 @@

    Product Update Report -

    -
    +
    Date - + Menu Category - - @for (s of menuCategories; track s) { + + @for (s of menuCategories(); track s) { {{ s.name }} } - +
    - + Name @@ -41,10 +41,10 @@ New Price - + New Price - + ₹  @@ -56,5 +56,5 @@
    - +
    diff --git a/bookie/src/app/update-product-prices/update-product-prices.component.ts b/bookie/src/app/update-product-prices/update-product-prices.component.ts index f859fd9..ef57339 100644 --- a/bookie/src/app/update-product-prices/update-product-prices.component.ts +++ b/bookie/src/app/update-product-prices/update-product-prices.component.ts @@ -1,6 +1,6 @@ import { CurrencyPipe } from '@angular/common'; -import { Component, OnInit, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { Component, inject, computed, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatOptionModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -12,14 +12,18 @@ import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, Router } from '@angular/router'; import moment from 'moment'; -import { map } from 'rxjs/operators'; -import { MenuCategory } from '../core/menu-category'; +import { MenuCategoryService } from '../menu-category/menu-category.service'; import { ToCsvService } from '../shared/to-csv.service'; import { UpdateProductPrices } from './update-product-prices'; -import { UpdateProductPricesDataSource } from './update-product-prices-datasource'; import { UpdateProductPricesService } from './update-product-prices.service'; +export interface UpdateProductPricesFormData { + date: Date; + menuCategory: string; + prices: { newPrice: number | null }[]; +} + @Component({ selector: 'app-update-product-prices', templateUrl: './update-product-prices.component.html', @@ -27,7 +31,6 @@ import { UpdateProductPricesService } from './update-product-prices.service'; imports: [ CurrencyPipe, MatButtonModule, - MatDatepickerModule, MatFormFieldModule, MatIconModule, @@ -35,77 +38,43 @@ import { UpdateProductPricesService } from './update-product-prices.service'; MatOptionModule, MatSelectModule, MatTableModule, - ReactiveFormsModule, + FormField, ], }) -export class UpdateProductPricesComponent implements OnInit { +export class UpdateProductPricesComponent { + private menuCategoryService = inject(MenuCategoryService); private route = inject(ActivatedRoute); private router = inject(Router); private toCsv = inject(ToCsvService); private snackBar = inject(MatSnackBar); private ser = inject(UpdateProductPricesService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); + date = input(null, { transform: (v: string | null | undefined) => v ?? null }); - info: UpdateProductPrices = new UpdateProductPrices(); - dataSource: UpdateProductPricesDataSource = new UpdateProductPricesDataSource(this.info.items); - form: FormGroup<{ - date: FormControl; - menuCategory: FormControl; - prices: FormArray< - FormGroup<{ - newPrice: FormControl; - }> - >; - }>; + infoResource = this.ser.get(this.id, this.date); - menuCategories: MenuCategory[] = []; + menuCategoriesResource = this.menuCategoryService.list(undefined); + + info = computed(() => this.infoResource.value() ?? new UpdateProductPrices()); + dataSource = computed(() => this.info().items); + formModel = linkedSignal({ + source: () => this.info(), + computation: (info): UpdateProductPricesFormData => { + return { + date: info.date ? moment(info.date, 'DD-MMM-YYYY').toDate() : new Date(), + menuCategory: info.menuCategoryId !== undefined ? info.menuCategoryId : '', + prices: info.items.map((x) => ({ newPrice: x.newPrice })), + }; + }, + }); + + form = form(this.formModel); + + menuCategories = computed(() => this.menuCategoriesResource.value() ?? []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['name', 'oldPrice', 'newPrice']; - constructor() { - // Create form - this.form = new FormGroup({ - date: new FormControl(new Date(), { nonNullable: true }), - menuCategory: new FormControl('', { nonNullable: true }), - prices: new FormArray< - FormGroup<{ - newPrice: FormControl; - }> - >([]), - }); - } - - ngOnInit() { - this.route.data - .pipe( - map((value) => { - const data = value as { menuCategories: MenuCategory[]; info: UpdateProductPrices }; - data.menuCategories.unshift(new MenuCategory({ id: undefined, name: '-- All Categories --' })); - return data; - }), - ) - .subscribe((data: { menuCategories: MenuCategory[]; info: UpdateProductPrices }) => { - this.menuCategories = data.menuCategories; - this.loadData(data.info); - }); - } - - loadData(info: UpdateProductPrices) { - this.info = info; - this.form.controls.date.setValue(moment(this.info.date, 'DD-MMM-YYYY').toDate()); - this.form.controls.menuCategory.setValue(this.info.menuCategoryId !== undefined ? this.info.menuCategoryId : ''); - this.form.controls.prices.clear(); - - this.info.items.forEach((x) => - this.form.controls.prices.push( - new FormGroup({ - newPrice: new FormControl(x.newPrice), - }), - ), - ); - this.dataSource = new UpdateProductPricesDataSource(this.info.items); - } - show() { const info = this.getInfo(); const route = ['update-product-prices']; @@ -120,16 +89,16 @@ export class UpdateProductPricesComponent implements OnInit { } getInfo(): UpdateProductPrices { - const formModel = this.form.value; - const array = this.form.controls.prices; - this.info.items.forEach((item, index) => { - item.newPrice = array.controls[index].value.newPrice ?? null; + const formModel = this.formModel(); + const info = this.info(); + info.items.forEach((item, index) => { + item.newPrice = formModel.prices[index]?.newPrice ?? null; }); return { date: moment(formModel.date).format('DD-MMM-YYYY'), menuCategoryId: formModel.menuCategory, - items: [...this.info.items], + items: [...info.items], }; } @@ -137,7 +106,7 @@ export class UpdateProductPricesComponent implements OnInit { const headers = { Details: 'details', }; - const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource.data)], { + const csvData = new Blob([this.toCsv.toCsv(headers, this.dataSource())], { type: 'text/csv;charset=utf-8;', }); const link = document.createElement('a'); @@ -152,10 +121,10 @@ export class UpdateProductPricesComponent implements OnInit { this.ser.save(this.getInfo()).subscribe({ next: (result: UpdateProductPrices) => { this.snackBar.open('', 'Success'); - this.loadData(result); + this.infoResource.value.set(result); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } diff --git a/bookie/src/app/update-product-prices/update-product-prices.resolver.spec.ts b/bookie/src/app/update-product-prices/update-product-prices.resolver.spec.ts deleted file mode 100644 index 26b7d97..0000000 --- a/bookie/src/app/update-product-prices/update-product-prices.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { UpdateProductPricesResolver } from './update-product-prices-resolver.service'; - -describe('UpdateProductPricesResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [UpdateProductPricesResolver], - }); - }); - - it('should be created', inject([UpdateProductPricesResolver], (service: UpdateProductPricesResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/update-product-prices/update-product-prices.resolver.ts b/bookie/src/app/update-product-prices/update-product-prices.resolver.ts deleted file mode 100644 index a763127..0000000 --- a/bookie/src/app/update-product-prices/update-product-prices.resolver.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { UpdateProductPrices } from './update-product-prices'; -import { UpdateProductPricesService } from './update-product-prices.service'; - -export const updateProductPricesResolver: ResolveFn = (route) => { - const date = route.queryParamMap.get('date') ?? null; - const id = route.paramMap.get('id'); - return inject(UpdateProductPricesService).get(id, date); -}; diff --git a/bookie/src/app/update-product-prices/update-product-prices.routes.ts b/bookie/src/app/update-product-prices/update-product-prices.routes.ts index 59e698c..2e98858 100644 --- a/bookie/src/app/update-product-prices/update-product-prices.routes.ts +++ b/bookie/src/app/update-product-prices/update-product-prices.routes.ts @@ -1,9 +1,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; -import { menuCategoryListResolver } from '../menu-category/menu-category-list.resolver'; import { UpdateProductPricesComponent } from './update-product-prices.component'; -import { updateProductPricesResolver } from './update-product-prices.resolver'; export const routes: Routes = [ { @@ -13,10 +11,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - menuCategories: menuCategoryListResolver, - info: updateProductPricesResolver, - }, runGuardsAndResolvers: 'always', }, { @@ -26,10 +20,6 @@ export const routes: Routes = [ data: { permission: 'Products', }, - resolve: { - menuCategories: menuCategoryListResolver, - info: updateProductPricesResolver, - }, runGuardsAndResolvers: 'always', }, ]; diff --git a/bookie/src/app/update-product-prices/update-product-prices.service.ts b/bookie/src/app/update-product-prices/update-product-prices.service.ts index b4d8652..1813636 100644 --- a/bookie/src/app/update-product-prices/update-product-prices.service.ts +++ b/bookie/src/app/update-product-prices/update-product-prices.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpParams } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpParams, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -16,15 +16,17 @@ export class UpdateProductPricesService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null, date: string | null): Observable { - const getUrl: string = id === null ? url : `${url}/${id}`; - const options = { params: new HttpParams() }; - if (date !== null) { - options.params = options.params.set('d', date); - } - return this.http - .get(getUrl, options) - .pipe(catchError(this.log.handleError(serviceName, 'get'))) as Observable; + get(id: Signal, date: Signal): HttpResourceRef { + return httpResource(() => { + const idVal = id(); + const getUrl = idVal === null ? url : `${url}/${idVal}`; + let params = new HttpParams(); + const d = date(); + if (d !== null) { + params = params.set('d', d); + } + return { url: getUrl, params }; + }); } save(item: UpdateProductPrices): Observable { diff --git a/bookie/src/app/users/user-detail/user-detail.component.html b/bookie/src/app/users/user-detail/user-detail.component.html index d3cc3f4..81390d7 100644 --- a/bookie/src/app/users/user-detail/user-detail.component.html +++ b/bookie/src/app/users/user-detail/user-detail.component.html @@ -1,32 +1,32 @@

    User

    -
    +
    Name - +
    Password - + {{ hide ? 'visibility' : 'visibility_off' }}
    - Is Locked Out? + Is Locked Out?
    -
    - @for (r of item.roles; track r; let i = $index) { -
    - {{ r.name }} +
    + @for (r of form.roles; track r; let i = $index) { +
    + {{ r.name().value() }}
    }
    - - + +
    diff --git a/bookie/src/app/users/user-detail/user-detail.component.ts b/bookie/src/app/users/user-detail/user-detail.component.ts index fad4b2d..595069b 100644 --- a/bookie/src/app/users/user-detail/user-detail.component.ts +++ b/bookie/src/app/users/user-detail/user-detail.component.ts @@ -1,5 +1,5 @@ -import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; -import { FormArray, FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { AfterViewInit, Component, ElementRef, ViewChild, computed, inject, linkedSignal, input } from '@angular/core'; +import { form, FormField } from '@angular/forms/signals'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDialog } from '@angular/material/dialog'; @@ -14,74 +14,57 @@ import { User } from '../../core/user'; import { ConfirmDialogComponent } from '../../shared/confirm-dialog/confirm-dialog.component'; import { UserService } from '../user.service'; +export interface UserDetailFormData { + name: string; + password: string; + lockedOut: boolean; + roles: { id: string; name: string; enabled: boolean }[]; +} + @Component({ selector: 'app-user-detail', templateUrl: './user-detail.component.html', styleUrls: ['./user-detail.component.css'], imports: [ MatButtonModule, - MatCheckboxModule, MatDividerModule, MatFormFieldModule, MatIconModule, MatInputModule, - ReactiveFormsModule, + FormField, ], }) -export class UserDetailComponent implements OnInit, AfterViewInit { +export class UserDetailComponent implements AfterViewInit { + @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; private route = inject(ActivatedRoute); private router = inject(Router); private snackBar = inject(MatSnackBar); private dialog = inject(MatDialog); private ser = inject(UserService); + id = input(null, { transform: (v: string | null | undefined) => v ?? null }); - @ViewChild('nameElement', { static: true }) nameElement?: ElementRef; - form: FormGroup<{ - name: FormControl; - password: FormControl; - lockedOut: FormControl; - roles: FormArray< - FormGroup<{ - role: FormControl; - }> - >; - }>; + itemResource = this.ser.get(this.id); - item: User = new User(); - hide: boolean; + item = computed(() => this.itemResource.value() ?? new User()); + formModel = linkedSignal({ + source: this.item, + computation: (itemVal): UserDetailFormData => { + return { + name: itemVal.name ?? '', + password: '', + lockedOut: itemVal.lockedOut, + roles: itemVal.roles.map((x) => ({ id: x.id ?? '', name: x.name, enabled: x.enabled })), + }; + }, + }); + + form = form(this.formModel); + + hide = true; constructor() { this.hide = true; - // Create form - this.form = new FormGroup({ - name: new FormControl(null), - password: new FormControl(null), - lockedOut: new FormControl(false, { nonNullable: true }), - roles: new FormArray }>>([]), - }); - } - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { item: User }; - this.showItem(data.item); - }); - } - - showItem(item: User) { - this.item = item; - this.form.controls.name.setValue(item.name); - this.form.controls.password.setValue(''); - this.form.controls.lockedOut.setValue(item.lockedOut); - this.form.controls.roles.clear(); - this.item.roles.forEach((x) => - this.form.controls.roles.push( - new FormGroup({ - role: new FormControl(x.enabled, { nonNullable: true }), - }), - ), - ); } ngAfterViewInit() { @@ -96,26 +79,26 @@ export class UserDetailComponent implements OnInit, AfterViewInit { this.ser.saveOrUpdate(this.getItem()).subscribe({ next: () => { this.snackBar.open('', 'Success'); - if ((this.item.id as string) === 'me') { + if ((this.item().id as string) === 'me') { this.router.navigateByUrl('/'); } else { this.router.navigateByUrl('/users'); } }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } delete() { - this.ser.delete(this.item.id as string).subscribe({ + this.ser.delete(this.item().id as string).subscribe({ next: () => { this.snackBar.open('', 'Success'); this.router.navigateByUrl('/users'); }, - error: (error) => { - this.snackBar.open(error, 'Error'); + error: (error: unknown) => { + this.snackBar.open(error as string, 'Error'); }, }); } @@ -134,14 +117,13 @@ export class UserDetailComponent implements OnInit, AfterViewInit { } getItem(): User { - const formModel = this.form.value; - this.item.name = formModel.name ?? ''; - this.item.password = formModel.password ?? ''; - this.item.lockedOut = formModel.lockedOut ?? true; - const array = this.form.controls.roles; - this.item.roles.forEach((item, index) => { - item.enabled = array.controls[index].value.role ?? false; + const formModel = this.formModel(); + return new User({ + ...this.item(), + name: formModel.name ?? '', + password: formModel.password ?? '', + lockedOut: formModel.lockedOut ?? true, + roles: formModel.roles.map((x) => ({ id: x.id ?? '', name: x.name, enabled: x.enabled })), }); - return this.item; } } diff --git a/bookie/src/app/users/user-list.resolver.spec.ts b/bookie/src/app/users/user-list.resolver.spec.ts deleted file mode 100644 index c380204..0000000 --- a/bookie/src/app/users/user-list.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { UserListResolver } from './user-list-resolver.service'; - -describe('UserListResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [UserListResolver], - }); - }); - - it('should be created', inject([UserListResolver], (service: UserListResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/users/user-list.resolver.ts b/bookie/src/app/users/user-list.resolver.ts deleted file mode 100644 index deecc7c..0000000 --- a/bookie/src/app/users/user-list.resolver.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { User } from '../core/user'; -import { UserService } from './user.service'; - -export const userListResolver: ResolveFn = () => { - return inject(UserService).list(); -}; diff --git a/bookie/src/app/users/user-list/user-list-datasource.ts b/bookie/src/app/users/user-list/user-list-datasource.ts deleted file mode 100644 index 3246724..0000000 --- a/bookie/src/app/users/user-list/user-list-datasource.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { DataSource } from '@angular/cdk/collections'; -import { Observable, of as observableOf } from 'rxjs'; - -import { User } from '../../core/user'; - -export class UserListDataSource extends DataSource { - constructor(public data: User[]) { - super(); - } - - connect(): Observable { - return observableOf(this.data); - } - - disconnect() {} -} diff --git a/bookie/src/app/users/user-list/user-list.component.html b/bookie/src/app/users/user-list/user-list.component.html index cbd8be2..0a5ddf5 100644 --- a/bookie/src/app/users/user-list/user-list.component.html +++ b/bookie/src/app/users/user-list/user-list.component.html @@ -5,7 +5,7 @@ Add - + Name diff --git a/bookie/src/app/users/user-list/user-list.component.ts b/bookie/src/app/users/user-list/user-list.component.ts index c4a3fc4..f3b1893 100644 --- a/bookie/src/app/users/user-list/user-list.component.ts +++ b/bookie/src/app/users/user-list/user-list.component.ts @@ -1,32 +1,22 @@ -import { Component, OnInit, inject } from '@angular/core'; +import { Component, computed, inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatTableModule } from '@angular/material/table'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { User } from '../../core/user'; import { LocalTimePipe } from '../../shared/local-time.pipe'; -import { UserListDataSource } from './user-list-datasource'; - +import { UserService } from '../user.service'; @Component({ selector: 'app-user-list', templateUrl: './user-list.component.html', styleUrls: ['./user-list.component.css'], imports: [LocalTimePipe, MatButtonModule, MatIconModule, MatTableModule, RouterLink], }) -export class UserListComponent implements OnInit { +export class UserListComponent { + private userService = inject(UserService); private route = inject(ActivatedRoute); + listResource = this.userService.list(); - dataSource: UserListDataSource = new UserListDataSource([]); - list: User[] = []; - /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ + dataSource = computed(() => this.listResource.value() ?? []); displayedColumns = ['name', 'lockedOut', 'roles', 'last']; - - ngOnInit() { - this.route.data.subscribe((value) => { - const data = value as { list: User[] }; - this.list = data.list; - }); - this.dataSource = new UserListDataSource(this.list); - } } diff --git a/bookie/src/app/users/user.resolver.spec.ts b/bookie/src/app/users/user.resolver.spec.ts deleted file mode 100644 index 7f1b0cb..0000000 --- a/bookie/src/app/users/user.resolver.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { inject, TestBed } from '@angular/core/testing'; - -import { UserResolver } from './user-resolver.service'; - -describe('UserResolver', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [UserResolver], - }); - }); - - it('should be created', inject([UserResolver], (service: UserResolver) => { - expect(service).toBeTruthy(); - })); -}); diff --git a/bookie/src/app/users/user.resolver.ts b/bookie/src/app/users/user.resolver.ts deleted file mode 100644 index fd12395..0000000 --- a/bookie/src/app/users/user.resolver.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { inject } from '@angular/core'; -import { ResolveFn } from '@angular/router'; - -import { User } from '../core/user'; -import { UserService } from './user.service'; - -export const userResolver: ResolveFn = (route) => { - const id = route.paramMap.get('id'); - return inject(UserService).get(id); -}; diff --git a/bookie/src/app/users/user.service.ts b/bookie/src/app/users/user.service.ts index 766b75f..5cf2812 100644 --- a/bookie/src/app/users/user.service.ts +++ b/bookie/src/app/users/user.service.ts @@ -1,5 +1,5 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable, inject } from '@angular/core'; +import { HttpClient, HttpHeaders, httpResource, HttpResourceRef } from '@angular/common/http'; +import { Injectable, Signal, inject } from '@angular/core'; import { Observable } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -19,17 +19,15 @@ export class UserService { private http = inject(HttpClient); private log = inject(ErrorLoggerService); - get(id: string | null): Observable { - const getUrl: string = id === null ? `${url}` : `${url}/${id}`; - return this.http - .get(getUrl) - .pipe(catchError(this.log.handleError(serviceName, `get id=${id}`))) as Observable; + get(id: Signal | string | null): HttpResourceRef { + return httpResource(() => { + const idVal = typeof id === 'function' ? id() : id; + return idVal === null || idVal === undefined ? url : `${url}/${idVal}`; + }); } - list(): Observable { - return this.http - .get(`${url}/list`) - .pipe(catchError(this.log.handleError(serviceName, 'list'))) as Observable; + list(): HttpResourceRef { + return httpResource(() => `${url}/list`); } save(user: User): Observable { diff --git a/bookie/src/app/users/users.routes.ts b/bookie/src/app/users/users.routes.ts index 532d0c9..3cfd472 100644 --- a/bookie/src/app/users/users.routes.ts +++ b/bookie/src/app/users/users.routes.ts @@ -2,9 +2,7 @@ import { Routes } from '@angular/router'; import { authGuard } from '../auth/auth-guard.service'; import { UserDetailComponent } from './user-detail/user-detail.component'; -import { userListResolver } from './user-list.resolver'; import { UserListComponent } from './user-list/user-list.component'; -import { userResolver } from './user.resolver'; export const routes: Routes = [ { @@ -14,9 +12,6 @@ export const routes: Routes = [ data: { permission: 'Users', }, - resolve: { - list: userListResolver, - }, }, { path: 'new', @@ -25,16 +20,10 @@ export const routes: Routes = [ data: { permission: 'Users', }, - resolve: { - item: userResolver, - }, }, { path: ':id', component: UserDetailComponent, canActivate: [authGuard], - resolve: { - item: userResolver, - }, }, ]; diff --git a/bookie/src/styles.sass b/bookie/src/styles.sass index 1d70917..d45ca8b 100644 --- a/bookie/src/styles.sass +++ b/bookie/src/styles.sass @@ -33,14 +33,14 @@ a text-decoration: underline -.mat-mdc-button.mat-primary, -.mat-mdc-raised-button.mat-primary, -.mat-mdc-unelevated-button.mat-primary +.mat-mdc-button.mat-primary:not(:disabled), +.mat-mdc-raised-button.mat-primary:not(:disabled), +.mat-mdc-unelevated-button.mat-primary:not(:disabled) background: var(--mat-sys-primary) !important color: var(--mat-sys-on-primary) !important -.mat-mdc-button.mat-warn, -.mat-mdc-raised-button.mat-warn, -.mat-mdc-unelevated-button.mat-warn +.mat-mdc-button.mat-warn:not(:disabled), +.mat-mdc-raised-button.mat-warn:not(:disabled), +.mat-mdc-unelevated-button.mat-warn:not(:disabled) background: var(--mat-sys-error) !important color: var(--mat-sys-on-error) !important diff --git a/bookie/tsconfig.app.json b/bookie/tsconfig.app.json index 0a6a03b..8bcd825 100644 --- a/bookie/tsconfig.app.json +++ b/bookie/tsconfig.app.json @@ -6,5 +6,13 @@ "types": [] }, "include": ["src/**/*.ts"], - "exclude": ["src/**/*.spec.ts"] + "exclude": ["src/**/*.spec.ts"], + "angularCompilerOptions": { + "extendedDiagnostics": { + "checks": { + "nullishCoalescingNotNullable": "suppress", + "optionalChainNotNullable": "suppress" + } + } + } } diff --git a/bookie/yarn.lock b/bookie/yarn.lock index 7fdd9e9..d4c497c 100644 --- a/bookie/yarn.lock +++ b/bookie/yarn.lock @@ -2,132 +2,6 @@ # yarn lockfile v1 -"@algolia/abtesting@1.12.2": - version "1.12.2" - resolved "https://registry.yarnpkg.com/@algolia/abtesting/-/abtesting-1.12.2.tgz#1cba5e3c654d02c6d435822a0a0070a5c435daa6" - integrity sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-abtesting@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz#264a72f0e9d2fe0d0dc5c3d2d16bbb9cfe2ce9e8" - integrity sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-analytics@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.46.2.tgz#3f00a237508aa0c46c9c02dea9c855e0a78e241f" - integrity sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-common@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.46.2.tgz#7f282fd8f721b0d96958445df2170f4c7dce6aac" - integrity sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg== - -"@algolia/client-insights@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.46.2.tgz#194b7b529ee8a4ffd5d70037745082996c3b9aa0" - integrity sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-personalization@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.46.2.tgz#d604da7f0a3df1b3e2a9fe338d368e48fb781f8e" - integrity sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-query-suggestions@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz#f13bc5897bfbdc19509d430a26e9bbe2402e00c9" - integrity sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/client-search@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.46.2.tgz#771367916aaa3fb7a19d5944f8375504b0568ba6" - integrity sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/ingestion@1.46.2": - version "1.46.2" - resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.46.2.tgz#2a5d8a592d9f864dfb438722506382af56f8554f" - integrity sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/monitoring@1.46.2": - version "1.46.2" - resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.46.2.tgz#bd199368a49cb799cf12cfe76c49de6dd3021148" - integrity sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/recommend@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.46.2.tgz#e74bade1254046ed9be8ccd37f2a116ab9799508" - integrity sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q== - dependencies: - "@algolia/client-common" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -"@algolia/requester-browser-xhr@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz#7662480143405e815e1eed99136b4b2acd838ee7" - integrity sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg== - dependencies: - "@algolia/client-common" "5.46.2" - -"@algolia/requester-fetch@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz#dee07f0131b75f30d083bafd6fb878afe7402eb9" - integrity sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw== - dependencies: - "@algolia/client-common" "5.46.2" - -"@algolia/requester-node-http@5.46.2": - version "5.46.2" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz#7869d67cb2926bbdbfbfed2b4757e547c2e227eb" - integrity sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg== - dependencies: - "@algolia/client-common" "5.46.2" - "@ampproject/remapping@2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -136,178 +10,172 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@angular-devkit/architect@0.2101.1", "@angular-devkit/architect@>= 0.2100.0 < 0.2200.0": - version "0.2101.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.2101.1.tgz#d36db61c0b7e3b2fe3e925900f2acf65be37f653" - integrity sha512-8x7hKcFs3hnpDaIj9fyzinh4X74oQaMxMsZzBf4dBL7EwokjPIf2fadQsZd8a5M+Ja4tIgTnXH9ySyaRFWGNXA== +"@angular-devkit/architect@0.2201.3", "@angular-devkit/architect@>= 0.2200.0 < 0.2300.0": + version "0.2201.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.2201.3.tgz#c885e6d229db2cb4d34295899a8e47d277421d00" + integrity sha512-5WX6rooTQZCh+yE9k3O5hc7nnQtzy1nw6fQpaTuCzIgPG8teQuVtdxegBsM3OcjJac1r+qJLo+KmTRfnqcfsyg== dependencies: - "@angular-devkit/core" "21.1.1" + "@angular-devkit/core" "22.1.3" rxjs "7.8.2" -"@angular-devkit/core@21.1.1", "@angular-devkit/core@>= 21.0.0 < 22.0.0": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-21.1.1.tgz#4a889c8e75849811981d33b3ab59a88157485eae" - integrity sha512-rCwfBUemyRoAfrO4c85b49lkPiD5WljWE+IK7vjUNIFFf4TXOS4tg4zxqopUDVE4zEjXORa5oHCEc5HCerjn1g== +"@angular-devkit/core@22.1.3", "@angular-devkit/core@>= 22.0.0 < 23.0.0": + version "22.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-22.1.3.tgz#460714465203f95c7c92054de46647515021f8f8" + integrity sha512-ASK8oZVElt/Zpz5FrzJjLnnUbzp/fW57eFFSRgpA+n9KRnuFi6YvNdSS3HkG5049Jcukce+PiMBdfzw/jBVkEw== dependencies: - ajv "8.17.1" + ajv "8.20.0" ajv-formats "3.0.1" jsonc-parser "3.3.1" - picomatch "4.0.3" + picomatch "4.0.5" rxjs "7.8.2" source-map "0.7.6" -"@angular-devkit/schematics@21.1.1", "@angular-devkit/schematics@>= 21.0.0 < 22.0.0": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-21.1.1.tgz#485db31989fe04b9dea23ec1b5f7b0a979c24b1f" - integrity sha512-3ptEOuALghEYEPVbhRa7g8a+YmvmHqHVNqF9XqCbG22nPGWkE58qfNNbXi3tF9iQxzKSGw5Iy5gYUvSvpsdcfw== +"@angular-devkit/schematics@22.1.3", "@angular-devkit/schematics@>= 22.0.0 < 23.0.0": + version "22.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-22.1.3.tgz#4cd8083a395470a1b58e2456af1ebef985a99d96" + integrity sha512-ebY5bwZVB0onxxyTbJch//VidVVV8jo/F13n+TV5s/3ZywsC3/XZsfMHaxlFmpvP/G17+/C9JVoEXT+uwjT+/Q== dependencies: - "@angular-devkit/core" "21.1.1" + "@angular-devkit/core" "22.1.3" jsonc-parser "3.3.1" - magic-string "0.30.21" - ora "9.0.0" + magic-string "1.0.0" + ora "9.4.1" rxjs "7.8.2" -"@angular-eslint/builder@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/builder/-/builder-21.1.0.tgz#00cf1e6a786435ffe594b3b93c275b19e0078923" - integrity sha512-pcUlDkGqeZ+oQC0oEjnkDDlB96gbgHQhnBUKdhYAiAOSuiBod4+npP0xQOq5chYtRNPBprhDqgrJrp5DBeDMOA== +"@angular-eslint/builder@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/builder/-/builder-22.1.0.tgz#d38388a397239e2c65addb0ca6428dd4e7199ace" + integrity sha512-gmdk06PK0whNJlapIQjRnhud2/n+oIIDBIoLUHWFFxhHRs+ZstVc6+81gf+sYDOm1Ehmb0V3nZAg3YpT1Mk0Eg== dependencies: - "@angular-devkit/architect" ">= 0.2100.0 < 0.2200.0" - "@angular-devkit/core" ">= 21.0.0 < 22.0.0" + "@angular-devkit/architect" ">= 0.2200.0 < 0.2300.0" + "@angular-devkit/core" ">= 22.0.0 < 23.0.0" -"@angular-eslint/bundled-angular-compiler@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-21.1.0.tgz#56ef7b91cdc406161afab748aab476e31bfdd4b1" - integrity sha512-t52J6FszgEHaJ+IjuzU9qaWfVxsjlVNkAP+B5z2t4NDgbbDDsmI+QJh0OtP1qdlqzjh2pbocEml30KhYmNZm/Q== +"@angular-eslint/bundled-angular-compiler@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-22.1.0.tgz#603becba751c43afcfa19503022e129584e49056" + integrity sha512-iOtOQ2jtrtko1rIQo6i+g3ezxGL0lyYv80j4GccFTK1JGh4K+AqYkmaBvfUfNtqoE/7VcKsOoyxaFt6iIpKhaQ== -"@angular-eslint/eslint-plugin-template@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-21.1.0.tgz#7d8c27a968313e5aa94f02e2d1bba30d5e140f5a" - integrity sha512-FlbRfOCn8IUHvP1ebcCSQFVNh+4X/HqZqL7SW5oj9WIYPiOX9ijS03ndNbfX/pBPSIi8GHLKMjLt8zIy1l5Lww== +"@angular-eslint/eslint-plugin-template@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-22.1.0.tgz#30642c56aa8a634dc45e2dc103840ad27937c142" + integrity sha512-GK/Mwhwvj+MX6DefD29/IfuYjcai5CsCbYJ6Qb9P6IAzZaQqw+EN+CiXxIwzMnzm2edLcJzAsX8iBk4X7sVi2Q== dependencies: - "@angular-eslint/bundled-angular-compiler" "21.1.0" - "@angular-eslint/utils" "21.1.0" + "@angular-eslint/bundled-angular-compiler" "22.1.0" + "@angular-eslint/utils" "22.1.0" aria-query "5.3.2" axobject-query "4.1.0" -"@angular-eslint/eslint-plugin@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin/-/eslint-plugin-21.1.0.tgz#92581dcaf1e03fb8624f42bedd6e6ca7ce1273e6" - integrity sha512-oNp+4UzN2M3KwGwEw03NUdXz93vqJd9sMzTbGXWF9+KVfA2LjckGDTrI6g6asGcJMdyTo07rDcnw0m0MkLB5VA== +"@angular-eslint/eslint-plugin@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/eslint-plugin/-/eslint-plugin-22.1.0.tgz#d445da381aaf79a6afbdab76a825141bddbf995a" + integrity sha512-nRwdbUiW7vF0gbwtxw2hRGPZYZCNWOTLZKw4HM+I37o5YFIA0CFLtbyRKgZWs6JZCIqzTYSwCyKNsW41Qw0FwQ== dependencies: - "@angular-eslint/bundled-angular-compiler" "21.1.0" - "@angular-eslint/utils" "21.1.0" + "@angular-eslint/bundled-angular-compiler" "22.1.0" + "@angular-eslint/utils" "22.1.0" ts-api-utils "^2.1.0" -"@angular-eslint/schematics@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/schematics/-/schematics-21.1.0.tgz#ba2e989cfd8d4cc57d04ad754f81228f3bb70ca0" - integrity sha512-Hal1mYwx4MTjCcNHqfIlua31xrk2tZJoyTiXiGQ21cAeK4sFuY+9V7/8cxbwJMGftX0G4J7uhx8woOdIFuqiZw== +"@angular-eslint/schematics@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/schematics/-/schematics-22.1.0.tgz#e9e7bd786d8496177d85dd9180c501e69338afb7" + integrity sha512-/Z7MEO9ys9P5w5itM2mpNW4R/QNAVxtDdcU5LVFulSx/lo7zCDx1rZ/tLDuzbN5k5RGQy5ZkdRIs0MoscsGXQQ== dependencies: - "@angular-devkit/core" ">= 21.0.0 < 22.0.0" - "@angular-devkit/schematics" ">= 21.0.0 < 22.0.0" - "@angular-eslint/eslint-plugin" "21.1.0" - "@angular-eslint/eslint-plugin-template" "21.1.0" + "@angular-devkit/core" ">= 22.0.0 < 23.0.0" + "@angular-devkit/schematics" ">= 22.0.0 < 23.0.0" + "@angular-eslint/eslint-plugin" "22.1.0" + "@angular-eslint/eslint-plugin-template" "22.1.0" ignore "7.0.5" - semver "7.7.3" + semver "7.8.5" strip-json-comments "3.1.1" -"@angular-eslint/template-parser@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/template-parser/-/template-parser-21.1.0.tgz#7af5cff19cf522dfe4182b680d569202c60b54e4" - integrity sha512-PYVgNbjNtuD5/QOuS6cHR8A7bRqsVqxtUUXGqdv76FYMAajQcAvyfR0QxOkqf3NmYxgNgO3hlUHWq0ILjVbcow== +"@angular-eslint/template-parser@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/template-parser/-/template-parser-22.1.0.tgz#ff92e9a4809bc8fb0b3904c3b4aa8dcf0075fa18" + integrity sha512-gcufZLI/Rl2fOWtBk2MgMRkH1t+OrbJGxIsfT0w3pVjKm0zwi7njM/dtPbVjCHzsGhx7szQMvY0i0UwTBVYkSw== dependencies: - "@angular-eslint/bundled-angular-compiler" "21.1.0" - eslint-scope "^9.0.0" + "@angular-eslint/bundled-angular-compiler" "22.1.0" + eslint-scope "9.1.2" -"@angular-eslint/utils@21.1.0": - version "21.1.0" - resolved "https://registry.yarnpkg.com/@angular-eslint/utils/-/utils-21.1.0.tgz#e6985d1f8e62564157364b65ad8d736e4b1ff8b9" - integrity sha512-rWINgxGREu+NFUPCpAVsBGG8B4hfXxyswM0N5GbjykvsfB5W6PUix2Gsoh++iEsZPT+c9lvgXL5GbpwfanjOow== +"@angular-eslint/utils@22.1.0": + version "22.1.0" + resolved "https://registry.yarnpkg.com/@angular-eslint/utils/-/utils-22.1.0.tgz#d85addc71f157dc75c578f2e1909b752518ba46e" + integrity sha512-zDPJqgOxlkG20UJWsVDSvnEtC2MfIP0+yKMaQUBL+2nrEknV/fVLrz7ApnerWiDrGTcAms5si49KV10MarMpRA== dependencies: - "@angular-eslint/bundled-angular-compiler" "21.1.0" + "@angular-eslint/bundled-angular-compiler" "22.1.0" -"@angular/build@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/build/-/build-21.1.1.tgz#4625669c40c56138f22de33e515473d5d4722866" - integrity sha512-OqlfH7tkahw/lFT6ACU6mqt3AGgTxxT27JTqpzZOeGo1ferR9dq1O6/CT4GiNyr/Z1AMfs7rBWlQH68y1QZb2g== +"@angular/build@^22.1.3": + version "22.1.3" + resolved "https://registry.yarnpkg.com/@angular/build/-/build-22.1.3.tgz#31277362e8caabeb53ba0cf81114ff0b2e873022" + integrity sha512-Hjen3LcVZUCNZy+epgO+/PMUpD/L8Y4vODS+Q8F0Lkva7YWQwycbJtrEr6xvFfMxp6xexxxIwB9+5b8voKSihQ== dependencies: "@ampproject/remapping" "2.3.0" - "@angular-devkit/architect" "0.2101.1" - "@babel/core" "7.28.5" - "@babel/helper-annotate-as-pure" "7.27.3" + "@angular-devkit/architect" "0.2201.3" + "@babel/core" "8.0.1" + "@babel/helper-annotate-as-pure" "8.0.0" "@babel/helper-split-export-declaration" "7.24.7" - "@inquirer/confirm" "5.1.21" - "@vitejs/plugin-basic-ssl" "2.1.0" - beasties "0.3.5" + "@inquirer/confirm" "6.1.1" + "@vitejs/plugin-basic-ssl" "2.3.0" + beasties "0.4.3" browserslist "^4.26.0" - esbuild "0.27.2" - https-proxy-agent "7.0.6" - istanbul-lib-instrument "6.0.3" + esbuild "0.28.1" + https-proxy-agent "9.1.0" jsonc-parser "3.3.1" - listr2 "9.0.5" - magic-string "0.30.21" + listr2 "10.2.2" + magic-string "1.0.0" mrmime "2.0.1" - parse5-html-rewriting-stream "8.0.0" - picomatch "4.0.3" - piscina "5.1.4" - rolldown "1.0.0-beta.58" - sass "1.97.1" - semver "7.7.3" + oxc-parser "0.142.0" + parse5-html-rewriting-stream "8.0.1" + picomatch "4.0.5" + piscina "5.2.0" + rolldown "1.2.0" + sass "1.101.0" + semver "7.8.5" source-map-support "0.5.21" - tinyglobby "0.2.15" - undici "7.18.2" - vite "7.3.0" - watchpack "2.5.0" + tinyglobby "0.2.17" + vite "8.1.5" + watchpack "2.5.2" optionalDependencies: - lmdb "3.4.4" + lmdb "3.5.6" -"@angular/cdk@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-21.1.1.tgz#797605278fa0486a33f01bf50a7ec346444492e8" - integrity sha512-lzscv+A6FCQdyWIr0t0QHXEgkLzS9wJwgeOOOhtxbixxxuk7xVXdcK/jnswE1Maugh1m696jUkOhZpffks3psA== +"@angular/cdk@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-22.1.1.tgz#1cd02f6831f30324171eb575e1875d278c62c689" + integrity sha512-P8YuW/r5MS8aeKF0NruktKGHQShOMctvhs3H/51BOwJrMZi5qtWJ40t1yqTrNnewSJIKI0/AroUEmEOqA9Ml9Q== dependencies: parse5 "^8.0.0" tslib "^2.3.0" -"@angular/cli@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-21.1.1.tgz#f9094f75c3c2e9a0fad387c8fa894aa5c8cc7512" - integrity sha512-eXhHuYvruWHBn7lX3GuAyLq29+ELwPADOW8ShzZkWRPNlIDiFDsS5pXrxkM9ez+8f86kfDHh88Twevn4UBUqQg== +"@angular/cli@^22.1.3": + version "22.1.3" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-22.1.3.tgz#0a0647abfe30ab9c76990e93f5e8d15bb9b78f9d" + integrity sha512-GB1Pv8CXAHXE2/hqiwSGD6JRIyT4wswadjH1j3DH2+6os1zc7CBm28/YtlKPPIHZKVOZLDqV6uW+bRQTtdOw2A== dependencies: - "@angular-devkit/architect" "0.2101.1" - "@angular-devkit/core" "21.1.1" - "@angular-devkit/schematics" "21.1.1" - "@inquirer/prompts" "7.10.1" - "@listr2/prompt-adapter-inquirer" "3.0.5" - "@modelcontextprotocol/sdk" "1.25.2" - "@schematics/angular" "21.1.1" - "@yarnpkg/lockfile" "1.1.0" - algoliasearch "5.46.2" - ini "6.0.0" + "@angular-devkit/architect" "0.2201.3" + "@angular-devkit/core" "22.1.3" + "@angular-devkit/schematics" "22.1.3" + "@inquirer/prompts" "8.5.2" + "@listr2/prompt-adapter-inquirer" "4.2.4" + "@modelcontextprotocol/sdk" "1.29.0" + "@schematics/angular" "22.1.3" jsonc-parser "3.3.1" - listr2 "9.0.5" - npm-package-arg "13.0.2" - pacote "21.0.4" - parse5-html-rewriting-stream "8.0.0" - resolve "1.22.11" - semver "7.7.3" + listr2 "10.2.2" + npm-package-arg "14.0.0" + parse5-html-rewriting-stream "8.0.1" + semver "7.8.5" yargs "18.0.0" - zod "4.3.5" + zod "4.4.3" -"@angular/common@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-21.1.1.tgz#f55655b7d13a6896efc10ede243de9498ff33c78" - integrity sha512-Di2I6TooHdKun3SqRr45o4LbWJq/ZdwUt3fg0X3obPYaP/f6TrFQ4TMjcl03EfPufPtoQx6O+d32rcWVLhDxyw== +"@angular/common@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-22.1.1.tgz#b061ad0b07bf6a74e8dec62b28f4cf717cb7a79c" + integrity sha512-5iiyPWqO3acpOPMcJWYtVbXF5z9wy43MFQQdd7wZPHfYOIC7c3KRnziWrRpELae+SkEB4srAYr6XIu9rQ743nw== dependencies: tslib "^2.3.0" -"@angular/compiler-cli@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-21.1.1.tgz#fe3640996a5e45739d5b846ec7665e62206ca7e7" - integrity sha512-CCB8SZS0BzqLOdOaMpPpOW256msuatYCFDRTaT+awYIY1vQp/eLXzkMTD2uqyHraQy8cReeH/P6optRP9A077Q== +"@angular/compiler-cli@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-22.1.1.tgz#6d64294f8bdb32b40f5e6b085ad0ded1d9e53d5b" + integrity sha512-GLcwWqUg4i2eru3nKy989Me7483+ZPofnwgw9aMc96MWl8y8CD9CTrSff+fwh2/crUsQIqGg/uehIZRjISMD0A== dependencies: - "@babel/core" "7.28.5" + "@babel/core" "8.0.1" "@jridgewell/sourcemap-codec" "^1.4.14" chokidar "^5.0.0" convert-source-map "^1.5.1" @@ -316,169 +184,135 @@ tslib "^2.3.0" yargs "^18.0.0" -"@angular/compiler@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-21.1.1.tgz#6921cfd531eb243a05502b24c3e1475ef7cf51e3" - integrity sha512-Urd3bh0zv0MQ//S7RRTanIkOMAZH/A7vSMXUDJ3aflplNs7JNbVqBwDNj8NoX1V+os+fd8JRJOReCc1EpH4ZKQ== +"@angular/compiler@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-22.1.1.tgz#9743248279c5769d1ba0d866fb674ffb0744f9b7" + integrity sha512-UfQZALwewk+WyE5fqrXT3CK0sxWXre4XojAvUdFQSZsVHTZEM1QD4FncuePa44I6BQMhfqQUvYNlqFnev4WOQg== dependencies: tslib "^2.3.0" -"@angular/core@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-21.1.1.tgz#decd6806aba2185a6fd56ee5b8efa6c69b5766c9" - integrity sha512-KFRCEhsi02pY1EqJ5rnze4mzSaacqh14D8goDhtmARiUH0tefaHR+uKyu4bKSrWga2T/ExG0DJX52LhHRs2qSw== +"@angular/core@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-22.1.1.tgz#3bdae393c3c977596b60fb5b19c9e35b7ea3cdce" + integrity sha512-QFZNFzyFw9l1B1D7NCEU3YiLLBnMSejyp9mzJrzZ9vzc70BsewikcLFwuj+qqleqFmi5VW3f9GFNgwUq8dWGAg== dependencies: tslib "^2.3.0" -"@angular/forms@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-21.1.1.tgz#15603edbf2b58c3d58ea3ea85e65db2646b83f35" - integrity sha512-NBbJOynLOeMsPo03+3dfdxE0P7SB7SXRqoFJ7WP2sOgOIxODna/huo2blmRlnZAVPTn1iQEB9Q+UeyP5c4/1+w== +"@angular/forms@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-22.1.1.tgz#daacbc654285e7b4b1ad3bfca4a23878e5976144" + integrity sha512-6c5IJaCw6hAsBYl+LeQARwV4eGxfHwHTlTWfCB5dOYjMSgCCjaivkNTCUepYXFo5Fkdvw1qDiWIpAfgusAxmww== dependencies: "@standard-schema/spec" "^1.0.0" tslib "^2.3.0" + zod "^4.0.10" -"@angular/material-moment-adapter@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/material-moment-adapter/-/material-moment-adapter-21.1.1.tgz#b8cd00246662b0b309fdd93d942b9384143bdfbb" - integrity sha512-c/cP2+19QUX5/3wtKGCwtUc/Von2rasRh4V76xTNTNdKiYstgn+EoeFuJyU7VG2agI/oPIXiG4PY3e+2giuAYw== +"@angular/material-moment-adapter@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/material-moment-adapter/-/material-moment-adapter-22.1.1.tgz#91f445960442408e4d03b3a9cc3b0bf8b8acb0ae" + integrity sha512-nTxGXXs97zwv5o6dd+Go3IsDoY3I8G4Z6K8EKa8CpWH9Z+yL/P1zsy6q5Wo3g5naIQr/XETexKBMgihZBxe3mg== dependencies: tslib "^2.3.0" -"@angular/material@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-21.1.1.tgz#09afb3e2ed584ad6e0fa8243116267afaa538ae7" - integrity sha512-flRS8Mqf41n5lhrG/D0iPl2zyhhEZBaASFjCMSk5idUWMfwdYlKtCaJ3iRFClIixBUwGPrp8ivjBGKsRGfM/Zw== +"@angular/material@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-22.1.1.tgz#611eb06eb36a20b52fa4100a6b2b193c751de92e" + integrity sha512-wXNNstkLrUJwmP/cZl+C64chL5qH0WbnHIeYbiXrPwgriAD10prbVBoSq2CWbBrAhQ691pDdFKVSLG5tC224jg== dependencies: tslib "^2.3.0" -"@angular/platform-browser-dynamic@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.1.1.tgz#1538af05f9de50600332448b62aa9c8e9eed1e58" - integrity sha512-lawT3bdjXZVmVNXVoPS0UiB8Qxw5jEYXHx2m38JvHGv7/pl0Sgr+wa6f+/4pvTwu3VZb/8ohkVdFicPfrU21Jw== +"@angular/platform-browser@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-22.1.1.tgz#7fca2545d5f23a2dccc1ed8ef02c895921adb496" + integrity sha512-u1HMINw++YTUzMbJB9zVhqch1iEiEl5vA88HjZYzoDagBcnIev30GRWI+QEy4Dy9GRg64hrCOl9Fke78dLQgYQ== dependencies: tslib "^2.3.0" -"@angular/platform-browser@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-21.1.1.tgz#5f8c6b19a3194113328a5891372c81e604f27b85" - integrity sha512-d6liZjPz29GUZ6dhxytFL/W2nMsYwPpc/E/vZpr5yV+u+gI2VjbnLbl8SG+jjj0/Hyq7s4aGhEKsRrCJJMXgNw== +"@angular/router@^22.1.1": + version "22.1.1" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-22.1.1.tgz#40a112823c402519cbb47c6d0d038a1d90aee21e" + integrity sha512-sD+dN+UOAhdrqnOp3OWuR+O50msXFt+16OGL6RrM9af40iATkUbEAgU62N4KITKl4ACDisg8yhyb9J3dwCEyzQ== dependencies: tslib "^2.3.0" -"@angular/router@^21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-21.1.1.tgz#0df028038e5ded6091e60cd7cfabce5ed1a8ee6c" - integrity sha512-3ypbtH3KfzuVgebdEET9+bRwn1VzP//KI0tIqleCGi4rblP3WQ/HwIGa5Qhdcxmw/kbmABKLRXX2kRUvidKs/Q== +"@babel/code-frame@^7.0.0": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.7.tgz#f2fbbfea87c44a21590ec515b778b2c26d8866e7" + integrity sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw== dependencies: - tslib "^2.3.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1", "@babel/code-frame@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" - integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== - dependencies: - "@babel/helper-validator-identifier" "^7.28.5" + "@babel/helper-validator-identifier" "^7.29.7" js-tokens "^4.0.0" picocolors "^1.1.1" -"@babel/compat-data@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" - integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== - -"@babel/core@7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.5.tgz#4c81b35e51e1b734f510c99b07dfbc7bbbb48f7e" - integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw== +"@babel/code-frame@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-8.0.0.tgz#f374ea9392011ffecf223805dd0d9315606e5bbf" + integrity sha512-dYYg153EyN2Ekbqw2zAsbd6/JR+9N2SEoC7YV2GyyqMM7x9bLDTjBD6XBhSMLH0wtIVyJj03jWNriQhaN+eoCw== dependencies: - "@babel/code-frame" "^7.27.1" - "@babel/generator" "^7.28.5" - "@babel/helper-compilation-targets" "^7.27.2" - "@babel/helper-module-transforms" "^7.28.3" - "@babel/helpers" "^7.28.4" - "@babel/parser" "^7.28.5" - "@babel/template" "^7.27.2" - "@babel/traverse" "^7.28.5" - "@babel/types" "^7.28.5" - "@jridgewell/remapping" "^2.3.5" + "@babel/helper-validator-identifier" "^8.0.0" + js-tokens "^10.0.0" + +"@babel/compat-data@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-8.0.0.tgz#e780eb6052d8ceeaeadd3a6cd82dda470a945622" + integrity sha512-DOjnob/cXOUgDOozCDeq/aK2p5y8dUIVdf6tNhEV1HQRd6I8aQ4f4fbtHRVEvb6lP3BGomrKHiS8ICAASSVQSw== + +"@babel/core@8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-8.0.1.tgz#dcb133d3ddcfb2b5a6558da03bf240319da0b8c8" + integrity sha512-5FgxM4dLQpMJHSiVATk8foW263dVHQHBVpXYiimNECVWG01f4nFyEbQixeT6Mwvg7TayREJ2gpKl3o2RoMdnqw== + dependencies: + "@babel/code-frame" "^8.0.0" + "@babel/generator" "^8.0.0" + "@babel/helper-compilation-targets" "^8.0.0" + "@babel/helpers" "^8.0.0" + "@babel/parser" "^8.0.0" + "@babel/template" "^8.0.0" + "@babel/traverse" "^8.0.0" + "@babel/types" "^8.0.0" + "@types/gensync" "^1.0.5" convert-source-map "^2.0.0" - debug "^4.1.0" + empathic "^2.0.1" gensync "^1.0.0-beta.2" + import-meta-resolve "^4.2.0" json5 "^2.2.3" - semver "^6.3.1" + obug "^2.1.1" + semver "^7.7.3" -"@babel/core@^7.23.9": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" - integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== +"@babel/generator@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-8.0.0.tgz#24b7b53a74fa8e74cc2377e054fecef4dcdada96" + integrity sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g== dependencies: - "@babel/code-frame" "^7.28.6" - "@babel/generator" "^7.28.6" - "@babel/helper-compilation-targets" "^7.28.6" - "@babel/helper-module-transforms" "^7.28.6" - "@babel/helpers" "^7.28.6" - "@babel/parser" "^7.28.6" - "@babel/template" "^7.28.6" - "@babel/traverse" "^7.28.6" - "@babel/types" "^7.28.6" - "@jridgewell/remapping" "^2.3.5" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.28.5", "@babel/generator@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" - integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== - dependencies: - "@babel/parser" "^7.28.6" - "@babel/types" "^7.28.6" + "@babel/parser" "^8.0.0" + "@babel/types" "^8.0.0" "@jridgewell/gen-mapping" "^0.3.12" "@jridgewell/trace-mapping" "^0.3.28" + "@types/jsesc" "^2.5.0" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@7.27.3": - version "7.27.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" - integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== +"@babel/helper-annotate-as-pure@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-8.0.0.tgz#e094d0ea95f319cdc399fe25ec82e4b3dddb8461" + integrity sha512-NSpMkMsvvZqzThJ0p1B02cbtA2ObEyfBvq950bmNkyxsxvcxwhvvCB036rKhlEnuBBo30bOrk13u3FzlKSoRrw== dependencies: - "@babel/types" "^7.27.3" + "@babel/types" "^8.0.0" -"@babel/helper-compilation-targets@^7.27.2", "@babel/helper-compilation-targets@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" - integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== +"@babel/helper-compilation-targets@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-8.0.0.tgz#63f230f427c9ea82323d829c935f6190d93b3736" + integrity sha512-JwculLABZvyPvyLBpwU/E/IbH2uM3mnxNtIJpxnIfb24y1PrdVxK5Dqjle4DpgqpGRnwgC7G8IkzPdSXZrO1Ew== dependencies: - "@babel/compat-data" "^7.28.6" - "@babel/helper-validator-option" "^7.27.1" + "@babel/compat-data" "^8.0.0" + "@babel/helper-validator-option" "^8.0.0" browserslist "^4.24.0" - lru-cache "^5.1.1" - semver "^6.3.1" + lru-cache "^11.0.0" + semver "^7.7.3" -"@babel/helper-globals@^7.28.0": - version "7.28.0" - resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" - integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== - -"@babel/helper-module-imports@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" - integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== - dependencies: - "@babel/traverse" "^7.28.6" - "@babel/types" "^7.28.6" - -"@babel/helper-module-transforms@^7.28.3", "@babel/helper-module-transforms@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" - integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== - dependencies: - "@babel/helper-module-imports" "^7.28.6" - "@babel/helper-validator-identifier" "^7.28.5" - "@babel/traverse" "^7.28.6" +"@babel/helper-globals@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-8.0.0.tgz#c93789d6c1c2f1b65a97a07515c471a049559bf1" + integrity sha512-lLozHOM6sWWlxNo8CYqHy4MBZeTvHXNgVPBfPOGsjPKUzHC2Az9QwB6gxdQmpwHl6GlQtbGgS+lj5887guDiLw== "@babel/helper-split-export-declaration@7.24.7": version "7.24.7" @@ -487,309 +321,340 @@ dependencies: "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== +"@babel/helper-string-parser@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f" + integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw== -"@babel/helper-validator-identifier@^7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" - integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== +"@babel/helper-string-parser@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz#4d47d9ad35d0f5bd7d202b348bf558328a347977" + integrity sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg== -"@babel/helper-validator-option@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" - integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== +"@babel/helper-validator-identifier@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" + integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== -"@babel/helpers@^7.28.4", "@babel/helpers@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" - integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== +"@babel/helper-validator-identifier@^8.0.0", "@babel/helper-validator-identifier@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz#60e427a9be7a101af52f14588def2dad8a9f9881" + integrity sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg== + +"@babel/helper-validator-option@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-8.0.0.tgz#53307a6882254fa8d940017a701a8f7ec603a1a9" + integrity sha512-U4Dybxh4WESWHt5XhBeExi4DrY0/DNK1aHpQbsrQXCUbFHuMweT0TpLEWKvaraV2Y6fS+ZXunsZ8zIuZIgvF2Q== + +"@babel/helpers@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-8.0.0.tgz#2c612d4b7fdbd5f1d2fa7321015e36b02d1a2d79" + integrity sha512-wfbi91pM3py96oIiJEz7qIpyXDytgr9zQC1HEWwlGNVRAEmItuU/0a41ZUKu1sJGyhhOIpc4t5vk4PYzt8wpsg== dependencies: - "@babel/template" "^7.28.6" - "@babel/types" "^7.28.6" + "@babel/template" "^8.0.0" + "@babel/types" "^8.0.0" -"@babel/parser@^7.23.9", "@babel/parser@^7.28.5", "@babel/parser@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" - integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== +"@babel/parser@^8.0.0", "@babel/parser@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-8.0.4.tgz#244e21ca23ab54c6f5373af2122cb3a618f9dd39" + integrity sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g== dependencies: - "@babel/types" "^7.28.6" + "@babel/types" "^8.0.4" "@babel/runtime@^7.26.10": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.6.tgz#d267a43cb1836dc4d182cce93ae75ba954ef6d2b" - integrity sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA== + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.7.tgz#12022450c45a4da6d8d8287b18a4ff2ddb23f768" + integrity sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw== -"@babel/template@^7.27.2", "@babel/template@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" - integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== +"@babel/template@^8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-8.0.0.tgz#18c12626b0d6d23a0443771655864ed7566a3452" + integrity sha512-eAD0QW/AlbamBbw0FeGiwasbCVPq5ncW0HNVyLP3B9czqLyh4gvw+5JTSNt6le9+ziAU7mqDZsKTHf3jTb4chQ== dependencies: - "@babel/code-frame" "^7.28.6" - "@babel/parser" "^7.28.6" - "@babel/types" "^7.28.6" + "@babel/code-frame" "^8.0.0" + "@babel/parser" "^8.0.0" + "@babel/types" "^8.0.0" -"@babel/traverse@^7.28.5", "@babel/traverse@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" - integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== +"@babel/traverse@^8.0.0": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-8.0.4.tgz#71fc3f8861a4548e7f2938fdecac73e25d1db1ed" + integrity sha512-bZnmqzGG8UZneG1lLxBoWIH0G6Gr1D846Yu4/3XnY6FhCndMR49u26nTY08u/dAxWmLWF9vGQOuC+84FfIUoeg== dependencies: - "@babel/code-frame" "^7.28.6" - "@babel/generator" "^7.28.6" - "@babel/helper-globals" "^7.28.0" - "@babel/parser" "^7.28.6" - "@babel/template" "^7.28.6" - "@babel/types" "^7.28.6" - debug "^4.3.1" + "@babel/code-frame" "^8.0.0" + "@babel/generator" "^8.0.0" + "@babel/helper-globals" "^8.0.0" + "@babel/parser" "^8.0.4" + "@babel/template" "^8.0.0" + "@babel/types" "^8.0.4" + obug "^2.1.1" -"@babel/types@^7.24.7", "@babel/types@^7.27.3", "@babel/types@^7.28.5", "@babel/types@^7.28.6": - version "7.28.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" - integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== +"@babel/types@^7.24.7": + version "7.29.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.8.tgz#1229eef31d85156d70fa3f4cd859376d0eaf6863" + integrity sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg== dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.28.5" + "@babel/helper-string-parser" "^7.29.7" + "@babel/helper-validator-identifier" "^7.29.7" -"@emnapi/core@^1.7.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" - integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== +"@babel/types@^8.0.0", "@babel/types@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-8.0.4.tgz#8c208701320c9f0323b5b6a233d093e52c1e3b41" + integrity sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g== dependencies: - "@emnapi/wasi-threads" "1.1.0" + "@babel/helper-string-parser" "^8.0.0" + "@babel/helper-validator-identifier" "^8.0.4" + +"@emnapi/core@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.11.1.tgz#b9e1064f3a6b1631e241e638eb48d736bfd372a6" + integrity sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ== + dependencies: + "@emnapi/wasi-threads" "1.2.2" tslib "^2.4.0" -"@emnapi/runtime@^1.7.1": - version "1.8.1" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" - integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== +"@emnapi/core@1.11.2": + version "1.11.2" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.11.2.tgz#fab0a0f3c492d11f5a9ac9065d0d73955ee1c1c9" + integrity sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA== + dependencies: + "@emnapi/wasi-threads" "1.2.2" + tslib "^2.4.0" + +"@emnapi/runtime@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.11.1.tgz#58f1f3d5d81a9b12f793ab688c96371901027c24" + integrity sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw== dependencies: tslib "^2.4.0" -"@emnapi/wasi-threads@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" - integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== +"@emnapi/runtime@1.11.2": + version "1.11.2" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.11.2.tgz#eb22f04d76febfdf4f87fdaff54c8a53f6bf0dbd" + integrity sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA== dependencies: tslib "^2.4.0" -"@esbuild/aix-ppc64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz#521cbd968dcf362094034947f76fa1b18d2d403c" - integrity sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw== +"@emnapi/wasi-threads@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz#4c93becf5bfa3b13d1bbdcc06aee38321ad8139a" + integrity sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA== + dependencies: + tslib "^2.4.0" -"@esbuild/android-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz#61ea550962d8aa12a9b33194394e007657a6df57" - integrity sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA== +"@esbuild/aix-ppc64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz#7a01a8d2ec2fbb2dac78adad09b0fa781e4082be" + integrity sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ== -"@esbuild/android-arm@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.2.tgz#554887821e009dd6d853f972fde6c5143f1de142" - integrity sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA== +"@esbuild/android-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz#b540a27d14e4afd058496a4dbec4d3f414db110a" + integrity sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg== -"@esbuild/android-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.2.tgz#a7ce9d0721825fc578f9292a76d9e53334480ba2" - integrity sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A== +"@esbuild/android-arm@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.1.tgz#704bd297de6d762de54eabbeafbf55f6756abe2f" + integrity sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ== -"@esbuild/darwin-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz#2cb7659bd5d109803c593cfc414450d5430c8256" - integrity sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg== +"@esbuild/android-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.1.tgz#d1cb166d34b0fbf0fe8ab460a5594f24a378701e" + integrity sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng== -"@esbuild/darwin-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz#e741fa6b1abb0cd0364126ba34ca17fd5e7bf509" - integrity sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA== +"@esbuild/darwin-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz#1034b26457fc886368fe61bbd09f653f6afa8e54" + integrity sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q== -"@esbuild/freebsd-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz#2b64e7116865ca172d4ce034114c21f3c93e397c" - integrity sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g== +"@esbuild/darwin-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz#65556a432a1e4d72032d8218c1932fcca1a49772" + integrity sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ== -"@esbuild/freebsd-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz#e5252551e66f499e4934efb611812f3820e990bb" - integrity sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA== +"@esbuild/freebsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz#2e61e0592f9030d7e3dae18ee25ebc535918aef6" + integrity sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw== -"@esbuild/linux-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz#dc4acf235531cd6984f5d6c3b13dbfb7ddb303cb" - integrity sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw== +"@esbuild/freebsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz#c95ec289959ef8079c4dca817a1e2c4be66b9bd3" + integrity sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ== -"@esbuild/linux-arm@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz#56a900e39240d7d5d1d273bc053daa295c92e322" - integrity sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw== +"@esbuild/linux-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz#40b22175dda06182f3ee8141186c5ff304c4a717" + integrity sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g== -"@esbuild/linux-ia32@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz#d4a36d473360f6870efcd19d52bbfff59a2ed1cc" - integrity sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w== +"@esbuild/linux-arm@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz#c09a0f67917592ac0de892a9be4d3814debd2a6c" + integrity sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ== -"@esbuild/linux-loong64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz#fcf0ab8c3eaaf45891d0195d4961cb18b579716a" - integrity sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg== +"@esbuild/linux-ia32@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz#a580f9c676797833891e519fc7a1337c8afd8db3" + integrity sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w== -"@esbuild/linux-mips64el@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz#598b67d34048bb7ee1901cb12e2a0a434c381c10" - integrity sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw== +"@esbuild/linux-loong64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz#46452cf321dc7f9e91c2fa780a56bb56e79cd68b" + integrity sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg== -"@esbuild/linux-ppc64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz#3846c5df6b2016dab9bc95dde26c40f11e43b4c0" - integrity sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ== +"@esbuild/linux-mips64el@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz#4211b3184dd6608f53dcb22e39f5d34ee08852c8" + integrity sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ== -"@esbuild/linux-riscv64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz#173d4475b37c8d2c3e1707e068c174bb3f53d07d" - integrity sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA== +"@esbuild/linux-ppc64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz#697857c2a61cb9b0b6bb6652e40c1dc5e1ca8e5d" + integrity sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ== -"@esbuild/linux-s390x@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz#f7a4790105edcab8a5a31df26fbfac1aa3dacfab" - integrity sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w== +"@esbuild/linux-riscv64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz#d192943eb146a40ac4c6497d0cf7be35b986bf08" + integrity sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ== -"@esbuild/linux-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz#2ecc1284b1904aeb41e54c9ddc7fcd349b18f650" - integrity sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA== +"@esbuild/linux-s390x@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz#acea0356da0e0ebc08f97cf7b9c2e401e1e648dc" + integrity sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag== -"@esbuild/netbsd-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz#e2863c2cd1501845995cb11adf26f7fe4be527b0" - integrity sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw== +"@esbuild/linux-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz#6f0c3ce0cb64c534b70c4c45ecb2c16d34e35dfd" + integrity sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA== -"@esbuild/netbsd-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz#93f7609e2885d1c0b5a1417885fba8d1fcc41272" - integrity sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA== +"@esbuild/netbsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz#8bcd77077a0dce3378b574fedb26d2a253b73d36" + integrity sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw== -"@esbuild/openbsd-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz#a1985604a203cdc325fd47542e106fafd698f02e" - integrity sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA== +"@esbuild/netbsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz#e7fb2a01e99c830c94e6623cd9fefb4c8fb58347" + integrity sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg== -"@esbuild/openbsd-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz#8209e46c42f1ffbe6e4ef77a32e1f47d404ad42a" - integrity sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg== +"@esbuild/openbsd-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz#c52909372db8b86e2c55e05a8940033b5660a3b2" + integrity sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q== -"@esbuild/openharmony-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz#8fade4441893d9cc44cbd7dcf3776f508ab6fb2f" - integrity sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag== +"@esbuild/openbsd-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz#c427b9be5a64c262ff9a7eb70b5fbbaadf446c6c" + integrity sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw== -"@esbuild/sunos-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz#980d4b9703a16f0f07016632424fc6d9a789dfc2" - integrity sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg== +"@esbuild/openharmony-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz#dc9b147baca2e6c4b3c85571741ef4860a489097" + integrity sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg== -"@esbuild/win32-arm64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz#1c09a3633c949ead3d808ba37276883e71f6111a" - integrity sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg== +"@esbuild/sunos-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz#ce866d12df13c15e4c99f073a3d466f6e0649b3a" + integrity sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ== -"@esbuild/win32-ia32@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz#1b1e3a63ad4bef82200fef4e369e0fff7009eee5" - integrity sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ== +"@esbuild/win32-arm64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz#7468e3692d01d629d5941e5d83817bb80f9e39b4" + integrity sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA== -"@esbuild/win32-x64@0.27.2": - version "0.27.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz#9e585ab6086bef994c6e8a5b3a0481219ada862b" - integrity sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ== +"@esbuild/win32-ia32@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz#a5bc0063fb2bcab6d0ed63f2a1537958bc269ec6" + integrity sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg== + +"@esbuild/win32-x64@0.28.1": + version "0.28.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz#10064ee44f4347b90c9a02b446bbf80a91632b12" + integrity sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A== "@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": - version "4.9.1" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" - integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== + version "4.10.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz#8911bd72b2c3640a543609e0400b8c4d2e7e7cb6" + integrity sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg== dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2": +"@eslint-community/regexpp@^4.12.2": version "4.12.2" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== -"@eslint/config-array@^0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" - integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== +"@eslint/config-array@^0.23.5": + version "0.23.5" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.23.5.tgz#56e86d243049195d8acc0c06a1b3dfdc3fa3de95" + integrity sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA== dependencies: - "@eslint/object-schema" "^2.1.7" + "@eslint/object-schema" "^3.0.5" debug "^4.3.1" - minimatch "^3.1.2" + minimatch "^10.2.4" -"@eslint/config-helpers@^0.4.2": - version "0.4.2" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" - integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== +"@eslint/config-helpers@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.7.0.tgz#09ee4aa07b73f059ec2d4c74bf4b2ff02b322377" + integrity sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw== dependencies: - "@eslint/core" "^0.17.0" + "@eslint/core" "^1.2.1" -"@eslint/core@^0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" - integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== +"@eslint/core@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-1.2.1.tgz#c1da7cd1b82fa8787f98b5629fb811848a1b63ce" + integrity sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ== dependencies: "@types/json-schema" "^7.0.15" -"@eslint/eslintrc@^3.3.1": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.3.tgz#26393a0806501b5e2b6a43aa588a4d8df67880ac" - integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ== +"@eslint/js@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583" + integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA== + +"@eslint/object-schema@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091" + integrity sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw== + +"@eslint/plugin-kit@^0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz#4b0962f3f2c7ce8bc98b3ecfe34525c09d2cb729" + integrity sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A== dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^10.0.1" - globals "^14.0.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.1" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - -"@eslint/js@9.39.2": - version "9.39.2" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.2.tgz#2d4b8ec4c3ea13c1b3748e0c97ecd766bdd80599" - integrity sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA== - -"@eslint/object-schema@^2.1.7": - version "2.1.7" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" - integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== - -"@eslint/plugin-kit@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" - integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== - dependencies: - "@eslint/core" "^0.17.0" + "@eslint/core" "^1.2.1" levn "^0.4.1" -"@hono/node-server@^1.19.7": - version "1.19.9" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac" - integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw== +"@harperfast/extended-iterable@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@harperfast/extended-iterable/-/extended-iterable-1.0.3.tgz#471489c5058331017e821bf6c33de70fc2c073ee" + integrity sha512-sSAYhQca3rDWtQUHSAPeO7axFIUJOI6hn1gjRC5APVE1a90tuyT8f5WIgRsFhhWA7htNkju2veB9eWL6YHi/Lw== -"@humanfs/core@^0.19.1": - version "0.19.1" - resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" - integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== +"@hono/node-server@^1.19.9": + version "1.19.17" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.17.tgz#99bd8625cdbae82652a135c71363cd6322fae483" + integrity sha512-dSneS5qhiauZWGDCeK4o695Xd9nUNjviSZCMQrj10eetr8Uln1ucn6bbphOM6UynAMMtNIzZNSpL9vnASJwrPQ== + +"@humanfs/core@^0.19.2": + version "0.19.2" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.2.tgz#a8272ca03b2acf492670222b2320b6c421bfde60" + integrity sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA== + dependencies: + "@humanfs/types" "^0.15.0" "@humanfs/node@^0.16.6": - version "0.16.7" - resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" - integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + version "0.16.8" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.8.tgz#8f800cccc13f4f8cd3116e2d9c0a94939da3e3ed" + integrity sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ== dependencies: - "@humanfs/core" "^0.19.1" + "@humanfs/core" "^0.19.2" + "@humanfs/types" "^0.15.0" "@humanwhocodes/retry" "^0.4.0" +"@humanfs/types@^0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@humanfs/types/-/types-0.15.0.tgz#f2a09f62012390b2bff3fc6fb248ddec8c09a090" + integrity sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q== + "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" @@ -805,174 +670,144 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== -"@inquirer/ansi@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-1.0.2.tgz#674a4c4d81ad460695cb2a1fc69d78cd187f337e" - integrity sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ== +"@inquirer/ansi@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-2.0.7.tgz#86de22810cac3ed406ec10f8d66016815b8226b4" + integrity sha512-3eTuUO1vH2cZm2ZKHeQxnOqlTi9EfZDGgIe3BL3I4u+rJHocr9Fz86M4fjYABPvFnQG/gGK551HqDiIcETwU6Q== -"@inquirer/checkbox@^4.3.2": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-4.3.2.tgz#e1483e6519d6ffef97281a54d2a5baa0d81b3f3b" - integrity sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA== +"@inquirer/checkbox@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-5.2.1.tgz#7f148b3153a776cee202015b10f9a985068d188d" + integrity sha512-b6xmA/VlTe0ZgDQHDui+Nav470u7u49nRd8/iuhOcQPO9Ch7lGuogydhi2VOmNlZ+zXcM8IcPuNSwQcdJaF/kw== dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/ansi" "^2.0.7" + "@inquirer/core" "^11.2.1" + "@inquirer/figures" "^2.0.7" + "@inquirer/type" "^4.0.7" -"@inquirer/confirm@5.1.21", "@inquirer/confirm@^5.1.21": - version "5.1.21" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.21.tgz#610c4acd7797d94890a6e2dde2c98eb1e891dd12" - integrity sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ== +"@inquirer/confirm@6.1.1", "@inquirer/confirm@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-6.1.1.tgz#9c6a7d79c6132b2af57fdb75747f056204e55356" + integrity sha512-eb8DBZcz/2qHWQda4rk2JiQk5h9QV/cVHi1yjt0f69WFZMRFn0sJTye3EAP8icut8UDMjQPsaH5KbcOogefrFQ== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/core@^10.3.2": - version "10.3.2" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.3.2.tgz#535979ff3ff4fe1e7cc4f83e2320504c743b7e20" - integrity sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A== +"@inquirer/core@^11.2.1": + version "11.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-11.2.1.tgz#54ccd8f7d47852140b6066cbd77d63b2c2b168fd" + integrity sha512-Qd6GJT1yVyrZZCfN8W2qKF5ApmqryXRhRKCuip8h01x2w/esJQ2XIYc6f9abMIHgKQdBfFTSOdbHRLAhuM09UA== dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" + "@inquirer/ansi" "^2.0.7" + "@inquirer/figures" "^2.0.7" + "@inquirer/type" "^4.0.7" cli-width "^4.1.0" - mute-stream "^2.0.0" + fast-wrap-ansi "^0.2.0" + mute-stream "^3.0.0" signal-exit "^4.1.0" - wrap-ansi "^6.2.0" - yoctocolors-cjs "^2.1.3" -"@inquirer/editor@^4.2.23": - version "4.2.23" - resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-4.2.23.tgz#fe046a3bfdae931262de98c1052437d794322e0b" - integrity sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ== +"@inquirer/editor@^5.2.2": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-5.2.2.tgz#7c73e2fc0e7bd4c40cfd38a180ae5bbd24d32b90" + integrity sha512-ZRVd/oD+sYsUd5zVm0NflqEzlqfYCyHNsqkHl2oWXEUHs12tCbcSFi+wVFEvD8+LGRaMUsVrE7qeo6lSG/S1Vg== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/external-editor" "^1.0.3" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.2.1" + "@inquirer/external-editor" "^3.0.3" + "@inquirer/type" "^4.0.7" -"@inquirer/expand@^4.0.23": - version "4.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-4.0.23.tgz#a38b5f32226d75717c370bdfed792313b92bdc05" - integrity sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew== +"@inquirer/expand@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-5.1.1.tgz#e2afeac247d97dd64ee18aa81e902bdd1fe0ea70" + integrity sha512-YmQpenjbFSHAK3sOd44puHh3V1KXXr+JiNpUztoSQ4drLh2rTVzTap/YtlAVu/5xavifIlBfNEzJ/neZJ1a/1g== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/external-editor@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-1.0.3.tgz#c23988291ee676290fdab3fd306e64010a6d13b8" - integrity sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA== +"@inquirer/external-editor@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-3.0.3.tgz#d79e772542cf8d340642e9dabd3a1ea7f5a30104" + integrity sha512-6thf5I8q7lZwzGLAxPaaGEREEkZ3nyePPDQ1oyobblxmEE8mqTLguScP7pDjUTAibiyb4hfXl+qjUEJ+di/aNA== dependencies: chardet "^2.1.1" - iconv-lite "^0.7.0" + iconv-lite "^0.7.2" -"@inquirer/figures@^1.0.15": - version "1.0.15" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.15.tgz#dbb49ed80df11df74268023b496ac5d9acd22b3a" - integrity sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g== +"@inquirer/figures@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-2.0.7.tgz#f5cc5843732a81304d06a0db4b53cc7dbda15541" + integrity sha512-aJ8TBPOGB6f/2qziPfElISTCEd5XOYTFckA2SGjhNmiKzfK/u4ot3v0DUzGVdUnKjN10EqnnEPck36BkyfLnJw== -"@inquirer/input@^4.3.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-4.3.1.tgz#778683b4c4c4d95d05d4b05c4a854964b73565b4" - integrity sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g== +"@inquirer/input@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-5.1.2.tgz#9305cb170dfc3a5323e5eac885a945e7cddd5c4b" + integrity sha512-9K/DDBSQpOyZSkt6sOVP9Vo0TR7atX2kuILsUu0x3wVcVbe97lJwIJKMLdMw25tDYuXl/qp6erT0Xs1rfmcfZg== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/number@^3.0.23": - version "3.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-3.0.23.tgz#3fdec2540d642093fd7526818fd8d4bdc7335094" - integrity sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg== +"@inquirer/number@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-4.1.1.tgz#b133668d8e0e099b4133abb915221501e0ff75d7" + integrity sha512-XF4IXAbPnGPgw0wsbC/i2tPcyfdZgDpUlhsqU0SfT4IRIGWha6Xm9VRgN5yYxJq+jnyXlfXI/nQ3ulfk0iEICA== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/password@^4.0.23": - version "4.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-4.0.23.tgz#b9f5187c8c92fd7aa9eceb9d8f2ead0d7e7b000d" - integrity sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA== +"@inquirer/password@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-5.1.1.tgz#f21efb614da9c905095262f51781fd2a721fceac" + integrity sha512-3XBfF7DAsp5qeDsvN5Rd1HmbNokVvEQoUM0QLrRcybC9nX96w3Pbmu7qUsb3IT3J3jBvs2+mTXaKHOUsgHMLzg== dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" + "@inquirer/ansi" "^2.0.7" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/prompts@7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.10.1.tgz#e1436c0484cf04c22548c74e2cd239e989d5f847" - integrity sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg== +"@inquirer/prompts@8.5.2": + version "8.5.2" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-8.5.2.tgz#09c0132ada2bbba94c91d341115e1e41cb3f1525" + integrity sha512-IYR/3C/paEVVQYQvdDlFZVjRCJVYHHON0XXMH91KO9GSxs0TdKYWlUdvfQl2EfAHDxUaN3IBffkE/BDTh5nJ6g== dependencies: - "@inquirer/checkbox" "^4.3.2" - "@inquirer/confirm" "^5.1.21" - "@inquirer/editor" "^4.2.23" - "@inquirer/expand" "^4.0.23" - "@inquirer/input" "^4.3.1" - "@inquirer/number" "^3.0.23" - "@inquirer/password" "^4.0.23" - "@inquirer/rawlist" "^4.1.11" - "@inquirer/search" "^3.2.2" - "@inquirer/select" "^4.4.2" + "@inquirer/checkbox" "^5.2.1" + "@inquirer/confirm" "^6.1.1" + "@inquirer/editor" "^5.2.2" + "@inquirer/expand" "^5.1.1" + "@inquirer/input" "^5.1.2" + "@inquirer/number" "^4.1.1" + "@inquirer/password" "^5.1.1" + "@inquirer/rawlist" "^5.3.1" + "@inquirer/search" "^4.2.1" + "@inquirer/select" "^5.2.1" -"@inquirer/rawlist@^4.1.11": - version "4.1.11" - resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-4.1.11.tgz#313c8c3ffccb7d41e990c606465726b4a898a033" - integrity sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw== +"@inquirer/rawlist@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-5.3.1.tgz#66f6b8e6aa82d47399c433b8262128e7c1a4f9ce" + integrity sha512-QqdTqQddL3qPX/PPrjobpsO25NZ4dWXgTLenrR445L2ptLEYE6Z+PD5c5CNDJNx4ugRgELAIpSIJxZaO2jJ2Og== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/core" "^11.2.1" + "@inquirer/type" "^4.0.7" -"@inquirer/search@^3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-3.2.2.tgz#4cc6fd574dcd434e4399badc37c742c3fd534ac8" - integrity sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA== +"@inquirer/search@^4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-4.2.1.tgz#c8f4b78ab3f866fdf0503fac0cd08c4a6661c11e" + integrity sha512-xJj8QWKRSrfKoBIITLZK61dD3zwo0Rz11fgDImku30/Oe81zMdIdGgrLY2h6RkJ+KZ/GhNYIRMKnH/62qBTA5g== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/core" "^11.2.1" + "@inquirer/figures" "^2.0.7" + "@inquirer/type" "^4.0.7" -"@inquirer/select@^4.4.2": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-4.4.2.tgz#2ac8fca960913f18f1d1b35323ed8fcd27d89323" - integrity sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w== +"@inquirer/select@^5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-5.2.1.tgz#3a05e76e58d9e1bb095e912c3e7093aa04cd4604" + integrity sha512-FlDndEUww8m7BfukO2nJa25vhD+H5jxxCv4oGioKqzyWz3nPHhhw4LKdYRSlXuAx7DsdWia7iyaBPKKS95Evfw== dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/ansi" "^2.0.7" + "@inquirer/core" "^11.2.1" + "@inquirer/figures" "^2.0.7" + "@inquirer/type" "^4.0.7" -"@inquirer/type@^3.0.10", "@inquirer/type@^3.0.8": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.10.tgz#11ed564ec78432a200ea2601a212d24af8150d50" - integrity sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA== - -"@isaacs/balanced-match@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29" - integrity sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ== - -"@isaacs/brace-expansion@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz#4b3dabab7d8e75a429414a96bd67bf4c1d13e0f3" - integrity sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA== - dependencies: - "@isaacs/balanced-match" "^4.0.1" - -"@isaacs/fs-minipass@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" - integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== - dependencies: - minipass "^7.0.4" - -"@istanbuljs/schema@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== +"@inquirer/type@^4.0.6", "@inquirer/type@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-4.0.7.tgz#9c6f0d857fe6ad549a3a932343b64e76acb34b10" + integrity sha512-t28inv14nMQ1PhKpsJPY+kEs/c00qzeCOS2gTNRyTjG5d6qsVA2fItxW4hkvGZ5lvanGLdtCzVIx5dwdRpN1+g== "@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": version "0.3.13" @@ -982,14 +817,6 @@ "@jridgewell/sourcemap-codec" "^1.5.0" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/remapping@^2.3.5": - version "2.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" - integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== - dependencies: - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.24" - "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" @@ -1008,54 +835,54 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@listr2/prompt-adapter-inquirer@3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz#5e5def882a7fc493cb97224b3174e0c02cd84184" - integrity sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA== +"@listr2/prompt-adapter-inquirer@4.2.4": + version "4.2.4" + resolved "https://registry.yarnpkg.com/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-4.2.4.tgz#28fcb5727d88e364bb4d404fefc34134ff62a41e" + integrity sha512-/KRI2DMD7JGSYaREF0Ygl7AefJ/2ase4Gc5cBiKqT5l4tFjsSJfhFGcc5nSkgl0Sp9LkCQNzl/cqbVJYP2L3dw== dependencies: - "@inquirer/type" "^3.0.8" + "@inquirer/type" "^4.0.6" -"@lmdb/lmdb-darwin-arm64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.4.tgz#baf0a0135e1e688fd9478f6da1b926e9b45ed5b8" - integrity sha512-XaKL705gDWd6XVls3ATDj13ZdML/LqSIxwgnYpG8xTzH2ifArx8fMMDdvqGE/Emd+W6R90W2fveZcJ0AyS8Y0w== +"@lmdb/lmdb-darwin-arm64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.5.6.tgz#81ab45551e1d839dc709bdf24ca133cfb52ccfb4" + integrity sha512-mY5FG4TjPAkY4P0w+OhHaUka5mDh2TX2WKYIwuKzJ1zeW3VvRgxdam/lGJTquI+bthTx5CSHDW+BAQCnNAzkEA== -"@lmdb/lmdb-darwin-x64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.4.tgz#aca17a2d7083a4379eb605cdad77889646f0a8fb" - integrity sha512-GPHGEVcwJlkD01GmIr7B4kvbIcUDS2+kBadVEd7lU4can1RZaZQLDDBJRrrNfS2Kavvl0VLI/cMv7UASAXGrww== +"@lmdb/lmdb-darwin-x64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.5.6.tgz#ce7577fd38136c61f3b346b520cb3af299bc0f54" + integrity sha512-foa+pwitysO8k+xhs7psBFfTKnVgR69NlZRRTHaFVDqphh7AdGpLeyRzKw/ofatr/sN6TiHRRW6mmop0ZrrppQ== -"@lmdb/lmdb-linux-arm64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.4.tgz#924616da168cc71e134e5ad27feeecbd878b247c" - integrity sha512-mALqr7DE42HsiwVTKpQWxacjHoJk+e9p00RWIJqTACh/hpucxp/0lK/XMh5XzWnU/TDCZLukq1+vNqnNumTP/Q== +"@lmdb/lmdb-linux-arm64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.5.6.tgz#2ffb1710ef0547f8de40d50c5ada6d1895923797" + integrity sha512-HmiyFFdJa38s1heCMSooSPaBSFTHJ3C+ERPp28xAPlDX1YiALJVOgbry065nXd8Y7KISWjnw05zpG1RX8IfftA== -"@lmdb/lmdb-linux-arm@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.4.tgz#d094fe134482c9de5c1675d99a7412ef4cce3b0c" - integrity sha512-cmev5/dZr5ACKri9f6GU6lZCXTjMhV72xujlbOhFCgFXrt4W0TxGsmY8kA1BITvH60JBKE50cSxsiulybAbrrw== +"@lmdb/lmdb-linux-arm@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.5.6.tgz#a480c7fac3769a1b71337702cd6c938b300a8599" + integrity sha512-QR4YRyR5h5Z8eGXrNQjiyo2NNDfqi3tCc9dQG5Is1blCt+qWw1ZoBWhlWAr5d+jshkifMIJjVHzHGKbkKzF8Tw== -"@lmdb/lmdb-linux-x64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.4.tgz#5d4ff698bd2f0060a57eb4c034e7e815b1c8886f" - integrity sha512-QjLs8OcmCNcraAcLoZyFlo0atzBJniQLLwhtR+ymQqS5kLYpV5RqwriL87BW+ZiR9ZiGgZx3evrz5vnWPtJ1fQ== +"@lmdb/lmdb-linux-x64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.5.6.tgz#6b50738a5d779fe090ce1ab7bfb41a9c88ea92f3" + integrity sha512-ADzCuCF2cTNiX9kDScqcz1fjnAkxPpQNneV3KFTdV3wWtVlI2sTGzySoMTgDpinkMMFj1NTJlxA6XR8fwc4hlA== -"@lmdb/lmdb-win32-arm64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.4.tgz#ac17086fd0ef7113464d594b8478ff5fdf632a5e" - integrity sha512-tr/pwHDlZ33forLGAr0tI04cRmP4SgF93yHbb+2zvZiDEyln5yMHhbKDySxY66aUOkhvBvTuHq9q/3YmTj6ZHQ== +"@lmdb/lmdb-win32-arm64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.5.6.tgz#5a5872d6a275bfa8d4423d78906f7202ec352c97" + integrity sha512-J7A9aEQsQiv0TYtBGL7NDIPp2lOS8nnl+zm4sWZm1xlsTTaQ4PgD096Adzdrk27rw3UxCkDXdCUa4ax41oztBQ== -"@lmdb/lmdb-win32-x64@3.4.4": - version "3.4.4" - resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.4.tgz#2e47e87aa64d4539ee5c2c3be1b8af043d21707b" - integrity sha512-KRzfocJzB/mgoTCqnMawuLSKheHRVTqWfSmouIgYpFs6Hx4zvZSvsZKSCEb5gHmICy7qsx9l06jk3MFTtiFVAQ== +"@lmdb/lmdb-win32-x64@3.5.6": + version "3.5.6" + resolved "https://registry.yarnpkg.com/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.5.6.tgz#8e26cbb62abb1454130fe73bd475df3b24a97567" + integrity sha512-1g7G0knRX2iV/voDu54yxrGqw5Dk0w2oIYb7dgJq8IkOi+m7wbD8Q3QpPFjh0C01G58S88dqGn03len6UPCXsg== -"@modelcontextprotocol/sdk@1.25.2": - version "1.25.2" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz#2284560b4e044b4ce5f328ee180931110cb8c5cf" - integrity sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww== +"@modelcontextprotocol/sdk@1.29.0": + version "1.29.0" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz#79786d8b525e269de850ac82b1f1f757f3915f44" + integrity sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ== dependencies: - "@hono/node-server" "^1.19.7" + "@hono/node-server" "^1.19.9" ajv "^8.17.1" ajv-formats "^3.0.1" content-type "^1.0.5" @@ -1063,44 +890,45 @@ cross-spawn "^7.0.5" eventsource "^3.0.2" eventsource-parser "^3.0.0" - express "^5.0.1" - express-rate-limit "^7.5.0" - jose "^6.1.1" + express "^5.2.1" + express-rate-limit "^8.2.1" + hono "^4.11.4" + jose "^6.1.3" json-schema-typed "^8.0.2" pkce-challenge "^5.0.0" raw-body "^3.0.0" zod "^3.25 || ^4.0" - zod-to-json-schema "^3.25.0" + zod-to-json-schema "^3.25.1" -"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz#9edec61b22c3082018a79f6d1c30289ddf3d9d11" - integrity sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw== +"@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz#22619f76a6b10ba78c8b74025b0d9754cad69cc7" + integrity sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ== -"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz#33677a275204898ad8acbf62734fc4dc0b6a4855" - integrity sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw== +"@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz#c2fc0573afe08b0cf213e66eef76842b121d1577" + integrity sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w== -"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz#19edf7cdc2e7063ee328403c1d895a86dd28f4bb" - integrity sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg== +"@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz#4e3822f5522e18ed92611b894dc5db1bc882f39d" + integrity sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw== -"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz#94fb0543ba2e28766c3fc439cabbe0440ae70159" - integrity sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw== +"@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz#27ec4bc7eb6c311c982a50f1a6e1e1414638a6f8" + integrity sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw== -"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz#4a0609ab5fe44d07c9c60a11e4484d3c38bbd6e3" - integrity sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg== +"@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz#37317d833c7d01d086f6155fa59c478adb6839f6" + integrity sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ== -"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz#0aa5502d547b57abfc4ac492de68e2006e417242" - integrity sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ== +"@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz#a1c79dcc9ae5f8c02aea8c2f144e5af6a822e5e8" + integrity sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ== "@napi-rs/nice-android-arm-eabi@1.1.1": version "1.1.1" @@ -1210,470 +1038,477 @@ "@napi-rs/nice-win32-ia32-msvc" "1.1.1" "@napi-rs/nice-win32-x64-msvc" "1.1.1" -"@napi-rs/wasm-runtime@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz#c3705ab549d176b8dc5172723d6156c3dc426af2" - integrity sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A== +"@napi-rs/wasm-runtime@^1.1.6": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz#c70706532e5827c0932ca6bf43ee2c512f29c639" + integrity sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw== dependencies: - "@emnapi/core" "^1.7.1" - "@emnapi/runtime" "^1.7.1" - "@tybys/wasm-util" "^0.10.1" + "@tybys/wasm-util" "^0.10.3" -"@npmcli/agent@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/agent/-/agent-4.0.0.tgz#2bb2b1c0a170940511554a7986ae2a8be9fedcce" - integrity sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA== +"@oxc-parser/binding-android-arm-eabi@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.142.0.tgz#12951a56ed573c0246ceacbc94e29d7e90d3925a" + integrity sha512-ZiRGDutGsv1G6bL/ozy/koC0Sv39T1DqyoC4KD1DOy9ZoACm1O5UWhEK2c02Qdk+4lfLVkvFa/mQ0fm/4h1BtQ== + +"@oxc-parser/binding-android-arm64@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.142.0.tgz#c29c254ac550771a4de17f2a815d153ebf82487e" + integrity sha512-WZkvGRLNQTz8lR9zP5nLjUdlroRCopBu3g9zF1p/laE6DzT1UbQo8Rdz5MWhaJUPYg/6gp+jo7HUgsyKaN1FtQ== + +"@oxc-parser/binding-darwin-arm64@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.142.0.tgz#dd2c46a9d4a5599d127b050cb7229cf1a28dc019" + integrity sha512-l4khS8LQOOVYsGRVARo1gSaCT/aBSceUVXgtovWc2+drnxVuDr082WA3OCHVdVzIz5JIrP/y9CWsSKxBDNmYGg== + +"@oxc-parser/binding-darwin-x64@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.142.0.tgz#45d169072658ee22f4cb9b4f93c320259905d28f" + integrity sha512-QBsNF3nqlXmcH2B1YOPqQYmCJoy4HuIjUxGbBO/k5JAJUl68ghU2psRY2zPk+RyBaWqKP/qfL4oaFgEMCdwskA== + +"@oxc-parser/binding-freebsd-x64@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.142.0.tgz#add219d6a838028268f8158168e566ae264dcfb8" + integrity sha512-b7Q7m4Cqc6XqNhri3R+QhU+GVy646Pn+bkdhrDdWym/Fdi0ZUa+d73H9dm5H91JtbtAQ/z1d8XKMW3oOV8a4tQ== + +"@oxc-parser/binding-linux-arm-gnueabihf@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.142.0.tgz#ea64a9a807dd246d43fba59def1a0f9f729079ee" + integrity sha512-3riVS5IhdH3uCZj1Y9ftDQlR0dvLsIlw/edrRqk8JhgNd5K0XSs+UBtgh50N13CAlW9/TXj6sVGXaKNBocd0Yg== + +"@oxc-parser/binding-linux-arm-musleabihf@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.142.0.tgz#a304dc50b69c723f38ec9349e1a55d92725666a6" + integrity sha512-NmXUOpgpTSkhl795TiXmWppTwmSJ92RC1qvD6e4XOF+slgmo3e6Ah+kEu+6AN8s7NAOEwqGmir58MgSQSWmBSA== + +"@oxc-parser/binding-linux-arm64-gnu@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.142.0.tgz#597e255b0a4350e61d530e915775beb3b40d88b6" + integrity sha512-gc0EXsKtXgerujmU2Bql3u1L1HsSQ2774R83idq/FoNMPVV/RY/1ErFsvnit7KoiP/sLvzQixeUo4Ut0ic0wmw== + +"@oxc-parser/binding-linux-arm64-musl@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.142.0.tgz#255ea22fe9dca6d6e528e9b1082906aa167c84b2" + integrity sha512-F2XvmWSE0uWpie+jHKKIFgdVOe9ypGhkEZxKx5DuW215K6cbAC274yYaPkcM7EqY4Df3Weyhpcz3lsURyH2LVg== + +"@oxc-parser/binding-linux-ppc64-gnu@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.142.0.tgz#86e7bc2cebe2e1ea5d1b4127271968cc8da3bca0" + integrity sha512-wLMbT21U/QxknQsk+VvNF0b9D2/aGWhcaQQQ+VYlE8FwD5+GoWZIPPXNzyHmkYyhm0KB3itL+TBavjMatqNnYA== + +"@oxc-parser/binding-linux-riscv64-gnu@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.142.0.tgz#9494de6f64ae967f9e33390cc758cb09742390ed" + integrity sha512-+G8F/4ckwT7FCJV4H2bt09xEzJbjNCfuL4Sp1AYNaFtFMVtgIGMuJlteT82U+K0UIZ/DzAR/LDlMFnEuajG7Kw== + +"@oxc-parser/binding-linux-riscv64-musl@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.142.0.tgz#86094e70a5a68f1273ba6020be3598ea70d711c7" + integrity sha512-hTsHtTLxMAfCo+rpF5K3qZJKW2NpPN/CHd4mYB3y7XlSdspHkd2gehDIofP64AacA9nWQw2tY3O7wR6UY8IVOA== + +"@oxc-parser/binding-linux-s390x-gnu@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.142.0.tgz#560228fe1c257425143a9b483bdd15c717c35730" + integrity sha512-6y7qYY3TCUDYjqswImdTGl92y+KA/80twALegQPN27kfY+bG7Ib1+L3jbmrCZQx6wrVnai9IPsEZp07I0hx7JQ== + +"@oxc-parser/binding-linux-x64-gnu@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.142.0.tgz#8a3cd3272eb8f0d12c75ae18c9bf873b7fe637a1" + integrity sha512-i69kAWU+2LgoH5bR+zWiiu+UzAw7Oxkwv7COeJTeY19pn4e70nKQcr9Pm6cL2Z0Z54d+gl9qADlK/0yyuCPiBA== + +"@oxc-parser/binding-linux-x64-musl@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.142.0.tgz#0033a6136bc2d49f316ea73333c9bd52c1cb94bd" + integrity sha512-4SQs678MmjYVrmhAgCWD4o0vpaFszXw9xLX5p2Z9MMFcltxiLkA88wQjh80YHjPrXtpyZ2CWI5m+1yNKM0m2Pw== + +"@oxc-parser/binding-openharmony-arm64@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.142.0.tgz#abd8fcd6baa64b0530d26a12a9e834670173e029" + integrity sha512-YHpx9N7Ln3a++Tc8rv+H7mrK1zyJQOAwCFg8LZ3lTs1T5afGWeZrLPhPT9HLnIwSjCyJqPWVMIrMxbjcmBr2oQ== + +"@oxc-parser/binding-wasm32-wasi@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.142.0.tgz#0e9317b01f1ef22a9c06cdcb261e266491555de8" + integrity sha512-3pLDyY3+oogW73RM5uehNgAiR/Xfb7fvO2Q1Z1gIqZ2+50XDVQmBVlRkHXZTU4gKnQHpwETNsYQVsJ3joVB2iA== dependencies: - agent-base "^7.1.0" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.1" - lru-cache "^11.2.1" - socks-proxy-agent "^8.0.3" + "@emnapi/core" "1.11.2" + "@emnapi/runtime" "1.11.2" + "@napi-rs/wasm-runtime" "^1.1.6" -"@npmcli/fs@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-5.0.0.tgz#674619771907342b3d1ac197aaf1deeb657e3539" - integrity sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og== - dependencies: - semver "^7.3.5" +"@oxc-parser/binding-win32-arm64-msvc@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.142.0.tgz#2e5fc33327d632482510b4a4fda8e8f2140edfc7" + integrity sha512-Had/VeVY28Oyb0K+Q4FV8KCzoBycIh93oDK6pCbya9lkzdq+ikMHMgBubsdqqlybjJmQRawCQRrnBRHyQwYvcQ== -"@npmcli/git@^7.0.0": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-7.0.1.tgz#d1f6462af0e9901536e447beea922bc20dcc5762" - integrity sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA== - dependencies: - "@npmcli/promise-spawn" "^9.0.0" - ini "^6.0.0" - lru-cache "^11.2.1" - npm-pick-manifest "^11.0.1" - proc-log "^6.0.0" - promise-retry "^2.0.1" - semver "^7.3.5" - which "^6.0.0" +"@oxc-parser/binding-win32-ia32-msvc@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.142.0.tgz#d10783beee866182c9101788d3c20349df1df925" + integrity sha512-GGi3+YphVHavvgs6gum2UXoNCqzHAmPt/nXkn8ZQZstV2Q1qZD1Mn8fz/nWrDkefHQtrG/+1/XrbMxsBTo6Svw== -"@npmcli/installed-package-contents@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz#18e5070704cfe0278f9ae48038558b6efd438426" - integrity sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA== - dependencies: - npm-bundled "^5.0.0" - npm-normalize-package-bin "^5.0.0" +"@oxc-parser/binding-win32-x64-msvc@0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.142.0.tgz#bad12594427efa9b345596de61e1232d0c052cb8" + integrity sha512-Ny/Wv4Us1LGC/ljwNTp+Hx3r/pH15EFfeDF0p+n898gt+TtRd6C9SccHcuUhDiNTb8s5tt7jdeAMDRQZ4Vq6hg== -"@npmcli/node-gyp@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz#35475a58b5d791764a7252231197a14deefe8e47" - integrity sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ== +"@oxc-project/types@=0.139.0": + version "0.139.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.139.0.tgz#38d76b9dbf934c2a02be174fb32ceebf182fe742" + integrity sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw== -"@npmcli/package-json@^7.0.0": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-7.0.4.tgz#f4178e5d90b888f3bdf666915706f613c2d870d7" - integrity sha512-0wInJG3j/K40OJt/33ax47WfWMzZTm6OQxB9cDhTt5huCP2a9g2GnlsxmfN+PulItNPIpPrZ+kfwwUil7eHcZQ== - dependencies: - "@npmcli/git" "^7.0.0" - glob "^13.0.0" - hosted-git-info "^9.0.0" - json-parse-even-better-errors "^5.0.0" - proc-log "^6.0.0" - semver "^7.5.3" - validate-npm-package-license "^3.0.4" +"@oxc-project/types@=0.140.0": + version "0.140.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.140.0.tgz#2acc1bd45ff24951059d01ce7552d26e1574c5ac" + integrity sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ== -"@npmcli/promise-spawn@^9.0.0": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz#20e80cbdd2f24ad263a15de3ebbb1673cb82005b" - integrity sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q== - dependencies: - which "^6.0.0" +"@oxc-project/types@=0.143.0": + version "0.143.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.143.0.tgz#c3e4f3178b7b54e4dd194eac6d45258a60f0092b" + integrity sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA== -"@npmcli/redact@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@npmcli/redact/-/redact-4.0.0.tgz#c91121e02b7559a997614a2c1057cd7fc67608c4" - integrity sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q== +"@oxc-project/types@^0.142.0": + version "0.142.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.142.0.tgz#0b4bd7841ef3dd267a69184b97452cc0b313fb52" + integrity sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ== -"@npmcli/run-script@^10.0.0": - version "10.0.3" - resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-10.0.3.tgz#85c16cd893e44cad5edded441b002d8a1d3a8a8e" - integrity sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw== - dependencies: - "@npmcli/node-gyp" "^5.0.0" - "@npmcli/package-json" "^7.0.0" - "@npmcli/promise-spawn" "^9.0.0" - node-gyp "^12.1.0" - proc-log "^6.0.0" - which "^6.0.0" +"@parcel/watcher-android-arm64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz#99aaa3223d43807c9340af439cad7e9b6d26ada6" + integrity sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA== -"@oxc-project/types@=0.106.0": - version "0.106.0" - resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.106.0.tgz#52d06030fea43c03d0955cffadeb90b005a29ae2" - integrity sha512-QdsH3rZq480VnOHSHgPYOhjL8O8LBdcnSjM408BpPCCUc0JYYZPG9Gafl9i3OcGk/7137o+gweb4cCv3WAUykg== +"@parcel/watcher-darwin-arm64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz#024496e586b4744f09ce532bbe89fe38ef02a64e" + integrity sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw== -"@parcel/watcher-android-arm64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz#5f32e0dba356f4ac9a11068d2a5c134ca3ba6564" - integrity sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A== +"@parcel/watcher-darwin-x64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz#a4621df1359a93d39a332d9bab5ff09016a0608f" + integrity sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw== -"@parcel/watcher-darwin-arm64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz#88d3e720b59b1eceffce98dac46d7c40e8be5e8e" - integrity sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA== +"@parcel/watcher-freebsd-x64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz#7f565ed1a5b3a5e604e6a4799121518265d62a3d" + integrity sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ== -"@parcel/watcher-darwin-x64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz#bf05d76a78bc15974f15ec3671848698b0838063" - integrity sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg== +"@parcel/watcher-linux-arm-glibc@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz#ad7d3825e67b81999165da42593022045abc0889" + integrity sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg== -"@parcel/watcher-freebsd-x64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz#8bc26e9848e7303ac82922a5ae1b1ef1bdb48a53" - integrity sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng== +"@parcel/watcher-linux-arm-musl@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz#fe7d1cccb2c483215c090e938cf5cf404d2f9a8c" + integrity sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw== -"@parcel/watcher-linux-arm-glibc@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz#1328fee1deb0c2d7865079ef53a2ba4cc2f8b40a" - integrity sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ== +"@parcel/watcher-linux-arm64-glibc@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz#7e239dcb4646c4c79f006a7131a48238249530da" + integrity sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g== -"@parcel/watcher-linux-arm-musl@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz#bad0f45cb3e2157746db8b9d22db6a125711f152" - integrity sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg== +"@parcel/watcher-linux-arm64-musl@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz#c58b8d9c6d8d81594be00dd83aab741c1aaf7e0e" + integrity sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA== -"@parcel/watcher-linux-arm64-glibc@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz#b75913fbd501d9523c5f35d420957bf7d0204809" - integrity sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA== +"@parcel/watcher-linux-x64-glibc@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz#5184fa9a770478d86e56875f4ee163a0abdc8791" + integrity sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A== -"@parcel/watcher-linux-arm64-musl@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz#da5621a6a576070c8c0de60dea8b46dc9c3827d4" - integrity sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA== +"@parcel/watcher-linux-x64-musl@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz#2d1c55aa7246cbc7670e2612058a8a542c9cf246" + integrity sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw== -"@parcel/watcher-linux-x64-glibc@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz#ce437accdc4b30f93a090b4a221fd95cd9b89639" - integrity sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ== +"@parcel/watcher-win32-arm64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz#15e09432040fee9e2213aa9c10ed589012526def" + integrity sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ== -"@parcel/watcher-linux-x64-musl@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz#02400c54b4a67efcc7e2327b249711920ac969e2" - integrity sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg== - -"@parcel/watcher-win32-arm64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz#caae3d3c7583ca0a7171e6bd142c34d20ea1691e" - integrity sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q== - -"@parcel/watcher-win32-ia32@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz#9ac922550896dfe47bfc5ae3be4f1bcaf8155d6d" - integrity sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g== - -"@parcel/watcher-win32-x64@2.5.6": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz#73fdafba2e21c448f0e456bbe13178d8fe11739d" - integrity sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw== +"@parcel/watcher-win32-x64@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz#9bee199a2a4accd557b451ac2c1c793f305ae012" + integrity sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A== "@parcel/watcher@^2.4.1": - version "2.5.6" - resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.6.tgz#3f932828c894f06d0ad9cfefade1756ecc6ef1f1" - integrity sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ== + version "2.6.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.6.0.tgz#99661f6220070b76a766aba6b7e313a087a1be4f" + integrity sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w== dependencies: detect-libc "^2.0.3" is-glob "^4.0.3" node-addon-api "^7.0.0" - picomatch "^4.0.3" + picomatch "^4.0.4" optionalDependencies: - "@parcel/watcher-android-arm64" "2.5.6" - "@parcel/watcher-darwin-arm64" "2.5.6" - "@parcel/watcher-darwin-x64" "2.5.6" - "@parcel/watcher-freebsd-x64" "2.5.6" - "@parcel/watcher-linux-arm-glibc" "2.5.6" - "@parcel/watcher-linux-arm-musl" "2.5.6" - "@parcel/watcher-linux-arm64-glibc" "2.5.6" - "@parcel/watcher-linux-arm64-musl" "2.5.6" - "@parcel/watcher-linux-x64-glibc" "2.5.6" - "@parcel/watcher-linux-x64-musl" "2.5.6" - "@parcel/watcher-win32-arm64" "2.5.6" - "@parcel/watcher-win32-ia32" "2.5.6" - "@parcel/watcher-win32-x64" "2.5.6" + "@parcel/watcher-android-arm64" "2.6.0" + "@parcel/watcher-darwin-arm64" "2.6.0" + "@parcel/watcher-darwin-x64" "2.6.0" + "@parcel/watcher-freebsd-x64" "2.6.0" + "@parcel/watcher-linux-arm-glibc" "2.6.0" + "@parcel/watcher-linux-arm-musl" "2.6.0" + "@parcel/watcher-linux-arm64-glibc" "2.6.0" + "@parcel/watcher-linux-arm64-musl" "2.6.0" + "@parcel/watcher-linux-x64-glibc" "2.6.0" + "@parcel/watcher-linux-x64-musl" "2.6.0" + "@parcel/watcher-win32-arm64" "2.6.0" + "@parcel/watcher-win32-x64" "2.6.0" -"@rolldown/binding-android-arm64@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.58.tgz#7d747001348130a85bc95590ef823d1af2673fcb" - integrity sha512-mWj5eE4Qc8TbPdGGaaLvBb9XfDPvE1EmZkJQgiGKwchkWH4oAJcRAKMTw7ZHnb1L+t7Ah41sBkAecaIsuUgsug== +"@rolldown/binding-android-arm64@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz#f58cb9a0a8128ed0582282720528547fc5c035f3" + integrity sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ== -"@rolldown/binding-darwin-arm64@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.58.tgz#f6e8ecebafc4adcb0ce944a7d56945130d49c463" - integrity sha512-wFxUymI/5R8bH8qZFYDfAxAN9CyISEIYke+95oZPiv6EWo88aa5rskjVcCpKA532R+klFmdqjbbaD56GNmTF4Q== +"@rolldown/binding-android-arm64@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.0.tgz#18b16c76ef035d88a12905e84a5875fd39a869b4" + integrity sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw== -"@rolldown/binding-darwin-x64@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.58.tgz#0f40092bab5f03fcb84e0b79859204625c3791ee" - integrity sha512-ybp3MkPj23VDV9PhtRwdU5qrGhlViWRV5BjKwO6epaSlUD5lW0WyY+roN3ZAzbma/9RrMTgZ/a/gtQq8YXOcqw== +"@rolldown/binding-android-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz#001b8b0b01844701efda1bb6bed84b681c4a488b" + integrity sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw== -"@rolldown/binding-freebsd-x64@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.58.tgz#a7c40cab44a0542ef2c01cf5becf8b1c3ce61357" - integrity sha512-Evxj3yh7FWvyklUYZa0qTVT9N2zX9TPDqGF056hl8hlCZ9/ndQ2xMv6uw9PD1VlLpukbsqL+/C6M0qwipL0QMg== +"@rolldown/binding-darwin-arm64@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz#441144c05a4a831aa75269abc3a4a324374ea707" + integrity sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw== -"@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.58.tgz#ea32cdd6bf4658e2dbb4aeaf113485a76df49aa7" - integrity sha512-tYeXprDOrEgVHUbPXH6MPso4cM/c6RTkmJNICMQlYdki4hGMh92aj3yU6CKs+4X5gfG0yj5kVUw/L4M685SYag== +"@rolldown/binding-darwin-arm64@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.0.tgz#2d66d02ade26d1ef79f98f65d7598fd9dae0a77b" + integrity sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg== -"@rolldown/binding-linux-arm64-gnu@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.58.tgz#a565985e9b26c0ba8f824267750ab41598a5a456" - integrity sha512-N78vmZzP6zG967Ohr+MasCjmKtis0geZ1SOVmxrA0/bklTQSzH5kHEjW5Qn+i1taFno6GEre1E40v0wuWsNOQw== +"@rolldown/binding-darwin-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz#5e87c602ed634a6fef092e2162e24fbfb881c4ec" + integrity sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA== -"@rolldown/binding-linux-arm64-musl@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.58.tgz#e2f55ce5fe2a8d74db58277950eac2baff7022be" - integrity sha512-l+p4QVtG72C7wI2SIkNQw/KQtSjuYwS3rV6AKcWrRBF62ClsFUcif5vLaZIEbPrCXu5OFRXigXFJnxYsVVZqdQ== +"@rolldown/binding-darwin-x64@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz#c82e30652cef52c4af925d5c66c8955a40319816" + integrity sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g== -"@rolldown/binding-linux-x64-gnu@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.58.tgz#f48d2fc6fde05fbf708c885851a560387ede9fea" - integrity sha512-urzJX0HrXxIh0FfxwWRjfPCMeInU9qsImLQxHBgLp5ivji1EEUnOfux8KxPPnRQthJyneBrN2LeqUix9DYrNaQ== +"@rolldown/binding-darwin-x64@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.0.tgz#2f8a8beecd275e4291730c3f5b21b45399c81c4d" + integrity sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw== -"@rolldown/binding-linux-x64-musl@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.58.tgz#8cd95a4b5c0ead36c8f6fbecf3cc6d24a575e2c1" - integrity sha512-7ijfVK3GISnXIwq/1FZo+KyAUJjL3kWPJ7rViAL6MWeEBhEgRzJ0yEd9I8N9aut8Y8ab+EKFJyRNMWZuUBwQ0A== +"@rolldown/binding-darwin-x64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz#f32e0b286714bd03a421d693415d05d97d265b77" + integrity sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA== -"@rolldown/binding-openharmony-arm64@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.58.tgz#a3938a606633fb3341cba7c47ef3397577fc1502" - integrity sha512-/m7sKZCS+cUULbzyJTIlv8JbjNohxbpAOA6cM+lgWgqVzPee3U6jpwydrib328JFN/gF9A99IZEnuGYqEDJdww== +"@rolldown/binding-freebsd-x64@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz#c32e9ce7fa1c0fb2b80913a2a3a05c3e907d06b0" + integrity sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA== -"@rolldown/binding-wasm32-wasi@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.58.tgz#0f203bef3898d438a372996e6d02e73c057d05c5" - integrity sha512-6SZk7zMgv+y3wFFQ9qE5P9NnRHcRsptL1ypmudD26PDY+PvFCvfHRkJNfclWnvacVGxjowr7JOL3a9fd1wWhUw== +"@rolldown/binding-freebsd-x64@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.0.tgz#2b66b88e282ea2ebd2ab721ea88d209d600508c0" + integrity sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ== + +"@rolldown/binding-freebsd-x64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz#5f38ad5761b6b7b21b57a99566bb52634c60ab19" + integrity sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg== + +"@rolldown/binding-linux-arm-gnueabihf@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz#ce90b5e22316adeb502ea010582f498cd0604f27" + integrity sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw== + +"@rolldown/binding-linux-arm-gnueabihf@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.0.tgz#e3c3a54ab4b7855dd7b1388bd564344e78f2a9d8" + integrity sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ== + +"@rolldown/binding-linux-arm-gnueabihf@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz#ab4dcd07f1bd88e8d659ae0c3bb9d2f290adb897" + integrity sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw== + +"@rolldown/binding-linux-arm64-gnu@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz#91947110c4ddaa4eefb004e52688070977085201" + integrity sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q== + +"@rolldown/binding-linux-arm64-gnu@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.0.tgz#1af753d6af0db3e408193d945f592f328947fd39" + integrity sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w== + +"@rolldown/binding-linux-arm64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz#d279b7016039a725fb66d82784b9841f42df83da" + integrity sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw== + +"@rolldown/binding-linux-arm64-musl@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz#eb32b2d4108c1c702b91e8cde8a043eae5caa94d" + integrity sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA== + +"@rolldown/binding-linux-arm64-musl@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.0.tgz#1caa273824312871204d2b58747425ea49739ef1" + integrity sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ== + +"@rolldown/binding-linux-arm64-musl@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz#d08bbc93d2742214548c5adf7df7788944e5a89a" + integrity sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q== + +"@rolldown/binding-linux-ppc64-gnu@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz#ccb943c11e5a72655cbb02fc1163541ceb640782" + integrity sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg== + +"@rolldown/binding-linux-ppc64-gnu@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.0.tgz#95a1a48e3051f1f8d9cab3703de62ea418c9924e" + integrity sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw== + +"@rolldown/binding-linux-ppc64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz#6418e63745b3193f26ab3bb88744b3a4a1356d7c" + integrity sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w== + +"@rolldown/binding-linux-s390x-gnu@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz#a33731ee567e90b75fac6e5e55307e8a2b3038f0" + integrity sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA== + +"@rolldown/binding-linux-s390x-gnu@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.0.tgz#2d3f7543b193f8462a4c12e9aefd2ad72fbbe518" + integrity sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ== + +"@rolldown/binding-linux-s390x-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz#77ec30d0704cf4eb1cb4a63f501c9852c6728cf4" + integrity sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg== + +"@rolldown/binding-linux-x64-gnu@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz#a74c01aaacedfc11c39b6feba33a5fa0c654949f" + integrity sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ== + +"@rolldown/binding-linux-x64-gnu@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.0.tgz#0d428b854214bcaf0c8b81fc668c59932b20283b" + integrity sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ== + +"@rolldown/binding-linux-x64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz#3b9b6e0dd3e86c597f42858748ca25f1dfd58ed8" + integrity sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w== + +"@rolldown/binding-linux-x64-musl@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz#28cd178494fa1e65dba412229b5ce55c4dd5cbd1" + integrity sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg== + +"@rolldown/binding-linux-x64-musl@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.0.tgz#3ef09dc3980913b3db489e5b568db3f51b7c02f8" + integrity sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw== + +"@rolldown/binding-linux-x64-musl@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz#f78033c592c8bd2af48284a45f8e4baaa0befbf5" + integrity sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A== + +"@rolldown/binding-openharmony-arm64@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz#f7c75fa913fc20884d26a7d488d4f5c597cd71c0" + integrity sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw== + +"@rolldown/binding-openharmony-arm64@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.0.tgz#bc2afd9513b85fd3cc176e3d0cb32727f4611598" + integrity sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA== + +"@rolldown/binding-openharmony-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz#36e951f5a6fca922a5205e283d0a82b9f98199ca" + integrity sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug== + +"@rolldown/binding-wasm32-wasi@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz#c379581947787081df363ea106140fcd5fec252d" + integrity sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA== dependencies: - "@napi-rs/wasm-runtime" "^1.1.1" + "@emnapi/core" "1.11.1" + "@emnapi/runtime" "1.11.1" + "@napi-rs/wasm-runtime" "^1.1.6" -"@rolldown/binding-win32-arm64-msvc@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.58.tgz#584d15565dc97864b9e3411a62c284ee9ca47e3e" - integrity sha512-sFqfYPnBZ6xBhMkadB7UD0yjEDRvs7ipR3nCggblN+N4ODCXY6qhg/bKL39+W+dgQybL7ErD4EGERVbW9DAWvg== +"@rolldown/binding-wasm32-wasi@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.0.tgz#50c6eb1a34c699deb824a7fd2dbbe664e773a70f" + integrity sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g== + dependencies: + "@emnapi/core" "1.11.2" + "@emnapi/runtime" "1.11.2" + "@napi-rs/wasm-runtime" "^1.1.6" -"@rolldown/binding-win32-x64-msvc@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.58.tgz#0ea3b07fdf23cac94dc512c1c79ebd91391aa616" - integrity sha512-AnFWJdAqB8+IDPcGrATYs67Kik/6tnndNJV2jGRmwlbeNiQQ8GhRJU8ETRlINfII0pqi9k4WWLnb00p1QCxw/Q== +"@rolldown/binding-win32-arm64-msvc@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz#f23c88694f7a729a12f395024aee38df80a16ba3" + integrity sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw== -"@rolldown/pluginutils@1.0.0-beta.58": - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.58.tgz#33da8a49fe2141782114d50459a56ae57f869190" - integrity sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w== +"@rolldown/binding-win32-arm64-msvc@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.0.tgz#548e33a9362f50ca326e49bdfd35d4e1aaa68d9a" + integrity sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA== -"@rollup/rollup-android-arm-eabi@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz#f762035679a6b168138c94c960fda0b0cdb00d98" - integrity sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA== +"@rolldown/binding-win32-arm64-msvc@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz#c1e494ac47e13bd857fca0b3ad59c33580241f7e" + integrity sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw== -"@rollup/rollup-android-arm64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz#1061ce0bfa6a6da361bda52a2949612769cd22ef" - integrity sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg== +"@rolldown/binding-win32-x64-msvc@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz#3377c8de0e56a8857f11217561147090e874cb46" + integrity sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA== -"@rollup/rollup-darwin-arm64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz#20d65f967566000d22ef6c9defb0f96d2f95ed79" - integrity sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg== +"@rolldown/binding-win32-x64-msvc@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.0.tgz#7a655b9b4cac46a46eb18a0fae6bbc9ca22db4e4" + integrity sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg== -"@rollup/rollup-darwin-x64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz#2a805303beb4cd44bfef993c39582cb0f1794f90" - integrity sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA== +"@rolldown/binding-win32-x64-msvc@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz#b0effffcd6872f8a021373eb437916b1b52283a4" + integrity sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg== -"@rollup/rollup-freebsd-arm64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz#7cf26a60d7245e9207a253ac07f11ddfcc47d622" - integrity sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g== - -"@rollup/rollup-freebsd-x64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz#2b1acc1e624b47f676f526df30bb4357ea21f9b6" - integrity sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA== - -"@rollup/rollup-linux-arm-gnueabihf@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz#1ba1ef444365a51687c7af2824b370791a1e3aaf" - integrity sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q== - -"@rollup/rollup-linux-arm-musleabihf@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz#e49863b683644bbbb9abc5b051c9b9d59774c3a0" - integrity sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA== - -"@rollup/rollup-linux-arm64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz#fda3bfd43d2390d2d99bc7d9617c2db2941da52b" - integrity sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw== - -"@rollup/rollup-linux-arm64-musl@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz#aea6199031404f80a0ccf33d5d3a63de53819da0" - integrity sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw== - -"@rollup/rollup-linux-loong64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz#f467333a5691f69a18295a7051e1cebb6815fdfe" - integrity sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q== - -"@rollup/rollup-linux-loong64-musl@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz#e46dffc29692caa743140636eb0d1d9a24ed0fc3" - integrity sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ== - -"@rollup/rollup-linux-ppc64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz#be5b4494047ccbaadf1542fe9ac45b7788e73968" - integrity sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ== - -"@rollup/rollup-linux-ppc64-musl@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz#b14ce2b0fe9c37fd0646ec3095087c1d64c791f4" - integrity sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA== - -"@rollup/rollup-linux-riscv64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz#b78357f88ee7a34f677b118714594e37a2362a8c" - integrity sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ== - -"@rollup/rollup-linux-riscv64-musl@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz#f44107ec0c30d691552c89eb3e4f287c33c56c3c" - integrity sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ== - -"@rollup/rollup-linux-s390x-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz#ddb1cf80fb21b376a45a4e93ffdbeb15205d38f3" - integrity sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg== - -"@rollup/rollup-linux-x64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz#0da46a644c87e1d8b13da5e2901037193caea8d3" - integrity sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A== - -"@rollup/rollup-linux-x64-musl@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz#e561c93b6a23114a308396806551c25e28d3e303" - integrity sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw== - -"@rollup/rollup-openbsd-x64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz#52490600775364a0476f26be7ddc416dfa11439b" - integrity sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw== - -"@rollup/rollup-openharmony-arm64@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz#c25988aae57bd21fa7d0fcb014ef85ec8987ad2c" - integrity sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA== - -"@rollup/rollup-win32-arm64-msvc@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz#572a8cd78442441121f1a6b5ad686ab723c31ae4" - integrity sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ== - -"@rollup/rollup-win32-ia32-msvc@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz#431fa95c0be8377907fe4e7070aaa4016c7b7e3b" - integrity sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA== - -"@rollup/rollup-win32-x64-gnu@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz#19db67feb9c5fe09b1358efd1d97c5f6b299d347" - integrity sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA== - -"@rollup/rollup-win32-x64-msvc@4.57.0": - version "4.57.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz#6f38851da1123ac0380121108abd31ff21205c3d" - integrity sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ== +"@rolldown/pluginutils@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz#e3fcee093fbb5ce765e1ad088ff4de2889f6f9be" + integrity sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw== "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@schematics/angular@21.1.1": - version "21.1.1" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-21.1.1.tgz#04c3671f1ddc7df02b0735e1e89140794bdde39c" - integrity sha512-WijqITteakpFOplx7IGHIdBOdTU04Ul4qweilY1CRK3KdzQRuAf31KiKUFrJiGW076cyokmAQmBoZcngh9rCNw== +"@schematics/angular@22.1.3": + version "22.1.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-22.1.3.tgz#a118272c3e2686dc434cae57da034812e92beed6" + integrity sha512-5f5f0tKp3d25hjNGkvw2dtGgTN4wxPNhv1AXnhFkh+mLinQK9Qwzr2iEXDDrAuJEkvz1ACHq631IURWph0lqew== dependencies: - "@angular-devkit/core" "21.1.1" - "@angular-devkit/schematics" "21.1.1" + "@angular-devkit/core" "22.1.3" + "@angular-devkit/schematics" "22.1.3" jsonc-parser "3.3.1" + typescript "6.0.3" -"@sigstore/bundle@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@sigstore/bundle/-/bundle-4.0.0.tgz#854eda43eb6a59352037e49000177c8904572f83" - integrity sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A== - dependencies: - "@sigstore/protobuf-specs" "^0.5.0" - -"@sigstore/core@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@sigstore/core/-/core-3.1.0.tgz#b418de73f56333ad9e369b915173d8c98e9b96d5" - integrity sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A== - -"@sigstore/protobuf-specs@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@sigstore/protobuf-specs/-/protobuf-specs-0.5.0.tgz#e5f029edcb3a4329853a09b603011e61043eb005" - integrity sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA== - -"@sigstore/sign@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@sigstore/sign/-/sign-4.1.0.tgz#63df15a137337b29f463a1d1c51e1f7d4c1db2f1" - integrity sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg== - dependencies: - "@sigstore/bundle" "^4.0.0" - "@sigstore/core" "^3.1.0" - "@sigstore/protobuf-specs" "^0.5.0" - make-fetch-happen "^15.0.3" - proc-log "^6.1.0" - promise-retry "^2.0.1" - -"@sigstore/tuf@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@sigstore/tuf/-/tuf-4.0.1.tgz#9b080390936d79ea3b6a893b64baf3123e92d6d3" - integrity sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw== - dependencies: - "@sigstore/protobuf-specs" "^0.5.0" - tuf-js "^4.1.0" - -"@sigstore/verify@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@sigstore/verify/-/verify-3.1.0.tgz#4046d4186421db779501fe87fa5acaa5d4d21b08" - integrity sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag== - dependencies: - "@sigstore/bundle" "^4.0.0" - "@sigstore/core" "^3.1.0" - "@sigstore/protobuf-specs" "^0.5.0" - -"@standard-schema/spec@^1.0.0": +"@standard-schema/spec@^1.0.0", "@standard-schema/spec@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== -"@tufjs/canonical-json@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz#a52f61a3d7374833fca945b2549bc30a2dd40d0a" - integrity sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA== - -"@tufjs/models@4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@tufjs/models/-/models-4.1.0.tgz#494b39cf5e2f6855d80031246dd236d8086069b3" - integrity sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww== - dependencies: - "@tufjs/canonical-json" "2.0.0" - minimatch "^10.1.1" - -"@tybys/wasm-util@^0.10.1": - version "0.10.1" - resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" - integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== +"@tybys/wasm-util@^0.10.3": + version "0.10.3" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.3.tgz#015cba9e9dd47ce14d03d2a8c5d547bfb169665d" + integrity sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg== dependencies: tslib "^2.4.0" @@ -1695,10 +1530,20 @@ resolved "https://registry.yarnpkg.com/@types/esrecurse/-/esrecurse-4.3.1.tgz#6f636af962fbe6191b830bd676ba5986926bccec" integrity sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw== -"@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@^1.0.8": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" - integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== +"@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@^1.0.8": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.9.tgz#cf3f0e876d7bee15a93ab925b82bf570a3904a24" + integrity sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg== + +"@types/gensync@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/gensync/-/gensync-1.0.5.tgz#1819eba537d036dcf4ec7e8c8f15fbfe938e99a0" + integrity sha512-MbsRCT7mTikHwKZ0X+LVUTLRrZZRLipTuXEO9qOYO+zmjMVk81axyClMROf6uoPD9MRVu46bx8zoR0Ad9q3NAg== + +"@types/jsesc@^2.5.0": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@types/jsesc/-/jsesc-2.5.1.tgz#c34defc608ec94b68dc6a12a581b440942c6d503" + integrity sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw== "@types/json-schema@^7.0.15": version "7.0.15" @@ -1720,169 +1565,166 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== -"@typescript-eslint/eslint-plugin@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz#d8899e5c2eccf5c4a20d01c036a193753748454d" - integrity sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ== +"@typescript-eslint/eslint-plugin@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.66.0.tgz#76e86aa5a2459fbf5bbd7a839c0dc0cce1d56224" + integrity sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A== dependencies: "@eslint-community/regexpp" "^4.12.2" - "@typescript-eslint/scope-manager" "8.54.0" - "@typescript-eslint/type-utils" "8.54.0" - "@typescript-eslint/utils" "8.54.0" - "@typescript-eslint/visitor-keys" "8.54.0" + "@typescript-eslint/scope-manager" "8.66.0" + "@typescript-eslint/type-utils" "8.66.0" + "@typescript-eslint/utils" "8.66.0" + "@typescript-eslint/visitor-keys" "8.66.0" ignore "^7.0.5" natural-compare "^1.4.0" - ts-api-utils "^2.4.0" + ts-api-utils "^2.5.0" -"@typescript-eslint/parser@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.54.0.tgz#3d01a6f54ed247deb9982621f70e7abf1810bd97" - integrity sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA== +"@typescript-eslint/parser@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.66.0.tgz#88e3865ecf73b0118134e7cb831da87a961a57a1" + integrity sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g== dependencies: - "@typescript-eslint/scope-manager" "8.54.0" - "@typescript-eslint/types" "8.54.0" - "@typescript-eslint/typescript-estree" "8.54.0" - "@typescript-eslint/visitor-keys" "8.54.0" + "@typescript-eslint/scope-manager" "8.66.0" + "@typescript-eslint/types" "8.66.0" + "@typescript-eslint/typescript-estree" "8.66.0" + "@typescript-eslint/visitor-keys" "8.66.0" debug "^4.4.3" -"@typescript-eslint/project-service@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.54.0.tgz#f582aceb3d752544c8e1b11fea8d95d00cf9adc6" - integrity sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g== +"@typescript-eslint/project-service@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.66.0.tgz#828f788895df52d9eb2b543445a3a5a13e35ab4e" + integrity sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g== dependencies: - "@typescript-eslint/tsconfig-utils" "^8.54.0" - "@typescript-eslint/types" "^8.54.0" + "@typescript-eslint/tsconfig-utils" "^8.66.0" + "@typescript-eslint/types" "^8.66.0" debug "^4.4.3" -"@typescript-eslint/scope-manager@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz#307dc8cbd80157e2772c2d36216857415a71ab33" - integrity sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg== +"@typescript-eslint/scope-manager@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.66.0.tgz#4fffcc6ebd0df9fe7983c0256967567ea6f5ac63" + integrity sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g== dependencies: - "@typescript-eslint/types" "8.54.0" - "@typescript-eslint/visitor-keys" "8.54.0" + "@typescript-eslint/types" "8.66.0" + "@typescript-eslint/visitor-keys" "8.66.0" -"@typescript-eslint/tsconfig-utils@8.54.0", "@typescript-eslint/tsconfig-utils@^8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz#71dd7ba1674bd48b172fc4c85b2f734b0eae3dbc" - integrity sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw== +"@typescript-eslint/tsconfig-utils@8.66.0", "@typescript-eslint/tsconfig-utils@^8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.66.0.tgz#3a89066c507aa30541dc176804685b4b444e1e52" + integrity sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g== -"@typescript-eslint/type-utils@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz#64965317dd4118346c2fa5ee94492892200e9fb9" - integrity sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA== +"@typescript-eslint/type-utils@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.66.0.tgz#b2315303eca72fad9afa7be4f58f053c8f2a0479" + integrity sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g== dependencies: - "@typescript-eslint/types" "8.54.0" - "@typescript-eslint/typescript-estree" "8.54.0" - "@typescript-eslint/utils" "8.54.0" + "@typescript-eslint/types" "8.66.0" + "@typescript-eslint/typescript-estree" "8.66.0" + "@typescript-eslint/utils" "8.66.0" debug "^4.4.3" - ts-api-utils "^2.4.0" + ts-api-utils "^2.5.0" -"@typescript-eslint/types@8.54.0", "@typescript-eslint/types@^8.0.0", "@typescript-eslint/types@^8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.54.0.tgz#c12d41f67a2e15a8a96fbc5f2d07b17331130889" - integrity sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA== +"@typescript-eslint/types@8.66.0", "@typescript-eslint/types@^8.0.0", "@typescript-eslint/types@^8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.66.0.tgz#3cacab94d3b564c1d48c56eb37b89f89a6d48479" + integrity sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ== -"@typescript-eslint/typescript-estree@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz#3c7716905b2b811fadbd2114804047d1bfc86527" - integrity sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA== +"@typescript-eslint/typescript-estree@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.66.0.tgz#1a38c3a97dc6c669b66d585d7f90ebc4fbb32a50" + integrity sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg== dependencies: - "@typescript-eslint/project-service" "8.54.0" - "@typescript-eslint/tsconfig-utils" "8.54.0" - "@typescript-eslint/types" "8.54.0" - "@typescript-eslint/visitor-keys" "8.54.0" + "@typescript-eslint/project-service" "8.66.0" + "@typescript-eslint/tsconfig-utils" "8.66.0" + "@typescript-eslint/types" "8.66.0" + "@typescript-eslint/visitor-keys" "8.66.0" debug "^4.4.3" - minimatch "^9.0.5" + minimatch "^10.2.2" semver "^7.7.3" tinyglobby "^0.2.15" - ts-api-utils "^2.4.0" + ts-api-utils "^2.5.0" -"@typescript-eslint/utils@8.54.0", "@typescript-eslint/utils@^8.0.0", "@typescript-eslint/utils@^8.53.1": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.54.0.tgz#c79a4bcbeebb4f571278c0183ed1cb601d84c6c8" - integrity sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA== +"@typescript-eslint/utils@8.66.0", "@typescript-eslint/utils@^8.0.0", "@typescript-eslint/utils@^8.65.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.66.0.tgz#e277d67427043cdca2580ee91aa62921e4689969" + integrity sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA== dependencies: "@eslint-community/eslint-utils" "^4.9.1" - "@typescript-eslint/scope-manager" "8.54.0" - "@typescript-eslint/types" "8.54.0" - "@typescript-eslint/typescript-estree" "8.54.0" + "@typescript-eslint/scope-manager" "8.66.0" + "@typescript-eslint/types" "8.66.0" + "@typescript-eslint/typescript-estree" "8.66.0" -"@typescript-eslint/visitor-keys@8.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz#0e4b50124b210b8600b245dd66cbad52deb15590" - integrity sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA== +"@typescript-eslint/visitor-keys@8.66.0": + version "8.66.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.66.0.tgz#4c494e94745fb2724a4f37a310091e56b644d18a" + integrity sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg== dependencies: - "@typescript-eslint/types" "8.54.0" - eslint-visitor-keys "^4.2.1" + "@typescript-eslint/types" "8.66.0" + eslint-visitor-keys "^5.0.0" -"@vitejs/plugin-basic-ssl@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.1.0.tgz#c70d2a922bc437f154089d7ef0505db4b383eb7b" - integrity sha512-dOxxrhgyDIEUADhb/8OlV9JIqYLgos03YorAueTIeOUskLJSEsfwCByjbu98ctXitUN3znXKp0bYD/WHSudCeA== +"@vitejs/plugin-basic-ssl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.3.0.tgz#f505b1c197d8cb4fd6e213a78847574ecc51e2f9" + integrity sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ== -"@vitest/expect@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.18.tgz#361510d99fbf20eb814222e4afcb8539d79dc94d" - integrity sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ== +"@vitest/expect@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.1.10.tgz#799c06fc44bb0cf7e2784137b627c5cc173285d4" + integrity sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA== dependencies: - "@standard-schema/spec" "^1.0.0" + "@standard-schema/spec" "^1.1.0" "@types/chai" "^5.2.2" - "@vitest/spy" "4.0.18" - "@vitest/utils" "4.0.18" - chai "^6.2.1" - tinyrainbow "^3.0.3" + "@vitest/spy" "4.1.10" + "@vitest/utils" "4.1.10" + chai "^6.2.2" + tinyrainbow "^3.1.0" -"@vitest/mocker@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.18.tgz#b9735da114ef65ea95652c5bdf13159c6fab4865" - integrity sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ== +"@vitest/mocker@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.1.10.tgz#2413987ab4cd7fa1c2b614b404c407bf6ad1ead1" + integrity sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow== dependencies: - "@vitest/spy" "4.0.18" + "@vitest/spy" "4.1.10" estree-walker "^3.0.3" magic-string "^0.30.21" -"@vitest/pretty-format@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.18.tgz#fbccd4d910774072ec15463553edb8ca5ce53218" - integrity sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw== +"@vitest/pretty-format@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.1.10.tgz#75542e7273a08cc10fd4d8dad4e3eb1f16cd958c" + integrity sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q== dependencies: - tinyrainbow "^3.0.3" + tinyrainbow "^3.1.0" -"@vitest/runner@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.18.tgz#c2c0a3ed226ec85e9312f9cc8c43c5b3a893a8b1" - integrity sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw== +"@vitest/runner@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.1.10.tgz#febf0a21a9168421422d1955370e606feab60355" + integrity sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg== dependencies: - "@vitest/utils" "4.0.18" + "@vitest/utils" "4.1.10" pathe "^2.0.3" -"@vitest/snapshot@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.18.tgz#bcb40fd6d742679c2ac927ba295b66af1c6c34c5" - integrity sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA== +"@vitest/snapshot@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.1.10.tgz#7e3e9fec7d4d47232e493cfdcbd2170de4371c04" + integrity sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw== dependencies: - "@vitest/pretty-format" "4.0.18" + "@vitest/pretty-format" "4.1.10" + "@vitest/utils" "4.1.10" magic-string "^0.30.21" pathe "^2.0.3" -"@vitest/spy@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.18.tgz#ba0f20503fb6d08baf3309d690b3efabdfa88762" - integrity sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw== +"@vitest/spy@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.1.10.tgz#5c0bfa97b56bba9e37403c976db776ff6ab56f65" + integrity sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw== -"@vitest/utils@4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.18.tgz#9636b16d86a4152ec68a8d6859cff702896433d4" - integrity sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA== +"@vitest/utils@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.1.10.tgz#ffc71055f18bfccb1fd0586365ebc2824892e403" + integrity sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA== dependencies: - "@vitest/pretty-format" "4.0.18" - tinyrainbow "^3.0.3" - -"@yarnpkg/lockfile@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + "@vitest/pretty-format" "4.1.10" + convert-source-map "^2.0.0" + tinyrainbow "^3.1.0" JSONStream@^1.0.4: version "1.3.5" @@ -1892,11 +1734,6 @@ JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -abbrev@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-4.0.0.tgz#ec933f0e27b6cd60e89b5c6b2a304af42209bb05" - integrity sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA== - accepts@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" @@ -1910,20 +1747,20 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.15.0: - version "8.15.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" - integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +acorn@^8.16.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.18.0.tgz#4faf01b2d6d326bfeed97aea1f52220b5f4c1940" + integrity sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ== add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== -agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.4" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" - integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== +agent-base@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-9.0.0.tgz#ec9efb08314e1e75b0852d74aabf9a387f99834e" + integrity sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA== ajv-formats@3.0.1, ajv-formats@^3.0.1: version "3.0.1" @@ -1932,65 +1769,45 @@ ajv-formats@3.0.1, ajv-formats@^3.0.1: dependencies: ajv "^8.0.0" -ajv@8.17.1, ajv@^8.0.0, ajv@^8.17.1: - version "8.17.1" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" - integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== +ajv@8.20.0, ajv@^8.0.0, ajv@^8.17.1: + version "8.20.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.20.0.tgz#304b3636add88ba7d936760dd50ece006dea95f9" + integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== dependencies: fast-deep-equal "^3.1.3" fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== +ajv@^6.14.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.15.0.tgz#07e982c74626167aa7a2495c53817892d7139492" + integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -algoliasearch@5.46.2: - version "5.46.2" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.46.2.tgz#3afba0e53f3293e39cfde9b2ef27c583d44bf2a5" - integrity sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q== +angular-eslint@^22.1.0: + version "22.1.0" + resolved "https://registry.yarnpkg.com/angular-eslint/-/angular-eslint-22.1.0.tgz#b8e91d79f994eb44ad294d3aff04367732af3dde" + integrity sha512-LU5a6MOSeQTETnc4xaHi10p9S1cstNczr93sChi3rx8IzgH4+risIsjjQHVLSnQDrSGH2O8jAGCaChker7f7TQ== dependencies: - "@algolia/abtesting" "1.12.2" - "@algolia/client-abtesting" "5.46.2" - "@algolia/client-analytics" "5.46.2" - "@algolia/client-common" "5.46.2" - "@algolia/client-insights" "5.46.2" - "@algolia/client-personalization" "5.46.2" - "@algolia/client-query-suggestions" "5.46.2" - "@algolia/client-search" "5.46.2" - "@algolia/ingestion" "1.46.2" - "@algolia/monitoring" "1.46.2" - "@algolia/recommend" "5.46.2" - "@algolia/requester-browser-xhr" "5.46.2" - "@algolia/requester-fetch" "5.46.2" - "@algolia/requester-node-http" "5.46.2" - -angular-eslint@^21.1.0: - version "21.1.0" - resolved "https://registry.yarnpkg.com/angular-eslint/-/angular-eslint-21.1.0.tgz#14896e0669a12e0f4a00cb3dba5da5cfdad82839" - integrity sha512-qXpIEBNYpfgpBaFblnyFegVSQjWCVUdCXTHvMcvtNtmMgtPwIDKvG8wuJo5BbQ/MNt2d8npmnRUaS2ddzdCzww== - dependencies: - "@angular-devkit/core" ">= 21.0.0 < 22.0.0" - "@angular-devkit/schematics" ">= 21.0.0 < 22.0.0" - "@angular-eslint/builder" "21.1.0" - "@angular-eslint/eslint-plugin" "21.1.0" - "@angular-eslint/eslint-plugin-template" "21.1.0" - "@angular-eslint/schematics" "21.1.0" - "@angular-eslint/template-parser" "21.1.0" + "@angular-devkit/core" ">= 22.0.0 < 23.0.0" + "@angular-devkit/schematics" ">= 22.0.0 < 23.0.0" + "@angular-eslint/builder" "22.1.0" + "@angular-eslint/eslint-plugin" "22.1.0" + "@angular-eslint/eslint-plugin-template" "22.1.0" + "@angular-eslint/schematics" "22.1.0" + "@angular-eslint/template-parser" "22.1.0" "@typescript-eslint/types" "^8.0.0" "@typescript-eslint/utils" "^8.0.0" ansi-escapes@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.2.0.tgz#31b25afa3edd3efc09d98c2fee831d460ff06b49" - integrity sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw== + version "7.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz#5395bb74b2150a4a1d6e3c2565f4aeca78d28627" + integrity sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg== dependencies: environment "^1.0.0" @@ -1999,7 +1816,7 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.0.1: +ansi-regex@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== @@ -2011,23 +1828,18 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" -ansi-styles@^6.2.1: +ansi-styles@^6.2.1, ansi-styles@^6.2.3: version "6.2.3" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - aria-query@5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" @@ -2121,17 +1933,6 @@ async-function@^1.0.0: resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== -autoprefixer@^10.4.19: - version "10.4.23" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.23.tgz#c6aa6db8e7376fcd900f9fd79d143ceebad8c4e6" - integrity sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA== - dependencies: - browserslist "^4.28.1" - caniuse-lite "^1.0.30001760" - fraction.js "^5.3.4" - picocolors "^1.1.1" - postcss-value-parser "^4.2.0" - available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -2149,15 +1950,20 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -baseline-browser-mapping@^2.9.0: - version "2.9.18" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.9.18.tgz#c8281693035a9261b10d662a5379650a6c2d1ff7" - integrity sha512-e23vBV1ZLfjb9apvfPk4rHVu2ry6RIr2Wfs+O324okSidrX7pTAnEJPCh/O5BtRlr7QtZI7ktOP3vsqr7Z5XoA== +balanced-match@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a" + integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== -beasties@0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/beasties/-/beasties-0.3.5.tgz#a52abea4ead105c1aded66b1a01a74e96585dc81" - integrity sha512-NaWu+f4YrJxEttJSm16AzMIFtVldCvaJ68b1L098KpqXmxt9xOLtKoLkKxb8ekhOrLqEJAbvT6n6SEvB/sac7A== +baseline-browser-mapping@^2.11.12: + version "2.11.13" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz#660073103c1bee93e54df55f117b7528adf6af19" + integrity sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ== + +beasties@0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/beasties/-/beasties-0.4.3.tgz#987fc0d31126186de723e43858cfa235f530e87a" + integrity sha512-fIIeLOcbAB/K1kb1HBVJoiq1alHL4RCYBSo5e7HzrNkkgMggXR1Vqt/Z9JWnkfe/qdCo66Ux3QRwZioAIBdWRA== dependencies: css-select "^6.0.0" css-what "^7.0.0" @@ -2167,21 +1973,22 @@ beasties@0.3.5: picocolors "^1.1.1" postcss "^8.4.49" postcss-media-query-parser "^0.2.3" + postcss-safe-parser "^7.0.1" body-parser@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.2.tgz#1a32cdb966beaf68de50a9dfbe5b58f83cb8890c" - integrity sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.3.0.tgz#6d8662f4d8c336028b8ac9aa24251b0ca64ba437" + integrity sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw== dependencies: bytes "^3.1.2" - content-type "^1.0.5" + content-type "^2.0.0" debug "^4.4.3" - http-errors "^2.0.0" - iconv-lite "^0.7.0" + http-errors "^2.0.1" + iconv-lite "^0.7.2" on-finished "^2.4.1" - qs "^6.14.1" - raw-body "^3.0.1" - type-is "^2.0.1" + qs "^6.15.2" + raw-body "^3.0.2" + type-is "^2.1.0" boolbase@^1.0.0: version "1.0.0" @@ -2189,37 +1996,30 @@ boolbase@^1.0.0: integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== brace-expansion@^1.1.7: - version "1.1.12" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" - integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + version "1.1.18" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.18.tgz#3ce74d89885136be1535341f8c3d4425c29a5cab" + integrity sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== +brace-expansion@^5.0.8: + version "5.0.9" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-5.0.9.tgz#7c72438809b5fa5babf54199a1f1c281a6984fcf" + integrity sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg== dependencies: - balanced-match "^1.0.0" + balanced-match "^4.0.2" -braces@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== +browserslist@^4.24.0, browserslist@^4.26.0: + version "4.28.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.8.tgz#a3c79ceb70028527e5da7dafc887f3200b5168c0" + integrity sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA== dependencies: - fill-range "^7.1.1" - -browserslist@^4.24.0, browserslist@^4.26.0, browserslist@^4.28.1: - version "4.28.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" - integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== - dependencies: - baseline-browser-mapping "^2.9.0" - caniuse-lite "^1.0.30001759" - electron-to-chromium "^1.5.263" - node-releases "^2.0.27" - update-browserslist-db "^1.2.0" + baseline-browser-mapping "^2.11.12" + caniuse-lite "^1.0.30001809" + electron-to-chromium "^1.5.402" + node-releases "^2.0.53" + update-browserslist-db "^1.3.0" buffer-from@^1.0.0: version "1.1.2" @@ -2231,24 +2031,7 @@ bytes@^3.1.2, bytes@~3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacache@^20.0.0, cacache@^20.0.1: - version "20.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-20.0.3.tgz#bd65205d5e6d86e02bbfaf8e4ce6008f1b81d119" - integrity sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw== - dependencies: - "@npmcli/fs" "^5.0.0" - fs-minipass "^3.0.0" - glob "^13.0.0" - lru-cache "^11.1.0" - minipass "^7.0.3" - minipass-collect "^2.0.1" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - p-map "^7.0.2" - ssri "^13.0.0" - unique-filename "^5.0.0" - -call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== @@ -2256,14 +2039,14 @@ call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply- es-errors "^1.3.0" function-bind "^1.1.2" -call-bind@^1.0.7, call-bind@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" - integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== +call-bind@^1.0.7, call-bind@^1.0.8, call-bind@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.9.tgz#39a644700c80bc7d0ca9102fc6d1d43b2fd7eee7" + integrity sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ== dependencies: - call-bind-apply-helpers "^1.0.0" - es-define-property "^1.0.0" - get-intrinsic "^1.2.4" + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + get-intrinsic "^1.3.0" set-function-length "^1.2.2" call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: @@ -2274,11 +2057,6 @@ call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: call-bind-apply-helpers "^1.0.2" get-intrinsic "^1.3.0" -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - camelcase-keys@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" @@ -2293,12 +2071,12 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30001759, caniuse-lite@^1.0.30001760: - version "1.0.30001766" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz#b6f6b55cb25a2d888d9393104d14751c6a7d6f7a" - integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA== +caniuse-lite@^1.0.30001809: + version "1.0.30001809" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz#e6cf71f14ddfe008f114dd2a846923be3c03a07b" + integrity sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ== -chai@^6.2.1: +chai@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== @@ -2312,30 +2090,15 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@^5.6.2: version "5.6.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== chardet@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-2.1.1.tgz#5c75593704a642f71ee53717df234031e65373c8" - integrity sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ== - -chokidar@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" - integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== - dependencies: - readdirp "^4.0.1" + version "2.2.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-2.2.0.tgz#005d664f2cbd4961888d2e2c32c5a69e59d8eec4" + integrity sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA== chokidar@^5.0.0: version "5.0.0" @@ -2344,11 +2107,6 @@ chokidar@^5.0.0: dependencies: readdirp "^5.0.0" -chownr@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" - integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== - cli-cursor@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" @@ -2361,13 +2119,13 @@ cli-spinners@^3.2.0: resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-3.4.0.tgz#1f11f6d48c4e5bc6849fcb4efa0dc98f9e7299ea" integrity sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw== -cli-truncate@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-5.1.1.tgz#455476face9904d94b7d11e98d9adbca15292ea5" - integrity sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A== +cli-truncate@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-5.2.0.tgz#c8e72aaca8339c773d128c36e0a17c6315b694eb" + integrity sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw== dependencies: - slice-ansi "^7.1.0" - string-width "^8.0.0" + slice-ansi "^8.0.0" + string-width "^8.2.0" cli-width@^4.1.0: version "4.1.0" @@ -2416,16 +2174,6 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.20: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -commander@^14.0.2: - version "14.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.2.tgz#b71fd37fe4069e4c3c7c13925252ada4eba14e8e" - integrity sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ== - compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -2455,15 +2203,20 @@ concat-stream@^2.0.0: typedarray "^0.0.6" content-disposition@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.1.tgz#a8b7bbeb2904befdfb6787e5c0c086959f605f9b" - integrity sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q== + version "1.1.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.1.0.tgz#f3db789c752d45564cc7e9e1e0b31790d4a38e17" + integrity sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g== content-type@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== +content-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-2.0.0.tgz#2fb3ede69dffa0af78ca7c4ce7589680638b56df" + integrity sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ== + conventional-changelog-angular@^5.0.12: version "5.0.13" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" @@ -2722,13 +2475,6 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -2736,6 +2482,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -2863,10 +2616,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.263: - version "1.5.279" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.279.tgz#67dfdeb22fd81412d0d18d1d9b2c749e9b8945cb" - integrity sha512-0bblUU5UNdOt5G7XqGiJtpZMONma6WAfq9vsFmtn9x1+joAObr6x1chfqyxFSDCAFwFhCQDrqeAr6MYdpwJ9Hg== +electron-to-chromium@^1.5.402: + version "1.5.403" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.403.tgz#8a6e422bc68c5d2fa4d8c5fa2ba9a583c3d4452c" + integrity sha512-MQsYmdaLzvaCX5j+ZZBr5Fm6uCCnPQcRtlvmvRlWqrXy+BH2O4ffXIAScF+JQznQWB9brWp4lSD9Z4yNmaf2BA== emoji-regex@^10.3.0: version "10.6.0" @@ -2878,48 +2631,36 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +empathic@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/empathic/-/empathic-2.0.1.tgz#37b1bede31093e04a03d2abce95ea323fee8ef49" + integrity sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q== + encodeurl@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== -encoding@^0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - entities@^4.2.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -entities@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" - integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== - entities@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/entities/-/entities-7.0.1.tgz#26e8a88889db63417dcb9a1e79a3f1bc92b5976b" integrity sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA== -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== +entities@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-8.0.0.tgz#c1df5fe3602429747fa233d0dd26f142f0ce4743" + integrity sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA== environment@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== -err-code@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" - integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== - error-ex@^1.3.1: version "1.3.4" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" @@ -2927,10 +2668,20 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9, es-abstract@^1.24.0: - version "1.24.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.1.tgz#f0c131ed5ea1bb2411134a8dd94def09c46c7899" - integrity sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw== +es-abstract-get@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-abstract-get/-/es-abstract-get-1.0.0.tgz#1eae87101f42bedeb6a740e8c5051271aef89088" + integrity sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg== + dependencies: + es-errors "^1.3.0" + es-object-atoms "^1.1.2" + is-callable "^1.2.7" + object-inspect "^1.13.4" + +es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9, es-abstract@^1.24.0, es-abstract@^1.24.2: + version "1.24.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.2.tgz#2dbd38c180735ee983f77585140a2706a963ed9a" + integrity sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg== dependencies: array-buffer-byte-length "^1.0.2" arraybuffer.prototype.slice "^1.0.4" @@ -2997,15 +2748,15 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-module-lexer@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" - integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== +es-module-lexer@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.1.tgz#5bf2df06999dbbe5f006a5f46a11fb9f5b7b391b" + integrity sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA== -es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" - integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1, es-object-atoms@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz#a2d0b373205724dfa525d23b0c3e1b1ca582c99b" + integrity sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw== dependencies: es-errors "^1.3.0" @@ -3027,45 +2778,48 @@ es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: hasown "^2.0.2" es-to-primitive@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" - integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.4.tgz#0c854291cf0d7b439d6b9e5771ea837ffaf1f991" + integrity sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw== dependencies: + es-abstract-get "^1.0.0" + es-define-property "^1.0.1" + es-errors "^1.3.0" is-callable "^1.2.7" - is-date-object "^1.0.5" - is-symbol "^1.0.4" + is-date-object "^1.1.0" + is-symbol "^1.1.1" -esbuild@0.27.2, esbuild@^0.27.0: - version "0.27.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.2.tgz#d83ed2154d5813a5367376bb2292a9296fc83717" - integrity sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw== +esbuild@0.28.1: + version "0.28.1" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.1.tgz#ef45b4634c9c9d97a296aea4114a5f9840f95578" + integrity sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw== optionalDependencies: - "@esbuild/aix-ppc64" "0.27.2" - "@esbuild/android-arm" "0.27.2" - "@esbuild/android-arm64" "0.27.2" - "@esbuild/android-x64" "0.27.2" - "@esbuild/darwin-arm64" "0.27.2" - "@esbuild/darwin-x64" "0.27.2" - "@esbuild/freebsd-arm64" "0.27.2" - "@esbuild/freebsd-x64" "0.27.2" - "@esbuild/linux-arm" "0.27.2" - "@esbuild/linux-arm64" "0.27.2" - "@esbuild/linux-ia32" "0.27.2" - "@esbuild/linux-loong64" "0.27.2" - "@esbuild/linux-mips64el" "0.27.2" - "@esbuild/linux-ppc64" "0.27.2" - "@esbuild/linux-riscv64" "0.27.2" - "@esbuild/linux-s390x" "0.27.2" - "@esbuild/linux-x64" "0.27.2" - "@esbuild/netbsd-arm64" "0.27.2" - "@esbuild/netbsd-x64" "0.27.2" - "@esbuild/openbsd-arm64" "0.27.2" - "@esbuild/openbsd-x64" "0.27.2" - "@esbuild/openharmony-arm64" "0.27.2" - "@esbuild/sunos-x64" "0.27.2" - "@esbuild/win32-arm64" "0.27.2" - "@esbuild/win32-ia32" "0.27.2" - "@esbuild/win32-x64" "0.27.2" + "@esbuild/aix-ppc64" "0.28.1" + "@esbuild/android-arm" "0.28.1" + "@esbuild/android-arm64" "0.28.1" + "@esbuild/android-x64" "0.28.1" + "@esbuild/darwin-arm64" "0.28.1" + "@esbuild/darwin-x64" "0.28.1" + "@esbuild/freebsd-arm64" "0.28.1" + "@esbuild/freebsd-x64" "0.28.1" + "@esbuild/linux-arm" "0.28.1" + "@esbuild/linux-arm64" "0.28.1" + "@esbuild/linux-ia32" "0.28.1" + "@esbuild/linux-loong64" "0.28.1" + "@esbuild/linux-mips64el" "0.28.1" + "@esbuild/linux-ppc64" "0.28.1" + "@esbuild/linux-riscv64" "0.28.1" + "@esbuild/linux-s390x" "0.28.1" + "@esbuild/linux-x64" "0.28.1" + "@esbuild/netbsd-arm64" "0.28.1" + "@esbuild/netbsd-x64" "0.28.1" + "@esbuild/openbsd-arm64" "0.28.1" + "@esbuild/openbsd-x64" "0.28.1" + "@esbuild/openharmony-arm64" "0.28.1" + "@esbuild/sunos-x64" "0.28.1" + "@esbuild/win32-arm64" "0.28.1" + "@esbuild/win32-ia32" "0.28.1" + "@esbuild/win32-x64" "0.28.1" escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -3098,18 +2852,18 @@ eslint-config-prettier@^10.1.5: integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w== eslint-import-resolver-node@^0.3.9: - version "0.3.9" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" - integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + version "0.3.10" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.10.tgz#84ce3005abfc300588cf23bbac1aabec1fc6e8c1" + integrity sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ== dependencies: debug "^3.2.7" - is-core-module "^2.13.0" - resolve "^1.22.4" + is-core-module "^2.16.1" + resolve "^2.0.0-next.6" eslint-module-utils@^2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz#f76d3220bfb83c057651359295ab5854eaad75ff" - integrity sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw== + version "2.14.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.14.0.tgz#611f8e1c6ceb29a93eb949e1cc670b8287764819" + integrity sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig== dependencies: debug "^3.2.7" @@ -3139,30 +2893,22 @@ eslint-plugin-import@^2.31.0: tsconfig-paths "^3.15.0" eslint-plugin-perfectionist@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.4.0.tgz#4849ee1e5b88a85dbee6bde3a217cc0d0351ea8f" - integrity sha512-XxpUMpeVaSJF5rpF6NHmhj3xavHZrflKcRbDssAUWrHUU/+l3l7PPYnVJ6IOpR2KjQ1Blucaeb0cFL3LIBis0A== + version "5.10.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-5.10.1.tgz#3fb3401fe97eae57aa1194a1fd824ff95becb497" + integrity sha512-Kprsp9Us0GqAesYaAIzUViw57xYp5WBqzXrcE0Mtww++E5fexWXYBipMuuD7yvyH4vvpBH0+oJ+OMAmZ0oYXkw== dependencies: - "@typescript-eslint/utils" "^8.53.1" + "@typescript-eslint/utils" "^8.65.0" natural-orderby "^5.0.0" eslint-plugin-unused-imports@^4.1.4: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.3.0.tgz#69ff9c4f83f02f7789808bbbab77636cb742af50" - integrity sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA== + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz#a831f0a2937d7631eba30cb87091ab7d3a5da0e1" + integrity sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ== -eslint-scope@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" - integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - -eslint-scope@^9.0.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-9.1.0.tgz#dfcb41d6c0d73df6b977a50cf3e91c41ddb4154e" - integrity sha512-CkWE42hOJsNj9FJRaoMX9waUFYhqY4jmyLFdAdzZr6VaCg3ynLYx4WnOdkaIifGfH4gsUcBTn4OZbHXkpLD0FQ== +eslint-scope@9.1.2, eslint-scope@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-9.1.2.tgz#b9de6ace2fab1cff24d2e58d85b74c8fcea39802" + integrity sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ== dependencies: "@types/esrecurse" "^4.3.1" "@types/estree" "^1.0.8" @@ -3174,37 +2920,34 @@ eslint-visitor-keys@^3.4.3: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" - integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== +eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be" + integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== -eslint@^9.28.0: - version "9.39.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.2.tgz#cb60e6d16ab234c0f8369a3fe7cc87967faf4b6c" - integrity sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw== +eslint@^10.8.1: + version "10.8.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-10.8.1.tgz#fb37d514c19b6dd5b2d6b70169fd26fddfa97967" + integrity sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ== dependencies: "@eslint-community/eslint-utils" "^4.8.0" - "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.21.1" - "@eslint/config-helpers" "^0.4.2" - "@eslint/core" "^0.17.0" - "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.39.2" - "@eslint/plugin-kit" "^0.4.1" + "@eslint-community/regexpp" "^4.12.2" + "@eslint/config-array" "^0.23.5" + "@eslint/config-helpers" "^0.7.0" + "@eslint/core" "^1.2.1" + "@eslint/plugin-kit" "^0.7.2" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" - ajv "^6.12.4" - chalk "^4.0.0" + ajv "^6.14.0" cross-spawn "^7.0.6" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.4.0" - eslint-visitor-keys "^4.2.1" - espree "^10.4.0" - esquery "^1.5.0" + eslint-scope "^9.1.2" + eslint-visitor-keys "^5.0.1" + espree "^11.2.0" + esquery "^1.7.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^8.0.0" @@ -3214,21 +2957,20 @@ eslint@^9.28.0: imurmurhash "^0.1.4" is-glob "^4.0.0" json-stable-stringify-without-jsonify "^1.0.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" + minimatch "^10.2.5" natural-compare "^1.4.0" optionator "^0.9.3" -espree@^10.0.1, espree@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" - integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== +espree@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-11.2.0.tgz#01d5e47dc332aaba3059008362454a8cc34ccaa5" + integrity sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw== dependencies: - acorn "^8.15.0" + acorn "^8.16.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.2.1" + eslint-visitor-keys "^5.0.1" -esquery@^1.5.0: +esquery@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== @@ -3264,15 +3006,15 @@ etag@^1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eventemitter3@^5.0.1: +eventemitter3@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== eventsource-parser@^3.0.0, eventsource-parser@^3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz#292e165e34cacbc936c3c92719ef326d4aeb4e90" - integrity sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg== + version "3.1.0" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.1.0.tgz#4e198eb91cd333d0a8ddcc036502b3618a25f449" + integrity sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg== eventsource@^3.0.2: version "3.0.7" @@ -3281,22 +3023,20 @@ eventsource@^3.0.2: dependencies: eventsource-parser "^3.0.1" -expect-type@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" - integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== +expect-type@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.4.0.tgz#24edf7f0cc69a44d008567ba4594ab96f3c3a3d6" + integrity sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA== -exponential-backoff@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6" - integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA== +express-rate-limit@^8.2.1: + version "8.6.2" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-8.6.2.tgz#1a6c7fb6c5f5a83883c14f1d198fcdff60087c5d" + integrity sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A== + dependencies: + debug "^4.4.3" + ip-address "^10.2.0" -express-rate-limit@^7.5.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" - integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== - -express@^5.0.1: +express@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== @@ -3345,10 +3085,29 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-string-truncated-width@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz#23afe0da67d752ca0727538f1e6967759728ce49" + integrity sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g== + +fast-string-width@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fast-string-width/-/fast-string-width-3.0.2.tgz#16dbabb491ce5585b5ecb675b65c165d71688eeb" + integrity sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg== + dependencies: + fast-string-truncated-width "^3.0.2" + fast-uri@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" - integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + version "3.1.5" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.5.tgz#610f37419a030270430cecd68d74e3d4d96725d0" + integrity sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw== + +fast-wrap-ansi@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz#95e952a0145bce3f59ad56e179f84c48d4072935" + integrity sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q== + dependencies: + fast-string-width "^3.0.2" fdir@^6.5.0: version "6.5.0" @@ -3369,13 +3128,6 @@ file-entry-cache@^8.0.0: dependencies: flat-cache "^4.0.0" -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - finalhandler@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.1.tgz#a2c517a6559852bcdb06d1f8bd7f51b68fad8099" @@ -3427,9 +3179,9 @@ flat-cache@^4.0.0: keyv "^4.5.4" flatted@^3.2.9: - version "3.3.3" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" - integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + version "3.4.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.4.tgz#aeeca2a506303f0cee61c59e6c9f2a88d2f29fc6" + integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q== for-each@^0.3.3, for-each@^0.3.5: version "0.3.5" @@ -3443,7 +3195,7 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^5.2.1, fraction.js@^5.3.4: +fraction.js@^5.2.1: version "5.3.4" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-5.3.4.tgz#8c0fcc6a9908262df4ed197427bdeef563e0699a" integrity sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ== @@ -3453,14 +3205,7 @@ fresh@^2.0.0: resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== -fs-minipass@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-3.0.3.tgz#79a85981c4dc120065e96f62086bf6f9dc26cc54" - integrity sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw== - dependencies: - minipass "^7.0.3" - -fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -3471,16 +3216,19 @@ function-bind@^1.1.2: integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" - integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + version "1.2.0" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.2.0.tgz#758f3e84fa542672454bd5e14cb081a5ce07f70c" + integrity sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew== dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" + call-bind "^1.0.9" + call-bound "^1.0.4" + es-define-property "^1.0.1" + es-errors "^1.3.0" functions-have-names "^1.2.3" - hasown "^2.0.2" + has-property-descriptors "^1.0.2" + hasown "^2.0.4" is-callable "^1.2.7" + is-document.all "^1.0.0" functions-have-names@^1.2.3: version "1.2.3" @@ -3502,10 +3250,10 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.0, get-east-asian-width@^1.3.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz#9bc4caa131702b4b61729cb7e42735bc550c9ee6" - integrity sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q== +get-east-asian-width@^1.0.0, get-east-asian-width@^1.3.1, get-east-asian-width@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz#216900f91df11a8b2c198c3e1d93d6c035a776b9" + integrity sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA== get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: version "1.3.0" @@ -3591,25 +3339,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-13.0.0.tgz#9d9233a4a274fc28ef7adce5508b7ef6237a1be3" - integrity sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA== - dependencies: - minimatch "^10.1.1" - minipass "^7.1.2" - path-scurry "^2.0.0" - -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== - globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -3623,15 +3352,15 @@ gopd@^1.0.1, gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.1.2, graceful-fs@^4.2.6: +graceful-fs@^4.1.2: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== handlebars@^4.7.7: - version "4.7.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" - integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + version "4.7.9" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.9.tgz#6f139082ab58dc4e5a0e51efe7db5ae890d56a0f" + integrity sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ== dependencies: minimist "^1.2.5" neo-async "^2.6.2" @@ -3655,11 +3384,6 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" @@ -3686,13 +3410,25 @@ has-tostringtag@^1.0.2: dependencies: has-symbols "^1.0.3" -hasown@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" - integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== +hasown@^2.0.2, hasown@^2.0.3, hasown@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003" + integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A== dependencies: function-bind "^1.1.2" +hono@^4.11.4: + version "4.13.1" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.13.1.tgz#d4a606b792954d07a6215d12c01b7cf59da03cbc" + integrity sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw== + +hosted-git-info@^10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-10.1.1.tgz#50d93ed3ab3b81002122814cd56d5595f550d32c" + integrity sha512-DeOnSPAvOndYKfw075gt8yZzQ7S2hNztw34zBTfhIzLhmBTswIBg5/y+pqu/VD5cYWm5goAFTusDmUEmKZ0PEQ== + dependencies: + lru-cache "^11.1.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -3705,13 +3441,6 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -hosted-git-info@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-9.0.2.tgz#b38c8a802b274e275eeeccf9f4a1b1a0a8557ada" - integrity sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg== - dependencies: - lru-cache "^11.1.0" - htmlparser2@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.1.0.tgz#fe3f2e12c73b6e462d4e10395db9c1119e4d6ae4" @@ -3722,11 +3451,6 @@ htmlparser2@^10.0.0: domutils "^3.2.2" entities "^7.0.1" -http-cache-semantics@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#205f4db64f8562b76a4ff9235aa5279839a09dd5" - integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== - http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.1.tgz#36d2f65bc909c8790018dd36fb4d93da6caae06b" @@ -3738,49 +3462,28 @@ http-errors@^2.0.0, http-errors@^2.0.1, http-errors@~2.0.1: statuses "~2.0.2" toidentifier "~1.0.1" -http-proxy-agent@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" - integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== +https-proxy-agent@9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-9.1.0.tgz#a9f60f79bc1578c37b166dd7f58b6bcb5c57e44b" + integrity sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA== dependencies: - agent-base "^7.1.0" + agent-base "9.0.0" debug "^4.3.4" - -https-proxy-agent@7.0.6, https-proxy-agent@^7.0.1: - version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" - integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== - dependencies: - agent-base "^7.1.2" - debug "4" + proxy-agent-negotiate "1.1.0" husky@^9.1.7: version "9.1.7" resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== -iconv-lite@^0.6.2: - version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" - integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== +iconv-lite@^0.7.2, iconv-lite@~0.7.0: + version "0.7.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.3.tgz#84ee12f963e7de50bc01a13e160a078b3b0f415f" + integrity sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -iconv-lite@^0.7.0, iconv-lite@~0.7.0: - version "0.7.2" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" - integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -ignore-walk@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-8.0.0.tgz#380c173badc3a18c57ff33440753f0052f572b14" - integrity sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A== - dependencies: - minimatch "^10.0.3" - -ignore@7.0.5, ignore@^7.0.5: +ignore@7.0.5: version "7.0.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== @@ -3790,18 +3493,20 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -immutable@^5.0.2: - version "5.1.4" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.4.tgz#e3f8c1fe7b567d56cf26698f31918c241dae8c1f" - integrity sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA== +ignore@^7.0.5: + version "7.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.6.tgz#6a57aaef4c90df27ac3590875d29e8f11988c88e" + integrity sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw== -import-fresh@^3.2.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" - integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" +immutable@^5.1.5: + version "5.1.9" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.9.tgz#ac23c3a01992ab665e14ac9ffff298f28cd74a0c" + integrity sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg== + +import-meta-resolve@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz#08cb85b5bd37ecc8eb1e0f670dc2767002d43734" + integrity sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg== imurmurhash@^0.1.4: version "0.1.4" @@ -3818,11 +3523,6 @@ inherits@^2.0.3, inherits@~2.0.3, inherits@~2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@6.0.0, ini@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-6.0.0.tgz#efc7642b276f6a37d22fdf56ef50889d7146bf30" - integrity sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ== - ini@^1.3.2: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -3837,10 +3537,10 @@ internal-slot@^1.1.0: hasown "^2.0.2" side-channel "^1.1.0" -ip-address@^10.0.1: - version "10.1.0" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4" - integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== +ip-address@^10.2.0: + version "10.5.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.5.0.tgz#fcd6d7dfe9e68416b7cb71afe9bc960b3e38c13b" + integrity sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g== ipaddr.js@1.9.1: version "1.9.1" @@ -3892,12 +3592,12 @@ is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.16.1, is-core-module@^2.5.0: - version "2.16.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" - integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== +is-core-module@^2.16.1, is-core-module@^2.16.2, is-core-module@^2.5.0: + version "2.16.2" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.2.tgz#3e07450a8080ebce3fbf0cac494f4d2ab324e082" + integrity sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA== dependencies: - hasown "^2.0.2" + hasown "^2.0.3" is-data-view@^1.0.1, is-data-view@^1.0.2: version "1.0.2" @@ -3908,7 +3608,7 @@ is-data-view@^1.0.1, is-data-view@^1.0.2: get-intrinsic "^1.2.6" is-typed-array "^1.1.13" -is-date-object@^1.0.5, is-date-object@^1.1.0: +is-date-object@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== @@ -3916,6 +3616,13 @@ is-date-object@^1.0.5, is-date-object@^1.1.0: call-bound "^1.0.2" has-tostringtag "^1.0.2" +is-document.all@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-document.all/-/is-document.all-1.0.0.tgz#163a4bfb362c6ed7b118ce46cdecc4e37dee3195" + integrity sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g== + dependencies: + call-bound "^1.0.4" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -3933,7 +3640,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-fullwidth-code-point@^5.0.0: +is-fullwidth-code-point@^5.0.0, is-fullwidth-code-point@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz#046b2a6d4f6b156b2233d3207d4b5a9783999b98" integrity sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ== @@ -3981,11 +3688,6 @@ is-number-object@^1.1.1: call-bound "^1.0.3" has-tostringtag "^1.0.2" -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -4031,7 +3733,7 @@ is-string@^1.1.1: call-bound "^1.0.3" has-tostringtag "^1.0.2" -is-symbol@^1.0.4, is-symbol@^1.1.1: +is-symbol@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== @@ -4094,49 +3796,26 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isexe@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" - integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== - -istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" - integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - javascript-natural-sort@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== -jose@^6.1.1: - version "6.1.3" - resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" - integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== +jose@^6.1.3: + version "6.2.8" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.8.tgz#39c1459fe5eac84eb39b1623b8077dcf9ca6c506" + integrity sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ== + +js-tokens@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-10.0.0.tgz#dffe7599b4a8bb7fe30aff8d0235234dffb79831" + integrity sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q== js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" - integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== - dependencies: - argparse "^2.0.1" - jsesc@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -4157,11 +3836,6 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-parse-even-better-errors@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz#93c89f529f022e5dadc233409324f0167b1e903e" - integrity sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -4204,7 +3878,7 @@ jsonc-parser@3.3.1: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz#f2a524b4f7fd11e3d791e559977ad60b98b798b4" integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ== -jsonparse@^1.2.0, jsonparse@^1.3.1: +jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== @@ -4229,54 +3903,126 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lightningcss-android-arm64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz#9a6841f88ae50fc83502903892b41af41bc2b907" + integrity sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg== + +lightningcss-darwin-arm64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz#c0f2c31c0bfd19fa4dd3f18e957a1f1a152097d6" + integrity sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg== + +lightningcss-darwin-x64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz#cb0705965acb538c6683949ce6925fb3cdf7c361" + integrity sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ== + +lightningcss-freebsd-x64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz#763538828b26bab2680dadafcc84ee78b0eb502b" + integrity sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg== + +lightningcss-linux-arm-gnueabihf@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz#6862e3176a331aedbdec1ed352b4d7d0dd0784de" + integrity sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ== + +lightningcss-linux-arm64-gnu@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz#c6a3a2ed15141daf6bdc2628930f8e39bdf473aa" + integrity sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg== + +lightningcss-linux-arm64-musl@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz#7fa1334971fc82845f9827df6ef8a0b20914bac6" + integrity sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ== + +lightningcss-linux-x64-gnu@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz#8b927862ea8c2bbc6831a46509244b50d9936e55" + integrity sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg== + +lightningcss-linux-x64-musl@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz#0c525bb077dfd94404c059cfe42dad797e96aeaf" + integrity sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw== + +lightningcss-win32-arm64-msvc@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz#850ee1103dac989cfab50e3ac22d1a69e394e63d" + integrity sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA== + +lightningcss-win32-x64-msvc@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz#e343ae152eed3609dc6e11949d1a3bf39a1c946f" + integrity sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA== + +lightningcss@^1.32.0, lightningcss@^1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.33.0.tgz#c08867d71a79385c6e190214fd72fef3e5f95f0b" + integrity sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.33.0" + lightningcss-darwin-arm64 "1.33.0" + lightningcss-darwin-x64 "1.33.0" + lightningcss-freebsd-x64 "1.33.0" + lightningcss-linux-arm-gnueabihf "1.33.0" + lightningcss-linux-arm64-gnu "1.33.0" + lightningcss-linux-arm64-musl "1.33.0" + lightningcss-linux-x64-gnu "1.33.0" + lightningcss-linux-x64-musl "1.33.0" + lightningcss-win32-arm64-msvc "1.33.0" + lightningcss-win32-x64-msvc "1.33.0" + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -lint-staged@^16.1.2: - version "16.2.7" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.2.7.tgz#c4a635960c17b52fe774f1f40aee8ce1bd86531f" - integrity sha512-lDIj4RnYmK7/kXMya+qJsmkRFkGolciXjrsZ6PC25GdTfWOAWetR0ZbsNXRAj1EHHImRSalc+whZFg56F5DVow== +lint-staged@^17.3.0: + version "17.3.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-17.3.0.tgz#f13483b12f11790746e0ec82808ca0614ba80f4b" + integrity sha512-woZS3vNe3UKqBaLPvbLOtKRY4tLANpWQhom12MGWqC8Mh1lCOO+WgSwmX2amjJAqTY9BkXYW87fCUH5H9Ph6xw== dependencies: - commander "^14.0.2" - listr2 "^9.0.5" - micromatch "^4.0.8" - nano-spawn "^2.0.0" - pidtree "^0.6.0" + picomatch "^4.0.5" string-argv "^0.3.2" - yaml "^2.8.1" + tinyexec "^1.2.4" + optionalDependencies: + yaml "^2.9.0" -listr2@9.0.5, listr2@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-9.0.5.tgz#92df7c4416a6da630eb9ef46da469b70de97b316" - integrity sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g== +listr2@10.2.2: + version "10.2.2" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-10.2.2.tgz#01d987a6e3fb03b17612968617366f28fdeaf4d3" + integrity sha512-JtNtbZj8q5BnDMR7trpwvwk3RIrANtIVzEUm8w7amp6xelLgyuq+4WZoTH913XaQAoH/cNdYhaNzBPA2U3xbDw== dependencies: - cli-truncate "^5.0.0" - colorette "^2.0.20" - eventemitter3 "^5.0.1" + cli-truncate "^5.2.0" + eventemitter3 "^5.0.4" log-update "^6.1.0" rfdc "^1.4.1" - wrap-ansi "^9.0.0" + wrap-ansi "^10.0.0" -lmdb@3.4.4: - version "3.4.4" - resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-3.4.4.tgz#a6ca8803887c13d672542fb35f0ba1c267d4e95f" - integrity sha512-+Y2DqovevLkb6DrSQ6SXTYLEd6kvlRbhsxzgJrk7BUfOVA/mt21ak6pFDZDKxiAczHMWxrb02kXBTSTIA0O94A== +lmdb@3.5.6: + version "3.5.6" + resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-3.5.6.tgz#c45d2d40f65f91770d45dccbba8dba7f422a5388" + integrity sha512-j3uE8ReKNyUWDjhfEFSJqE/1DLtfTR5Z8yFzVHvBjAk37wNg7HdScjcv8ttPHRvrdgPQMPWxFFI0SsdBzI5lBw== dependencies: + "@harperfast/extended-iterable" "^1.0.3" msgpackr "^1.11.2" node-addon-api "^6.1.0" node-gyp-build-optional-packages "5.2.2" ordered-binary "^1.5.3" weak-lru-cache "^1.2.2" optionalDependencies: - "@lmdb/lmdb-darwin-arm64" "3.4.4" - "@lmdb/lmdb-darwin-x64" "3.4.4" - "@lmdb/lmdb-linux-arm" "3.4.4" - "@lmdb/lmdb-linux-arm64" "3.4.4" - "@lmdb/lmdb-linux-x64" "3.4.4" - "@lmdb/lmdb-win32-arm64" "3.4.4" - "@lmdb/lmdb-win32-x64" "3.4.4" + "@lmdb/lmdb-darwin-arm64" "3.5.6" + "@lmdb/lmdb-darwin-x64" "3.5.6" + "@lmdb/lmdb-linux-arm" "3.5.6" + "@lmdb/lmdb-linux-arm64" "3.5.6" + "@lmdb/lmdb-linux-x64" "3.5.6" + "@lmdb/lmdb-win32-arm64" "3.5.6" + "@lmdb/lmdb-win32-x64" "3.5.6" load-json-file@^4.0.0: version "4.0.0" @@ -4323,15 +4069,10 @@ lodash.ismatch@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g== -lodash.merge@^4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - lodash@^4.17.15: - version "4.17.23" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.23.tgz#f113b0378386103be4f6893388c73d0bde7f2c5a" - integrity sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w== + version "4.18.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" + integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== log-symbols@^7.0.1: version "7.0.1" @@ -4352,17 +4093,10 @@ log-update@^6.1.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" -lru-cache@^11.0.0, lru-cache@^11.1.0, lru-cache@^11.2.1: - version "11.2.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.5.tgz#6811ae01652ae5d749948cdd80bcc22218c6744f" - integrity sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" +lru-cache@^11.0.0, lru-cache@^11.1.0: + version "11.5.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.5.2.tgz#00e16665c90c620fba14a3c368732a976493f760" + integrity sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g== lru-cache@^6.0.0: version "6.0.0" @@ -4371,30 +4105,20 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@0.30.21, magic-string@^0.30.21: +magic-string@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-1.0.0.tgz#e0f1c16d20b1a993d6481007f49fe1f5ca9b38ff" + integrity sha512-CGvjzMN08iv6w1mm4/x3Gh1hLb4VnyRUA15FFpl6CsCIGGoe36k7kY5KNz9QDbSBN5I/fWHM6ZlIkUTa5xdUEA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +magic-string@^0.30.21: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" -make-fetch-happen@^15.0.0, make-fetch-happen@^15.0.1, make-fetch-happen@^15.0.3: - version "15.0.3" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz#1578d72885f2b3f9e5daa120b36a14fc31a84610" - integrity sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw== - dependencies: - "@npmcli/agent" "^4.0.0" - cacache "^20.0.1" - http-cache-semantics "^4.1.1" - minipass "^7.0.2" - minipass-fetch "^5.0.0" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^1.0.0" - proc-log "^6.0.0" - promise-retry "^2.0.1" - ssri "^13.0.0" - map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -4411,9 +4135,9 @@ math-intrinsics@^1.1.0: integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== mathjs@^15.1.0: - version "15.1.0" - resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-15.1.0.tgz#e910f626c5d66ff1902eb69c3b2e7b7d010fc39e" - integrity sha512-HfnAcScQm9drGryodlDqeS3WAl4gUTYGDcOtcqL/8s23MZ28Ib1i8XnYK3ZdjNuaW/L4BAp9lIp8vxAMrcuu1w== + version "15.2.0" + resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-15.2.0.tgz#ddfbf50a9aeaec2edfb524195e8202ca29f8e757" + integrity sha512-UAQzSVob9rNLdGpqcFMYmSu9dkuLYy7Lr2hBEQS5SHQdknA9VppJz3cy2KkpMzTODunad6V6cNv+5kOLsePLow== dependencies: "@babel/runtime" "^7.26.10" complex.js "^2.2.5" @@ -4426,9 +4150,9 @@ mathjs@^15.1.0: typed-function "^4.2.1" media-typer@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" - integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.1.tgz#6f035400dfe3ab9d5607bc77546ce30cc2f9c6b8" + integrity sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ== meow@^8.0.0: version "8.1.2" @@ -4452,14 +4176,6 @@ merge-descriptors@^2.0.0: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== -micromatch@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" - integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - mime-db@^1.54.0: version "1.54.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" @@ -4482,27 +4198,20 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@^10.0.3, minimatch@^10.1.1: - version "10.1.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.1.1.tgz#e6e61b9b0c1dcab116b5a7d1458e8b6ae9e73a55" - integrity sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ== +minimatch@^10.2.2, minimatch@^10.2.4, minimatch@^10.2.5: + version "10.2.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.2.6.tgz#fd956bbe0b77241e9f15ac5dccb1c638060968ef" + integrity sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A== dependencies: - "@isaacs/brace-expansion" "^5.0.0" + brace-expansion "^5.0.8" minimatch@^3.0.4, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -4517,64 +4226,6 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minipass-collect@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-2.0.1.tgz#1621bc77e12258a12c60d34e2276ec5c20680863" - integrity sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw== - dependencies: - minipass "^7.0.3" - -minipass-fetch@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-5.0.0.tgz#644ed3fa172d43b3163bb32f736540fc138c4afb" - integrity sha512-fiCdUALipqgPWrOVTz9fw0XhcazULXOSU6ie40DDbX1F49p1dBrSRBuswndTx1x3vEb/g0FT7vC4c4C2u/mh3A== - dependencies: - minipass "^7.0.3" - minipass-sized "^1.0.3" - minizlib "^3.0.1" - optionalDependencies: - encoding "^0.1.13" - -minipass-flush@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" - integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== - dependencies: - minipass "^3.0.0" - -minipass-pipeline@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" - integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== - dependencies: - minipass "^3.0.0" - -minipass-sized@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/minipass-sized/-/minipass-sized-1.0.3.tgz#70ee5a7c5052070afacfbc22977ea79def353b70" - integrity sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g== - dependencies: - minipass "^3.0.0" - -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^7.0.2, minipass@^7.0.3, minipass@^7.0.4, minipass@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" - integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== - -minizlib@^3.0.1, minizlib@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c" - integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== - dependencies: - minipass "^7.1.2" - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -4596,40 +4247,35 @@ ms@^2.1.1, ms@^2.1.3: integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== msgpackr-extract@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz#e9d87023de39ce714872f9e9504e3c1996d61012" - integrity sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA== + version "3.0.4" + resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz#d252698947f7a1a62478d22bfb789ba48dd4c1ac" + integrity sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw== dependencies: node-gyp-build-optional-packages "5.2.2" optionalDependencies: - "@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.3" - "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.3" + "@msgpackr-extract/msgpackr-extract-darwin-arm64" "3.0.4" + "@msgpackr-extract/msgpackr-extract-darwin-x64" "3.0.4" + "@msgpackr-extract/msgpackr-extract-linux-arm" "3.0.4" + "@msgpackr-extract/msgpackr-extract-linux-arm64" "3.0.4" + "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.4" + "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.4" msgpackr@^1.11.2: - version "1.11.8" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.11.8.tgz#8283c79eb6e5d488f6fb3fac4996006baa390614" - integrity sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA== + version "1.12.1" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.12.1.tgz#61d48d6becf4d5c4d659b2c5260240dc2c09bd44" + integrity sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ== optionalDependencies: msgpackr-extract "^3.0.2" -mute-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" - integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== +mute-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-3.0.0.tgz#cd8014dd2acb72e1e91bb67c74f0019e620ba2d1" + integrity sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw== -nano-spawn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/nano-spawn/-/nano-spawn-2.0.0.tgz#f1250434c09ae18870d4f729fc54b406cf85a3e1" - integrity sha512-tacvGzUY5o2D8CBh2rrwxyNojUsZNU2zjNTzKQrkgGJQTbGAfArVWXSKMBokBeeg6C7OLRGUEyoFlYbfeWQIqw== - -nanoid@^3.3.11: - version "3.3.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +nanoid@^3.3.17: + version "3.3.18" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.18.tgz#f66a2de1199ffde0fcf21c8a5f13106b1c081913" + integrity sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w== natural-compare@^1.4.0: version "1.4.0" @@ -4661,6 +4307,16 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== +node-exports-info@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/node-exports-info/-/node-exports-info-1.6.2.tgz#243a3105677d6781cd26e6a72350fd928a5cb46f" + integrity sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag== + dependencies: + array.prototype.flatmap "^1.3.3" + es-errors "^1.3.0" + object.entries "^1.1.9" + semver "^6.3.1" + node-gyp-build-optional-packages@5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz#522f50c2d53134d7f3a76cd7255de4ab6c96a3a4" @@ -4668,33 +4324,10 @@ node-gyp-build-optional-packages@5.2.2: dependencies: detect-libc "^2.0.1" -node-gyp@^12.1.0: - version "12.2.0" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-12.2.0.tgz#ff73f6f509e33d8b7e768f889ffc9738ad117b07" - integrity sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ== - dependencies: - env-paths "^2.2.0" - exponential-backoff "^3.1.1" - graceful-fs "^4.2.6" - make-fetch-happen "^15.0.0" - nopt "^9.0.0" - proc-log "^6.0.0" - semver "^7.3.5" - tar "^7.5.4" - tinyglobby "^0.2.12" - which "^6.0.0" - -node-releases@^2.0.27: - version "2.0.27" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" - integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== - -nopt@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-9.0.0.tgz#6bff0836b2964d24508b6b41b5a9a49c4f4a1f96" - integrity sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw== - dependencies: - abbrev "^4.0.0" +node-releases@^2.0.53: + version "2.0.53" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.53.tgz#0fe5ad8a7935e075172f574e56f0c20f07fa41af" + integrity sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ== normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" @@ -4716,66 +4349,15 @@ normalize-package-data@^3.0.0: semver "^7.3.4" validate-npm-package-license "^3.0.1" -npm-bundled@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-5.0.0.tgz#5025d847cfd06c7b8d9432df01695d0133d9ee80" - integrity sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw== +npm-package-arg@14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-14.0.0.tgz#0e3557c2af3029a70cd25dbe330eb1f77dcbfaf1" + integrity sha512-69XQh3k+dtGa1p+7RaR57IuG3rCko96xr/nUfN4yDYBXbTYICiWcOpsFKLN2GtGE9cyIljE+f1exnaYt9MvM+Q== dependencies: - npm-normalize-package-bin "^5.0.0" - -npm-install-checks@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-8.0.0.tgz#f5d18e909bb8318d85093e9d8f36ac427c1cbe30" - integrity sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA== - dependencies: - semver "^7.1.1" - -npm-normalize-package-bin@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz#2b207ff260f2e525ddce93356614e2f736728f89" - integrity sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag== - -npm-package-arg@13.0.2, npm-package-arg@^13.0.0: - version "13.0.2" - resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-13.0.2.tgz#72a80f2afe8329860e63854489415e9e9a2f78a7" - integrity sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA== - dependencies: - hosted-git-info "^9.0.0" - proc-log "^6.0.0" + hosted-git-info "^10.1.0" + proc-log "^7.0.0" semver "^7.3.5" - validate-npm-package-name "^7.0.0" - -npm-packlist@^10.0.1: - version "10.0.3" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-10.0.3.tgz#e22c039357faf81a75d1b0cdf53dd113f2bed9c7" - integrity sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg== - dependencies: - ignore-walk "^8.0.0" - proc-log "^6.0.0" - -npm-pick-manifest@^11.0.1: - version "11.0.3" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz#76cf6593a351849006c36b38a7326798e2a76d13" - integrity sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ== - dependencies: - npm-install-checks "^8.0.0" - npm-normalize-package-bin "^5.0.0" - npm-package-arg "^13.0.0" - semver "^7.3.5" - -npm-registry-fetch@^19.0.0: - version "19.1.1" - resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz#51e96d21f409a9bc4f96af218a8603e884459024" - integrity sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw== - dependencies: - "@npmcli/redact" "^4.0.0" - jsonparse "^1.3.1" - make-fetch-happen "^15.0.0" - minipass "^7.0.2" - minipass-fetch "^5.0.0" - minizlib "^3.0.1" - npm-package-arg "^13.0.0" - proc-log "^6.0.0" + validate-npm-package-name "^8.0.0" nth-check@^2.1.1: version "2.1.1" @@ -4811,6 +4393,16 @@ object.assign@^4.1.7: has-symbols "^1.1.0" object-keys "^1.1.1" +object.entries@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.9.tgz#e4770a6a1444afb61bd39f984018b5bede25f8b3" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-object-atoms "^1.1.1" + object.fromentries@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" @@ -4841,9 +4433,9 @@ object.values@^1.2.1: es-object-atoms "^1.0.0" obug@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.1.tgz#2cba74ff241beb77d63055ddf4cd1e9f90b538be" - integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== + version "2.1.4" + resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.4.tgz#9090d8a548a522517915d2aa6aae907197ac6cf8" + integrity sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA== on-finished@^2.4.1: version "2.4.1" @@ -4878,10 +4470,10 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" -ora@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/ora/-/ora-9.0.0.tgz#945236f5ce78a024cf4c25df6c46ecd09ab6e685" - integrity sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A== +ora@9.4.1: + version "9.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-9.4.1.tgz#ba7644f3c7c92a8f830fbc48ca770b9eaf4bc55c" + integrity sha512-6VlU9MLXbjVQD04AZCMX28hVtA5bUoadvUqO76MUCVA0ilwJbMiHsITRPfyVm6p/BC0Av/BXMujx39WCe1LEqw== dependencies: chalk "^5.6.2" cli-cursor "^5.0.0" @@ -4889,9 +4481,8 @@ ora@9.0.0: is-interactive "^2.0.0" is-unicode-supported "^2.1.0" log-symbols "^7.0.1" - stdin-discarder "^0.2.2" + stdin-discarder "^0.3.2" string-width "^8.1.0" - strip-ansi "^7.1.2" ordered-binary@^1.5.3: version "1.6.1" @@ -4899,14 +4490,43 @@ ordered-binary@^1.5.3: integrity sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w== own-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" - integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + version "1.0.2" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.2.tgz#31448ec1f781ecb1447f6f6aa0d6534222af59de" + integrity sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg== dependencies: - get-intrinsic "^1.2.6" + call-bound "^1.0.4" + get-intrinsic "^1.3.0" object-keys "^1.1.1" safe-push-apply "^1.0.0" +oxc-parser@0.142.0: + version "0.142.0" + resolved "https://registry.yarnpkg.com/oxc-parser/-/oxc-parser-0.142.0.tgz#be0421d3e08eed60b56f280b6f57a7d123b51ef8" + integrity sha512-kKR+jPiRJYJDexVoziIg/FVGvr1fT1FZSSJOk6tVoMKKSlsf1Cso+cgGCJkOEDWOP174vRntCPFKg+AS7InWvw== + dependencies: + "@oxc-project/types" "^0.142.0" + optionalDependencies: + "@oxc-parser/binding-android-arm-eabi" "0.142.0" + "@oxc-parser/binding-android-arm64" "0.142.0" + "@oxc-parser/binding-darwin-arm64" "0.142.0" + "@oxc-parser/binding-darwin-x64" "0.142.0" + "@oxc-parser/binding-freebsd-x64" "0.142.0" + "@oxc-parser/binding-linux-arm-gnueabihf" "0.142.0" + "@oxc-parser/binding-linux-arm-musleabihf" "0.142.0" + "@oxc-parser/binding-linux-arm64-gnu" "0.142.0" + "@oxc-parser/binding-linux-arm64-musl" "0.142.0" + "@oxc-parser/binding-linux-ppc64-gnu" "0.142.0" + "@oxc-parser/binding-linux-riscv64-gnu" "0.142.0" + "@oxc-parser/binding-linux-riscv64-musl" "0.142.0" + "@oxc-parser/binding-linux-s390x-gnu" "0.142.0" + "@oxc-parser/binding-linux-x64-gnu" "0.142.0" + "@oxc-parser/binding-linux-x64-musl" "0.142.0" + "@oxc-parser/binding-openharmony-arm64" "0.142.0" + "@oxc-parser/binding-wasm32-wasi" "0.142.0" + "@oxc-parser/binding-win32-arm64-msvc" "0.142.0" + "@oxc-parser/binding-win32-ia32-msvc" "0.142.0" + "@oxc-parser/binding-win32-x64-msvc" "0.142.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -4956,11 +4576,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-map@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-7.0.4.tgz#b81814255f542e252d5729dca4d66e5ec14935b8" - integrity sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ== - p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" @@ -4971,36 +4586,6 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pacote@21.0.4: - version "21.0.4" - resolved "https://registry.yarnpkg.com/pacote/-/pacote-21.0.4.tgz#59cd2a2b5a4c8c1b625f33991a96b136d1c05d95" - integrity sha512-RplP/pDW0NNNDh3pnaoIWYPvNenS7UqMbXyvMqJczosiFWTeGGwJC2NQBLqKf4rGLFfwCOnntw1aEp9Jiqm1MA== - dependencies: - "@npmcli/git" "^7.0.0" - "@npmcli/installed-package-contents" "^4.0.0" - "@npmcli/package-json" "^7.0.0" - "@npmcli/promise-spawn" "^9.0.0" - "@npmcli/run-script" "^10.0.0" - cacache "^20.0.0" - fs-minipass "^3.0.0" - minipass "^7.0.2" - npm-package-arg "^13.0.0" - npm-packlist "^10.0.1" - npm-pick-manifest "^11.0.1" - npm-registry-fetch "^19.0.0" - proc-log "^6.0.0" - promise-retry "^2.0.1" - sigstore "^4.0.0" - ssri "^13.0.0" - tar "^7.4.3" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -5019,12 +4604,12 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse5-html-rewriting-stream@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz#3f442e5b5811a5456e2a56b68ea44ef153b44d92" - integrity sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw== +parse5-html-rewriting-stream@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.1.tgz#4472a20f2ce1d70022763b49a40b8da7d3d52cb9" + integrity sha512-NaRku2aMpUN1Sh1Gyk1KWUh2A7EJx2c6qYzvwsPtqhoHoaURshdrceYK3LunVCm3WHhm6FS7Vcczbvdh3/UIVw== dependencies: - entities "^6.0.0" + entities "^8.0.0" parse5 "^8.0.0" parse5-sax-parser "^8.0.0" @@ -5036,11 +4621,11 @@ parse5-sax-parser@^8.0.0: parse5 "^8.0.0" parse5@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-8.0.0.tgz#aceb267f6b15f9b6e6ba9e35bfdd481fc2167b12" - integrity sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA== + version "8.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-8.0.1.tgz#f43bcd2cd683efe084075333e9ce0da7d06da31e" + integrity sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw== dependencies: - entities "^6.0.0" + entities "^8.0.0" parseurl@^1.3.3: version "1.3.3" @@ -5067,18 +4652,10 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.1.tgz#4b6572376cfd8b811fca9cd1f5c24b3cbac0fe10" - integrity sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA== - dependencies: - lru-cache "^11.0.0" - minipass "^7.1.2" - path-to-regexp@^8.0.0: - version "8.3.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" - integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA== + version "8.4.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.4.2.tgz#795c420c4f7ca45c5b887366f622ee0c9852cccd" + integrity sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA== path-type@^3.0.0: version "3.0.0" @@ -5097,20 +4674,10 @@ picocolors@^1.1.1: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@4.0.3, picomatch@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" - integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pidtree@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" - integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== +picomatch@4.0.5, picomatch@^4.0.3, picomatch@^4.0.4, picomatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.5.tgz#51ea57a17d86f605f81039595fbc40ed06a55fab" + integrity sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A== pify@^2.3.0: version "2.3.0" @@ -5122,10 +4689,10 @@ pify@^3.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== -piscina@5.1.4: - version "5.1.4" - resolved "https://registry.yarnpkg.com/piscina/-/piscina-5.1.4.tgz#86ca2b8e42bcbfc258dc7b09d918ee04b2327a67" - integrity sha512-7uU4ZnKeQq22t9AsmHGD2w4OYQGonwFnTypDypaWi7Qr2EvQIFVtG8J5D/3bE7W123Wdc9+v4CZDu5hJXVCtBg== +piscina@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/piscina/-/piscina-5.2.0.tgz#3a9a568ab9e3a0556b5c94522ba305962de13e3b" + integrity sha512-DszUCKeVN/5G5QKo6jAVHL8fmKnkJvQ0ACiVgY7YGCq3TUB2oznAOayvZPIAdEThvhczkXR+qm3IHsNXpFCYfA== optionalDependencies: "@napi-rs/nice" "^1.0.4" @@ -5134,7 +4701,7 @@ pkce-challenge@^5.0.0: resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.1.tgz#3b4446865b17b1745e9ace2016a31f48ddf6230d" integrity sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ== -possible-typed-array-names@^1.0.0: +possible-typed-array-names@^1.0.0, possible-typed-array-names@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== @@ -5144,17 +4711,17 @@ postcss-media-query-parser@^0.2.3: resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244" integrity sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig== -postcss-value-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" - integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== +postcss-safe-parser@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz#36e4f7e608111a0ca940fd9712ce034718c40ec0" + integrity sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A== -postcss@^8.4.49, postcss@^8.5.6: - version "8.5.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" - integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== +postcss@^8.4.49, postcss@^8.5.17, postcss@^8.5.25: + version "8.5.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.26.tgz#6e75135780c7e10df3433bf2266c552d35c8c620" + integrity sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ== dependencies: - nanoid "^3.3.11" + nanoid "^3.3.17" picocolors "^1.1.1" source-map-js "^1.2.1" @@ -5164,28 +4731,20 @@ prelude-ls@^1.2.1: integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier@^3.4.2: - version "3.8.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173" - integrity sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg== + version "3.9.6" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.6.tgz#b3ea5146515d40fc53f18aa63f74dfab1e10dbf6" + integrity sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g== -proc-log@^6.0.0, proc-log@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-6.1.0.tgz#18519482a37d5198e231133a70144a50f21f0215" - integrity sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ== +proc-log@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-7.0.0.tgz#46c9cc943ed4127272b49b34faa8855b44e3a976" + integrity sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg== process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== -promise-retry@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" - integrity sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g== - dependencies: - err-code "^2.0.2" - retry "^0.12.0" - proxy-addr@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -5194,6 +4753,11 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +proxy-agent-negotiate@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-agent-negotiate/-/proxy-agent-negotiate-1.1.0.tgz#de7d37aede9d71e74346125d6f484fac8092b615" + integrity sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ== + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -5204,12 +4768,13 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qs@^6.14.0, qs@^6.14.1: - version "6.14.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.1.tgz#a41d85b9d3902f31d27861790506294881871159" - integrity sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ== +qs@^6.14.0, qs@^6.15.2: + version "6.15.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.15.3.tgz#76852132a58ed5c7c0ef67e4441b9bb5d6061b3b" + integrity sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A== dependencies: - side-channel "^1.1.0" + es-define-property "^1.0.1" + side-channel "^1.1.1" quick-lru@^4.0.1: version "4.0.1" @@ -5217,11 +4782,11 @@ quick-lru@^4.0.1: integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== range-parser@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.3.0.tgz#d7f19be812bb62721472b45d3be219ef09572b47" + integrity sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw== -raw-body@^3.0.0, raw-body@^3.0.1: +raw-body@^3.0.0, raw-body@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.2.tgz#3e3ada5ae5568f9095d84376fd3a49b8fb000a51" integrity sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA== @@ -5289,15 +4854,10 @@ readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readdirp@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" - integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== - readdirp@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-5.0.0.tgz#fbf1f71a727891d685bb1786f9ba74084f6e2f91" - integrity sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ== + version "5.1.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-5.1.1.tgz#520bca06f9d1ae1b96cc0800dbe84b983d19422c" + integrity sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA== redent@^3.0.0: version "3.0.0" @@ -5312,7 +4872,7 @@ reflect-metadata@^0.2.0: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== -reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: +reflect.getprototypeof@^1.0.10, reflect.getprototypeof@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== @@ -5348,20 +4908,28 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@1.22.11, resolve@^1.10.0, resolve@^1.22.4: - version "1.22.11" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" - integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== +resolve@^1.10.0: + version "1.22.12" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.12.tgz#f5b2a680897c69c238a13cd16b15671f8b73549f" + integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== dependencies: + es-errors "^1.3.0" is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +resolve@^2.0.0-next.6: + version "2.0.0-next.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.7.tgz#ba3b035d4b1ee7c522426eee73cabcb0fd5515dd" + integrity sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ== + dependencies: + es-errors "^1.3.0" + is-core-module "^2.16.2" + node-exports-info "^1.6.0" + object-keys "^1.1.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + restore-cursor@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" @@ -5370,71 +4938,81 @@ restore-cursor@^5.0.0: onetime "^7.0.0" signal-exit "^4.1.0" -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== - rfdc@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -rolldown@1.0.0-beta.58: - version "1.0.0-beta.58" - resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.0.0-beta.58.tgz#495a104a596ba7be1c5be77aa6be220c7d1188f3" - integrity sha512-v1FCjMZCan7f+xGAHBi+mqiE4MlH7I+SXEHSQSJoMOGNNB2UYtvMiejsq9YuUOiZjNeUeV/a21nSFbrUR+4ZCQ== +rolldown@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.2.0.tgz#02157b8547dd99917da192375c0d4f9357d89830" + integrity sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA== dependencies: - "@oxc-project/types" "=0.106.0" - "@rolldown/pluginutils" "1.0.0-beta.58" + "@oxc-project/types" "=0.140.0" + "@rolldown/pluginutils" "^1.0.0" optionalDependencies: - "@rolldown/binding-android-arm64" "1.0.0-beta.58" - "@rolldown/binding-darwin-arm64" "1.0.0-beta.58" - "@rolldown/binding-darwin-x64" "1.0.0-beta.58" - "@rolldown/binding-freebsd-x64" "1.0.0-beta.58" - "@rolldown/binding-linux-arm-gnueabihf" "1.0.0-beta.58" - "@rolldown/binding-linux-arm64-gnu" "1.0.0-beta.58" - "@rolldown/binding-linux-arm64-musl" "1.0.0-beta.58" - "@rolldown/binding-linux-x64-gnu" "1.0.0-beta.58" - "@rolldown/binding-linux-x64-musl" "1.0.0-beta.58" - "@rolldown/binding-openharmony-arm64" "1.0.0-beta.58" - "@rolldown/binding-wasm32-wasi" "1.0.0-beta.58" - "@rolldown/binding-win32-arm64-msvc" "1.0.0-beta.58" - "@rolldown/binding-win32-x64-msvc" "1.0.0-beta.58" + "@rolldown/binding-android-arm64" "1.2.0" + "@rolldown/binding-darwin-arm64" "1.2.0" + "@rolldown/binding-darwin-x64" "1.2.0" + "@rolldown/binding-freebsd-x64" "1.2.0" + "@rolldown/binding-linux-arm-gnueabihf" "1.2.0" + "@rolldown/binding-linux-arm64-gnu" "1.2.0" + "@rolldown/binding-linux-arm64-musl" "1.2.0" + "@rolldown/binding-linux-ppc64-gnu" "1.2.0" + "@rolldown/binding-linux-s390x-gnu" "1.2.0" + "@rolldown/binding-linux-x64-gnu" "1.2.0" + "@rolldown/binding-linux-x64-musl" "1.2.0" + "@rolldown/binding-openharmony-arm64" "1.2.0" + "@rolldown/binding-wasm32-wasi" "1.2.0" + "@rolldown/binding-win32-arm64-msvc" "1.2.0" + "@rolldown/binding-win32-x64-msvc" "1.2.0" -rollup@^4.43.0: - version "4.57.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.57.0.tgz#9fa13c1fb779d480038f45708b5e01b9449b6853" - integrity sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA== +rolldown@~1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.1.5.tgz#339aae250844351fc55b74e2652d3ebd6fba389d" + integrity sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA== dependencies: - "@types/estree" "1.0.8" + "@oxc-project/types" "=0.139.0" + "@rolldown/pluginutils" "^1.0.0" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.57.0" - "@rollup/rollup-android-arm64" "4.57.0" - "@rollup/rollup-darwin-arm64" "4.57.0" - "@rollup/rollup-darwin-x64" "4.57.0" - "@rollup/rollup-freebsd-arm64" "4.57.0" - "@rollup/rollup-freebsd-x64" "4.57.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.57.0" - "@rollup/rollup-linux-arm-musleabihf" "4.57.0" - "@rollup/rollup-linux-arm64-gnu" "4.57.0" - "@rollup/rollup-linux-arm64-musl" "4.57.0" - "@rollup/rollup-linux-loong64-gnu" "4.57.0" - "@rollup/rollup-linux-loong64-musl" "4.57.0" - "@rollup/rollup-linux-ppc64-gnu" "4.57.0" - "@rollup/rollup-linux-ppc64-musl" "4.57.0" - "@rollup/rollup-linux-riscv64-gnu" "4.57.0" - "@rollup/rollup-linux-riscv64-musl" "4.57.0" - "@rollup/rollup-linux-s390x-gnu" "4.57.0" - "@rollup/rollup-linux-x64-gnu" "4.57.0" - "@rollup/rollup-linux-x64-musl" "4.57.0" - "@rollup/rollup-openbsd-x64" "4.57.0" - "@rollup/rollup-openharmony-arm64" "4.57.0" - "@rollup/rollup-win32-arm64-msvc" "4.57.0" - "@rollup/rollup-win32-ia32-msvc" "4.57.0" - "@rollup/rollup-win32-x64-gnu" "4.57.0" - "@rollup/rollup-win32-x64-msvc" "4.57.0" - fsevents "~2.3.2" + "@rolldown/binding-android-arm64" "1.1.5" + "@rolldown/binding-darwin-arm64" "1.1.5" + "@rolldown/binding-darwin-x64" "1.1.5" + "@rolldown/binding-freebsd-x64" "1.1.5" + "@rolldown/binding-linux-arm-gnueabihf" "1.1.5" + "@rolldown/binding-linux-arm64-gnu" "1.1.5" + "@rolldown/binding-linux-arm64-musl" "1.1.5" + "@rolldown/binding-linux-ppc64-gnu" "1.1.5" + "@rolldown/binding-linux-s390x-gnu" "1.1.5" + "@rolldown/binding-linux-x64-gnu" "1.1.5" + "@rolldown/binding-linux-x64-musl" "1.1.5" + "@rolldown/binding-openharmony-arm64" "1.1.5" + "@rolldown/binding-wasm32-wasi" "1.1.5" + "@rolldown/binding-win32-arm64-msvc" "1.1.5" + "@rolldown/binding-win32-x64-msvc" "1.1.5" + +rolldown@~1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.2.3.tgz#103bdcbbd575d51265277b8b510f080827b6eb6f" + integrity sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A== + dependencies: + "@oxc-project/types" "=0.143.0" + "@rolldown/pluginutils" "^1.0.0" + optionalDependencies: + "@rolldown/binding-android-arm64" "1.2.3" + "@rolldown/binding-darwin-arm64" "1.2.3" + "@rolldown/binding-darwin-x64" "1.2.3" + "@rolldown/binding-freebsd-x64" "1.2.3" + "@rolldown/binding-linux-arm-gnueabihf" "1.2.3" + "@rolldown/binding-linux-arm64-gnu" "1.2.3" + "@rolldown/binding-linux-arm64-musl" "1.2.3" + "@rolldown/binding-linux-ppc64-gnu" "1.2.3" + "@rolldown/binding-linux-s390x-gnu" "1.2.3" + "@rolldown/binding-linux-x64-gnu" "1.2.3" + "@rolldown/binding-linux-x64-musl" "1.2.3" + "@rolldown/binding-openharmony-arm64" "1.2.3" + "@rolldown/binding-win32-arm64-msvc" "1.2.3" + "@rolldown/binding-win32-x64-msvc" "1.2.3" router@^2.2.0: version "2.2.0" @@ -5455,13 +5033,13 @@ rxjs@7.8.2, rxjs@~7.8.0: tslib "^2.1.0" safe-array-concat@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" - integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + version "1.1.4" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.4.tgz#a54cc9b61a57f33b42abad3cbdda3a2b38cc5719" + integrity sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg== dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - get-intrinsic "^1.2.6" + call-bind "^1.0.9" + call-bound "^1.0.4" + get-intrinsic "^1.3.0" has-symbols "^1.1.0" isarray "^2.0.5" @@ -5497,13 +5075,13 @@ safe-regex-test@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass@1.97.1: - version "1.97.1" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.1.tgz#f36e492baf8ccdd08d591b58d3d8b53ea35ab905" - integrity sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A== +sass@1.101.0: + version "1.101.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.101.0.tgz#c2db5bbf2f956be7277f6223b899d0d4be3c899b" + integrity sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw== dependencies: - chokidar "^4.0.0" - immutable "^5.0.2" + chokidar "^5.0.0" + immutable "^5.1.5" source-map-js ">=0.6.2 <2.0.0" optionalDependencies: "@parcel/watcher" "^2.4.1" @@ -5518,10 +5096,10 @@ seedrandom@^3.0.5: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== -semver@7.7.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.7.3: - version "7.7.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" - integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== +semver@7.8.5, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver@^7.7.3: + version "7.8.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69" + integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA== semver@^6.0.0, semver@^6.3.1: version "6.3.1" @@ -5603,13 +5181,13 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel-list@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" - integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== +side-channel-list@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.1.tgz#c2e0b5a14a540aebee3bbc6c3f8666cc9b509127" + integrity sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w== dependencies: es-errors "^1.3.0" - object-inspect "^1.13.3" + object-inspect "^1.13.4" side-channel-map@^1.0.1: version "1.0.1" @@ -5632,14 +5210,14 @@ side-channel-weakmap@^1.0.2: object-inspect "^1.13.3" side-channel-map "^1.0.1" -side-channel@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" - integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== +side-channel@^1.1.0, side-channel@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.1.tgz#ea02c62e05dc4bea67d4442f0fb71ee192f8e0ab" + integrity sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ== dependencies: es-errors "^1.3.0" - object-inspect "^1.13.3" - side-channel-list "^1.0.0" + object-inspect "^1.13.4" + side-channel-list "^1.0.1" side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" @@ -5653,18 +5231,6 @@ signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -sigstore@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/sigstore/-/sigstore-4.1.0.tgz#d34b92a544a05e003a2430209d26d8dfafd805a0" - integrity sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA== - dependencies: - "@sigstore/bundle" "^4.0.0" - "@sigstore/core" "^3.1.0" - "@sigstore/protobuf-specs" "^0.5.0" - "@sigstore/sign" "^4.1.0" - "@sigstore/tuf" "^4.0.1" - "@sigstore/verify" "^3.1.0" - slice-ansi@^7.1.0: version "7.1.2" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.2.tgz#adf7be70aa6d72162d907cd0e6d5c11f507b5403" @@ -5673,27 +5239,13 @@ slice-ansi@^7.1.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks-proxy-agent@^8.0.3: - version "8.0.5" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" - integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== +slice-ansi@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-8.0.0.tgz#22d0b66d18bc5c57f488bfcf36cbde3bef731537" + integrity sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg== dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - socks "^2.8.3" - -socks@^2.8.3: - version "2.8.7" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.7.tgz#e2fb1d9a603add75050a2067db8c381a0b5669ea" - integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A== - dependencies: - ip-address "^10.0.1" - smart-buffer "^4.2.0" + ansi-styles "^6.2.3" + is-fullwidth-code-point "^5.1.0" "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1: version "1.2.1" @@ -5740,9 +5292,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.22" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" - integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== + version "3.0.23" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz#b069e687b1291a32f126893ed76a27a745ee2133" + integrity sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw== split2@^3.0.0: version "3.2.2" @@ -5758,13 +5310,6 @@ split@^1.0.0: dependencies: through "2" -ssri@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-13.0.0.tgz#4226b303dc474003d88905f9098cb03361106c74" - integrity sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng== - dependencies: - minipass "^7.0.3" - stackback@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" @@ -5795,15 +5340,15 @@ statuses@^2.0.1, statuses@^2.0.2, statuses@~2.0.2: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== -std-env@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" - integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== +std-env@^4.0.0-rc.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-4.2.0.tgz#8ebe0ec60485668ab47227b312f4254cdf80c9d3" + integrity sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw== -stdin-discarder@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.2.2.tgz#390037f44c4ae1a1ae535c5fe38dc3aba8d997be" - integrity sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ== +stdin-discarder@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/stdin-discarder/-/stdin-discarder-0.3.2.tgz#998ab3b9a988661e6036a9bfdc96f43649e8e83e" + integrity sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A== stop-iteration-iterator@^1.1.0: version "1.1.0" @@ -5836,36 +5381,37 @@ string-width@^7.0.0, string-width@^7.2.0: get-east-asian-width "^1.0.0" strip-ansi "^7.1.0" -string-width@^8.0.0, string-width@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-8.1.0.tgz#9e9fb305174947cf45c30529414b5da916e9e8d1" - integrity sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg== +string-width@^8.1.0, string-width@^8.2.0, string-width@^8.2.1: + version "8.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-8.2.2.tgz#7310516493df575742fe98af6fae87d85d5ed0ac" + integrity sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg== dependencies: - get-east-asian-width "^1.3.0" - strip-ansi "^7.1.0" + get-east-asian-width "^1.5.0" + strip-ansi "^7.1.2" string.prototype.trim@^1.2.10: - version "1.2.10" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" - integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + version "1.2.11" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz#e6bd19cda3985d05a42dda31f3ddf4d35d3430e3" + integrity sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w== dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" + call-bind "^1.0.9" + call-bound "^1.0.4" define-data-property "^1.1.4" define-properties "^1.2.1" - es-abstract "^1.23.5" - es-object-atoms "^1.0.0" + es-abstract "^1.24.2" + es-object-atoms "^1.1.2" has-property-descriptors "^1.0.2" + safe-regex-test "^1.1.0" string.prototype.trimend@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" - integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + version "1.0.10" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz#be6bcf4f3fe0460bdeccdb2cf4f971b310f8346e" + integrity sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw== dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" + call-bind "^1.0.9" + call-bound "^1.0.4" define-properties "^1.2.1" - es-object-atoms "^1.0.0" + es-object-atoms "^1.1.2" string.prototype.trimstart@^1.0.8: version "1.0.8" @@ -5903,11 +5449,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: ansi-regex "^5.0.1" strip-ansi@^7.1.0, strip-ansi@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" - integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.2.0.tgz#d22a269522836a627af8d04b5c3fd2c7fa3e32e3" + integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== dependencies: - ansi-regex "^6.0.1" + ansi-regex "^6.2.2" strip-bom@^3.0.0: version "3.0.0" @@ -5921,7 +5467,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -5933,29 +5479,11 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -tar@^7.4.3, tar@^7.5.4: - version "7.5.7" - resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.7.tgz#adf99774008ba1c89819f15dbd6019c630539405" - integrity sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ== - dependencies: - "@isaacs/fs-minipass" "^4.0.0" - chownr "^3.0.0" - minipass "^7.1.2" - minizlib "^3.1.0" - yallist "^5.0.0" - text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -5991,30 +5519,23 @@ tinybench@^2.9.0: resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== -tinyexec@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.2.tgz#bdd2737fe2ba40bd6f918ae26642f264b99ca251" - integrity sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg== +tinyexec@^1.0.2, tinyexec@^1.2.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.3.0.tgz#aacc1dbb1d4e93e6ad8dd64944e09f9ad147a474" + integrity sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ== -tinyglobby@0.2.15, tinyglobby@^0.2.12, tinyglobby@^0.2.15: - version "0.2.15" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" - integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== +tinyglobby@0.2.17, tinyglobby@^0.2.15, tinyglobby@^0.2.17: + version "0.2.17" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== dependencies: fdir "^6.5.0" - picomatch "^4.0.3" + picomatch "^4.0.4" -tinyrainbow@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" - integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" +tinyrainbow@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.1.1.tgz#c0168387d3d8d70b6b3c2c0936de5fee738cea20" + integrity sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw== toidentifier@~1.0.1: version "1.0.1" @@ -6026,10 +5547,10 @@ trim-newlines@^3.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== -ts-api-utils@^2.1.0, ts-api-utils@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8" - integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA== +ts-api-utils@^2.1.0, ts-api-utils@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1" + integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== tsconfig-paths@^3.15.0: version "3.15.0" @@ -6046,15 +5567,6 @@ tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tuf-js@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tuf-js/-/tuf-js-4.1.0.tgz#ae4ef9afa456fcb4af103dc50a43bc031f066603" - integrity sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ== - dependencies: - "@tufjs/models" "4.1.0" - debug "^4.4.3" - make-fetch-happen "^15.0.1" - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -6077,12 +5589,12 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" - integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== +type-is@^2.0.1, type-is@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.1.0.tgz#71d1a7053293582e16ac9f3ebaf1ab9aa49e5570" + integrity sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA== dependencies: - content-type "^1.0.5" + content-type "^2.0.0" media-typer "^1.1.0" mime-types "^3.0.0" @@ -6120,16 +5632,16 @@ typed-array-byte-offset@^1.0.4: reflect.getprototypeof "^1.0.9" typed-array-length@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" - integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + version "1.0.8" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.8.tgz#0b70e982c9e9dafe2def6d6458ff4b3f2d2b6d70" + integrity sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g== dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - reflect.getprototypeof "^1.0.6" + call-bind "^1.0.9" + for-each "^0.3.5" + gopd "^1.2.0" + is-typed-array "^1.1.15" + possible-typed-array-names "^1.1.0" + reflect.getprototypeof "^1.0.10" typed-function@^4.2.1: version "4.2.2" @@ -6142,19 +5654,19 @@ typedarray@^0.0.6: integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== typescript-eslint@^8.33.1: - version "8.54.0" - resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.54.0.tgz#f4ef3b8882a5ddc2a41968e014194c178ab23f6a" - integrity sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ== + version "8.66.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.66.0.tgz#0809b6d25c8a0924690ba30dc1f05607093c11fb" + integrity sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw== dependencies: - "@typescript-eslint/eslint-plugin" "8.54.0" - "@typescript-eslint/parser" "8.54.0" - "@typescript-eslint/typescript-estree" "8.54.0" - "@typescript-eslint/utils" "8.54.0" + "@typescript-eslint/eslint-plugin" "8.66.0" + "@typescript-eslint/parser" "8.66.0" + "@typescript-eslint/typescript-estree" "8.66.0" + "@typescript-eslint/utils" "8.66.0" -typescript@~5.9.3: - version "5.9.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" - integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== +typescript@6.0.3, typescript@~6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.3.tgz#90251dc007916e972786cb94d74d15b185577d21" + integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== uglify-js@^3.1.4: version "3.19.3" @@ -6171,34 +5683,15 @@ unbox-primitive@^1.1.0: has-symbols "^1.1.0" which-boxed-primitive "^1.1.1" -undici@7.18.2: - version "7.18.2" - resolved "https://registry.yarnpkg.com/undici/-/undici-7.18.2.tgz#6cf724ef799a67d94fd55adf66b1e184176efcdf" - integrity sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw== - -unique-filename@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-5.0.0.tgz#8b17bbde1a7ca322dd1a1d23fe17c2b798c43f8f" - integrity sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg== - dependencies: - unique-slug "^6.0.0" - -unique-slug@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-6.0.0.tgz#f46fd688a9bd972fd356c23d95812a3a4862ed88" - integrity sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw== - dependencies: - imurmurhash "^0.1.4" - unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -update-browserslist-db@^1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" - integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== +update-browserslist-db@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.3.0.tgz#9ff2604d5b949051639c01a223a16619f8a2b2c7" + integrity sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -6215,7 +5708,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: +validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== @@ -6223,76 +5716,73 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validate-npm-package-name@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz#e57c3d721a4c8bbff454a246e7f7da811559ea0d" - integrity sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A== +validate-npm-package-name@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-8.0.0.tgz#fcd22bb2a1bb4830814f5f1ad127852ab06cf6e7" + integrity sha512-SCv6OOV6Xj2/3cXy3dGmADluJTNcL3o7hZAglNPTe+WYuEuvxgJzxPrSDLZhF+CwyQOubqgecjMmTJGMVLWjYQ== vary@^1, vary@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -vite@7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.0.tgz#066c7a835993a66e82004eac3e185d0d157fd658" - integrity sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg== +vite@8.1.5: + version "8.1.5" + resolved "https://registry.yarnpkg.com/vite/-/vite-8.1.5.tgz#ccffce3ee487b1886223b24ebb27b91674827d30" + integrity sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw== dependencies: - esbuild "^0.27.0" - fdir "^6.5.0" - picomatch "^4.0.3" - postcss "^8.5.6" - rollup "^4.43.0" - tinyglobby "^0.2.15" + lightningcss "^1.32.0" + picomatch "^4.0.5" + postcss "^8.5.17" + rolldown "~1.1.5" + tinyglobby "^0.2.17" optionalDependencies: fsevents "~2.3.3" -"vite@^6.0.0 || ^7.0.0": - version "7.3.1" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" - integrity sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA== +"vite@^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.2.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-8.2.1.tgz#6fc8d8bb843bd52353091fac978e194d4de5b31d" + integrity sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw== dependencies: - esbuild "^0.27.0" - fdir "^6.5.0" - picomatch "^4.0.3" - postcss "^8.5.6" - rollup "^4.43.0" - tinyglobby "^0.2.15" + lightningcss "^1.33.0" + picomatch "^4.0.5" + postcss "^8.5.25" + rolldown "~1.2.1" + tinyglobby "^0.2.17" optionalDependencies: fsevents "~2.3.3" vitest@^4.0.8: - version "4.0.18" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.18.tgz#56f966353eca0b50f4df7540cd4350ca6d454a05" - integrity sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ== + version "4.1.10" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.1.10.tgz#7e9285efe264b1167050b7a3a7ff34788e1b7afc" + integrity sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw== dependencies: - "@vitest/expect" "4.0.18" - "@vitest/mocker" "4.0.18" - "@vitest/pretty-format" "4.0.18" - "@vitest/runner" "4.0.18" - "@vitest/snapshot" "4.0.18" - "@vitest/spy" "4.0.18" - "@vitest/utils" "4.0.18" - es-module-lexer "^1.7.0" - expect-type "^1.2.2" + "@vitest/expect" "4.1.10" + "@vitest/mocker" "4.1.10" + "@vitest/pretty-format" "4.1.10" + "@vitest/runner" "4.1.10" + "@vitest/snapshot" "4.1.10" + "@vitest/spy" "4.1.10" + "@vitest/utils" "4.1.10" + es-module-lexer "^2.0.0" + expect-type "^1.3.0" magic-string "^0.30.21" obug "^2.1.1" pathe "^2.0.3" picomatch "^4.0.3" - std-env "^3.10.0" + std-env "^4.0.0-rc.1" tinybench "^2.9.0" tinyexec "^1.0.2" tinyglobby "^0.2.15" - tinyrainbow "^3.0.3" - vite "^6.0.0 || ^7.0.0" + tinyrainbow "^3.1.0" + vite "^6.0.0 || ^7.0.0 || ^8.0.0" why-is-node-running "^2.3.0" -watchpack@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.0.tgz#fa115d5ccaa4bf3aa594f586257c0bc4768939fd" - integrity sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA== +watchpack@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.5.2.tgz#e12e82d84674266fc1c6dbfe38891b92ff0522ec" + integrity sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg== dependencies: - glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" weak-lru-cache@^1.2.2: @@ -6341,12 +5831,12 @@ which-collection@^1.0.2: is-weakset "^2.0.3" which-typed-array@^1.1.16, which-typed-array@^1.1.19: - version "1.1.20" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.20.tgz#3fdb7adfafe0ea69157b1509f3a1cd892bd1d122" - integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== + version "1.1.22" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.22.tgz#8f3cc78aefb40b437346dd40a1dbfa5d1da43fe9" + integrity sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.8" + call-bind "^1.0.9" call-bound "^1.0.4" for-each "^0.3.5" get-proto "^1.0.1" @@ -6360,13 +5850,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -which@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/which/-/which-6.0.0.tgz#a3a721a14cdd9b991a722e493c177eeff82ff32a" - integrity sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg== - dependencies: - isexe "^3.1.1" - why-is-node-running@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" @@ -6385,14 +5868,14 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== +wrap-ansi@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-10.0.0.tgz#b83ddcc14dbc5596f1b07e153bf6f863c1acbb57" + integrity sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.2.3" + string-width "^8.2.0" + strip-ansi "^7.1.2" wrap-ansi@^7.0.0: version "7.0.0" @@ -6427,25 +5910,15 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yallist@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" - integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== - -yaml@^2.8.1: - version "2.8.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.2.tgz#5694f25eca0ce9c3e7a9d9e00ce0ddabbd9e35c5" - integrity sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A== +yaml@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.9.0.tgz#78274afd93598a1dfdd6130df6a566defcbf9aa4" + integrity sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA== yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.9" @@ -6457,7 +5930,7 @@ yargs-parser@^22.0.0: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-22.0.0.tgz#87b82094051b0567717346ecd00fd14804b357c8" integrity sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw== -yargs@18.0.0, yargs@^18.0.0: +yargs@18.0.0: version "18.0.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-18.0.0.tgz#6c84259806273a746b09f579087b68a3c2d25bd1" integrity sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg== @@ -6470,9 +5943,9 @@ yargs@18.0.0, yargs@^18.0.0: yargs-parser "^22.0.0" yargs@^16.0.0, yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + version "16.2.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.2.tgz#c56731dca0d2788ae0866dd3c83907d6bab85f7d" + integrity sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w== dependencies: cliui "^7.0.2" escalade "^3.1.1" @@ -6482,32 +5955,34 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^18.0.0: + version "18.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-18.1.0.tgz#cd7e98c703ef51695bbbf062ed58f28e94291b56" + integrity sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg== + dependencies: + cliui "^9.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + string-width "^8.2.1" + y18n "^5.0.5" + yargs-parser "^22.0.0" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yoctocolors-cjs@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" - integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== - yoctocolors@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.2.tgz#d795f54d173494e7d8db93150cec0ed7f678c83a" - integrity sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug== + version "2.2.0" + resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.2.0.tgz#c4b68ee477f3982c33e4de24a5aa4a354be506d3" + integrity sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg== -zod-to-json-schema@^3.25.0: - version "3.25.1" - resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba" - integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA== +zod-to-json-schema@^3.25.1: + version "3.25.2" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz#3fa799a7badd554541472fb65843fdc460b2e5aa" + integrity sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA== -zod@4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.5.tgz#aeb269a6f9fc259b1212c348c7c5432aaa474d2a" - integrity sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g== - -"zod@^3.25 || ^4.0": - version "4.3.6" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a" - integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg== +zod@4.4.3, "zod@^3.25 || ^4.0", zod@^4.0.10: + version "4.4.3" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.4.3.tgz#b680f172885d18bbebf21a834ea25e55a1bbf356" + integrity sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==
    Units {{ s.units }}