Merge branch 'Part-DB:master' into update-script

This commit is contained in:
d-buchmann 2025-01-16 07:43:00 +01:00 committed by GitHub
commit 468d2c1aad
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 1580 additions and 568 deletions

0
.env.dev Normal file
View file

View file

@ -1 +1 @@
1.14.5 1.15.1

View file

@ -20,7 +20,7 @@
import {Controller} from "@hotwired/stimulus"; import {Controller} from "@hotwired/stimulus";
//import * as ZXing from "@zxing/library"; //import * as ZXing from "@zxing/library";
import {Html5QrcodeScanner, Html5Qrcode} from "html5-qrcode"; import {Html5QrcodeScanner, Html5Qrcode} from "@part-db/html5-qrcode";
/* stimulusFetch: 'lazy' */ /* stimulusFetch: 'lazy' */
export default class extends Controller { export default class extends Controller {
@ -50,7 +50,7 @@ export default class extends Controller {
}); });
this._scanner = new Html5QrcodeScanner(this.element.id, { this._scanner = new Html5QrcodeScanner(this.element.id, {
fps: 2, fps: 10,
qrbox: qrboxFunction, qrbox: qrboxFunction,
experimentalFeatures: { experimentalFeatures: {
//This option improves reading quality on android chrome //This option improves reading quality on android chrome
@ -61,6 +61,11 @@ export default class extends Controller {
this._scanner.render(this.onScanSuccess.bind(this)); this._scanner.render(this.onScanSuccess.bind(this));
} }
disconnect() {
this._scanner.pause();
this._scanner.clear();
}
onScanSuccess(decodedText, decodedResult) { onScanSuccess(decodedText, decodedResult) {
//Put our decoded Text into the input box //Put our decoded Text into the input box
document.getElementById('scan_dialog_input').value = decodedText; document.getElementById('scan_dialog_input').value = decodedText;

View file

@ -44,4 +44,18 @@ import "./register_events";
import "./tristate_checkboxes"; import "./tristate_checkboxes";
//Define jquery globally //Define jquery globally
window.$ = window.jQuery = require("jquery") window.$ = window.jQuery = require("jquery");
//Use the local WASM file for the ZXing library
import {
setZXingModuleOverrides,
} from "barcode-detector/pure";
import wasmFile from "../../node_modules/zxing-wasm/dist/reader/zxing_reader.wasm";
setZXingModuleOverrides({
locateFile: (path, prefix) => {
if (path.endsWith(".wasm")) {
return wasmFile;
}
return prefix + path;
},
});

View file

@ -4,6 +4,10 @@
use App\Kernel; use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_dir(dirname(__DIR__).'/vendor')) {
throw new LogicException('Dependencies are missing. Try running "composer install".');
}
//Increase xdebug.max_nesting_level to 1000 if required (see issue #411) //Increase xdebug.max_nesting_level to 1000 if required (see issue #411)
//Check if xdebug extension is active, and xdebug.max_nesting_level is set to 256 or lower //Check if xdebug extension is active, and xdebug.max_nesting_level is set to 256 or lower
if (extension_loaded('xdebug') && ((int) ini_get('xdebug.max_nesting_level')) <= 256) { if (extension_loaded('xdebug') && ((int) ini_get('xdebug.max_nesting_level')) <= 256) {

304
composer.lock generated
View file

@ -2869,16 +2869,16 @@
}, },
{ {
"name": "dompdf/dompdf", "name": "dompdf/dompdf",
"version": "v3.0.1", "version": "v3.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/dompdf/dompdf.git", "url": "https://github.com/dompdf/dompdf.git",
"reference": "2d622faf9aa1f8f7f24dd094e49b5cf6c0c5d4e6" "reference": "baf4084b27c7f4b5b7a221b19a94d11327664eb8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/2d622faf9aa1f8f7f24dd094e49b5cf6c0c5d4e6", "url": "https://api.github.com/repos/dompdf/dompdf/zipball/baf4084b27c7f4b5b7a221b19a94d11327664eb8",
"reference": "2d622faf9aa1f8f7f24dd094e49b5cf6c0c5d4e6", "reference": "baf4084b27c7f4b5b7a221b19a94d11327664eb8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2894,7 +2894,7 @@
"ext-json": "*", "ext-json": "*",
"ext-zip": "*", "ext-zip": "*",
"mockery/mockery": "^1.3", "mockery/mockery": "^1.3",
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10", "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11",
"squizlabs/php_codesniffer": "^3.5", "squizlabs/php_codesniffer": "^3.5",
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
}, },
@ -2927,9 +2927,9 @@
"homepage": "https://github.com/dompdf/dompdf", "homepage": "https://github.com/dompdf/dompdf",
"support": { "support": {
"issues": "https://github.com/dompdf/dompdf/issues", "issues": "https://github.com/dompdf/dompdf/issues",
"source": "https://github.com/dompdf/dompdf/tree/v3.0.1" "source": "https://github.com/dompdf/dompdf/tree/v3.0.2"
}, },
"time": "2024-12-05T14:59:38+00:00" "time": "2024-12-27T20:27:37+00:00"
}, },
{ {
"name": "dompdf/php-font-lib", "name": "dompdf/php-font-lib",
@ -8052,16 +8052,16 @@
}, },
{ {
"name": "spomky-labs/pki-framework", "name": "spomky-labs/pki-framework",
"version": "1.2.1", "version": "1.2.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Spomky-Labs/pki-framework.git", "url": "https://github.com/Spomky-Labs/pki-framework.git",
"reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6" "reference": "5ac374c3e295c8b917208ff41b4d30f76668478c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/0b10c8b53366729417d6226ae89a665f9e2d61b6", "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/5ac374c3e295c8b917208ff41b4d30f76668478c",
"reference": "0b10c8b53366729417d6226ae89a665f9e2d61b6", "reference": "5ac374c3e295c8b917208ff41b4d30f76668478c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8070,21 +8070,19 @@
"php": ">=8.1" "php": ">=8.1"
}, },
"require-dev": { "require-dev": {
"ekino/phpstan-banned-code": "^1.0", "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0",
"ext-gmp": "*", "ext-gmp": "*",
"ext-openssl": "*", "ext-openssl": "*",
"infection/infection": "^0.28", "infection/infection": "^0.28|^0.29",
"php-parallel-lint/php-parallel-lint": "^1.3", "php-parallel-lint/php-parallel-lint": "^1.3",
"phpstan/extension-installer": "^1.3", "phpstan/extension-installer": "^1.3|^2.0",
"phpstan/phpstan": "^1.8", "phpstan/phpstan": "^1.8|^2.0",
"phpstan/phpstan-beberlei-assert": "^1.0", "phpstan/phpstan-deprecation-rules": "^1.0|^2.0",
"phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.1|^2.0",
"phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.3|^2.0",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^10.1|^11.0", "phpunit/phpunit": "^10.1|^11.0",
"rector/rector": "^1.0", "rector/rector": "^1.0|^2.0",
"roave/security-advisories": "dev-latest", "roave/security-advisories": "dev-latest",
"symfony/phpunit-bridge": "^6.4|^7.0",
"symfony/string": "^6.4|^7.0", "symfony/string": "^6.4|^7.0",
"symfony/var-dumper": "^6.4|^7.0", "symfony/var-dumper": "^6.4|^7.0",
"symplify/easy-coding-standard": "^12.0" "symplify/easy-coding-standard": "^12.0"
@ -8147,7 +8145,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/Spomky-Labs/pki-framework/issues", "issues": "https://github.com/Spomky-Labs/pki-framework/issues",
"source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.1" "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.2.2"
}, },
"funding": [ "funding": [
{ {
@ -8159,7 +8157,7 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-03-30T18:03:49+00:00" "time": "2025-01-03T09:35:48+00:00"
}, },
{ {
"name": "symfony/apache-pack", "name": "symfony/apache-pack",
@ -8579,16 +8577,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v6.4.15", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd" "reference": "799445db3f15768ecc382ac5699e6da0520a0a04"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", "url": "https://api.github.com/repos/symfony/console/zipball/799445db3f15768ecc382ac5699e6da0520a0a04",
"reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", "reference": "799445db3f15768ecc382ac5699e6da0520a0a04",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8653,7 +8651,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v6.4.15" "source": "https://github.com/symfony/console/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -8669,7 +8667,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-06T14:19:14+00:00" "time": "2024-12-07T12:07:30+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
@ -8886,16 +8884,16 @@
}, },
{ {
"name": "symfony/doctrine-bridge", "name": "symfony/doctrine-bridge",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/doctrine-bridge.git", "url": "https://github.com/symfony/doctrine-bridge.git",
"reference": "429a4b6786901afcc085ee16dc3f2be621f33488" "reference": "2ba7e747a944b69f9f583c35173560afebbff995"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/429a4b6786901afcc085ee16dc3f2be621f33488", "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/2ba7e747a944b69f9f583c35173560afebbff995",
"reference": "429a4b6786901afcc085ee16dc3f2be621f33488", "reference": "2ba7e747a944b69f9f583c35173560afebbff995",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8974,7 +8972,7 @@
"description": "Provides integration for Doctrine with various Symfony components", "description": "Provides integration for Doctrine with various Symfony components",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.16" "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -8990,7 +8988,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-25T12:00:20+00:00" "time": "2024-12-18T10:42:42+00:00"
}, },
{ {
"name": "symfony/dotenv", "name": "symfony/dotenv",
@ -9068,16 +9066,16 @@
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
"version": "v6.4.14", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/error-handler.git", "url": "https://github.com/symfony/error-handler.git",
"reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9" "reference": "37ad2380e8c1a8cf62a1200a5c10080b679b446c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/9e024324511eeb00983ee76b9aedc3e6ecd993d9", "url": "https://api.github.com/repos/symfony/error-handler/zipball/37ad2380e8c1a8cf62a1200a5c10080b679b446c",
"reference": "9e024324511eeb00983ee76b9aedc3e6ecd993d9", "reference": "37ad2380e8c1a8cf62a1200a5c10080b679b446c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9123,7 +9121,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code", "description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/error-handler/tree/v6.4.14" "source": "https://github.com/symfony/error-handler/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -9139,7 +9137,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-05T15:34:40+00:00" "time": "2024-12-06T13:30:51+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
@ -9429,16 +9427,16 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v6.4.13", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "daea9eca0b08d0ed1dc9ab702a46128fd1be4958" "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/daea9eca0b08d0ed1dc9ab702a46128fd1be4958", "url": "https://api.github.com/repos/symfony/finder/zipball/1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7",
"reference": "daea9eca0b08d0ed1dc9ab702a46128fd1be4958", "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9473,7 +9471,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v6.4.13" "source": "https://github.com/symfony/finder/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -9489,7 +9487,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-10-01T08:30:56+00:00" "time": "2024-12-29T13:51:37+00:00"
}, },
{ {
"name": "symfony/flex", "name": "symfony/flex",
@ -9658,16 +9656,16 @@
}, },
{ {
"name": "symfony/framework-bundle", "name": "symfony/framework-bundle",
"version": "v6.4.13", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/framework-bundle.git", "url": "https://github.com/symfony/framework-bundle.git",
"reference": "e8b0bd921f9bd35ea4d1508067c3f3f6e2036418" "reference": "17d8ae2e7aa77154f942e8ac48849ac718b0963f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/framework-bundle/zipball/e8b0bd921f9bd35ea4d1508067c3f3f6e2036418", "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/17d8ae2e7aa77154f942e8ac48849ac718b0963f",
"reference": "e8b0bd921f9bd35ea4d1508067c3f3f6e2036418", "reference": "17d8ae2e7aa77154f942e8ac48849ac718b0963f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -9787,7 +9785,7 @@
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/framework-bundle/tree/v6.4.13" "source": "https://github.com/symfony/framework-bundle/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -9803,27 +9801,27 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-10-25T15:07:50+00:00" "time": "2024-12-19T14:08:41+00:00"
}, },
{ {
"name": "symfony/http-client", "name": "symfony/http-client",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-client.git", "url": "https://github.com/symfony/http-client.git",
"reference": "60a113666fa67e598abace38e5f46a0954d8833d" "reference": "88898d842eb29d7e1a903724c94e90a6ca9c0509"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/60a113666fa67e598abace38e5f46a0954d8833d", "url": "https://api.github.com/repos/symfony/http-client/zipball/88898d842eb29d7e1a903724c94e90a6ca9c0509",
"reference": "60a113666fa67e598abace38e5f46a0954d8833d", "reference": "88898d842eb29d7e1a903724c94e90a6ca9c0509",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.1",
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/deprecation-contracts": "^2.5|^3", "symfony/deprecation-contracts": "^2.5|^3",
"symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/http-client-contracts": "~3.4.4|^3.5.2",
"symfony/service-contracts": "^2.5|^3" "symfony/service-contracts": "^2.5|^3"
}, },
"conflict": { "conflict": {
@ -9880,7 +9878,7 @@
"http" "http"
], ],
"support": { "support": {
"source": "https://github.com/symfony/http-client/tree/v6.4.16" "source": "https://github.com/symfony/http-client/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -9896,7 +9894,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-27T11:52:33+00:00" "time": "2024-12-18T12:18:31+00:00"
}, },
{ {
"name": "symfony/http-client-contracts", "name": "symfony/http-client-contracts",
@ -10055,16 +10053,16 @@
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0" "reference": "c5647393c5ce11833d13e4b70fff4b571d4ac710"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/c5647393c5ce11833d13e4b70fff4b571d4ac710",
"reference": "8838b5b21d807923b893ccbfc2cbeda0f1bc00f0", "reference": "c5647393c5ce11833d13e4b70fff4b571d4ac710",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10149,7 +10147,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v6.4.16" "source": "https://github.com/symfony/http-kernel/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -10165,7 +10163,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-27T12:49:36+00:00" "time": "2024-12-31T14:49:31+00:00"
}, },
{ {
"name": "symfony/intl", "name": "symfony/intl",
@ -10332,16 +10330,16 @@
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
"version": "v6.4.13", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "1de1cf14d99b12c7ebbb850491ec6ae3ed468855" "reference": "ea87c8850a54ff039d3e0ab4ae5586dd4e6c0232"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/1de1cf14d99b12c7ebbb850491ec6ae3ed468855", "url": "https://api.github.com/repos/symfony/mime/zipball/ea87c8850a54ff039d3e0ab4ae5586dd4e6c0232",
"reference": "1de1cf14d99b12c7ebbb850491ec6ae3ed468855", "reference": "ea87c8850a54ff039d3e0ab4ae5586dd4e6c0232",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -10397,7 +10395,7 @@
"mime-type" "mime-type"
], ],
"support": { "support": {
"source": "https://github.com/symfony/mime/tree/v6.4.13" "source": "https://github.com/symfony/mime/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -10413,7 +10411,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-10-25T15:07:50+00:00" "time": "2024-12-02T11:09:41+00:00"
}, },
{ {
"name": "symfony/monolog-bridge", "name": "symfony/monolog-bridge",
@ -11726,16 +11724,16 @@
}, },
{ {
"name": "symfony/property-info", "name": "symfony/property-info",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/property-info.git", "url": "https://github.com/symfony/property-info.git",
"reference": "e4782ec1c2b6896e820896357f6a3d02249e63eb" "reference": "38b125d78e67668159f75383a293ec0c5d3f2963"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/property-info/zipball/e4782ec1c2b6896e820896357f6a3d02249e63eb", "url": "https://api.github.com/repos/symfony/property-info/zipball/38b125d78e67668159f75383a293ec0c5d3f2963",
"reference": "e4782ec1c2b6896e820896357f6a3d02249e63eb", "reference": "38b125d78e67668159f75383a293ec0c5d3f2963",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -11790,7 +11788,7 @@
"validator" "validator"
], ],
"support": { "support": {
"source": "https://github.com/symfony/property-info/tree/v6.4.16" "source": "https://github.com/symfony/property-info/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -11806,7 +11804,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-27T10:18:02+00:00" "time": "2024-12-26T19:01:29+00:00"
}, },
{ {
"name": "symfony/psr-http-message-bridge", "name": "symfony/psr-http-message-bridge",
@ -13051,16 +13049,16 @@
}, },
{ {
"name": "symfony/twig-bridge", "name": "symfony/twig-bridge",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/twig-bridge.git", "url": "https://github.com/symfony/twig-bridge.git",
"reference": "32ec012ed4f6426441a66014471bdb26674744be" "reference": "238e1aac992b5231c66faf10131ace7bdba97065"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/32ec012ed4f6426441a66014471bdb26674744be", "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/238e1aac992b5231c66faf10131ace7bdba97065",
"reference": "32ec012ed4f6426441a66014471bdb26674744be", "reference": "238e1aac992b5231c66faf10131ace7bdba97065",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13140,7 +13138,7 @@
"description": "Provides integration for Twig with various Symfony components", "description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/twig-bridge/tree/v6.4.16" "source": "https://github.com/symfony/twig-bridge/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -13156,7 +13154,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-25T11:59:11+00:00" "time": "2024-12-19T14:08:41+00:00"
}, },
{ {
"name": "symfony/twig-bundle", "name": "symfony/twig-bundle",
@ -13492,16 +13490,16 @@
}, },
{ {
"name": "symfony/validator", "name": "symfony/validator",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/validator.git", "url": "https://github.com/symfony/validator.git",
"reference": "9b0d1988b56511706bc91d96ead39acd77aaf34d" "reference": "a3c19a0e542d427c207e22242043ef35b5b99a2c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/validator/zipball/9b0d1988b56511706bc91d96ead39acd77aaf34d", "url": "https://api.github.com/repos/symfony/validator/zipball/a3c19a0e542d427c207e22242043ef35b5b99a2c",
"reference": "9b0d1988b56511706bc91d96ead39acd77aaf34d", "reference": "a3c19a0e542d427c207e22242043ef35b5b99a2c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -13569,7 +13567,7 @@
"description": "Provides tools to validate values", "description": "Provides tools to validate values",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/validator/tree/v6.4.16" "source": "https://github.com/symfony/validator/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -13585,7 +13583,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-27T09:48:51+00:00" "time": "2024-12-29T12:50:19+00:00"
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
@ -14911,16 +14909,16 @@
}, },
{ {
"name": "web-auth/webauthn-lib", "name": "web-auth/webauthn-lib",
"version": "4.9.1", "version": "4.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/web-auth/webauthn-lib.git", "url": "https://github.com/web-auth/webauthn-lib.git",
"reference": "fd7a0943c663b325e92ad562c2bcc943e77beeac" "reference": "008b25171c27cf4813420d0de31cc059bcc71f1a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/fd7a0943c663b325e92ad562c2bcc943e77beeac", "url": "https://api.github.com/repos/web-auth/webauthn-lib/zipball/008b25171c27cf4813420d0de31cc059bcc71f1a",
"reference": "fd7a0943c663b325e92ad562c2bcc943e77beeac", "reference": "008b25171c27cf4813420d0de31cc059bcc71f1a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -14985,7 +14983,7 @@
"webauthn" "webauthn"
], ],
"support": { "support": {
"source": "https://github.com/web-auth/webauthn-lib/tree/4.9.1" "source": "https://github.com/web-auth/webauthn-lib/tree/4.9.2"
}, },
"funding": [ "funding": [
{ {
@ -14997,20 +14995,20 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-07-16T18:36:36+00:00" "time": "2025-01-04T09:47:58+00:00"
}, },
{ {
"name": "web-auth/webauthn-symfony-bundle", "name": "web-auth/webauthn-symfony-bundle",
"version": "4.9.1", "version": "4.9.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/web-auth/webauthn-symfony-bundle.git", "url": "https://github.com/web-auth/webauthn-symfony-bundle.git",
"reference": "fa6dfa596db1cbf159079c0bb76d746ed84c4a26" "reference": "80aa16fa6f16ab8f017a4108ffcd2ecc12264c07"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/web-auth/webauthn-symfony-bundle/zipball/fa6dfa596db1cbf159079c0bb76d746ed84c4a26", "url": "https://api.github.com/repos/web-auth/webauthn-symfony-bundle/zipball/80aa16fa6f16ab8f017a4108ffcd2ecc12264c07",
"reference": "fa6dfa596db1cbf159079c0bb76d746ed84c4a26", "reference": "80aa16fa6f16ab8f017a4108ffcd2ecc12264c07",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15070,7 +15068,7 @@
"webauthn" "webauthn"
], ],
"support": { "support": {
"source": "https://github.com/web-auth/webauthn-symfony-bundle/tree/4.9.1" "source": "https://github.com/web-auth/webauthn-symfony-bundle/tree/4.9.2"
}, },
"funding": [ "funding": [
{ {
@ -15082,11 +15080,11 @@
"type": "patreon" "type": "patreon"
} }
], ],
"time": "2024-07-11T09:06:25+00:00" "time": "2025-01-04T09:38:56+00:00"
}, },
{ {
"name": "web-token/jwt-library", "name": "web-token/jwt-library",
"version": "3.4.6", "version": "3.4.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/web-token/jwt-library.git", "url": "https://github.com/web-token/jwt-library.git",
@ -15168,7 +15166,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/web-token/jwt-library/issues", "issues": "https://github.com/web-token/jwt-library/issues",
"source": "https://github.com/web-token/jwt-library/tree/3.4.6" "source": "https://github.com/web-token/jwt-library/tree/3.4.7"
}, },
"funding": [ "funding": [
{ {
@ -15649,16 +15647,16 @@
}, },
{ {
"name": "nikic/php-parser", "name": "nikic/php-parser",
"version": "v5.3.1", "version": "v5.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nikic/PHP-Parser.git", "url": "https://github.com/nikic/PHP-Parser.git",
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" "reference": "447a020a1f875a434d62f2a401f53b82a396e494"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494",
"reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "reference": "447a020a1f875a434d62f2a401f53b82a396e494",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15701,9 +15699,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nikic/PHP-Parser/issues", "issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0"
}, },
"time": "2024-10-08T18:51:32+00:00" "time": "2024-12-30T11:07:19+00:00"
}, },
{ {
"name": "phar-io/manifest", "name": "phar-io/manifest",
@ -15873,16 +15871,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "2.0.4", "version": "2.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "50d276fc3bf1430ec315f2f109bbde2769821524" "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/50d276fc3bf1430ec315f2f109bbde2769821524", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
"reference": "50d276fc3bf1430ec315f2f109bbde2769821524", "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -15927,7 +15925,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-12-17T17:14:01+00:00" "time": "2025-01-05T16:43:48+00:00"
}, },
{ {
"name": "phpstan/phpstan-doctrine", "name": "phpstan/phpstan-doctrine",
@ -16050,16 +16048,16 @@
}, },
{ {
"name": "phpstan/phpstan-symfony", "name": "phpstan/phpstan-symfony",
"version": "2.0.0", "version": "2.0.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan-symfony.git", "url": "https://github.com/phpstan/phpstan-symfony.git",
"reference": "1ef4dce2baabd464c2dd3109d051bad94efa1e79" "reference": "c08cd8e54a08d651bc402d304cfa161c3c3766c4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/1ef4dce2baabd464c2dd3109d051bad94efa1e79", "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/c08cd8e54a08d651bc402d304cfa161c3c3766c4",
"reference": "1ef4dce2baabd464c2dd3109d051bad94efa1e79", "reference": "c08cd8e54a08d651bc402d304cfa161c3c3766c4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -16115,9 +16113,9 @@
"description": "Symfony Framework extensions and rules for PHPStan", "description": "Symfony Framework extensions and rules for PHPStan",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan-symfony/issues", "issues": "https://github.com/phpstan/phpstan-symfony/issues",
"source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.0" "source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.1"
}, },
"time": "2024-11-06T10:13:40+00:00" "time": "2025-01-04T13:58:15+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@ -16543,21 +16541,21 @@
}, },
{ {
"name": "rector/rector", "name": "rector/rector",
"version": "2.0.4", "version": "2.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rectorphp/rector.git", "url": "https://github.com/rectorphp/rector.git",
"reference": "df5de7b80deced1ea7f719a0b4d02e4aee87dd21" "reference": "fa0cb009dc3df084bf549032ae4080a0481a2036"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/df5de7b80deced1ea7f719a0b4d02e4aee87dd21", "url": "https://api.github.com/repos/rectorphp/rector/zipball/fa0cb009dc3df084bf549032ae4080a0481a2036",
"reference": "df5de7b80deced1ea7f719a0b4d02e4aee87dd21", "reference": "fa0cb009dc3df084bf549032ae4080a0481a2036",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.4|^8.0", "php": "^7.4|^8.0",
"phpstan/phpstan": "^2.0.4" "phpstan/phpstan": "^2.1.1"
}, },
"conflict": { "conflict": {
"rector/rector-doctrine": "*", "rector/rector-doctrine": "*",
@ -16590,7 +16588,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/rectorphp/rector/issues", "issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.0.4" "source": "https://github.com/rectorphp/rector/tree/2.0.6"
}, },
"funding": [ "funding": [
{ {
@ -16598,7 +16596,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-12-26T23:06:19+00:00" "time": "2025-01-06T10:38:36+00:00"
}, },
{ {
"name": "roave/security-advisories", "name": "roave/security-advisories",
@ -16606,12 +16604,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git", "url": "https://github.com/Roave/SecurityAdvisories.git",
"reference": "9dd07280fc4c5f6c3d2a3da5e4058fc7288c2a1d" "reference": "6ec01b072baedc0e230b90c70e521007851c8f7c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/9dd07280fc4c5f6c3d2a3da5e4058fc7288c2a1d", "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/6ec01b072baedc0e230b90c70e521007851c8f7c",
"reference": "9dd07280fc4c5f6c3d2a3da5e4058fc7288c2a1d", "reference": "6ec01b072baedc0e230b90c70e521007851c8f7c",
"shasum": "" "shasum": ""
}, },
"conflict": { "conflict": {
@ -16733,7 +16731,7 @@
"datatables/datatables": "<1.10.10", "datatables/datatables": "<1.10.10",
"david-garcia/phpwhois": "<=4.3.1", "david-garcia/phpwhois": "<=4.3.1",
"dbrisinajumi/d2files": "<1", "dbrisinajumi/d2files": "<1",
"dcat/laravel-admin": "<=2.1.3", "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta",
"derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3",
"derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4",
"desperado/xml-bundle": "<=0.1.7", "desperado/xml-bundle": "<=0.1.7",
@ -16855,6 +16853,7 @@
"grumpydictator/firefly-iii": "<6.1.17", "grumpydictator/firefly-iii": "<6.1.17",
"gugoan/economizzer": "<=0.9.0.0-beta1", "gugoan/economizzer": "<=0.9.0.0-beta1",
"guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5",
"guzzlehttp/oauth-subscriber": "<0.8.1",
"guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5",
"haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2",
"harvesthq/chosen": "<1.8.7", "harvesthq/chosen": "<1.8.7",
@ -17018,7 +17017,7 @@
"netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15",
"nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6",
"nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13",
"nilsteampassnet/teampass": "<3.0.10", "nilsteampassnet/teampass": "<3.1.3.1-dev",
"nonfiction/nterchange": "<4.1.1", "nonfiction/nterchange": "<4.1.1",
"notrinos/notrinos-erp": "<=0.7", "notrinos/notrinos-erp": "<=0.7",
"noumo/easyii": "<=0.9", "noumo/easyii": "<=0.9",
@ -17079,10 +17078,10 @@
"phpmailer/phpmailer": "<6.5", "phpmailer/phpmailer": "<6.5",
"phpmussel/phpmussel": ">=1,<1.6", "phpmussel/phpmussel": ">=1,<1.6",
"phpmyadmin/phpmyadmin": "<5.2.1", "phpmyadmin/phpmyadmin": "<5.2.1",
"phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5", "phpmyfaq/phpmyfaq": "<3.2.5|==3.2.5|>=3.2.10,<=4.0.1",
"phpoffice/common": "<0.2.9", "phpoffice/common": "<0.2.9",
"phpoffice/phpexcel": "<1.8.1", "phpoffice/phpexcel": "<1.8.1",
"phpoffice/phpspreadsheet": "<1.29.4|>=2,<2.1.3|>=2.2,<2.3.2|>=3.3,<3.4", "phpoffice/phpspreadsheet": "<=1.29.6|>=2,<=2.1.5|>=2.2,<=2.3.4|>=3,<3.7",
"phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36",
"phpservermon/phpservermon": "<3.6", "phpservermon/phpservermon": "<3.6",
"phpsysinfo/phpsysinfo": "<3.4.3", "phpsysinfo/phpsysinfo": "<3.4.3",
@ -17208,6 +17207,7 @@
"squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1",
"ssddanbrown/bookstack": "<24.05.1", "ssddanbrown/bookstack": "<24.05.1",
"starcitizentools/citizen-skin": ">=2.6.3,<2.31", "starcitizentools/citizen-skin": ">=2.6.3,<2.31",
"starcitizentools/tabber-neue": ">=1.9.1,<2.7.2",
"statamic/cms": "<=5.16", "statamic/cms": "<=5.16",
"stormpath/sdk": "<9.9.99", "stormpath/sdk": "<9.9.99",
"studio-42/elfinder": "<=2.1.64", "studio-42/elfinder": "<=2.1.64",
@ -17279,7 +17279,7 @@
"thelia/thelia": ">=2.1,<2.1.3", "thelia/thelia": ">=2.1,<2.1.3",
"theonedemon/phpwhois": "<=4.2.5", "theonedemon/phpwhois": "<=4.2.5",
"thinkcmf/thinkcmf": "<6.0.8", "thinkcmf/thinkcmf": "<6.0.8",
"thorsten/phpmyfaq": "<4", "thorsten/phpmyfaq": "<=4.0.1",
"tikiwiki/tiki-manager": "<=17.1", "tikiwiki/tiki-manager": "<=17.1",
"timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1",
"tinymce/tinymce": "<7.2", "tinymce/tinymce": "<7.2",
@ -17363,7 +17363,7 @@
"xpressengine/xpressengine": "<3.0.15", "xpressengine/xpressengine": "<3.0.15",
"yab/quarx": "<2.4.5", "yab/quarx": "<2.4.5",
"yeswiki/yeswiki": "<=4.4.4", "yeswiki/yeswiki": "<=4.4.4",
"yetiforce/yetiforce-crm": "<=6.4", "yetiforce/yetiforce-crm": "<6.5",
"yidashi/yii2cmf": "<=2", "yidashi/yii2cmf": "<=2",
"yii2mod/yii2-cms": "<1.9.2", "yii2mod/yii2-cms": "<1.9.2",
"yiisoft/yii": "<1.1.29", "yiisoft/yii": "<1.1.29",
@ -17453,7 +17453,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-12-27T20:05:23+00:00" "time": "2025-01-06T20:04:58+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@ -18803,16 +18803,16 @@
}, },
{ {
"name": "symfony/web-profiler-bundle", "name": "symfony/web-profiler-bundle",
"version": "v6.4.16", "version": "v6.4.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/web-profiler-bundle.git", "url": "https://github.com/symfony/web-profiler-bundle.git",
"reference": "2d58fd04ac0d3c6279cadd0105959083ef1d7f5b" "reference": "979f8ee1a4f2464c20f3fef0d2111827fef2e97e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/2d58fd04ac0d3c6279cadd0105959083ef1d7f5b", "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/979f8ee1a4f2464c20f3fef0d2111827fef2e97e",
"reference": "2d58fd04ac0d3c6279cadd0105959083ef1d7f5b", "reference": "979f8ee1a4f2464c20f3fef0d2111827fef2e97e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -18865,7 +18865,7 @@
"dev" "dev"
], ],
"support": { "support": {
"source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.16" "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.17"
}, },
"funding": [ "funding": [
{ {
@ -18881,20 +18881,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-11-19T10:11:25+00:00" "time": "2024-12-08T23:00:41+00:00"
}, },
{ {
"name": "symplify/easy-coding-standard", "name": "symplify/easy-coding-standard",
"version": "12.5.4", "version": "12.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/easy-coding-standard/easy-coding-standard.git", "url": "https://github.com/easy-coding-standard/easy-coding-standard.git",
"reference": "5673ecbc03eef9d7b2f563819c80e8e1ce0161be" "reference": "16a6ac7f452e230fdcc81f1b35b2366903fcecf3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/5673ecbc03eef9d7b2f563819c80e8e1ce0161be", "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/16a6ac7f452e230fdcc81f1b35b2366903fcecf3",
"reference": "5673ecbc03eef9d7b2f563819c80e8e1ce0161be", "reference": "16a6ac7f452e230fdcc81f1b35b2366903fcecf3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -18930,7 +18930,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues", "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues",
"source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.5.4" "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.5.5"
}, },
"funding": [ "funding": [
{ {
@ -18942,7 +18942,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-12-12T15:36:04+00:00" "time": "2025-01-02T08:43:03+00:00"
}, },
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
@ -19020,9 +19020,9 @@
"ext-json": "*", "ext-json": "*",
"ext-mbstring": "*" "ext-mbstring": "*"
}, },
"platform-dev": {}, "platform-dev": [],
"platform-overrides": { "platform-overrides": {
"php": "8.1.0" "php": "8.1.0"
}, },
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View file

@ -51,12 +51,16 @@ nelmio_security:
img-src: img-src:
- '*' - '*'
- 'data:' - 'data:'
# Required for be able to load pictures in the QR code scanner
- 'blob:'
style-src: style-src:
- 'self' - 'self'
- 'unsafe-inline' - 'unsafe-inline'
- 'data:' - 'data:'
script-src: script-src:
- 'self' - 'self'
# Required for loading the Wasm for the barcode scanner:
- 'wasm-unsafe-eval'
object-src: object-src:
- 'self' - 'self'
- 'data:' - 'data:'

View file

@ -66,12 +66,14 @@
"@ckeditor/ckeditor5-watchdog": "^44.0.0", "@ckeditor/ckeditor5-watchdog": "^44.0.0",
"@ckeditor/ckeditor5-word-count": "^44.0.0", "@ckeditor/ckeditor5-word-count": "^44.0.0",
"@jbtronics/bs-treeview": "^1.0.1", "@jbtronics/bs-treeview": "^1.0.1",
"@part-db/html5-qrcode": "^3.1.0",
"@zxcvbn-ts/core": "^3.0.2", "@zxcvbn-ts/core": "^3.0.2",
"@zxcvbn-ts/language-common": "^3.0.3", "@zxcvbn-ts/language-common": "^3.0.3",
"@zxcvbn-ts/language-de": "^3.0.1", "@zxcvbn-ts/language-de": "^3.0.1",
"@zxcvbn-ts/language-en": "^3.0.1", "@zxcvbn-ts/language-en": "^3.0.1",
"@zxcvbn-ts/language-fr": "^3.0.1", "@zxcvbn-ts/language-fr": "^3.0.1",
"@zxcvbn-ts/language-ja": "^3.0.1", "@zxcvbn-ts/language-ja": "^3.0.1",
"barcode-detector": "^2.3.1",
"bootbox": "^6.0.0", "bootbox": "^6.0.0",
"bootswatch": "^5.1.3", "bootswatch": "^5.1.3",
"bs-custom-file-input": "^1.3.4", "bs-custom-file-input": "^1.3.4",
@ -87,7 +89,6 @@
"dompurify": "^3.0.3", "dompurify": "^3.0.3",
"emoji.json": "^15.0.0", "emoji.json": "^15.0.0",
"exports-loader": "^5.0.0", "exports-loader": "^5.0.0",
"html5-qrcode": "^2.2.1",
"json-formatter-js": "^2.3.4", "json-formatter-js": "^2.3.4",
"jszip": "^3.2.0", "jszip": "^3.2.0",
"katex": "^0.16.0", "katex": "^0.16.0",

View file

@ -108,8 +108,31 @@ class LabelController extends AbstractController
$pdf_data = null; $pdf_data = null;
$filename = 'invalid.pdf'; $filename = 'invalid.pdf';
//Generate PDF either when the form is submitted and valid, or the form was not submit yet, and generate is set
if (($form->isSubmitted() && $form->isValid()) || ($generate && !$form->isSubmitted() && $profile instanceof LabelProfile)) { if (($form->isSubmitted() && $form->isValid()) || ($generate && !$form->isSubmitted() && $profile instanceof LabelProfile)) {
//Check if the label should be saved as profile
if ($form->get('save_profile')->isClicked() && $this->isGranted('@labels.create_profiles')) { //@phpstan-ignore-line Phpstan does not recognize the isClicked method
//Retrieve the profile name from the form
$new_name = $form->get('save_profile_name')->getData();
//ensure that the name is not empty
if ($new_name === '' || $new_name === null) {
$form->get('save_profile_name')->addError(new FormError($this->translator->trans('label_generator.profile_name_empty')));
goto render;
}
$profile = new LabelProfile();
$profile->setName($form->get('save_profile_name')->getData());
$profile->setOptions($form_options);
$this->em->persist($profile);
$this->em->flush();
$this->addFlash('success', 'label_generator.profile_saved');
return $this->redirectToRoute('label_dialog_profile', [
'profile' => $profile->getID(),
'target_id' => (string) $form->get('target_id')->getData()
]);
}
$target_id = (string) $form->get('target_id')->getData(); $target_id = (string) $form->get('target_id')->getData();
$targets = $this->findObjects($form_options->getSupportedElement(), $target_id); $targets = $this->findObjects($form_options->getSupportedElement(), $target_id);
if ($targets !== []) { if ($targets !== []) {
@ -132,6 +155,7 @@ class LabelController extends AbstractController
} }
} }
render:
return $this->render('label_system/dialog.html.twig', [ return $this->render('label_system/dialog.html.twig', [
'form' => $form, 'form' => $form,
'pdf_data' => $pdf_data, 'pdf_data' => $pdf_data,

View file

@ -42,10 +42,10 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\Form\LabelSystem\ScanDialogType; use App\Form\LabelSystem\ScanDialogType;
use App\Services\LabelSystem\Barcodes\BarcodeScanHelper; use App\Services\LabelSystem\BarcodeScanner\BarcodeRedirector;
use App\Services\LabelSystem\Barcodes\BarcodeRedirector; use App\Services\LabelSystem\BarcodeScanner\BarcodeScanHelper;
use App\Services\LabelSystem\Barcodes\BarcodeScanResult; use App\Services\LabelSystem\BarcodeScanner\BarcodeSourceType;
use App\Services\LabelSystem\Barcodes\BarcodeSourceType; use App\Services\LabelSystem\BarcodeScanner\LocalBarcodeScanResult;
use Doctrine\ORM\EntityNotFoundException; use Doctrine\ORM\EntityNotFoundException;
use InvalidArgumentException; use InvalidArgumentException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -77,13 +77,21 @@ class ScanController extends AbstractController
$mode = $form['mode']->getData(); $mode = $form['mode']->getData();
} }
$infoModeData = null;
if ($input !== null) { if ($input !== null) {
try { try {
$scan_result = $this->barcodeNormalizer->scanBarcodeContent($input, $mode ?? null); $scan_result = $this->barcodeNormalizer->scanBarcodeContent($input, $mode ?? null);
try { //Perform a redirect if the info mode is not enabled
return $this->redirect($this->barcodeParser->getRedirectURL($scan_result)); if (!$form['info_mode']->getData()) {
} catch (EntityNotFoundException) { try {
$this->addFlash('success', 'scan.qr_not_found'); return $this->redirect($this->barcodeParser->getRedirectURL($scan_result));
} catch (EntityNotFoundException) {
$this->addFlash('success', 'scan.qr_not_found');
}
} else { //Otherwise retrieve infoModeData
$infoModeData = $scan_result->getDecodedForInfoMode();
} }
} catch (InvalidArgumentException) { } catch (InvalidArgumentException) {
$this->addFlash('error', 'scan.format_unknown'); $this->addFlash('error', 'scan.format_unknown');
@ -92,6 +100,7 @@ class ScanController extends AbstractController
return $this->render('label_system/scanner/scanner.html.twig', [ return $this->render('label_system/scanner/scanner.html.twig', [
'form' => $form, 'form' => $form,
'infoModeData' => $infoModeData,
]); ]);
} }
@ -109,7 +118,7 @@ class ScanController extends AbstractController
throw new InvalidArgumentException('Unknown type: '.$type); throw new InvalidArgumentException('Unknown type: '.$type);
} }
//Construct the scan result manually, as we don't have a barcode here //Construct the scan result manually, as we don't have a barcode here
$scan_result = new BarcodeScanResult( $scan_result = new LocalBarcodeScanResult(
target_type: BarcodeScanHelper::QR_TYPE_MAP[$type], target_type: BarcodeScanHelper::QR_TYPE_MAP[$type],
target_id: $id, target_id: $id,
//The routes are only used on the internal generated QR codes //The routes are only used on the internal generated QR codes

View file

@ -106,7 +106,7 @@ class PartFixtures extends Fixture implements DependentFixtureInterface
$partLot2->setComment('Test'); $partLot2->setComment('Test');
$partLot2->setNeedsRefill(true); $partLot2->setNeedsRefill(true);
$partLot2->setStorageLocation($manager->find(StorageLocation::class, 3)); $partLot2->setStorageLocation($manager->find(StorageLocation::class, 3));
$partLot2->setVendorBarcode('lot2_vendor_barcode'); $partLot2->setUserBarcode('lot2_vendor_barcode');
$part->addPartLot($partLot2); $part->addPartLot($partLot2);
$orderdetail = new Orderdetail(); $orderdetail = new Orderdetail();

View file

@ -68,7 +68,7 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
#[ORM\Index(columns: ['needs_refill'], name: 'part_lots_idx_needs_refill')] #[ORM\Index(columns: ['needs_refill'], name: 'part_lots_idx_needs_refill')]
#[ORM\Index(columns: ['vendor_barcode'], name: 'part_lots_idx_barcode')] #[ORM\Index(columns: ['vendor_barcode'], name: 'part_lots_idx_barcode')]
#[ValidPartLot] #[ValidPartLot]
#[UniqueEntity(['vendor_barcode'], message: 'validator.part_lot.vendor_barcode_must_be_unique')] #[UniqueEntity(['user_barcode'], message: 'validator.part_lot.vendor_barcode_must_be_unique')]
#[ApiResource( #[ApiResource(
operations: [ operations: [
new Get(security: 'is_granted("read", object)'), new Get(security: 'is_granted("read", object)'),
@ -166,10 +166,10 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
/** /**
* @var string|null The content of the barcode of this part lot (e.g. a barcode on the package put by the vendor) * @var string|null The content of the barcode of this part lot (e.g. a barcode on the package put by the vendor)
*/ */
#[ORM\Column(type: Types::STRING, nullable: true)] #[ORM\Column(name: "vendor_barcode", type: Types::STRING, nullable: true)]
#[Groups(['part_lot:read', 'part_lot:write'])] #[Groups(['part_lot:read', 'part_lot:write'])]
#[Length(max: 255)] #[Length(max: 255)]
protected ?string $vendor_barcode = null; protected ?string $user_barcode = null;
public function __clone() public function __clone()
{ {
@ -375,19 +375,19 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named
* null if no barcode is set. * null if no barcode is set.
* @return string|null * @return string|null
*/ */
public function getVendorBarcode(): ?string public function getUserBarcode(): ?string
{ {
return $this->vendor_barcode; return $this->user_barcode;
} }
/** /**
* Set the content of the barcode of this part lot (e.g. a barcode on the package put by the vendor). * Set the content of the barcode of this part lot (e.g. a barcode on the package put by the vendor).
* @param string|null $vendor_barcode * @param string|null $user_barcode
* @return $this * @return $this
*/ */
public function setVendorBarcode(?string $vendor_barcode): PartLot public function setUserBarcode(?string $user_barcode): PartLot
{ {
$this->vendor_barcode = $vendor_barcode; $this->user_barcode = $user_barcode;
return $this; return $this;
} }

View file

@ -1,57 +0,0 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\WebpackEncoreBundle\Event\RenderAssetTagEvent;
/**
* This class fixes the wrong pathes generated by webpack using the auto publicPath mode.
* Basically it replaces the wrong /auto/ part of the path with the correct /build/ in all encore entrypoints.
*/
class WebpackAutoPathSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
RenderAssetTagEvent::class => 'onRenderAssetTag'
];
}
public function onRenderAssetTag(RenderAssetTagEvent $event): void
{
if ($event->isScriptTag()) {
$event->setAttribute('src', $this->resolveAuto($event->getUrl()));
}
if ($event->isLinkTag()) {
$event->setAttribute('href', $this->resolveAuto($event->getUrl()));
}
}
private function resolveAuto(string $path): string
{
//Replace the first occurence of /auto/ with /build/ to get the correct path
return preg_replace('/\/auto\//', '/build/', $path, 1);
}
}

View file

@ -71,6 +71,22 @@ class LabelDialogType extends AbstractType
'label' => false, 'label' => false,
'disabled' => !$this->security->isGranted('@labels.edit_options') || $options['disable_options'], 'disabled' => !$this->security->isGranted('@labels.edit_options') || $options['disable_options'],
]); ]);
$builder->add('save_profile_name', TextType::class, [
'required' => false,
'attr' =>[
'placeholder' => 'label_generator.save_profile_name',
]
]);
$builder->add('save_profile', SubmitType::class, [
'label' => 'label_generator.save_profile',
'disabled' => !$this->security->isGranted('@labels.create_profiles'),
'attr' => [
'class' => 'btn btn-outline-success'
]
]);
$builder->add('update', SubmitType::class, [ $builder->add('update', SubmitType::class, [
'label' => 'label_generator.update', 'label' => 'label_generator.update',
]); ]);

View file

@ -41,8 +41,9 @@ declare(strict_types=1);
namespace App\Form\LabelSystem; namespace App\Form\LabelSystem;
use App\Services\LabelSystem\Barcodes\BarcodeSourceType; use App\Services\LabelSystem\BarcodeScanner\BarcodeSourceType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EnumType; use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
@ -55,6 +56,8 @@ class ScanDialogType extends AbstractType
{ {
$builder->add('input', TextType::class, [ $builder->add('input', TextType::class, [
'label' => 'scan_dialog.input', 'label' => 'scan_dialog.input',
//Do not trim the input, otherwise this damages Format06 barcodes which end with non-printable characters
'trim' => false,
'attr' => [ 'attr' => [
'autofocus' => true, 'autofocus' => true,
'id' => 'scan_dialog_input', 'id' => 'scan_dialog_input',
@ -71,9 +74,14 @@ class ScanDialogType extends AbstractType
null => 'scan_dialog.mode.auto', null => 'scan_dialog.mode.auto',
BarcodeSourceType::INTERNAL => 'scan_dialog.mode.internal', BarcodeSourceType::INTERNAL => 'scan_dialog.mode.internal',
BarcodeSourceType::IPN => 'scan_dialog.mode.ipn', BarcodeSourceType::IPN => 'scan_dialog.mode.ipn',
BarcodeSourceType::VENDOR => 'scan_dialog.mode.vendor', BarcodeSourceType::USER_DEFINED => 'scan_dialog.mode.user',
BarcodeSourceType::EIGP114 => 'scan_dialog.mode.eigp'
}, },
]);
$builder->add('info_mode', CheckboxType::class, [
'label' => 'scan_dialog.info_mode',
'required' => false,
]); ]);
$builder->add('submit', SubmitType::class, [ $builder->add('submit', SubmitType::class, [

View file

@ -101,6 +101,8 @@ class PartBaseType extends AbstractType
'dto_value' => $dto?->category, 'dto_value' => $dto?->category,
'label' => 'part.edit.category', 'label' => 'part.edit.category',
'disable_not_selectable' => true, 'disable_not_selectable' => true,
//Do not require category for new parts, so that the user must select the category by hand and cannot forget it (the requirement is handled by the constraint in the entity)
'required' => !$new_part,
]) ])
->add('footprint', StructuralEntityType::class, [ ->add('footprint', StructuralEntityType::class, [
'class' => Footprint::class, 'class' => Footprint::class,

View file

@ -103,10 +103,12 @@ class PartLotType extends AbstractType
'help' => 'part_lot.owner.help', 'help' => 'part_lot.owner.help',
]); ]);
$builder->add('vendor_barcode', TextType::class, [ $builder->add('user_barcode', TextType::class, [
'label' => 'part_lot.edit.vendor_barcode', 'label' => 'part_lot.edit.user_barcode',
'help' => 'part_lot.edit.vendor_barcode.help', 'help' => 'part_lot.edit.vendor_barcode.help',
'required' => false, 'required' => false,
//Do not remove whitespace chars on the beginning and end of the string
'trim' => false,
]); ]);
} }

View file

@ -94,7 +94,14 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface, Norm
public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool
{ {
return !isset($context[self::ALREADY_CALLED]) && is_array($data) && is_a($type, Part::class, true); //Only denormalize if we are doing a file import operation
if (!($context['partdb_import'] ?? false)) {
return false;
}
//Only make the denormalizer available on import operations
return !isset($context[self::ALREADY_CALLED])
&& is_array($data) && is_a($type, Part::class, true);
} }
private function normalizeKeys(array &$data): array private function normalizeKeys(array &$data): array

View file

@ -37,6 +37,7 @@ use App\Entity\Parts\Supplier;
use App\Entity\PriceInformations\Currency; use App\Entity\PriceInformations\Currency;
use App\Entity\PriceInformations\Orderdetail; use App\Entity\PriceInformations\Orderdetail;
use App\Entity\PriceInformations\Pricedetail; use App\Entity\PriceInformations\Pricedetail;
use App\Repository\Parts\CategoryRepository;
use App\Services\InfoProviderSystem\DTOs\FileDTO; use App\Services\InfoProviderSystem\DTOs\FileDTO;
use App\Services\InfoProviderSystem\DTOs\ParameterDTO; use App\Services\InfoProviderSystem\DTOs\ParameterDTO;
use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; use App\Services\InfoProviderSystem\DTOs\PartDetailDTO;
@ -158,7 +159,10 @@ final class DTOtoEntityConverter
$entity->setMass($dto->mass); $entity->setMass($dto->mass);
//Try to map the category to an existing entity (but never create a new one) //Try to map the category to an existing entity (but never create a new one)
$entity->setCategory($this->em->getRepository(Category::class)->findForInfoProvider($dto->category)); if ($dto->category) {
//@phpstan-ignore-next-line For some reason php does not recognize the repo returns a category
$entity->setCategory($this->em->getRepository(Category::class)->findForInfoProvider($dto->category));
}
$entity->setManufacturer($this->getOrCreateEntity(Manufacturer::class, $dto->manufacturer)); $entity->setManufacturer($this->getOrCreateEntity(Manufacturer::class, $dto->manufacturer));
$entity->setFootprint($this->getOrCreateEntity(Footprint::class, $dto->footprint)); $entity->setFootprint($this->getOrCreateEntity(Footprint::class, $dto->footprint));

View file

@ -205,7 +205,7 @@ class MouserProvider implements InfoProviderInterface
if (isset($arr['SearchResults'])) { if (isset($arr['SearchResults'])) {
$products = $arr['SearchResults']['Parts'] ?? []; $products = $arr['SearchResults']['Parts'] ?? [];
} else { } else {
throw new \RuntimeException('Unknown response format'); throw new \RuntimeException('Unknown response format: ' .json_encode($arr, JSON_THROW_ON_ERROR));
} }
$result = []; $result = [];

View file

@ -0,0 +1,166 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Services\LabelSystem\BarcodeScanner;
use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\Manufacturer;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityNotFoundException;
use InvalidArgumentException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* @see \App\Tests\Services\LabelSystem\Barcodes\BarcodeRedirectorTest
*/
final class BarcodeRedirector
{
public function __construct(private readonly UrlGeneratorInterface $urlGenerator, private readonly EntityManagerInterface $em)
{
}
/**
* Determines the URL to which the user should be redirected, when scanning a QR code.
*
* @param BarcodeScanResultInterface $barcodeScan The result of the barcode scan
* @return string the URL to which should be redirected
*
* @throws EntityNotFoundException
*/
public function getRedirectURL(BarcodeScanResultInterface $barcodeScan): string
{
if($barcodeScan instanceof LocalBarcodeScanResult) {
return $this->getURLLocalBarcode($barcodeScan);
}
if ($barcodeScan instanceof EIGP114BarcodeScanResult) {
return $this->getURLVendorBarcode($barcodeScan);
}
throw new InvalidArgumentException('Unknown $barcodeScan type: '.get_class($barcodeScan));
}
private function getURLLocalBarcode(LocalBarcodeScanResult $barcodeScan): string
{
switch ($barcodeScan->target_type) {
case LabelSupportedElement::PART:
return $this->urlGenerator->generate('app_part_show', ['id' => $barcodeScan->target_id]);
case LabelSupportedElement::PART_LOT:
//Try to determine the part to the given lot
$lot = $this->em->find(PartLot::class, $barcodeScan->target_id);
if (!$lot instanceof PartLot) {
throw new EntityNotFoundException();
}
return $this->urlGenerator->generate('app_part_show', ['id' => $lot->getPart()->getID()]);
case LabelSupportedElement::STORELOCATION:
return $this->urlGenerator->generate('part_list_store_location', ['id' => $barcodeScan->target_id]);
default:
throw new InvalidArgumentException('Unknown $type: '.$barcodeScan->target_type->name);
}
}
/**
* Gets the URL to a part from a scan of a Vendor Barcode
*/
private function getURLVendorBarcode(EIGP114BarcodeScanResult $barcodeScan): string
{
$part = $this->getPartFromVendor($barcodeScan);
return $this->urlGenerator->generate('app_part_show', ['id' => $part->getID()]);
}
/**
* Gets a part from a scan of a Vendor Barcode by filtering for parts
* with the same Info Provider Id or, if that fails, by looking for parts with a
* matching manufacturer product number. Only returns the first matching part.
*/
private function getPartFromVendor(EIGP114BarcodeScanResult $barcodeScan) : Part
{
// first check via the info provider ID (e.g. Vendor ID). This might fail if the part was not added via
// the info provider system or if the part was bought from a different vendor than the data was retrieved
// from.
if($barcodeScan->digikeyPartNumber) {
$qb = $this->em->getRepository(Part::class)->createQueryBuilder('part');
//Lower() to be case insensitive
$qb->where($qb->expr()->like('LOWER(part.providerReference.provider_id)', 'LOWER(:vendor_id)'));
$qb->setParameter('vendor_id', $barcodeScan->digikeyPartNumber);
$results = $qb->getQuery()->getResult();
if ($results) {
return $results[0];
}
}
if(!$barcodeScan->supplierPartNumber){
throw new EntityNotFoundException();
}
//Fallback to the manufacturer part number. This may return false positives, since it is common for
//multiple manufacturers to use the same part number for their version of a common product
//We assume the user is able to realize when this returns the wrong part
//If the barcode specifies the manufacturer we try to use that as well
$mpnQb = $this->em->getRepository(Part::class)->createQueryBuilder('part');
$mpnQb->where($mpnQb->expr()->like('LOWER(part.manufacturer_product_number)', 'LOWER(:mpn)'));
$mpnQb->setParameter('mpn', $barcodeScan->supplierPartNumber);
if($barcodeScan->mouserManufacturer){
$manufacturerQb = $this->em->getRepository(Manufacturer::class)->createQueryBuilder("manufacturer");
$manufacturerQb->where($manufacturerQb->expr()->like("LOWER(manufacturer.name)", "LOWER(:manufacturer_name)"));
$manufacturerQb->setParameter("manufacturer_name", $barcodeScan->mouserManufacturer);
$manufacturers = $manufacturerQb->getQuery()->getResult();
if($manufacturers) {
$mpnQb->andWhere($mpnQb->expr()->eq("part.manufacturer", ":manufacturer"));
$mpnQb->setParameter("manufacturer", $manufacturers);
}
}
$results = $mpnQb->getQuery()->getResult();
if($results){
return $results[0];
}
throw new EntityNotFoundException();
}
}

View file

@ -39,7 +39,7 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Services\LabelSystem\Barcodes; namespace App\Services\LabelSystem\BarcodeScanner;
use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\Part; use App\Entity\Parts\Part;
@ -75,20 +75,23 @@ final class BarcodeScanHelper
* will try to guess the type. * will try to guess the type.
* @param string $input * @param string $input
* @param BarcodeSourceType|null $type * @param BarcodeSourceType|null $type
* @return BarcodeScanResult * @return BarcodeScanResultInterface
*/ */
public function scanBarcodeContent(string $input, ?BarcodeSourceType $type = null): BarcodeScanResult public function scanBarcodeContent(string $input, ?BarcodeSourceType $type = null): BarcodeScanResultInterface
{ {
//Do specific parsing //Do specific parsing
if ($type === BarcodeSourceType::INTERNAL) { if ($type === BarcodeSourceType::INTERNAL) {
return $this->parseInternalBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode'); return $this->parseInternalBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode');
} }
if ($type === BarcodeSourceType::VENDOR) { if ($type === BarcodeSourceType::USER_DEFINED) {
return $this->parseVendorBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode'); return $this->parseUserDefinedBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode');
} }
if ($type === BarcodeSourceType::IPN) { if ($type === BarcodeSourceType::IPN) {
return $this->parseIPNBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode'); return $this->parseIPNBarcode($input) ?? throw new InvalidArgumentException('Could not parse barcode');
} }
if ($type === BarcodeSourceType::EIGP114) {
return $this->parseEIGP114Barcode($input);
}
//Null means auto and we try the different formats //Null means auto and we try the different formats
$result = $this->parseInternalBarcode($input); $result = $this->parseInternalBarcode($input);
@ -97,12 +100,17 @@ final class BarcodeScanHelper
return $result; return $result;
} }
//Try to parse as vendor barcode //Try to parse as User defined barcode
$result = $this->parseVendorBarcode($input); $result = $this->parseUserDefinedBarcode($input);
if ($result !== null) { if ($result !== null) {
return $result; return $result;
} }
//If the barcode is formatted as EIGP114, we can parse it directly
if (EIGP114BarcodeScanResult::isFormat06Code($input)) {
return $this->parseEIGP114Barcode($input);
}
//Try to parse as IPN barcode //Try to parse as IPN barcode
$result = $this->parseIPNBarcode($input); $result = $this->parseIPNBarcode($input);
if ($result !== null) { if ($result !== null) {
@ -112,11 +120,16 @@ final class BarcodeScanHelper
throw new InvalidArgumentException('Unknown barcode'); throw new InvalidArgumentException('Unknown barcode');
} }
private function parseVendorBarcode(string $input): ?BarcodeScanResult private function parseEIGP114Barcode(string $input): EIGP114BarcodeScanResult
{
return EIGP114BarcodeScanResult::parseFormat06Code($input);
}
private function parseUserDefinedBarcode(string $input): ?LocalBarcodeScanResult
{ {
$lot_repo = $this->entityManager->getRepository(PartLot::class); $lot_repo = $this->entityManager->getRepository(PartLot::class);
//Find only the first result //Find only the first result
$results = $lot_repo->findBy(['vendor_barcode' => $input], limit: 1); $results = $lot_repo->findBy(['user_barcode' => $input], limit: 1);
if (count($results) === 0) { if (count($results) === 0) {
return null; return null;
@ -124,14 +137,14 @@ final class BarcodeScanHelper
//We found a part, so use it to create the result //We found a part, so use it to create the result
$lot = $results[0]; $lot = $results[0];
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: LabelSupportedElement::PART_LOT, target_type: LabelSupportedElement::PART_LOT,
target_id: $lot->getID(), target_id: $lot->getID(),
source_type: BarcodeSourceType::VENDOR source_type: BarcodeSourceType::USER_DEFINED
); );
} }
private function parseIPNBarcode(string $input): ?BarcodeScanResult private function parseIPNBarcode(string $input): ?LocalBarcodeScanResult
{ {
$part_repo = $this->entityManager->getRepository(Part::class); $part_repo = $this->entityManager->getRepository(Part::class);
//Find only the first result //Find only the first result
@ -143,7 +156,7 @@ final class BarcodeScanHelper
//We found a part, so use it to create the result //We found a part, so use it to create the result
$part = $results[0]; $part = $results[0];
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: LabelSupportedElement::PART, target_type: LabelSupportedElement::PART,
target_id: $part->getID(), target_id: $part->getID(),
source_type: BarcodeSourceType::IPN source_type: BarcodeSourceType::IPN
@ -155,9 +168,9 @@ final class BarcodeScanHelper
* If the barcode could not be parsed at all, null is returned. If the barcode is a valid format, but could * If the barcode could not be parsed at all, null is returned. If the barcode is a valid format, but could
* not be found in the database, an exception is thrown. * not be found in the database, an exception is thrown.
* @param string $input * @param string $input
* @return BarcodeScanResult|null * @return LocalBarcodeScanResult|null
*/ */
private function parseInternalBarcode(string $input): ?BarcodeScanResult private function parseInternalBarcode(string $input): ?LocalBarcodeScanResult
{ {
$input = trim($input); $input = trim($input);
$matches = []; $matches = [];
@ -167,7 +180,7 @@ final class BarcodeScanHelper
//Extract parts from QR code's URL //Extract parts from QR code's URL
if (preg_match('#^https?://.*/scan/(\w+)/(\d+)/?$#', $input, $matches)) { if (preg_match('#^https?://.*/scan/(\w+)/(\d+)/?$#', $input, $matches)) {
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: self::QR_TYPE_MAP[strtolower($matches[1])], target_type: self::QR_TYPE_MAP[strtolower($matches[1])],
target_id: (int) $matches[2], target_id: (int) $matches[2],
source_type: BarcodeSourceType::INTERNAL source_type: BarcodeSourceType::INTERNAL
@ -183,7 +196,7 @@ final class BarcodeScanHelper
throw new InvalidArgumentException('Unknown prefix '.$prefix); throw new InvalidArgumentException('Unknown prefix '.$prefix);
} }
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: self::PREFIX_TYPE_MAP[$prefix], target_type: self::PREFIX_TYPE_MAP[$prefix],
target_id: $id, target_id: $id,
source_type: BarcodeSourceType::INTERNAL source_type: BarcodeSourceType::INTERNAL
@ -199,7 +212,7 @@ final class BarcodeScanHelper
throw new InvalidArgumentException('Unknown prefix '.$prefix); throw new InvalidArgumentException('Unknown prefix '.$prefix);
} }
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: self::PREFIX_TYPE_MAP[$prefix], target_type: self::PREFIX_TYPE_MAP[$prefix],
target_id: $id, target_id: $id,
source_type: BarcodeSourceType::INTERNAL source_type: BarcodeSourceType::INTERNAL
@ -208,7 +221,7 @@ final class BarcodeScanHelper
//Legacy Part-DB location labels used $L00336 format //Legacy Part-DB location labels used $L00336 format
if (preg_match('#^\$L(\d{5,})$#', $input, $matches)) { if (preg_match('#^\$L(\d{5,})$#', $input, $matches)) {
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: LabelSupportedElement::STORELOCATION, target_type: LabelSupportedElement::STORELOCATION,
target_id: (int) $matches[1], target_id: (int) $matches[1],
source_type: BarcodeSourceType::INTERNAL source_type: BarcodeSourceType::INTERNAL
@ -217,7 +230,7 @@ final class BarcodeScanHelper
//Legacy Part-DB used EAN8 barcodes for part labels. Format 0000001(2) (note the optional 8th digit => checksum) //Legacy Part-DB used EAN8 barcodes for part labels. Format 0000001(2) (note the optional 8th digit => checksum)
if (preg_match('#^(\d{7})\d?$#', $input, $matches)) { if (preg_match('#^(\d{7})\d?$#', $input, $matches)) {
return new BarcodeScanResult( return new LocalBarcodeScanResult(
target_type: LabelSupportedElement::PART, target_type: LabelSupportedElement::PART,
target_id: (int) $matches[1], target_id: (int) $matches[1],
source_type: BarcodeSourceType::INTERNAL source_type: BarcodeSourceType::INTERNAL

View file

@ -0,0 +1,36 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2025 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Services\LabelSystem\BarcodeScanner;
interface BarcodeScanResultInterface
{
/**
* Returns all data that was decoded from the barcode in a format, that can be shown in a table to the user.
* The return values of this function are not meant to be parsed by code again, but should just give a information
* to the user.
* The keys of the returned array are the first column of the table and the values are the second column.
* @return array<string, string|int|float|null>
*/
public function getDecodedForInfoMode(): array;
}

View file

@ -21,7 +21,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Services\LabelSystem\Barcodes; namespace App\Services\LabelSystem\BarcodeScanner;
/** /**
* This enum represents the different types, where a barcode/QR-code can be generated from * This enum represents the different types, where a barcode/QR-code can be generated from
@ -32,9 +32,14 @@ enum BarcodeSourceType
case INTERNAL; case INTERNAL;
/** This barcode is containing an internal part number (IPN) */ /** This barcode is containing an internal part number (IPN) */
case IPN; case IPN;
/** /**
* This barcode is a custom barcode from a third party like a vendor, which was set via the vendor_barcode * This barcode is a user defined barcode defined on a part lot
* field of a part lot.
*/ */
case VENDOR; case USER_DEFINED;
/**
* EIGP114 formatted barcodes like used by digikey, mouser, etc.
*/
case EIGP114;
} }

View file

@ -0,0 +1,332 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2025 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace App\Services\LabelSystem\BarcodeScanner;
/**
* This class represents the content of a EIGP114 barcode.
* Based on PR 811, EIGP 114.2018 (https://www.ecianow.org/assets/docs/GIPC/EIGP-114.2018%20ECIA%20Labeling%20Specification%20for%20Product%20and%20Shipment%20Identification%20in%20the%20Electronics%20Industry%20-%202D%20Barcode.pdf),
* , https://forum.digikey.com/t/digikey-product-labels-decoding-digikey-barcodes/41097
*/
class EIGP114BarcodeScanResult implements BarcodeScanResultInterface
{
/**
* @var string|null Ship date in format YYYYMMDD
*/
public readonly ?string $shipDate;
/**
* @var string|null Customer assigned part number Optional based on
* agreements between Distributor and Supplier
*/
public readonly ?string $customerPartNumber;
/**
* @var string|null Supplier assigned part number
*/
public readonly ?string $supplierPartNumber;
/**
* @var int|null Quantity of product
*/
public readonly ?int $quantity;
/**
* @var string|null Customer assigned purchase order number
*/
public readonly ?string $customerPO;
/**
* @var string|null Line item number from PO. Required on Logistic Label when
* used on back of Packing Slip. See Section 4.9
*/
public readonly ?string $customerPOLine;
/**
* 9D - YYWW (Year and Week of Manufacture). ) If no date code is used
* for a particular part, this field should be populated with N/T
* to indicate the product is Not Traceable by this data field.
* @var string|null
*/
public readonly ?string $dateCode;
/**
* 10D - YYWW (Year and Week of Manufacture). ) If no date code is used
* for a particular part, this field should be populated with N/T
* to indicate the product is Not Traceable by this data field.
* @var string|null
*/
public readonly ?string $alternativeDateCode;
/**
* Traceability number assigned to a batch or group of items. If
* no lot code is used for a particular part, this field should be
* populated with N/T to indicate the product is Not Traceable
* by this data field.
* @var string|null
*/
public readonly ?string $lotCode;
/**
* Country where part was manufactured. Two-letter code from
* ISO 3166 country code list
* @var string|null
*/
public readonly ?string $countryOfOrigin;
/**
* @var string|null Unique alphanumeric number assigned by supplier
* 3S - Package ID for Inner Pack when part of a mixed Logistic
* Carton. Always used in conjunction with a mixed logistic label
* with a 5S data identifier for Package ID.
*/
public readonly ?string $packageId1;
/**
* @var string|null
* 4S - Package ID for Logistic Carton with like items
*/
public readonly ?string $packageId2;
/**
* @var string|null
* 5S - Package ID for Logistic Carton with mixed items
*/
public readonly ?string $packageId3;
/**
* @var string|null Unique alphanumeric number assigned by supplier.
*/
public readonly ?string $packingListNumber;
/**
* @var string|null Ship date in format YYYYMMDD
*/
public readonly ?string $serialNumber;
/**
* @var string|null Code for sorting and classifying LEDs. Use when applicable
*/
public readonly ?string $binCode;
/**
* @var int|null Sequential carton count in format #/#” or “# of #”
*/
public readonly ?int $packageCount;
/**
* @var string|null Alphanumeric string assigned by the supplier to distinguish
* from one closely-related design variation to another. Use as
* required or when applicable
*/
public readonly ?string $revisionNumber;
/**
* @var string|null Digikey Extension: This is not represented in the ECIA spec, but the field being used is found in the ANSI MH10.8.2-2016 spec on which the ECIA spec is based. In the ANSI spec it is called First Level (Supplier Assigned) Part Number.
*/
public readonly ?string $digikeyPartNumber;
/**
* @var string|null Digikey Extension: This can be shared across multiple invoices and time periods and is generated as an order enters our system from any vector (web, API, phone order, etc.)
*/
public readonly ?string $digikeySalesOrderNumber;
/**
* @var string|null Digikey extension: This is typically assigned per shipment as items are being released to be picked in the warehouse. A SO can have many Invoice numbers
*/
public readonly ?string $digikeyInvoiceNumber;
/**
* @var string|null Digikey extension: This is for internal DigiKey purposes and defines the label type.
*/
public readonly ?string $digikeyLabelType;
/**
* @var string|null You will also see this as the last part of a URL for a product detail page. Ex https://www.digikey.com/en/products/detail/w%C3%BCrth-elektronik/860010672008/5726907
*/
public readonly ?string $digikeyPartID;
/**
* @var string|null Digikey Extension: For internal use of Digikey. Probably not needed
*/
public readonly ?string $digikeyNA;
/**
* @var string|null Digikey Extension: This is a field of varying length used to keep the barcode approximately the same size between labels. It is safe to ignore.
*/
public readonly ?string $digikeyPadding;
public readonly ?string $mouserPositionInOrder;
public readonly ?string $mouserManufacturer;
/**
*
* @param array<string, string> $data The fields of the EIGP114 barcode, where the key is the field name and the value is the field content
*/
public function __construct(public readonly array $data)
{
//IDs per EIGP 114.2018
$this->shipDate = $data['6D'] ?? null;
$this->customerPartNumber = $data['P'] ?? null;
$this->supplierPartNumber = $data['1P'] ?? null;
$this->quantity = isset($data['Q']) ? (int)$data['Q'] : null;
$this->customerPO = $data['K'] ?? null;
$this->customerPOLine = $data['4K'] ?? null;
$this->dateCode = $data['9D'] ?? null;
$this->alternativeDateCode = $data['10D'] ?? null;
$this->lotCode = $data['1T'] ?? null;
$this->countryOfOrigin = $data['4L'] ?? null;
$this->packageId1 = $data['3S'] ?? null;
$this->packageId2 = $data['4S'] ?? null;
$this->packageId3 = $data['5S'] ?? null;
$this->packingListNumber = $data['11K'] ?? null;
$this->serialNumber = $data['S'] ?? null;
$this->binCode = $data['33P'] ?? null;
$this->packageCount = isset($data['13Q']) ? (int)$data['13Q'] : null;
$this->revisionNumber = $data['2P'] ?? null;
//IDs used by Digikey
$this->digikeyPartNumber = $data['30P'] ?? null;
$this->digikeySalesOrderNumber = $data['1K'] ?? null;
$this->digikeyInvoiceNumber = $data['10K'] ?? null;
$this->digikeyLabelType = $data['11Z'] ?? null;
$this->digikeyPartID = $data['12Z'] ?? null;
$this->digikeyNA = $data['13Z'] ?? null;
$this->digikeyPadding = $data['20Z'] ?? null;
//IDs used by Mouser
$this->mouserPositionInOrder = $data['14K'] ?? null;
$this->mouserManufacturer = $data['1V'] ?? null;
}
/**
* Tries to guess the vendor of the barcode based on the supplied data field.
* This is experimental and should not be relied upon.
* @return string|null The guessed vendor as smallcase string (e.g. "digikey", "mouser", etc.), or null if the vendor could not be guessed
*/
public function guessBarcodeVendor(): ?string
{
//If the barcode data contains the digikey extensions, we assume it is a digikey barcode
if (isset($this->data['13Z']) || isset($this->data['20Z']) || isset($this->data['12Z']) || isset($this->data['11Z'])) {
return 'digikey';
}
//If the barcode data contains the mouser extensions, we assume it is a mouser barcode
if (isset($this->data['14K']) || isset($this->data['1V'])) {
return 'mouser';
}
//According to this thread (https://github.com/inventree/InvenTree/issues/853), Newark/element14 codes contains a "3P" field
if (isset($this->data['3P'])) {
return 'element14';
}
return null;
}
/**
* Checks if the given input is a valid format06 formatted data.
* This just perform a simple check for the header, the content might be malformed still.
* @param string $input
* @return bool
*/
public static function isFormat06Code(string $input): bool
{
//Code must begin with [)><RS>06<GS>
if(!str_starts_with($input, "[)>\u{1E}06\u{1D}")){
return false;
}
//Digikey does not put a trailer onto the barcode, so we just check for the header
return true;
}
/**
* Parses a format06 code a returns a new instance of this class
* @param string $input
* @return self
*/
public static function parseFormat06Code(string $input): self
{
//Ensure that the input is a valid format06 code
if (!self::isFormat06Code($input)) {
throw new \InvalidArgumentException("The given input is not a valid format06 code");
}
//Remove the trailer, if present
if (str_ends_with($input, "\u{1E}\u{04}")){
$input = substr($input, 5, -2);
}
//Split the input into the different fields (using the <GS> separator)
$parts = explode("\u{1D}", $input);
//The first field is the format identifier, which we do not need
array_shift($parts);
//Split the fields into key-value pairs
$results = [];
foreach($parts as $part) {
//^ 0* ([1-9]? \d* [A-Z])
//Start of the string Leading zeros are discarded Not a zero Any number of digits single uppercase Letter
// 00 1 4 K
if(!preg_match('/^0*([1-9]?\d*[A-Z])/', $part, $matches)) {
throw new \LogicException("Could not parse field: $part");
}
//Extract the key
$key = $matches[0];
//Extract the field value
$fieldValue = substr($part, strlen($matches[0]));
$results[$key] = $fieldValue;
}
return new self($results);
}
public function getDecodedForInfoMode(): array
{
$tmp = [
'Barcode type' => 'EIGP114',
'Guessed vendor from barcode' => $this->guessBarcodeVendor() ?? 'Unknown',
];
//Iterate over all fields of this object and add them to the array if they are not null
foreach((array) $this as $key => $value) {
//Skip data key
if ($key === 'data') {
continue;
}
if($value !== null) {
$tmp[$key] = $value;
}
}
return $tmp;
}
}

View file

@ -21,14 +21,15 @@
declare(strict_types=1); declare(strict_types=1);
namespace App\Services\LabelSystem\Barcodes; namespace App\Services\LabelSystem\BarcodeScanner;
use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\LabelSystem\LabelSupportedElement;
/** /**
* This class represents the result of a barcode scan, with the target type and the ID of the element * This class represents the result of a barcode scan of a barcode that uniquely identifies a local entity,
* like an internally generated barcode or a barcode that was added manually to the system by a user
*/ */
class BarcodeScanResult class LocalBarcodeScanResult implements BarcodeScanResultInterface
{ {
public function __construct( public function __construct(
public readonly LabelSupportedElement $target_type, public readonly LabelSupportedElement $target_type,
@ -36,4 +37,13 @@ class BarcodeScanResult
public readonly BarcodeSourceType $source_type, public readonly BarcodeSourceType $source_type,
) { ) {
} }
public function getDecodedForInfoMode(): array
{
return [
'Barcode type' => $this->source_type->name,
'Target type' => $this->target_type->name,
'Target ID' => $this->target_id,
];
}
} }

View file

@ -1,89 +0,0 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2022 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Services\LabelSystem\Barcodes;
use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\PartLot;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityNotFoundException;
use InvalidArgumentException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
/**
* @see \App\Tests\Services\LabelSystem\Barcodes\BarcodeRedirectorTest
*/
final class BarcodeRedirector
{
public function __construct(private readonly UrlGeneratorInterface $urlGenerator, private readonly EntityManagerInterface $em)
{
}
/**
* Determines the URL to which the user should be redirected, when scanning a QR code.
*
* @param BarcodeScanResult $barcodeScan The result of the barcode scan
* @return string the URL to which should be redirected
*
* @throws EntityNotFoundException
*/
public function getRedirectURL(BarcodeScanResult $barcodeScan): string
{
switch ($barcodeScan->target_type) {
case LabelSupportedElement::PART:
return $this->urlGenerator->generate('app_part_show', ['id' => $barcodeScan->target_id]);
case LabelSupportedElement::PART_LOT:
//Try to determine the part to the given lot
$lot = $this->em->find(PartLot::class, $barcodeScan->target_id);
if (!$lot instanceof PartLot) {
throw new EntityNotFoundException();
}
return $this->urlGenerator->generate('app_part_show', ['id' => $lot->getPart()->getID()]);
case LabelSupportedElement::STORELOCATION:
return $this->urlGenerator->generate('part_list_store_location', ['id' => $barcodeScan->target_id]);
default:
throw new InvalidArgumentException('Unknown $type: '.$barcodeScan->target_type->name);
}
}
}

View file

@ -408,15 +408,15 @@
"version": "v4.2.3" "version": "v4.2.3"
}, },
"symfony/console": { "symfony/console": {
"version": "5.3", "version": "6.4",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "master", "branch": "main",
"version": "5.3", "version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047" "ref": "1781ff40d8a17d87cf53f8d4cf0c8346ed2bb461"
}, },
"files": [ "files": [
"./bin/console" "bin/console"
] ]
}, },
"symfony/css-selector": { "symfony/css-selector": {
@ -468,15 +468,16 @@
"version": "v4.2.3" "version": "v4.2.3"
}, },
"symfony/flex": { "symfony/flex": {
"version": "1.19", "version": "2.4",
"recipe": { "recipe": {
"repo": "github.com/symfony/recipes", "repo": "github.com/symfony/recipes",
"branch": "main", "branch": "main",
"version": "1.0", "version": "2.4",
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172" "ref": "52e9754527a15e2b79d9a610f98185a1fe46622a"
}, },
"files": [ "files": [
".env" ".env",
".env.dev"
] ]
}, },
"symfony/form": { "symfony/form": {

View file

@ -59,7 +59,7 @@
<label class="col-sm-3 col-form-label">{% trans %}label_generator.selected_profile{% endtrans %}</label> <label class="col-sm-3 col-form-label">{% trans %}label_generator.selected_profile{% endtrans %}</label>
<div class="col-sm-9"> <div class="col-sm-9">
<span class="form-control-plaintext">{{ profile.name ?? '-' }} <span class="form-control-plaintext">{{ profile.name ?? '-' }}
{% if profile %} {% if profile and is_granted("edit", profile) %}
<a href="{{ entity_url(profile, 'edit') }}" title="{% trans %}label_generator.edit_profile{% endtrans %}" <a href="{{ entity_url(profile, 'edit') }}" title="{% trans %}label_generator.edit_profile{% endtrans %}"
><i class="fas fa-edit"></i></a> ><i class="fas fa-edit"></i></a>
{% endif %} {% endif %}
@ -91,6 +91,25 @@
</div> </div>
</div> </div>
</div> </div>
{% if is_granted("@labels.read_profiles") %}
<div class="form-group row">
<div class="offset-sm-3 col-sm-9">
<a class="btn btn-link" href="{{ path('label_profile_new') }}">{% trans %}label_generator.edit_profiles{% endtrans %}</a>
</div>
</div>
{% endif %}
<div class="form-group row">
<div class="offset-sm-3 col-sm-9">
<div class="input-group">
{{ form_widget(form.save_profile_name) }}
{{ form_widget(form.save_profile) }}
</div>
{{ form_errors(form.save_profile_name) }}
</div>
</div>
</div> </div>
</div> </div>

View file

@ -23,4 +23,22 @@
{{ form_end(form) }} {{ form_end(form) }}
{% if infoModeData %}
<hr>
<h4>{% trans %}label_scanner.decoded_info.title{% endtrans %}</h4>
<table class="table table-striped table-hover table-bordered table-sm">
<tbody>
{% for key, value in infoModeData %}
<tr>
<td>{{ key }}</td>
<td><code>{{ value }}</code></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %} {% endblock %}

View file

@ -108,7 +108,7 @@
<div class="collapse" id="{{ id }}"> <div class="collapse" id="{{ id }}">
{{ form_row(form.comment) }} {{ form_row(form.comment) }}
{{ form_row(form.owner) }} {{ form_row(form.owner) }}
{{ form_row(form.vendor_barcode) }} {{ form_row(form.user_barcode) }}
</div> </div>
</td> </td>
<td> <td>

View file

@ -115,6 +115,62 @@ class RedirectControllerTest extends WebTestCase
$this->client->followRedirects(false); $this->client->followRedirects(false);
$this->client->request('GET', $input_path); $this->client->request('GET', $input_path);
$this->assertResponseRedirects($redirect_path); self::assertResponseRedirects($redirect_path);
} }
/**
* Test if the user is redirected to the localized version of a page, based on his settings.
* We simulate the situation of a reverse proxy here, by adding a prefix to the path.
*
* @dataProvider urlAddLocaleDataProvider
* @group slow
*/
public function testAddLocaleReverseProxy(?string $user_locale, string $input_path, string $redirect_path): void
{
//Input path remains unchanged, as this is what the server receives from the proxy
//Redirect path must contain the proxy prefix
$redirect_path = 'http://localhost'. '/proxy' . $redirect_path;
/** @var User $user */
$user = $this->userRepo->findOneBy(['name' => 'user']);
//Set user locale
$user->setLanguage($user_locale);
$this->em->flush();
$this->client->followRedirects(false);
$this->client->request('GET', $input_path, [], [], ['HTTP_X_FORWARDED_PREFIX' => '/proxy']);
self::assertResponseRedirects($redirect_path);
}
/**
* Test if the user is redirected to the localized version of a page, based on his settings.
* We simulate the situation of serving Part-DB in a subfolder here.
*
* @dataProvider urlAddLocaleDataProvider
* @group slow
*/
public function testAddLocaleSubfolder(?string $user_locale, string $input_path, string $redirect_path): void
{
//Prefix our path with the proxy prefix
$input_path = '/folder'.$input_path;
//Redirect path is absolute
$redirect_path = 'http://localhost'. '/folder' . $redirect_path;
/** @var User $user */
$user = $this->userRepo->findOneBy(['name' => 'user']);
//Set user locale
$user->setLanguage($user_locale);
$this->em->flush();
$this->client->followRedirects(false);
$this->client->request('GET', $input_path, [], [], [
'SCRIPT_FILENAME' => '/var/www/html/folder/public/index.php',
'PHP_SELF' => '/folder/index.php',
]);
self::assertResponseRedirects($redirect_path);
}
} }

View file

@ -80,7 +80,10 @@ class PartNormalizerTest extends WebTestCase
$this->assertFalse($this->service->supportsDenormalization(new \stdClass(), Part::class)); $this->assertFalse($this->service->supportsDenormalization(new \stdClass(), Part::class));
$this->assertFalse($this->service->supportsDenormalization('string', Part::class)); $this->assertFalse($this->service->supportsDenormalization('string', Part::class));
$this->assertFalse($this->service->supportsDenormalization(['a' => 'b'], \stdClass::class)); $this->assertFalse($this->service->supportsDenormalization(['a' => 'b'], \stdClass::class));
$this->assertTrue($this->service->supportsDenormalization(['a' => 'b'], Part::class));
//Only support denormalization, if CSV import
$this->assertFalse($this->service->supportsDenormalization(['a' => 'b'], Part::class));
$this->assertTrue($this->service->supportsDenormalization(['a' => 'b'], Part::class, null, ['partdb_import' => true]));
} }
public function testDenormalize(): void public function testDenormalize(): void

View file

@ -148,7 +148,7 @@ class PartMergerTest extends KernelTestCase
public function testMergeOfPartLots(): void public function testMergeOfPartLots(): void
{ {
$lot1 = (new PartLot())->setAmount(2)->setNeedsRefill(true); $lot1 = (new PartLot())->setAmount(2)->setNeedsRefill(true);
$lot2 = (new PartLot())->setInstockUnknown(true)->setVendorBarcode('test'); $lot2 = (new PartLot())->setInstockUnknown(true)->setUserBarcode('test');
$lot3 = (new PartLot())->setDescription('lot3')->setAmount(3); $lot3 = (new PartLot())->setDescription('lot3')->setAmount(3);
$lot4 = (new PartLot())->setDescription('lot4')->setComment('comment'); $lot4 = (new PartLot())->setDescription('lot4')->setComment('comment');

View file

@ -39,12 +39,12 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Tests\Services\LabelSystem\Barcodes; namespace App\Tests\Services\LabelSystem\BarcodeScanner;
use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\LabelSystem\LabelSupportedElement;
use App\Services\LabelSystem\Barcodes\BarcodeRedirector; use App\Services\LabelSystem\BarcodeScanner\BarcodeRedirector;
use App\Services\LabelSystem\Barcodes\BarcodeScanResult; use App\Services\LabelSystem\BarcodeScanner\BarcodeSourceType;
use App\Services\LabelSystem\Barcodes\BarcodeSourceType; use App\Services\LabelSystem\BarcodeScanner\LocalBarcodeScanResult;
use Doctrine\ORM\EntityNotFoundException; use Doctrine\ORM\EntityNotFoundException;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
@ -60,17 +60,17 @@ final class BarcodeRedirectorTest extends KernelTestCase
public static function urlDataProvider(): \Iterator public static function urlDataProvider(): \Iterator
{ {
yield [new BarcodeScanResult(LabelSupportedElement::PART, 1, BarcodeSourceType::INTERNAL), '/en/part/1']; yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 1, BarcodeSourceType::INTERNAL), '/en/part/1'];
//Part lot redirects to Part info page (Part lot 1 is associated with part 3) //Part lot redirects to Part info page (Part lot 1 is associated with part 3)
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 1, BarcodeSourceType::INTERNAL), '/en/part/3']; yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 1, BarcodeSourceType::INTERNAL), '/en/part/3'];
yield [new BarcodeScanResult(LabelSupportedElement::STORELOCATION, 1, BarcodeSourceType::INTERNAL), '/en/store_location/1/parts']; yield [new LocalBarcodeScanResult(LabelSupportedElement::STORELOCATION, 1, BarcodeSourceType::INTERNAL), '/en/store_location/1/parts'];
} }
/** /**
* @dataProvider urlDataProvider * @dataProvider urlDataProvider
* @group DB * @group DB
*/ */
public function testGetRedirectURL(BarcodeScanResult $scanResult, string $url): void public function testGetRedirectURL(LocalBarcodeScanResult $scanResult, string $url): void
{ {
$this->assertSame($url, $this->service->getRedirectURL($scanResult)); $this->assertSame($url, $this->service->getRedirectURL($scanResult));
} }
@ -79,7 +79,7 @@ final class BarcodeRedirectorTest extends KernelTestCase
{ {
$this->expectException(EntityNotFoundException::class); $this->expectException(EntityNotFoundException::class);
//If we encounter an invalid lot, we must throw an exception //If we encounter an invalid lot, we must throw an exception
$this->service->getRedirectURL(new BarcodeScanResult(LabelSupportedElement::PART_LOT, $this->service->getRedirectURL(new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT,
12_345_678, BarcodeSourceType::INTERNAL)); 12_345_678, BarcodeSourceType::INTERNAL));
} }
} }

View file

@ -39,13 +39,14 @@ declare(strict_types=1);
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
namespace App\Tests\Services\LabelSystem\Barcodes; namespace App\Tests\Services\LabelSystem\BarcodeScanner;
use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\LabelSystem\LabelSupportedElement;
use App\Services\LabelSystem\Barcodes\BarcodeScanHelper; use App\Services\LabelSystem\BarcodeScanner\BarcodeScanHelper;
use App\Services\LabelSystem\Barcodes\BarcodeScanResult; use App\Services\LabelSystem\BarcodeScanner\BarcodeScanResultInterface;
use App\Services\LabelSystem\Barcodes\BarcodeSourceType; use App\Services\LabelSystem\BarcodeScanner\BarcodeSourceType;
use Com\Tecnick\Barcode\Barcode; use App\Services\LabelSystem\BarcodeScanner\EIGP114BarcodeScanResult;
use App\Services\LabelSystem\BarcodeScanner\LocalBarcodeScanResult;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class BarcodeScanHelperTest extends WebTestCase class BarcodeScanHelperTest extends WebTestCase
@ -61,56 +62,67 @@ class BarcodeScanHelperTest extends WebTestCase
public static function dataProvider(): \Iterator public static function dataProvider(): \Iterator
{ {
//QR URL content: //QR URL content:
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 1, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 1, BarcodeSourceType::INTERNAL),
'https://localhost:8000/scan/lot/1']; 'https://localhost:8000/scan/lot/1'];
yield [new BarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL),
'https://localhost:8000/scan/part/123']; 'https://localhost:8000/scan/part/123'];
yield [new BarcodeScanResult(LabelSupportedElement::STORELOCATION, 4, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::STORELOCATION, 4, BarcodeSourceType::INTERNAL),
'http://foo.bar/part-db/scan/location/4']; 'http://foo.bar/part-db/scan/location/4'];
//Current Code39 format: //Current Code39 format:
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL),
'L0010']; 'L0010'];
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 123, BarcodeSourceType::INTERNAL),
'L0123']; 'L0123'];
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 123456, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 123456, BarcodeSourceType::INTERNAL),
'L123456']; 'L123456'];
yield [new BarcodeScanResult(LabelSupportedElement::PART, 2, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 2, BarcodeSourceType::INTERNAL),
'P0002']; 'P0002'];
//Development phase Code39 barcodes: //Development phase Code39 barcodes:
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL),
'L-000010']; 'L-000010'];
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 10, BarcodeSourceType::INTERNAL),
'Lß000010']; 'Lß000010'];
yield [new BarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL),
'P-000123']; 'P-000123'];
yield [new BarcodeScanResult(LabelSupportedElement::STORELOCATION, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::STORELOCATION, 123, BarcodeSourceType::INTERNAL),
'S-000123']; 'S-000123'];
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 12_345_678, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 12_345_678, BarcodeSourceType::INTERNAL),
'L-12345678']; 'L-12345678'];
//Legacy storelocation format //Legacy storelocation format
yield [new BarcodeScanResult(LabelSupportedElement::STORELOCATION, 336, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::STORELOCATION, 336, BarcodeSourceType::INTERNAL),
'$L00336']; '$L00336'];
yield [new BarcodeScanResult(LabelSupportedElement::STORELOCATION, 12_345_678, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::STORELOCATION, 12_345_678, BarcodeSourceType::INTERNAL),
'$L12345678']; '$L12345678'];
//Legacy Part format //Legacy Part format
yield [new BarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL),
'0000123']; '0000123'];
yield [new BarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 123, BarcodeSourceType::INTERNAL),
'00001236']; '00001236'];
yield [new BarcodeScanResult(LabelSupportedElement::PART, 1_234_567, BarcodeSourceType::INTERNAL), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 1_234_567, BarcodeSourceType::INTERNAL),
'12345678']; '12345678'];
//Test IPN barcode //Test IPN barcode
yield [new BarcodeScanResult(LabelSupportedElement::PART, 2, BarcodeSourceType::IPN), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART, 2, BarcodeSourceType::IPN),
'IPN123']; 'IPN123'];
//Test vendor barcode //Test vendor barcode
yield [new BarcodeScanResult(LabelSupportedElement::PART_LOT, 2,BarcodeSourceType::VENDOR), yield [new LocalBarcodeScanResult(LabelSupportedElement::PART_LOT, 2,BarcodeSourceType::USER_DEFINED),
'lot2_vendor_barcode']; 'lot2_vendor_barcode'];
$eigp114Result = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
]);
yield [$eigp114Result, "[)>\x1E06\x1DP596-777A1-ND\x1D1PXAF4444\x1DQ3\x1D10D1452\x1D1TBF1103\x1D4LUS\x1E\x04"];
} }
public static function invalidDataProvider(): \Iterator public static function invalidDataProvider(): \Iterator
@ -131,7 +143,7 @@ class BarcodeScanHelperTest extends WebTestCase
/** /**
* @dataProvider dataProvider * @dataProvider dataProvider
*/ */
public function testNormalizeBarcodeContent(BarcodeScanResult $expected, string $input): void public function testNormalizeBarcodeContent(BarcodeScanResultInterface $expected, string $input): void
{ {
$this->assertEquals($expected, $this->service->scanBarcodeContent($input)); $this->assertEquals($expected, $this->service->scanBarcodeContent($input));
} }

View file

@ -0,0 +1,154 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2025 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Tests\Services\LabelSystem\BarcodeScanner;
use App\Services\LabelSystem\BarcodeScanner\EIGP114BarcodeScanResult;
use PHPUnit\Framework\TestCase;
class EIGP114BarcodeScanResultTest extends TestCase
{
public function testGuessBarcodeVendor(): void
{
//Generic barcode:
$barcode = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
]);
$this->assertNull($barcode->guessBarcodeVendor());
//Digikey barcode:
$barcode = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
'13Z' => 'Digi-Key',
]);
$this->assertEquals('digikey', $barcode->guessBarcodeVendor());
//Mouser barcode:
$barcode = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
'1V' => 'Mouser',
]);
$this->assertEquals('mouser', $barcode->guessBarcodeVendor());
//Farnell barcode:
$barcode = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
'3P' => 'Farnell',
]);
$this->assertEquals('element14', $barcode->guessBarcodeVendor());
}
public function testIsFormat06Code(): void
{
$this->assertFalse(EIGP114BarcodeScanResult::isFormat06Code(''));
$this->assertFalse(EIGP114BarcodeScanResult::isFormat06Code('test'));
$this->assertFalse(EIGP114BarcodeScanResult::isFormat06Code('12232435ew4rf'));
//Valid code (with trailer)
$this->assertTrue(EIGP114BarcodeScanResult::isFormat06Code("[)>\x1E06\x1DP596-777A1-ND\x1D1PXAF4444\x1DQ3\x1D10D1452\x1D1TBF1103\x1D4LUS\x1E\x04"));
//Valid code (digikey, without trailer)
$this->assertTrue(EIGP114BarcodeScanResult::isFormat06Code("[)>\x1e06\x1dPQ1045-ND\x1d1P364019-01\x1d30PQ1045-ND\x1dK12432 TRAVIS FOSS P\x1d1K85732873\x1d10K103332956\x1d9D231013\x1d1TQJ13P\x1d11K1\x1d4LTW\x1dQ3\x1d11ZPICK\x1d12Z7360988\x1d13Z999999\x1d20Z0000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
}
public function testParseFormat06CodeInvalid(): void
{
$this->expectException(\InvalidArgumentException::class);
EIGP114BarcodeScanResult::parseFormat06Code('');
}
public function testParseFormat06Code(): void
{
$barcode = EIGP114BarcodeScanResult::parseFormat06Code("[)>\x1E06\x1DP596-777A1-ND\x1D1PXAF4444\x1DQ3\x1D10D1452\x1D1TBF1103\x1D4LUS\x1E\x04");
$this->assertEquals([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
], $barcode->data);
}
public function testDataParsing(): void
{
$barcode = new EIGP114BarcodeScanResult([
'P' => '596-777A1-ND',
'1P' => 'XAF4444',
'Q' => '3',
'10D' => '1452',
'1T' => 'BF1103',
'4L' => 'US',
]);
$this->assertEquals('596-777A1-ND', $barcode->customerPartNumber);
$this->assertEquals('XAF4444', $barcode->supplierPartNumber);
$this->assertEquals(3, $barcode->quantity);
$this->assertEquals('1452', $barcode->alternativeDateCode);
$this->assertEquals('BF1103', $barcode->lotCode);
$this->assertEquals('US', $barcode->countryOfOrigin);
}
public function testDigikeyParsing(): void
{
$barcode = EIGP114BarcodeScanResult::parseFormat06Code("[)>\x1e06\x1dPQ1045-ND\x1d1P364019-01\x1d30PQ1045-ND\x1dK12432 TRAVIS FOSS P\x1d1K85732873\x1d10K103332956\x1d9D231013\x1d1TQJ13P\x1d11K1\x1d4LTW\x1dQ3\x1d11ZPICK\x1d12Z7360988\x1d13Z999999\x1d20Z0000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
$this->assertEquals('digikey', $barcode->guessBarcodeVendor());
$this->assertEquals('Q1045-ND', $barcode->customerPartNumber);
$this->assertEquals('364019-01', $barcode->supplierPartNumber);
$this->assertEquals(3, $barcode->quantity);
$this->assertEquals('231013', $barcode->dateCode);
$this->assertEquals('QJ13P', $barcode->lotCode);
$this->assertEquals('TW', $barcode->countryOfOrigin);
$this->assertEquals('Q1045-ND', $barcode->digikeyPartNumber);
$this->assertEquals('85732873', $barcode->digikeySalesOrderNumber);
$this->assertEquals('103332956', $barcode->digikeyInvoiceNumber);
$this->assertEquals('PICK', $barcode->digikeyLabelType);
$this->assertEquals('7360988', $barcode->digikeyPartID);
$this->assertEquals('999999', $barcode->digikeyNA);
$this->assertEquals('0000000000000000000000000000000000000000000000000000000000000000000000000000000000000', $barcode->digikeyPadding);
}
}

View file

@ -12223,5 +12223,101 @@ Bitte beachten Sie, dass Sie sich nicht als deaktivierter Benutzer ausgeben kön
<target>Erzeugter Code</target> <target>Erzeugter Code</target>
</segment> </segment>
</unit> </unit>
<unit id="5fgkpRc" name="info_providers.search.show_existing_part">
<segment state="translated">
<source>info_providers.search.show_existing_part</source>
<target>Bestehendes Bauteil anzeigen</target>
</segment>
</unit>
<unit id="iPO8lit" name="info_providers.search.edit_existing_part">
<segment state="translated">
<source>info_providers.search.edit_existing_part</source>
<target>Bestehendes Bauteil bearbeiten</target>
</segment>
</unit>
<unit id="gUMm8CJ" name="info_providers.search.existing_part_found.short">
<segment state="translated">
<source>info_providers.search.existing_part_found.short</source>
<target>Bauteil existiert bereits</target>
</segment>
</unit>
<unit id="bT1nkI9" name="info_providers.search.existing_part_found">
<segment state="translated">
<source>info_providers.search.existing_part_found</source>
<target>Dieses Bauteil (oder ein sehr ähnliches) existiert bereits in der Datenbank. Bitte überprüfen Sie, ob es das gleiche ist und ob Sie dies erneut erstellen möchten!</target>
</segment>
</unit>
<unit id="TDxYuTP" name="info_providers.search.update_existing_part">
<segment state="translated">
<source>info_providers.search.update_existing_part</source>
<target>Bestehendes Bauteil von Informationsquelle aktualisieren</target>
</segment>
</unit>
<unit id="X5tEZJs" name="part.create_from_info_provider.no_category_yet">
<segment state="translated">
<source>part.create_from_info_provider.no_category_yet</source>
<target>Die Kategorie konnte nicht automatisch von der Informationsquelle ermittelt werden. Überprüfen Sie die Daten und wählen Sie die Kategorie händisch aus.</target>
</segment>
</unit>
<unit id="v6oyTac" name="part_lot.edit.user_barcode">
<segment state="translated">
<source>part_lot.edit.user_barcode</source>
<target>Benutzer-Barcode</target>
</segment>
</unit>
<unit id="dXhegcm" name="scan_dialog.mode.user">
<segment state="translated">
<source>scan_dialog.mode.user</source>
<target>Benutzer definierter Barcode (in Bauteilebestand konfiguriert)</target>
</segment>
</unit>
<unit id="sSAJDdr" name="scan_dialog.mode.eigp">
<segment state="translated">
<source>scan_dialog.mode.eigp</source>
<target>EIGP 114 Barcode (z. B. der Datamatrix code auf Digikey und Mouser Bauteilen)</target>
</segment>
</unit>
<unit id="QSMS_Bd" name="scan_dialog.info_mode">
<segment state="translated">
<source>scan_dialog.info_mode</source>
<target>Info Modus (Barcode dekodieren und Inhalte anzeigen, aber nicht zum Bauteil weiterleiten)</target>
</segment>
</unit>
<unit id="k5Gvkgp" name="label_scanner.decoded_info.title">
<segment state="translated">
<source>label_scanner.decoded_info.title</source>
<target>Dekodierte Informationen</target>
</segment>
</unit>
<unit id="nmXQWcS" name="label_generator.edit_profiles">
<segment state="translated">
<source>label_generator.edit_profiles</source>
<target>Profile bearbeiten</target>
</segment>
</unit>
<unit id="JzfeFN6" name="label_generator.profile_name_empty">
<segment state="translated">
<source>label_generator.profile_name_empty</source>
<target>Der Profilname darf nicht leer sein!</target>
</segment>
</unit>
<unit id="0TP6The" name="label_generator.save_profile_name">
<segment state="translated">
<source>label_generator.save_profile_name</source>
<target>Profilname</target>
</segment>
</unit>
<unit id="OhUW6es" name="label_generator.save_profile">
<segment state="translated">
<source>label_generator.save_profile</source>
<target>Als neues Profil speichern</target>
</segment>
</unit>
<unit id="sqc4h7S" name="label_generator.profile_saved">
<segment state="translated">
<source>label_generator.profile_saved</source>
<target>Profil gespeichert!</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>

View file

@ -12263,5 +12263,65 @@ Please note, that you can not impersonate a disabled user. If you try you will g
<target>Category could not be automatically determined by the info provider. Review the data and select the category manually.</target> <target>Category could not be automatically determined by the info provider. Review the data and select the category manually.</target>
</segment> </segment>
</unit> </unit>
<unit id="v6oyTac" name="part_lot.edit.user_barcode">
<segment>
<source>part_lot.edit.user_barcode</source>
<target>User barcode</target>
</segment>
</unit>
<unit id="dXhegcm" name="scan_dialog.mode.user">
<segment>
<source>scan_dialog.mode.user</source>
<target>User defined barcode (configured at part lot)</target>
</segment>
</unit>
<unit id="sSAJDdr" name="scan_dialog.mode.eigp">
<segment>
<source>scan_dialog.mode.eigp</source>
<target>EIGP 114 barcode (e.g. the datamatrix codes on digikey and mouser orders)</target>
</segment>
</unit>
<unit id="QSMS_Bd" name="scan_dialog.info_mode">
<segment>
<source>scan_dialog.info_mode</source>
<target>Info mode (Decode barcode and show its contents, but do not redirect to part)</target>
</segment>
</unit>
<unit id="k5Gvkgp" name="label_scanner.decoded_info.title">
<segment>
<source>label_scanner.decoded_info.title</source>
<target>Decoded information</target>
</segment>
</unit>
<unit id="nmXQWcS" name="label_generator.edit_profiles">
<segment>
<source>label_generator.edit_profiles</source>
<target>Edit profiles</target>
</segment>
</unit>
<unit id="JzfeFN6" name="label_generator.profile_name_empty">
<segment>
<source>label_generator.profile_name_empty</source>
<target>Profile name must not be empty!</target>
</segment>
</unit>
<unit id="0TP6The" name="label_generator.save_profile_name">
<segment>
<source>label_generator.save_profile_name</source>
<target>Profile name</target>
</segment>
</unit>
<unit id="OhUW6es" name="label_generator.save_profile">
<segment>
<source>label_generator.save_profile</source>
<target>Save as new profile</target>
</segment>
</unit>
<unit id="sqc4h7S" name="label_generator.profile_saved">
<segment>
<source>label_generator.profile_saved</source>
<target>Profile saved!</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>

View file

@ -1,17 +1,23 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de"> <xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="de">
<file id="security.en"> <file id="security.en">
<unit id="aazoCks" name="user.login_error.user_disabled"> <unit id="GrLNa9P" name="user.login_error.user_disabled">
<segment state="translated"> <segment state="translated">
<source>user.login_error.user_disabled</source> <source>user.login_error.user_disabled</source>
<target>Ihr Account ist deaktiviert! Kontaktiere einen Administrator, wenn Sie denken, dass dies ein Fehler ist.</target> <target>Ihr Account ist deaktiviert! Kontaktiere einen Administrator, wenn Sie denken, dass dies ein Fehler ist.</target>
</segment> </segment>
</unit> </unit>
<unit id="Dpb9AmY" name="saml.error.cannot_login_local_user_per_saml"> <unit id="IFQ5XrG" name="saml.error.cannot_login_local_user_per_saml">
<segment state="translated"> <segment state="translated">
<source>saml.error.cannot_login_local_user_per_saml</source> <source>saml.error.cannot_login_local_user_per_saml</source>
<target>Sie können sich per SSO nicht als lokaler Nutzer einloggen! Nutzen Sie stattdessen ihr lokales Passwort.</target> <target>Sie können sich per SSO nicht als lokaler Nutzer einloggen! Nutzen Sie stattdessen ihr lokales Passwort.</target>
</segment> </segment>
</unit> </unit>
<unit id="wOYPZmb" name="saml.error.cannot_login_saml_user_locally">
<segment state="translated">
<source>saml.error.cannot_login_saml_user_locally</source>
<target>Sie können sich nicht mittels lokaler Authentifizierung als SAML Benutzer einloggen! Benutzen Sie stattdessen den SSO login.</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>

View file

@ -1,17 +1,23 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="it"> <xliff xmlns="urn:oasis:names:tc:xliff:document:2.0" version="2.0" srcLang="en" trgLang="it">
<file id="security.en"> <file id="security.en">
<unit id="aazoCks" name="user.login_error.user_disabled"> <unit id="GrLNa9P" name="user.login_error.user_disabled">
<segment state="translated"> <segment state="translated">
<source>user.login_error.user_disabled</source> <source>user.login_error.user_disabled</source>
<target>Il tuo account è disabilitato! Contatta un amministratore se ritieni che non sia corretto.</target> <target>Il tuo account è disabilitato! Contatta un amministratore se ritieni che non sia corretto.</target>
</segment> </segment>
</unit> </unit>
<unit id="Dpb9AmY" name="saml.error.cannot_login_local_user_per_saml"> <unit id="IFQ5XrG" name="saml.error.cannot_login_local_user_per_saml">
<segment state="translated"> <segment state="translated">
<source>saml.error.cannot_login_local_user_per_saml</source> <source>saml.error.cannot_login_local_user_per_saml</source>
<target>Non è possibile accedere come utente locale tramite SSO! Usare invece la password locale.</target> <target>Non è possibile accedere come utente locale tramite SSO! Usare invece la password locale.</target>
</segment> </segment>
</unit> </unit>
<unit id="wOYPZmb" name="saml.error.cannot_login_saml_user_locally">
<segment state="translated">
<source>saml.error.cannot_login_saml_user_locally</source>
<target>Non si può usare l'autenticazione locale per effettuare l'accesso come utente SAML! Usare l'accesso SSO.</target>
</segment>
</unit>
</file> </file>
</xliff> </xliff>

View file

@ -36,8 +36,8 @@ if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore Encore
// directory where compiled assets will be stored // directory where compiled assets will be stored
.setOutputPath('public/build/') .setOutputPath('public/build/')
// This value doesn't matter, as the public path is set to auto later down. This is just to prevent a warning // Do not use a / prefix, here as that would break asset loading when serving Part-DB under a prefix!
.setPublicPath('/build') .setPublicPath('build')
// only needed for CDN's or subdirectory deploy (this should not be needeed, as we use auto public path) // only needed for CDN's or subdirectory deploy (this should not be needeed, as we use auto public path)
//.setManifestKeyPrefix('build/') //.setManifestKeyPrefix('build/')
@ -59,6 +59,12 @@ Encore
.addEntry('app', './assets/js/app.js') .addEntry('app', './assets/js/app.js')
.addEntry('webauthn_tfa', './assets/js/webauthn_tfa.js') .addEntry('webauthn_tfa', './assets/js/webauthn_tfa.js')
//Configure to just output the zxing wasm file, without parsing it
.addRule({
test: /zxing_reader\.wasm$/,
type: "asset/resource"
})
//.addEntry('page1', './assets/js/page1.js') //.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js') //.addEntry('page2', './assets/js/page2.js')
@ -189,6 +195,10 @@ if (Encore.isDev()) {
module.exports = Encore.getWebpackConfig(); module.exports = Encore.getWebpackConfig();
//Enable webpack auto public path (this only works in combination with WebpackAutoPathSubscriber!!) //Enable webassembly support
module.exports.experiments = module.exports.experiments || {};
module.exports.experiments.asyncWebAssembly = true;
//Enable webpack auto public path
//We do it here to supress a warning caused by webpack Encore //We do it here to supress a warning caused by webpack Encore
module.exports.output.publicPath = 'auto'; module.exports.output.publicPath = 'auto';

371
yarn.lock
View file

@ -2,58 +2,58 @@
# yarn lockfile v1 # yarn lockfile v1
"@algolia/autocomplete-core@1.17.8": "@algolia/autocomplete-core@1.17.9":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.8.tgz#769e365d0e24233658eeb15a0a8b4572016c0924" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.9.tgz#83374c47dc72482aa45d6b953e89377047f0dcdc"
integrity sha512-WKQS6+83DYB7bsCN7HUxPGzwR1ZtKy+E8WybnuxnsGzQG/zd4j96R4USqsjz0/tOQVAA4hnlqNn9LtcaOIjCyQ== integrity sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ==
dependencies: dependencies:
"@algolia/autocomplete-plugin-algolia-insights" "1.17.8" "@algolia/autocomplete-plugin-algolia-insights" "1.17.9"
"@algolia/autocomplete-shared" "1.17.8" "@algolia/autocomplete-shared" "1.17.9"
"@algolia/autocomplete-js@1.17.8", "@algolia/autocomplete-js@^1.17.0": "@algolia/autocomplete-js@1.17.9", "@algolia/autocomplete-js@^1.17.0":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-js/-/autocomplete-js-1.17.8.tgz#2d4a5928d12bd51e16d84388e893431526bd542f" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-js/-/autocomplete-js-1.17.9.tgz#2f7e5599fdfe7d6c44b82ac5b64662b487615465"
integrity sha512-WQ5xZ5sY16UH6V0+ACpe2NoKPWs9L/m5uQQn8eNiM7jsHShonEhwV3/kB897k1TovfHqhtH0gPXXMN95taZAqA== integrity sha512-51xmsIfApj8LEceArnLe3UfS8HSgJJa70FUEYpnLryO6+KZL0pDPQHw1uVw6e5yJiKN0KelDmk2Sa2uJ+gVKJw==
dependencies: dependencies:
"@algolia/autocomplete-core" "1.17.8" "@algolia/autocomplete-core" "1.17.9"
"@algolia/autocomplete-preset-algolia" "1.17.8" "@algolia/autocomplete-preset-algolia" "1.17.9"
"@algolia/autocomplete-shared" "1.17.8" "@algolia/autocomplete-shared" "1.17.9"
htm "^3.1.1" htm "^3.1.1"
preact "^10.13.2" preact "^10.13.2"
"@algolia/autocomplete-plugin-algolia-insights@1.17.8": "@algolia/autocomplete-plugin-algolia-insights@1.17.9":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.8.tgz#e16f56e4c023bf3776347b6382b4a19e2c0341a8" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.9.tgz#74c86024d09d09e8bfa3dd90b844b77d9f9947b6"
integrity sha512-aNbLpDONZejsQKdozt0c6mFvUc8yINpv6WgHyJ9oZm4GFkwtbe0KWTlowyNIO/yRaoGC+Y0BkmSLMnGImy01eQ== integrity sha512-u1fEHkCbWF92DBeB/KHeMacsjsoI0wFhjZtlCq2ddZbAehshbZST6Hs0Avkc0s+4UyBGbMDnSuXHLuvRWK5iDQ==
dependencies: dependencies:
"@algolia/autocomplete-shared" "1.17.8" "@algolia/autocomplete-shared" "1.17.9"
"@algolia/autocomplete-plugin-recent-searches@^1.17.0": "@algolia/autocomplete-plugin-recent-searches@^1.17.0":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-recent-searches/-/autocomplete-plugin-recent-searches-1.17.8.tgz#1e7c6459cb909e899d9933a8297ba35106e77f82" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-recent-searches/-/autocomplete-plugin-recent-searches-1.17.9.tgz#607c9317834d1bc2661f2e036dd7eb4e87e180f6"
integrity sha512-bwH/fus481LyRMFhM1BTaiWDkHgmJ1ojlRxUSIPEVauszZFd0cLtWUf4FEwkoQS3NOUpj9xMJr5zVFmq4AoXHA== integrity sha512-UWJoCFKprKwDEuzfXWt34+Yf01qlR5P1pWEfWeYTNnmV27P3prw6sZKy7anE8+yXVkmiDss6oMVNyYyYZ7+ZtQ==
dependencies: dependencies:
"@algolia/autocomplete-core" "1.17.8" "@algolia/autocomplete-core" "1.17.9"
"@algolia/autocomplete-js" "1.17.8" "@algolia/autocomplete-js" "1.17.9"
"@algolia/autocomplete-preset-algolia" "1.17.8" "@algolia/autocomplete-preset-algolia" "1.17.9"
"@algolia/autocomplete-shared" "1.17.8" "@algolia/autocomplete-shared" "1.17.9"
"@algolia/autocomplete-preset-algolia@1.17.8": "@algolia/autocomplete-preset-algolia@1.17.9":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.8.tgz#cdcc63993ee69a9e9fb6ed518e8039af33709db1" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.9.tgz#911f3250544eb8ea4096fcfb268f156b085321b5"
integrity sha512-EHGmvfV9Y6HzDlTSt/AAdOthVTH8zgr6A4h9ehheDsAjqsyXj9uNvMAd4lq5bOJs+MZCWTcxpK+Btr9Tcihr3g== integrity sha512-Na1OuceSJeg8j7ZWn5ssMu/Ax3amtOwk76u4h5J4eK2Nx2KB5qt0Z4cOapCsxot9VcEN11ADV5aUSlQF4RhGjQ==
dependencies: dependencies:
"@algolia/autocomplete-shared" "1.17.8" "@algolia/autocomplete-shared" "1.17.9"
"@algolia/autocomplete-shared@1.17.8": "@algolia/autocomplete-shared@1.17.9":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.8.tgz#aad70ec1bda2ae75f284c23b52295c2e6ada9493" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.9.tgz#5f38868f7cb1d54b014b17a10fc4f7e79d427fa8"
integrity sha512-2w26RGB9zlyrnPpT/TpB0pbtukmUVYrKVt9ydlHnpPU7FgoiblUBpzzQTVzqMqYASGGjURaKLu7FakmaTIkClg== integrity sha512-iDf05JDQ7I0b7JEA/9IektxN/80a2MZ1ToohfmNS3rfeuQnIKI3IJlIafD0xu4StbtQTghx9T3Maa97ytkXenQ==
"@algolia/autocomplete-theme-classic@^1.17.0": "@algolia/autocomplete-theme-classic@^1.17.0":
version "1.17.8" version "1.17.9"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.17.8.tgz#cd635a6240da44dcd3aec72b0e5bea0382248710" resolved "https://registry.yarnpkg.com/@algolia/autocomplete-theme-classic/-/autocomplete-theme-classic-1.17.9.tgz#df73d5f6a3c4674d46df9add3bb751bfb1bcf144"
integrity sha512-70IJMktChk6mFTqegBYZk5MR0vquX+JEUG7rc4Jo75LTbe3BN4Lh6nUwaBXoLpx4v1zMID1vOsJ0Zv1M/3q3Jw== integrity sha512-nCv0uv5J5r9riF1rJLfUY3AAJ11IbFifNocYINWG4cyOctHGoiK5ZDyYdQOLA98TCVR7hUywIYpvVCJBZnjGaw==
"@ampproject/remapping@^2.2.0": "@ampproject/remapping@^2.2.0":
version "2.3.0" version "2.3.0"
@ -1664,10 +1664,10 @@
base64-js "1.3.1" base64-js "1.3.1"
unicode-trie "^2.0.0" unicode-trie "^2.0.0"
"@foliojs-fork/pdfkit@^0.15.2": "@foliojs-fork/pdfkit@^0.15.3":
version "0.15.2" version "0.15.3"
resolved "https://registry.yarnpkg.com/@foliojs-fork/pdfkit/-/pdfkit-0.15.2.tgz#6dbe57ed45f1dc022d0219f3810071b9007e347e" resolved "https://registry.yarnpkg.com/@foliojs-fork/pdfkit/-/pdfkit-0.15.3.tgz#590b31e770a98e2af62ce44f268a0d06b41ff32f"
integrity sha512-Wpj6BH4DGn+zAWmCk9agdbAw3Zxt+MpemjssLfYdnretWpZ014uR6Zo51E4ftVP75UA8a7mtt4TiCu09lIKsBw== integrity sha512-Obc0Wmy3bm7BINFVvPhcl2rnSSK61DQrlHU8aXnAqDk9LCjWdUOPwhgD8Ywz5VtuFjRxmVOM/kQ/XLIBjDvltw==
dependencies: dependencies:
"@foliojs-fork/fontkit" "^1.9.2" "@foliojs-fork/fontkit" "^1.9.2"
"@foliojs-fork/linebreak" "^1.1.1" "@foliojs-fork/linebreak" "^1.1.1"
@ -1680,44 +1680,44 @@
resolved "https://registry.yarnpkg.com/@foliojs-fork/restructure/-/restructure-2.0.2.tgz#73759aba2aff1da87b7c4554e6839c70d43c92b4" resolved "https://registry.yarnpkg.com/@foliojs-fork/restructure/-/restructure-2.0.2.tgz#73759aba2aff1da87b7c4554e6839c70d43c92b4"
integrity sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA== integrity sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==
"@formatjs/ecma402-abstract@2.3.1": "@formatjs/ecma402-abstract@2.3.2":
version "2.3.1" version "2.3.2"
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.1.tgz#cdeb3ffe1aeea9c4284b85b7e37e8e8615314c39" resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.2.tgz#0ee291effe7ee2c340742a6c95d92eacb5e6c00a"
integrity sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw== integrity sha512-6sE5nyvDloULiyOMbOTJEEgWL32w+VHkZQs8S02Lnn8Y/O5aQhjOEXwWzvR7SsBE/exxlSpY2EsWZgqHbtLatg==
dependencies: dependencies:
"@formatjs/fast-memoize" "2.2.5" "@formatjs/fast-memoize" "2.2.6"
"@formatjs/intl-localematcher" "0.5.9" "@formatjs/intl-localematcher" "0.5.10"
decimal.js "10" decimal.js "10"
tslib "2" tslib "2"
"@formatjs/fast-memoize@2.2.5": "@formatjs/fast-memoize@2.2.6":
version "2.2.5" version "2.2.6"
resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.5.tgz#54a4a1793d773b72c372d3dcab3595149aee7880" resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz#fac0a84207a1396be1f1aa4ee2805b179e9343d1"
integrity sha512-6PoewUMrrcqxSoBXAOJDiW1m+AmkrAj0RiXnOMD59GRaswjXhm3MDhgepXPBgonc09oSirAJTsAggzAGQf6A6g== integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw==
dependencies: dependencies:
tslib "2" tslib "2"
"@formatjs/icu-messageformat-parser@2.9.7": "@formatjs/icu-messageformat-parser@2.9.8":
version "2.9.7" version "2.9.8"
resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.7.tgz#84abd5c86ef2ad7cb82da63b3380c33808efb6da" resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.8.tgz#118e7156f8a8db6b27b650f09334db21456c681f"
integrity sha512-cuEHyRM5VqLQobANOjtjlgU7+qmk9Q3fDQuBiRRJ3+Wp3ZoZhpUPtUfuimZXsir6SaI2TaAJ+SLo9vLnV5QcbA== integrity sha512-hZlLNI3+Lev8IAXuwehLoN7QTKqbx3XXwFW1jh0AdIA9XJdzn9Uzr+2LLBspPm/PX0+NLIfykj/8IKxQqHUcUQ==
dependencies: dependencies:
"@formatjs/ecma402-abstract" "2.3.1" "@formatjs/ecma402-abstract" "2.3.2"
"@formatjs/icu-skeleton-parser" "1.8.11" "@formatjs/icu-skeleton-parser" "1.8.12"
tslib "2" tslib "2"
"@formatjs/icu-skeleton-parser@1.8.11": "@formatjs/icu-skeleton-parser@1.8.12":
version "1.8.11" version "1.8.12"
resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.11.tgz#e7c9918274dfa0c1c2bca1ab6e15ef49b10cf0bb" resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.12.tgz#43076747cdbe0f23bfac2b2a956bd8219716680d"
integrity sha512-8LlHHE/yL/zVJZHAX3pbKaCjZKmBIO6aJY1mkVh4RMSEu/2WRZ4Ysvv3kKXJ9M8RJLBHdnk1/dUQFdod1Dt7Dw== integrity sha512-QRAY2jC1BomFQHYDMcZtClqHR55EEnB96V7Xbk/UiBodsuFc5kujybzt87+qj1KqmJozFhk6n4KiT1HKwAkcfg==
dependencies: dependencies:
"@formatjs/ecma402-abstract" "2.3.1" "@formatjs/ecma402-abstract" "2.3.2"
tslib "2" tslib "2"
"@formatjs/intl-localematcher@0.5.9": "@formatjs/intl-localematcher@0.5.10":
version "0.5.9" version "0.5.10"
resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.9.tgz#43c6ee22be85b83340bcb09bdfed53657a2720db" resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz#1e0bd3fc1332c1fe4540cfa28f07e9227b659a58"
integrity sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA== integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q==
dependencies: dependencies:
tslib "2" tslib "2"
@ -1874,6 +1874,13 @@
resolved "https://registry.yarnpkg.com/@orchidjs/unicode-variants/-/unicode-variants-1.1.2.tgz#1fd71791a67fdd1591ebe0dcaadd3964537a824e" resolved "https://registry.yarnpkg.com/@orchidjs/unicode-variants/-/unicode-variants-1.1.2.tgz#1fd71791a67fdd1591ebe0dcaadd3964537a824e"
integrity sha512-5DobW1CHgnBROOEpFlEXytED5OosEWESFvg/VYmH0143oXcijYTprRYJTs+55HzGM4IqxiLFSuqEzu9mPNwVsA== integrity sha512-5DobW1CHgnBROOEpFlEXytED5OosEWESFvg/VYmH0143oXcijYTprRYJTs+55HzGM4IqxiLFSuqEzu9mPNwVsA==
"@part-db/html5-qrcode@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@part-db/html5-qrcode/-/html5-qrcode-3.1.1.tgz#96bf5e57796f3ec72ee6191ac7b8604298c98dfa"
integrity sha512-6lH77mvu9ClwIfKHWSOW1+jz+SkCJnbm/8XTuzqlcUWUIW8NRHC5x1wU7svV4gtoirqvBlQvaz1MaopVmfOAqQ==
dependencies:
barcode-detector "^2.3.1"
"@polka/url@^1.0.0-next.24": "@polka/url@^1.0.0-next.24":
version "1.0.0-next.28" version "1.0.0-next.28"
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73"
@ -1932,6 +1939,16 @@
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
"@types/dom-webcodecs@0.1.11":
version "0.1.11"
resolved "https://registry.yarnpkg.com/@types/dom-webcodecs/-/dom-webcodecs-0.1.11.tgz#2e36e5cc71789551f107e2fe15d956845fa19567"
integrity sha512-yPEZ3z7EohrmOxbk/QTAa0yonMFkNkjnVXqbGb7D4rMr+F1dGQ8ZUFxXkyLLJuiICPejZ0AZE9Rrk9wUCczx4A==
"@types/emscripten@^1.39.13":
version "1.39.13"
resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.13.tgz#afeb1648648dc096efe57983e20387627306e2aa"
integrity sha512-cFq+fO/isvhvmuP/+Sl4K4jtU6E23DoivtbO4r50e3odaxAiVdbfSYRDdJ4gCdxx+3aRjhphS5ZMwIH4hFy/Cw==
"@types/eslint-scope@^3.7.7": "@types/eslint-scope@^3.7.7":
version "3.7.7" version "3.7.7"
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5"
@ -1991,9 +2008,9 @@
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
"@types/node@*": "@types/node@*":
version "22.10.2" version "22.10.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.5.tgz#95af89a3fb74a2bb41ef9927f206e6472026e48b"
integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== integrity sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==
dependencies: dependencies:
undici-types "~6.20.0" undici-types "~6.20.0"
@ -2401,6 +2418,14 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
barcode-detector@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/barcode-detector/-/barcode-detector-2.3.1.tgz#91d0d4e3b913d87f94bae5d024b6b9b5cedc420c"
integrity sha512-D9KEtrquS1tmBZduxBZl8qublIKnRrFqD8TAHDYcLCyrHQBo+vitIxmjMJ61LvXjXyAMalOlO7q0Oh/9Rl2PbQ==
dependencies:
"@types/dom-webcodecs" "0.1.11"
zxing-wasm "1.3.4"
base64-js@1.3.1: base64-js@1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
@ -3110,11 +3135,11 @@ data-view-byte-offset@^1.0.1:
is-data-view "^1.0.1" is-data-view "^1.0.1"
datatables.net-bs5@^2, datatables.net-bs5@^2.0.0: datatables.net-bs5@^2, datatables.net-bs5@^2.0.0:
version "2.1.8" version "2.2.0"
resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.1.8.tgz#860717c4ee85ecb84812ba9a73fb1204aa2a68b6" resolved "https://registry.yarnpkg.com/datatables.net-bs5/-/datatables.net-bs5-2.2.0.tgz#ba80819825b96827d6361f8385b092c2a657a8af"
integrity sha512-YlGws8eI3iw/1AmKJH18+YMzm/UgGb6o9s14KAC24QT1/8anolm8GnVAgGcwUcvHm3hn1i8A5QXqgbqeMRINeg== integrity sha512-klqdrghM0BkBWulaWiGdKwdZyPHK+8coBGjhSQAZe/eQBnr7OLC8wl7NqPfQuVXv4J74HgO6K1gIYHKHbHjrtA==
dependencies: dependencies:
datatables.net "2.1.8" datatables.net "2.2.0"
jquery ">=1.7" jquery ">=1.7"
datatables.net-buttons-bs5@^3.0.0: datatables.net-buttons-bs5@^3.0.0:
@ -3202,10 +3227,10 @@ datatables.net-select@2.1.0:
datatables.net "^2" datatables.net "^2"
jquery ">=1.7" jquery ">=1.7"
datatables.net@2.1.8, datatables.net@^2, datatables.net@^2.0.0: datatables.net@2.2.0, datatables.net@^2, datatables.net@^2.0.0:
version "2.1.8" version "2.2.0"
resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.1.8.tgz#9b020f18e927cc924d72411f62dc595cc688669b" resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-2.2.0.tgz#d7e92ede9a3bf23ac4c360e475fbe6313f16fd56"
integrity sha512-47ULt+U4bcjbuGTpTlT6SnCuSFVRBxxdWa6X3NfvTObBJ2BZU0o+JUIl05wQ6cABNIavjbAV51gpgvFsMHL9zA== integrity sha512-q/G5ylL+AhMLFFHNYQAgvooCZtmbudc7wwzKkCZI4B1HnYec4SqnWtcTFjC7P6EtL1UGyx16FcjQ0U84S86mLg==
dependencies: dependencies:
jquery ">=1.7" jquery ">=1.7"
@ -3365,9 +3390,9 @@ domutils@^2.5.2, domutils@^2.8.0:
domhandler "^4.2.0" domhandler "^4.2.0"
domutils@^3.0.1: domutils@^3.0.1:
version "3.2.1" version "3.2.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.1.tgz#b39f4c390a1ae6f6a2c56a5f5a16d6438b6bce28" resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78"
integrity sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw== integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
dependencies: dependencies:
dom-serializer "^2.0.0" dom-serializer "^2.0.0"
domelementtype "^2.3.0" domelementtype "^2.3.0"
@ -3388,9 +3413,9 @@ duplexer@^0.1.2:
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
electron-to-chromium@^1.5.73: electron-to-chromium@^1.5.73:
version "1.5.76" version "1.5.78"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz#db20295c5061b68f07c8ea4dfcbd701485d94a3d" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.78.tgz#223cdc76a5d15ac731136e68430e92cb8d612d13"
integrity sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ== integrity sha512-UmwIt7HRKN1rsJfddG5UG7rCTCTAKoS9JeOy/R0zSenAyaZ8SU3RuXlwcratxhdxGRNpk03iq8O7BA3W7ibLVw==
emoji-regex@^7.0.1: emoji-regex@^7.0.1:
version "7.0.3" version "7.0.3"
@ -3449,10 +3474,10 @@ error-stack-parser@^2.1.4:
dependencies: dependencies:
stackframe "^1.3.4" stackframe "^1.3.4"
es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.6: es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.9:
version "1.23.8" version "1.23.9"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.8.tgz#99754723118355d82fcef9ce4c90ccbcd5d2a285" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606"
integrity sha512-lfab8IzDn6EpI1ibZakcgS6WsfEBiB+43cuJo+wgylx1xKXf+Sp+YR3vFuQwC/u3sxYwV8Cxe3B0DpVUu/WiJQ== integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==
dependencies: dependencies:
array-buffer-byte-length "^1.0.2" array-buffer-byte-length "^1.0.2"
arraybuffer.prototype.slice "^1.0.4" arraybuffer.prototype.slice "^1.0.4"
@ -3465,10 +3490,11 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.6:
es-define-property "^1.0.1" es-define-property "^1.0.1"
es-errors "^1.3.0" es-errors "^1.3.0"
es-object-atoms "^1.0.0" es-object-atoms "^1.0.0"
es-set-tostringtag "^2.0.3" es-set-tostringtag "^2.1.0"
es-to-primitive "^1.3.0" es-to-primitive "^1.3.0"
function.prototype.name "^1.1.8" function.prototype.name "^1.1.8"
get-intrinsic "^1.2.6" get-intrinsic "^1.2.7"
get-proto "^1.0.0"
get-symbol-description "^1.1.0" get-symbol-description "^1.1.0"
globalthis "^1.0.4" globalthis "^1.0.4"
gopd "^1.2.0" gopd "^1.2.0"
@ -3489,11 +3515,12 @@ es-abstract@^1.23.2, es-abstract@^1.23.5, es-abstract@^1.23.6:
object-inspect "^1.13.3" object-inspect "^1.13.3"
object-keys "^1.1.1" object-keys "^1.1.1"
object.assign "^4.1.7" object.assign "^4.1.7"
own-keys "^1.0.0" own-keys "^1.0.1"
regexp.prototype.flags "^1.5.3" regexp.prototype.flags "^1.5.3"
safe-array-concat "^1.1.3" safe-array-concat "^1.1.3"
safe-push-apply "^1.0.0" safe-push-apply "^1.0.0"
safe-regex-test "^1.1.0" safe-regex-test "^1.1.0"
set-proto "^1.0.0"
string.prototype.trim "^1.2.10" string.prototype.trim "^1.2.10"
string.prototype.trimend "^1.0.9" string.prototype.trimend "^1.0.9"
string.prototype.trimstart "^1.0.8" string.prototype.trimstart "^1.0.8"
@ -3531,14 +3558,15 @@ es-object-atoms@^1.0.0:
dependencies: dependencies:
es-errors "^1.3.0" es-errors "^1.3.0"
es-set-tostringtag@^2.0.3: es-set-tostringtag@^2.1.0:
version "2.0.3" version "2.1.0"
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
dependencies: dependencies:
get-intrinsic "^1.2.4" es-errors "^1.3.0"
get-intrinsic "^1.2.6"
has-tostringtag "^1.0.2" has-tostringtag "^1.0.2"
hasown "^2.0.1" hasown "^2.0.2"
es-to-primitive@^1.3.0: es-to-primitive@^1.3.0:
version "1.3.0" version "1.3.0"
@ -3655,15 +3683,15 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-glob@^3.0.3, fast-glob@^3.2.11: fast-glob@^3.0.3, fast-glob@^3.2.11:
version "3.3.2" version "3.3.3"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
dependencies: dependencies:
"@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.stat" "^2.0.2"
"@nodelib/fs.walk" "^1.2.3" "@nodelib/fs.walk" "^1.2.3"
glob-parent "^5.1.2" glob-parent "^5.1.2"
merge2 "^1.3.0" merge2 "^1.3.0"
micromatch "^4.0.4" micromatch "^4.0.8"
fast-json-stable-stringify@^2.0.0: fast-json-stable-stringify@^2.0.0:
version "2.1.0" version "2.1.0"
@ -3671,9 +3699,9 @@ fast-json-stable-stringify@^2.0.0:
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-uri@^3.0.1: fast-uri@^3.0.1:
version "3.0.3" version "3.0.5"
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.3.tgz#892a1c91802d5d7860de728f18608a0573142241" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.5.tgz#19f5f9691d0dab9b85861a7bb5d98fca961da9cd"
integrity sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw== integrity sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==
fastest-levenshtein@1.0.16, fastest-levenshtein@^1.0.12, fastest-levenshtein@^1.0.16: fastest-levenshtein@1.0.16, fastest-levenshtein@^1.0.12, fastest-levenshtein@^1.0.16:
version "1.0.16" version "1.0.16"
@ -3811,21 +3839,29 @@ get-caller-file@^2.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6: get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7:
version "1.2.6" version "1.2.7"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.6.tgz#43dd3dd0e7b49b82b2dfcad10dc824bf7fc265d5" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044"
integrity sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA== integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==
dependencies: dependencies:
call-bind-apply-helpers "^1.0.1" call-bind-apply-helpers "^1.0.1"
dunder-proto "^1.0.0"
es-define-property "^1.0.1" es-define-property "^1.0.1"
es-errors "^1.3.0" es-errors "^1.3.0"
es-object-atoms "^1.0.0" es-object-atoms "^1.0.0"
function-bind "^1.1.2" function-bind "^1.1.2"
get-proto "^1.0.0"
gopd "^1.2.0" gopd "^1.2.0"
has-symbols "^1.1.0" has-symbols "^1.1.0"
hasown "^2.0.2" hasown "^2.0.2"
math-intrinsics "^1.0.0" math-intrinsics "^1.1.0"
get-proto@^1.0.0, get-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
dependencies:
dunder-proto "^1.0.1"
es-object-atoms "^1.0.0"
get-symbol-description@^1.1.0: get-symbol-description@^1.1.0:
version "1.1.0" version "1.1.0"
@ -3979,14 +4015,14 @@ has-symbols@^1.0.0, has-symbols@^1.0.3, has-symbols@^1.1.0:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: has-tostringtag@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
dependencies: dependencies:
has-symbols "^1.0.3" has-symbols "^1.0.3"
hasown@^2.0.1, hasown@^2.0.2: hasown@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
@ -4008,11 +4044,6 @@ html-escaper@^2.0.2:
resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
html5-qrcode@^2.2.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/html5-qrcode/-/html5-qrcode-2.3.8.tgz#0b0cdf7a9926cfd4be530e13a51db47592adfa0d"
integrity sha512-jsr4vafJhwoLVEDW3n1KvPnCCXWaQfRng0/EEYk1vNcQGcG/htAdhJX0be8YyqMoSz7+hZvOZSTAepsabiuhiQ==
htmlparser2@^6.1.0: htmlparser2@^6.1.0:
version "6.1.0" version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@ -4109,13 +4140,13 @@ interpret@^3.1.1:
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
intl-messageformat@^10.2.5: intl-messageformat@^10.2.5:
version "10.7.10" version "10.7.11"
resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.10.tgz#fc8fc8c13b0a4104ba08dc2f5f9225f14945bcb7" resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.11.tgz#f24893b2a64e7b5ec29f9eceb4f1a58bde1346e0"
integrity sha512-hp7iejCBiJdW3zmOe18FdlJu8U/JsADSDiBPQhfdSeI8B9POtvPRvPh3nMlvhYayGMKLv6maldhR7y3Pf1vkpw== integrity sha512-IB2N1tmI24k2EFH3PWjU7ivJsnWyLwOWOva0jnXFa29WzB6fb0JZ5EMQGu+XN5lDtjHYFo0/UooP67zBwUg7rQ==
dependencies: dependencies:
"@formatjs/ecma402-abstract" "2.3.1" "@formatjs/ecma402-abstract" "2.3.2"
"@formatjs/fast-memoize" "2.2.5" "@formatjs/fast-memoize" "2.2.6"
"@formatjs/icu-messageformat-parser" "2.9.7" "@formatjs/icu-messageformat-parser" "2.9.8"
tslib "2" tslib "2"
is-arguments@^1.1.1: is-arguments@^1.1.1:
@ -4141,11 +4172,14 @@ is-arrayish@^0.2.1:
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-async-function@^2.0.0: is-async-function@^2.0.0:
version "2.0.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.0.tgz#1d1080612c493608e93168fc4458c245074c06a6"
integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== integrity sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==
dependencies: dependencies:
has-tostringtag "^1.0.0" call-bound "^1.0.3"
get-proto "^1.0.1"
has-tostringtag "^1.0.2"
safe-regex-test "^1.1.0"
is-bigint@^1.1.0: is-bigint@^1.1.0:
version "1.1.0" version "1.1.0"
@ -4231,11 +4265,14 @@ is-fullwidth-code-point@^3.0.0:
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-generator-function@^1.0.10: is-generator-function@^1.0.10:
version "1.0.10" version "1.1.0"
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca"
integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==
dependencies: dependencies:
has-tostringtag "^1.0.0" call-bound "^1.0.3"
get-proto "^1.0.0"
has-tostringtag "^1.0.2"
safe-regex-test "^1.1.0"
is-glob@^4.0.1, is-glob@~4.0.1: is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.3" version "4.0.3"
@ -4640,11 +4677,11 @@ marked@4.0.12:
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ== integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
marked@^15.0.4: marked@^15.0.4:
version "15.0.4" version "15.0.6"
resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.4.tgz#864dbf50227b6507646c771c2ef5f0de2924833e" resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.6.tgz#8165f16afb6f4b30a35bdcee657c3b8415820a8f"
integrity sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw== integrity sha512-Y07CUOE+HQXbVDCGl3LXggqJDbXDP2pArc2C1N1RRMN0ONiShoSsIInMd5Gsxupe7fKLpgimTV+HOJ9r7bA+pg==
math-intrinsics@^1.0.0, math-intrinsics@^1.1.0: math-intrinsics@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
@ -4669,7 +4706,7 @@ merge2@^1.2.3, merge2@^1.3.0:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micromatch@^4.0.0, micromatch@^4.0.4: micromatch@^4.0.0, micromatch@^4.0.8:
version "4.0.8" version "4.0.8"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
@ -4938,10 +4975,10 @@ opener@^1.5.2:
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
own-keys@^1.0.0: own-keys@^1.0.1:
version "1.0.0" version "1.0.1"
resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.0.tgz#4ab4f9758185bd8f2716f95453ea7da72fb56c09" resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358"
integrity sha512-HcuIjzpjrUbqZPGzWHVg95Bc2Y37KoY5n66QQyEGMzrIWVKHsgHcv8/Aq5Cu3qFUQJzMSPVP8MD3oaFoaME1lg== integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==
dependencies: dependencies:
get-intrinsic "^1.2.6" get-intrinsic "^1.2.6"
object-keys "^1.1.1" object-keys "^1.1.1"
@ -5071,12 +5108,12 @@ path-type@^4.0.0:
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pdfmake@^0.2.2: pdfmake@^0.2.2:
version "0.2.17" version "0.2.18"
resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.2.17.tgz#64beeb0b09c7e0ade39b6d4b379371818cea3da5" resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.2.18.tgz#0be32a9274466494a69285193b64f61f3198ea4e"
integrity sha512-ODOp1T232yr/HGjdYCq888paBE7RDCflCOSRDUtR9CyfXneOmnMPZJl8dxP9zEXbKiv9vfk9Z/3eK2V2B/Wx/Q== integrity sha512-Fe+GnMS8EVZu5rci/CDaQ+xmUoHvx8P+rvIlrwSYM6A5c7Aik8G6lpJbddhjBE2jXGjv6WcUCFCB06uZbjxkMw==
dependencies: dependencies:
"@foliojs-fork/linebreak" "^1.1.2" "@foliojs-fork/linebreak" "^1.1.2"
"@foliojs-fork/pdfkit" "^0.15.2" "@foliojs-fork/pdfkit" "^0.15.3"
iconv-lite "^0.6.3" iconv-lite "^0.6.3"
xmldoc "^1.3.0" xmldoc "^1.3.0"
@ -5130,11 +5167,11 @@ possible-typed-array-names@^1.0.0:
integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
postcss-calc@^10.0.2: postcss-calc@^10.0.2:
version "10.0.2" version "10.1.0"
resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.0.2.tgz#15f01635a27b9d38913a98c4ef2877f5b715b439" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-10.1.0.tgz#82548b9d52891b87cf6181a445bea4b78e2eedfb"
integrity sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg== integrity sha512-uQ/LDGsf3mgsSUEXmAt3VsCSHR3aKqtEIkmB+4PhzYwRYOW5MZs/GhCCFpsOtJJkP6EC6uGipbrnaTjqaJZcJw==
dependencies: dependencies:
postcss-selector-parser "^6.1.2" postcss-selector-parser "^7.0.0"
postcss-value-parser "^4.2.0" postcss-value-parser "^4.2.0"
postcss-calc@^9.0.1: postcss-calc@^9.0.1:
@ -5732,17 +5769,17 @@ rechoir@^0.8.0:
resolve "^1.20.0" resolve "^1.20.0"
reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9:
version "1.0.9" version "1.0.10"
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz#c905f3386008de95a62315f3ea8630404be19e2f" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9"
integrity sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q== integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==
dependencies: dependencies:
call-bind "^1.0.8" call-bind "^1.0.8"
define-properties "^1.2.1" define-properties "^1.2.1"
dunder-proto "^1.0.1" es-abstract "^1.23.9"
es-abstract "^1.23.6"
es-errors "^1.3.0" es-errors "^1.3.0"
get-intrinsic "^1.2.6" es-object-atoms "^1.0.0"
gopd "^1.2.0" get-intrinsic "^1.2.7"
get-proto "^1.0.1"
which-builtin-type "^1.2.1" which-builtin-type "^1.2.1"
regenerate-unicode-properties@^10.2.0: regenerate-unicode-properties@^10.2.0:
@ -5780,13 +5817,15 @@ regex-parser@^2.2.11:
integrity sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg== integrity sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==
regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3: regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3:
version "1.5.3" version "1.5.4"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19"
integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==
dependencies: dependencies:
call-bind "^1.0.7" call-bind "^1.0.8"
define-properties "^1.2.1" define-properties "^1.2.1"
es-errors "^1.3.0" es-errors "^1.3.0"
get-proto "^1.0.1"
gopd "^1.2.0"
set-function-name "^2.0.2" set-function-name "^2.0.2"
regexpu-core@^6.2.0: regexpu-core@^6.2.0:
@ -6036,6 +6075,15 @@ set-function-name@^2.0.2:
functions-have-names "^1.2.3" functions-have-names "^1.2.3"
has-property-descriptors "^1.0.2" has-property-descriptors "^1.0.2"
set-proto@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e"
integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==
dependencies:
dunder-proto "^1.0.1"
es-errors "^1.3.0"
es-object-atoms "^1.0.0"
setimmediate@^1.0.5: setimmediate@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
@ -6931,3 +6979,10 @@ yocto-queue@^1.0.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110"
integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==
zxing-wasm@1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/zxing-wasm/-/zxing-wasm-1.3.4.tgz#4bc45b78dc3594278bb0c24233bfb035ca9efab1"
integrity sha512-9l0QymyATF19FmI92QHe7Dayb+BUN7P7zFAt5iDgTnUf0dFWokz6GVA/W9EepjW5q8s3e89fIE/7uxpX27yqEQ==
dependencies:
"@types/emscripten" "^1.39.13"