2026-04-10

- corvée: met à jour les deps
- corvée: formate
This commit is contained in:
gcch 2026-04-10 17:21:57 +02:00
commit d50de6d534
85 changed files with 132090 additions and 31346 deletions

View file

@ -73,7 +73,11 @@ return new Config()
'multiline_comment_opening_closing' => true, 'multiline_comment_opening_closing' => true,
'native_constant_invocation' => true, 'native_constant_invocation' => true,
'native_function_casing' => true, 'native_function_casing' => true,
'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'namespaced', 'strict' => true], 'native_function_invocation' => [
'include' => ['@compiler_optimized'],
'scope' => 'namespaced',
'strict' => true,
],
'native_type_declaration_casing' => true, 'native_type_declaration_casing' => true,
'new_expression_parentheses' => true, 'new_expression_parentheses' => true,
'no_alias_functions' => ['sets' => ['@all']], 'no_alias_functions' => ['sets' => ['@all']],

View file

@ -1,9 +1,9 @@
{ {
"$schema": "./phpactor.schema.json", "$schema": "./phpactor.schema.json",
"indexer.exclude_patterns": [ "indexer.exclude_patterns": [
"/vendor/**/Tests/**/*",
"/vendor/**/tests/**/*",
"/var/cache/**/*", "/var/cache/**/*",
"/vendor/**/tests/**/*",
"/vendor/**/Tests/**/*",
"/vendor/composer/**/*" "/vendor/composer/**/*"
], ],
"language_server.diagnostic_outsource_timeout": 5, "language_server.diagnostic_outsource_timeout": 5,

View file

@ -15,9 +15,9 @@
"initialization_options": { "initialization_options": {
"settings": { "settings": {
"configPath": "cfg/oxlint.config.ts", "configPath": "cfg/oxlint.config.ts",
"run": "onType",
"disableNestedConfig": false, "disableNestedConfig": false,
"fixKind": "safe_fix", "fixKind": "safe_fix",
"run": "onType",
"unusedDisableDirectives": "deny" "unusedDisableDirectives": "deny"
} }
} }

200
bun.lock
View file

@ -8,14 +8,14 @@
"@mobily/ts-belt": "v4.0.0-rc.5", "@mobily/ts-belt": "v4.0.0-rc.5",
"@sentry/browser": "^10.47.0", "@sentry/browser": "^10.47.0",
"a11y-dialog": "^8.1.5", "a11y-dialog": "^8.1.5",
"effect": "^4.0.0-beta.43", "effect": "^4.0.0-beta.46",
"lit-html": "^3.3.2", "lit-html": "^3.3.2",
"purify-ts": "2.1.2", "purify-ts": "2.1.2",
"ts-pattern": "^5.9.0", "ts-pattern": "^5.9.0",
"valibot": "1.1.0", "valibot": "1.1.0",
}, },
"devDependencies": { "devDependencies": {
"@effect/language-service": "^0.84.3", "@effect/language-service": "^0.85.0",
"@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274", "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274",
"@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#0968f683", "@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#0968f683",
"@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#8de937e801", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#8de937e801",
@ -54,7 +54,7 @@
"stylelint-plugin-logical-css": "^2.1.0", "stylelint-plugin-logical-css": "^2.1.0",
"typescript": "6.0.2", "typescript": "6.0.2",
"typescript-eslint": "^8.58.1", "typescript-eslint": "^8.58.1",
"vite": "^8.0.7", "vite": "^8.0.8",
"vite-tsconfig-paths": "^6.1.1", "vite-tsconfig-paths": "^6.1.1",
}, },
}, },
@ -266,13 +266,13 @@
"@csstools/selector-specificity": ["@csstools/selector-specificity@6.0.0", "", { "peerDependencies": { "postcss-selector-parser": "^7.1.1" } }, "sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA=="], "@csstools/selector-specificity": ["@csstools/selector-specificity@6.0.0", "", { "peerDependencies": { "postcss-selector-parser": "^7.1.1" } }, "sha512-4sSgl78OtOXEX/2d++8A83zHNTgwCJMaR24FvsYL7Uf/VS8HZk9PTwR51elTbGqMuwH3szLvvOXEaVnqn0Z3zA=="],
"@effect/language-service": ["@effect/language-service@0.84.3", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-zpxi6rLCwst/cBQd7ElwDvt36Y6Jvz8v6bCLnNiOL6OXvdLmqjOFWyzWZdMh92vvBQA/aVKhfIAAOP3o4wKt0A=="], "@effect/language-service": ["@effect/language-service@0.85.1", "", { "bin": { "effect-language-service": "cli.js" } }, "sha512-EXnJjIy6zQ3nUO/MZ+ynWUb8B895KZPotd1++oTs9JjDkplwM7cb6zo8Zq2zU6piwq+KflO7amXbEfj1UMpHkw=="],
"@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="], "@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
"@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="], "@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="],
"@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="], "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
"@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.86.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.58.0", "comment-parser": "1.4.6", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.2.0" } }, "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw=="], "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.86.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.58.0", "comment-parser": "1.4.6", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~7.2.0" } }, "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw=="],
@ -282,17 +282,17 @@
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
"@eslint/config-array": ["@eslint/config-array@0.23.4", "", { "dependencies": { "@eslint/object-schema": "^3.0.4", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow=="], "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="],
"@eslint/config-helpers": ["@eslint/config-helpers@0.5.4", "", { "dependencies": { "@eslint/core": "^1.2.0" } }, "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg=="], "@eslint/config-helpers": ["@eslint/config-helpers@0.5.5", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w=="],
"@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="],
"@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="],
"@eslint/object-schema": ["@eslint/object-schema@3.0.4", "", {}, "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw=="], "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.0", "levn": "^0.4.1" } }, "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg=="], "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.1", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ=="],
"@gcch/configuration-eslint": ["@gcch/configuration-eslint@git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274f0bfebd5135a728960644f4b1cdcb8", { "dependencies": { "@eslint/js": "^10.0.1", "astro-eslint-parser": "^1.3.0", "eslint": "^10.0.3", "eslint-plugin-astro": "^1.6.0", "eslint-plugin-functional": "^9.0.4", "eslint-plugin-jsdoc": "^62.8.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-perfectionist": "^5.6.0", "eslint-plugin-sonarjs": "^4.0.2", "eslint-plugin-unicorn": "^63.0.0", "globals": "^17.4.0", "typescript-eslint": "^8.57.0" }, "peerDependencies": { "eslint": "^10.0.3", "typescript": "^6.0.1-rc" } }, "62ee424274f0bfebd5135a728960644f4b1cdcb8"], "@gcch/configuration-eslint": ["@gcch/configuration-eslint@git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274f0bfebd5135a728960644f4b1cdcb8", { "dependencies": { "@eslint/js": "^10.0.1", "astro-eslint-parser": "^1.3.0", "eslint": "^10.0.3", "eslint-plugin-astro": "^1.6.0", "eslint-plugin-functional": "^9.0.4", "eslint-plugin-jsdoc": "^62.8.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-perfectionist": "^5.6.0", "eslint-plugin-sonarjs": "^4.0.2", "eslint-plugin-unicorn": "^63.0.0", "globals": "^17.4.0", "typescript-eslint": "^8.57.0" }, "peerDependencies": { "eslint": "^10.0.3", "typescript": "^6.0.1-rc" } }, "62ee424274f0bfebd5135a728960644f4b1cdcb8"],
@ -338,7 +338,7 @@
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="], "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3", "", { "os": "win32", "cpu": "x64" }, "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ=="],
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.3", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
@ -512,49 +512,49 @@
"@reteps/dockerfmt": ["@reteps/dockerfmt@0.5.2", "", {}, "sha512-Hbr7yen4fP5TxGM54ucXa4o5NwWXatJ6Bd9I8gp0PValYbI4Rug2Gu+rVv7K7o/efQc3F5ctqWJz47rYaa8zBw=="], "@reteps/dockerfmt": ["@reteps/dockerfmt@0.5.2", "", {}, "sha512-Hbr7yen4fP5TxGM54ucXa4o5NwWXatJ6Bd9I8gp0PValYbI4Rug2Gu+rVv7K7o/efQc3F5ctqWJz47rYaa8zBw=="],
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.13", "", { "os": "android", "cpu": "arm64" }, "sha512-5ZiiecKH2DXAVJTNN13gNMUcCDg4Jy8ZjbXEsPnqa248wgOVeYRX0iqXXD5Jz4bI9BFHgKsI2qmyJynstbmr+g=="], "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.15", "", { "os": "android", "cpu": "arm64" }, "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA=="],
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tz/v/8G77seu8zAB3A5sK3UFoOl06zcshEzhUO62sAEtrEuW/H1CcyoupOrD+NbQJytYgA4CppXPzlrmp4JZKA=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg=="],
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-8DakphqOz8JrMYWTJmWA+vDJxut6LijZ8Xcdc4flOlAhU7PNVwo2MaWBF9iXjJAPo5rC/IxEFZDhJ3GC7NHvug=="], "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw=="],
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-4wBQFfjDuXYN/SVI8inBF3Aa+isq40rc6VMFbk5jcpolUBTe5cYnMsHZ51nFWsx3PVyyNN3vgoESki0Hmr/4BA=="], "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.15", "", { "os": "freebsd", "cpu": "x64" }, "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw=="],
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm" }, "sha512-JW/e4yPIXLms+jmnbwwy5LA/LxVwZUWLN8xug+V200wzaVi5TEGIWQlh8o91gWYFxW609euI98OCCemmWGuPrw=="], "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm" }, "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA=="],
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZfKWpXiUymDnavepCaM6KG/uGydJ4l2nBmMxg60Ci4CbeefpqjPWpfaZM7PThOhk2dssqBAcwLc6rAyr0uTdXg=="], "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w=="],
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-bmRg3O6Z0gq9yodKKWCIpnlH051sEfdVwt+6m5UDffAQMUUqU0xjnQqqAUm+Gu7ofAAly9DqiQDtKu2nPDEABA=="], "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ=="],
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8Wtnbw4k7pMYN9B/mOEAsQ8HOiq7AZ31Ig4M9BKn2So4xRaFEhtCSa4ZJaOutOWq50zpgR4N5+L/opnlaCx8wQ=="], "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "ppc64" }, "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ=="],
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "s390x" }, "sha512-D/0Nlo8mQuxSMohNJUF2lDXWRsFDsHldfRRgD9bRgktj+EndGPj4DOV37LqDKPYS+osdyhZEH7fTakTAEcW7qg=="], "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "s390x" }, "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ=="],
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-eRrPvat2YaVQcwwKi/JzOP6MKf1WRnOCr+VaI3cTWz3ZoLcP/654z90lVCJ4dAuMEpPdke0n+qyAqXDZdIC4rA=="], "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA=="],
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.13", "", { "os": "linux", "cpu": "x64" }, "sha512-PsdONiFRp8hR8KgVjTWjZ9s7uA3uueWL0t74/cKHfM4dR5zXYv4AjB8BvA+QDToqxAFg4ZkcVEqeu5F7inoz5w=="], "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.15", "", { "os": "linux", "cpu": "x64" }, "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw=="],
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.13", "", { "os": "none", "cpu": "arm64" }, "sha512-hCNXgC5dI3TVOLrPT++PKFNZ+1EtS0mLQwfXXXSUD/+rGlB65gZDwN/IDuxLpQP4x8RYYHqGomlUXzpO8aVI2w=="], "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.15", "", { "os": "none", "cpu": "arm64" }, "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg=="],
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.13", "", { "dependencies": { "@emnapi/core": "1.9.1", "@emnapi/runtime": "1.9.1", "@napi-rs/wasm-runtime": "^1.1.2" }, "cpu": "none" }, "sha512-viLS5C5et8NFtLWw9Sw3M/w4vvnVkbWkO7wSNh3C+7G1+uCkGpr6PcjNDSFcNtmXY/4trjPBqUfcOL+P3sWy/g=="], "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.15", "", { "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.3" }, "cpu": "none" }, "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q=="],
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-Fqa3Tlt1xL4wzmAYxGNFV36Hb+VfPc9PYU+E25DAnswXv3ODDu/yyWjQDbXMo5AGWkQVjLgQExuVu8I/UaZhPQ=="], "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA=="],
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.13", "", { "os": "win32", "cpu": "x64" }, "sha512-/pLI5kPkGEi44TDlnbio3St/5gUFeN51YWNAk/Gnv6mEQBOahRBh52qVFVBpmrnU01n2yysvBML9Ynu7K4kGAQ=="], "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.15", "", { "os": "win32", "cpu": "x64" }, "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g=="],
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.13", "", {}, "sha512-3ngTAv6F/Py35BsYbeeLeecvhMKdsKm4AoOETVhAA+Qc8nrA2I0kF7oa93mE9qnIurngOSpMnQ0x2nQY2FPviA=="], "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.15", "", {}, "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g=="],
"@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" } }, "sha512-bVFRAeJWMBcBCvJKIFCMJ1/yQToL4vPGqfmlnDZeypcxkqUDKQ/Y3ziLHXoDL2sx0lagcgU2vH1QhCQ67Aujjw=="], "@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.48.0", "", { "dependencies": { "@sentry/core": "10.48.0" } }, "sha512-SCiTLBXzugFKxev6NoKYBIhQoDk0gUh0AVVVepCBqfCJiWBG01Zvv0R5tCVohr4cWRllkQ8mlBdNQd/I7s9tdA=="],
"@sentry-internal/feedback": ["@sentry-internal/feedback@10.47.0", "", { "dependencies": { "@sentry/core": "10.47.0" } }, "sha512-pdvMmi4dQpX5S/vAAzrhHPIw3T3HjUgDNgUiCBrlp7N9/6zGO2gNPhUnNekP+CjgI/z0rvf49RLqlDenpNrMOg=="], "@sentry-internal/feedback": ["@sentry-internal/feedback@10.48.0", "", { "dependencies": { "@sentry/core": "10.48.0" } }, "sha512-tGkEyOM1HDS9qebDphUMEnyk3qq/50AnuTBiFmMJyjNzowylVGmRRk0sr3xkmbVHCDXQCiYnDmSVlJ2x4SDMrQ=="],
"@sentry-internal/replay": ["@sentry-internal/replay@10.47.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-ScdovxP7hJxgMt70+7hFvwT02GIaIUAxdEM/YPsayZBeCoAukPW8WiwztJfoKtsfPyKJ5A6f0H3PIxTPcA9Row=="], "@sentry-internal/replay": ["@sentry-internal/replay@10.48.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-sevRTePfuk4PNuz9KAKpmTZEomAU0aLXyIhOwA0OnUDdxPhkY8kq5lwDbuxTHv6DQUjUX3YgFbY45VH1JEqHKA=="],
"@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.47.0", "", { "dependencies": { "@sentry-internal/replay": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-A5OY8friSe6g8WAK4L8IeOPiEd9D3Ps40DzRH5j2f6SUja0t90mKMvHRcRf8zq0d4BkdB+JM7tjOkwxpuv8heA=="], "@sentry-internal/replay-canvas": ["@sentry-internal/replay-canvas@10.48.0", "", { "dependencies": { "@sentry-internal/replay": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-9nWuN2z4O+iwbTfuYV5ZmngBgJU/ZxfOo47A5RJP3Nu/kl59aJ1lUhILYOKyeNOIC/JyeERmpIcTxnlPXQzZ3Q=="],
"@sentry/browser": ["@sentry/browser@10.47.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.47.0", "@sentry-internal/feedback": "10.47.0", "@sentry-internal/replay": "10.47.0", "@sentry-internal/replay-canvas": "10.47.0", "@sentry/core": "10.47.0" } }, "sha512-rC0agZdxKA5XWfL4VwPOr/rJMogXDqZgnVzr93YWpFn9DMZT/7LzxSJVPIJwRUjx3bFEby3PcTa3YaX7pxm1AA=="], "@sentry/browser": ["@sentry/browser@10.48.0", "", { "dependencies": { "@sentry-internal/browser-utils": "10.48.0", "@sentry-internal/feedback": "10.48.0", "@sentry-internal/replay": "10.48.0", "@sentry-internal/replay-canvas": "10.48.0", "@sentry/core": "10.48.0" } }, "sha512-4jt2zX2ExgFcNe2x+W+/k81fmDUsOrquGtt028CiGuDuma6kEsWBI4JbooT1jhj2T+eeUxe3YGbM23Zhh7Ghhw=="],
"@sentry/core": ["@sentry/core@10.47.0", "", {}, "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA=="], "@sentry/core": ["@sentry/core@10.48.0", "", {}, "sha512-h8F+fXVwYC9ro5ZaO8V+v3vqc0awlXHGblEAuVxSGgh4IV/oFX+QVzXeDTTrFOFS6v/Vn5vAyu240eJrJAS6/g=="],
"@sindresorhus/base62": ["@sindresorhus/base62@1.0.0", "", {}, "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA=="], "@sindresorhus/base62": ["@sindresorhus/base62@1.0.0", "", {}, "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA=="],
@ -566,7 +566,7 @@
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="],
"@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
@ -580,7 +580,7 @@
"@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
"@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], "@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
@ -592,17 +592,17 @@
"@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.1", "@typescript-eslint/types": "^8.58.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g=="], "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.1", "@typescript-eslint/types": "^8.58.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0" } }, "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ=="], "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1" } }, "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w=="],
"@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw=="], "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw=="],
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/utils": "8.58.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg=="], "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1", "@typescript-eslint/utils": "8.58.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w=="],
"@typescript-eslint/types": ["@typescript-eslint/types@8.58.0", "", {}, "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww=="], "@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.1", "@typescript-eslint/tsconfig-utils": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg=="], "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.1", "@typescript-eslint/tsconfig-utils": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg=="],
"@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA=="], "@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ=="],
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ=="], "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ=="],
@ -694,7 +694,7 @@
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.13", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.17", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-HdrkN8eVG2CXxeifv/VdJ4A4RSra1DTW8dc/hdxzhGHN8QePs6gKaWM9pHPcpCoxYZJuOZ8drHmbdpLHjCYjLA=="],
"better-typescript-lib": ["better-typescript-lib@2.12.0", "", { "dependencies": { "@typescript/lib-decorators": "npm:@better-typescript-lib/decorators@2.12.0", "@typescript/lib-dom": "npm:@better-typescript-lib/dom@2.12.0", "@typescript/lib-es2015": "npm:@better-typescript-lib/es2015@2.12.0", "@typescript/lib-es2016": "npm:@better-typescript-lib/es2016@2.12.0", "@typescript/lib-es2017": "npm:@better-typescript-lib/es2017@2.12.0", "@typescript/lib-es2018": "npm:@better-typescript-lib/es2018@2.12.0", "@typescript/lib-es2019": "npm:@better-typescript-lib/es2019@2.12.0", "@typescript/lib-es2020": "npm:@better-typescript-lib/es2020@2.12.0", "@typescript/lib-es2021": "npm:@better-typescript-lib/es2021@2.12.0", "@typescript/lib-es2022": "npm:@better-typescript-lib/es2022@2.12.0", "@typescript/lib-es2023": "npm:@better-typescript-lib/es2023@2.12.0", "@typescript/lib-es2024": "npm:@better-typescript-lib/es2024@2.12.0", "@typescript/lib-es5": "npm:@better-typescript-lib/es5@2.12.0", "@typescript/lib-es6": "npm:@better-typescript-lib/es6@2.12.0", "@typescript/lib-esnext": "npm:@better-typescript-lib/esnext@2.12.0", "@typescript/lib-scripthost": "npm:@better-typescript-lib/scripthost@2.12.0", "@typescript/lib-webworker": "npm:@better-typescript-lib/webworker@2.12.0" }, "peerDependencies": { "typescript": ">=4.5.2" } }, "sha512-f7eO5Xs6Cczfx5eDRuDw/JYCrsdiC6gXdleB2KFZ5ZYgU/RRoev9swjt/eD0xo9PRDqNDwyjKx0n27CDHRZwvQ=="], "better-typescript-lib": ["better-typescript-lib@2.12.0", "", { "dependencies": { "@typescript/lib-decorators": "npm:@better-typescript-lib/decorators@2.12.0", "@typescript/lib-dom": "npm:@better-typescript-lib/dom@2.12.0", "@typescript/lib-es2015": "npm:@better-typescript-lib/es2015@2.12.0", "@typescript/lib-es2016": "npm:@better-typescript-lib/es2016@2.12.0", "@typescript/lib-es2017": "npm:@better-typescript-lib/es2017@2.12.0", "@typescript/lib-es2018": "npm:@better-typescript-lib/es2018@2.12.0", "@typescript/lib-es2019": "npm:@better-typescript-lib/es2019@2.12.0", "@typescript/lib-es2020": "npm:@better-typescript-lib/es2020@2.12.0", "@typescript/lib-es2021": "npm:@better-typescript-lib/es2021@2.12.0", "@typescript/lib-es2022": "npm:@better-typescript-lib/es2022@2.12.0", "@typescript/lib-es2023": "npm:@better-typescript-lib/es2023@2.12.0", "@typescript/lib-es2024": "npm:@better-typescript-lib/es2024@2.12.0", "@typescript/lib-es5": "npm:@better-typescript-lib/es5@2.12.0", "@typescript/lib-es6": "npm:@better-typescript-lib/es6@2.12.0", "@typescript/lib-esnext": "npm:@better-typescript-lib/esnext@2.12.0", "@typescript/lib-scripthost": "npm:@better-typescript-lib/scripthost@2.12.0", "@typescript/lib-webworker": "npm:@better-typescript-lib/webworker@2.12.0" }, "peerDependencies": { "typescript": ">=4.5.2" } }, "sha512-f7eO5Xs6Cczfx5eDRuDw/JYCrsdiC6gXdleB2KFZ5ZYgU/RRoev9swjt/eD0xo9PRDqNDwyjKx0n27CDHRZwvQ=="],
@ -712,13 +712,13 @@
"builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="], "builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="],
"bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], "bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="],
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
"cacheable": ["cacheable@2.3.4", "", { "dependencies": { "@cacheable/memory": "^2.0.8", "@cacheable/utils": "^2.4.0", "hookified": "^1.15.0", "keyv": "^5.6.0", "qified": "^0.9.0" } }, "sha512-djgxybDbw9fL/ZWMI3+CE8ZilNxcwFkVtDc1gJ+IlOSSWkSMPQabhV/XCHTQ6pwwN6aivXPZ43omTooZiX06Ew=="], "cacheable": ["cacheable@2.3.4", "", { "dependencies": { "@cacheable/memory": "^2.0.8", "@cacheable/utils": "^2.4.0", "hookified": "^1.15.0", "keyv": "^5.6.0", "qified": "^0.9.0" } }, "sha512-djgxybDbw9fL/ZWMI3+CE8ZilNxcwFkVtDc1gJ+IlOSSWkSMPQabhV/XCHTQ6pwwN6aivXPZ43omTooZiX06Ew=="],
"call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="],
"call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
@ -796,9 +796,9 @@
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"effect": ["effect@4.0.0-beta.43", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-AJYyDimIwJOn87uUz/JzmgDc5GfjxJbXvEbTvNzMa+M3Uer344bLo/O5mMRkqc1vBleA+Ygs4+dbE3QsqOkKTQ=="], "effect": ["effect@4.0.0-beta.46", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.5.3", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.8", "multipasta": "^0.2.7", "toml": "^3.0.0", "uuid": "^13.0.0", "yaml": "^2.8.2" } }, "sha512-3f6gXvvUMtEueCRY0tU76Vq2Pej1SAwwE+s0Owd5nD53yS5n4RZhUA1rlCGFuSbQFA225pGy8vO72+lpvu7u5A=="],
"electron-to-chromium": ["electron-to-chromium@1.5.331", "", {}, "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q=="], "electron-to-chromium": ["electron-to-chromium@1.5.334", "", {}, "sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog=="],
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
@ -808,7 +808,7 @@
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
"es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="], "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="],
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
@ -830,7 +830,7 @@
"eslint-compat-utils": ["eslint-compat-utils@0.6.5", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ=="], "eslint-compat-utils": ["eslint-compat-utils@0.6.5", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ=="],
"eslint-plugin-astro": ["eslint-plugin-astro@1.6.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@jridgewell/sourcemap-codec": "^1.4.14", "@typescript-eslint/types": "^7.7.1 || ^8", "astro-eslint-parser": "^1.3.0", "eslint-compat-utils": "^0.6.0", "globals": "^16.0.0", "postcss": "^8.4.14", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "eslint": ">=8.57.0" } }, "sha512-yGIbLHuj5MOUXa0s4sZ6cVhv6ehb+WLF80tsrGaxMk6VTUExruMzubQDzhOYt8fbR1c9vILCCRSCsKI7M1whig=="], "eslint-plugin-astro": ["eslint-plugin-astro@1.7.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@jridgewell/sourcemap-codec": "^1.4.14", "@typescript-eslint/types": "^7.7.1 || ^8", "astro-eslint-parser": "^1.3.0", "eslint-compat-utils": "^0.6.0", "globals": "^16.0.0", "postcss": "^8.4.14", "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "eslint": ">=8.57.0" } }, "sha512-89xpAn528UKCdmyysbg0AHHqi6sqcK89wXnJIpu4F0mFBN03zATEBNK7pRtMfl6gwtMOm5ECXs+Wz5qDHhwTFw=="],
"eslint-plugin-functional": ["eslint-plugin-functional@9.0.4", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.0", "deepmerge-ts": "^7.1.5", "escape-string-regexp": "^5.0.0", "is-immutable-type": "^5.0.1", "ts-api-utils": "^2.0.1", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": "^9.0.0 || ^10.0.0", "typescript": ">=4.7.4" }, "optionalPeers": ["typescript"] }, "sha512-zm4qaoqb2r50V4WXxt0Mj92buXGMECYvMxGQ6sSb+XeJ+Eec6zCHuMY2+AWK1mqiApvUz2tCtp1P3zcEPU0huw=="], "eslint-plugin-functional": ["eslint-plugin-functional@9.0.4", "", { "dependencies": { "@typescript-eslint/utils": "^8.26.0", "deepmerge-ts": "^7.1.5", "escape-string-regexp": "^5.0.0", "is-immutable-type": "^5.0.1", "ts-api-utils": "^2.0.1", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": "^9.0.0 || ^10.0.0", "typescript": ">=4.7.4" }, "optionalPeers": ["typescript"] }, "sha512-zm4qaoqb2r50V4WXxt0Mj92buXGMECYvMxGQ6sSb+XeJ+Eec6zCHuMY2+AWK1mqiApvUz2tCtp1P3zcEPU0huw=="],
@ -1290,7 +1290,7 @@
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
"postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], "postcss": ["postcss@8.5.9", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw=="],
"postcss-media-query-parser": ["postcss-media-query-parser@0.2.3", "", {}, "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig=="], "postcss-media-query-parser": ["postcss-media-query-parser@0.2.3", "", {}, "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig=="],
@ -1308,7 +1308,7 @@
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "prettier": ["prettier@3.8.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q=="],
"prettier-plugin-curly": ["prettier-plugin-curly@0.4.1", "", { "peerDependencies": { "prettier": "^3" } }, "sha512-Xc7zatoD0/08zYFv+hwnlqT5ekM81DCbBr73CWAsr1Fmx7qLQT/M0wfPx6w/+zfnmXH009xYvjzLUPcwzq7Fbw=="], "prettier-plugin-curly": ["prettier-plugin-curly@0.4.1", "", { "peerDependencies": { "prettier": "^3" } }, "sha512-Xc7zatoD0/08zYFv+hwnlqT5ekM81DCbBr73CWAsr1Fmx7qLQT/M0wfPx6w/+zfnmXH009xYvjzLUPcwzq7Fbw=="],
@ -1354,7 +1354,7 @@
"regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="],
"regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="], "regjsparser": ["regjsparser@0.13.1", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw=="],
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
@ -1368,7 +1368,7 @@
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"rolldown": ["rolldown@1.0.0-rc.13", "", { "dependencies": { "@oxc-project/types": "=0.123.0", "@rolldown/pluginutils": "1.0.0-rc.13" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-arm64": "1.0.0-rc.13", "@rolldown/binding-darwin-x64": "1.0.0-rc.13", "@rolldown/binding-freebsd-x64": "1.0.0-rc.13", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.13", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.13", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.13", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.13", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.13", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.13", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.13" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-bvVj8YJmf0rq4pSFmH7laLa6pYrhghv3PRzrCdRAr23g66zOKVJ4wkvFtgohtPLWmthgg8/rkaqRHrpUEh0Zbw=="], "rolldown": ["rolldown@1.0.0-rc.15", "", { "dependencies": { "@oxc-project/types": "=0.124.0", "@rolldown/pluginutils": "1.0.0-rc.15" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", "@rolldown/binding-darwin-x64": "1.0.0-rc.15", "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
@ -1438,7 +1438,7 @@
"side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
"side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
"side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
@ -1490,7 +1490,7 @@
"stylelint-config-recommended": ["stylelint-config-recommended@18.0.0", "", { "peerDependencies": { "stylelint": "^17.0.0" } }, "sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg=="], "stylelint-config-recommended": ["stylelint-config-recommended@18.0.0", "", { "peerDependencies": { "stylelint": "^17.0.0" } }, "sha512-mxgT2XY6YZ3HWWe3Di8umG6aBmWmHTblTgu/f10rqFXnyWxjKWwNdjSWkgkwCtxIKnqjSJzvFmPT5yabVIRxZg=="],
"stylelint-config-recommended-scss": ["stylelint-config-recommended-scss@17.0.0", "", { "dependencies": { "postcss-scss": "^4.0.9", "stylelint-config-recommended": "^18.0.0", "stylelint-scss": "^7.0.0" }, "peerDependencies": { "postcss": "^8.3.3", "stylelint": "^17.0.0" }, "optionalPeers": ["postcss"] }, "sha512-VkVD9r7jfUT/dq3mA3/I1WXXk2U71rO5wvU2yIil9PW5o1g3UM7Xc82vHmuVJHV7Y8ok5K137fmW5u3HbhtTOA=="], "stylelint-config-recommended-scss": ["stylelint-config-recommended-scss@17.0.1", "", { "dependencies": { "postcss-scss": "^4.0.9", "stylelint-config-recommended": "^18.0.0", "stylelint-scss": "^7.0.0" }, "peerDependencies": { "postcss": "^8.3.3", "stylelint": "^17.0.0" }, "optionalPeers": ["postcss"] }, "sha512-x5DVehzJudcwF0od3sGpgkln2PLLranFE7twwbp7dqDINCyZvwzFkMc6TLhNOvazRiVBJYATQLouJY0xPGB8WA=="],
"stylelint-config-sass-guidelines": ["stylelint-config-sass-guidelines@13.0.0", "", { "dependencies": { "@stylistic/stylelint-plugin": "^5.0.1", "postcss-scss": "^4.0.9", "stylelint-scss": "^7.0.0" }, "peerDependencies": { "postcss": "^8.4.21", "stylelint": "^17.1.0" } }, "sha512-YJT0X8h0OqyEo7ys3EycV5CGWt2rrkEYE8sHSN6sFnrxbXvHiy4KJFHDOWfyb3eWR6wtYpM+yIyvR2Plc8+pCg=="], "stylelint-config-sass-guidelines": ["stylelint-config-sass-guidelines@13.0.0", "", { "dependencies": { "@stylistic/stylelint-plugin": "^5.0.1", "postcss-scss": "^4.0.9", "stylelint-scss": "^7.0.0" }, "peerDependencies": { "postcss": "^8.4.21", "stylelint": "^17.1.0" } }, "sha512-YJT0X8h0OqyEo7ys3EycV5CGWt2rrkEYE8sHSN6sFnrxbXvHiy4KJFHDOWfyb3eWR6wtYpM+yIyvR2Plc8+pCg=="],
@ -1526,7 +1526,7 @@
"terser": ["terser@5.46.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ=="], "terser": ["terser@5.46.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ=="],
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
@ -1562,7 +1562,7 @@
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "undici-types": ["undici-types@7.19.2", "", {}, "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg=="],
"unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="],
@ -1588,7 +1588,7 @@
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="], "varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
"vite": ["vite@8.0.7", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.13", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-P1PbweD+2/udplnThz3btF4cf6AgPky7kk23RtHUkJIU5BIxwPprhRGmOAHs6FTI7UiGbTNrgNP6jSYD6JaRnw=="], "vite": ["vite@8.0.8", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.15", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw=="],
"vite-tsconfig-paths": ["vite-tsconfig-paths@6.1.1", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-2cihq7zliibCCZ8P9cKJrQBkfgdvcFkOOc3Y02o3GWUDLgqjWsZudaoiuOwO/gzTzy17cS5F7ZPo4bsnS4DGkg=="], "vite-tsconfig-paths": ["vite-tsconfig-paths@6.1.1", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-2cihq7zliibCCZ8P9cKJrQBkfgdvcFkOOc3Y02o3GWUDLgqjWsZudaoiuOwO/gzTzy17cS5F7ZPo4bsnS4DGkg=="],
@ -1632,38 +1632,10 @@
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"@gcch/configuration-eslint/eslint": ["eslint@10.1.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.3", "@eslint/config-helpers": "^0.5.3", "@eslint/core": "^1.1.1", "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA=="],
"@gcch/configuration-eslint/typescript-eslint": ["typescript-eslint@8.58.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.58.0", "@typescript-eslint/parser": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/utils": "8.58.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-e2TQzKfaI85fO+F3QywtX+tCTsu/D3WW5LVU6nz8hTFKFZ8yBJ6mSYRpXqdR3mFjPWmO0eWsTa5f+UpAOe/FMA=="],
"@gcch/configuration-prettier/prettier-plugin-sh": ["prettier-plugin-sh@0.18.0", "", { "dependencies": { "@reteps/dockerfmt": "^0.3.6", "sh-syntax": "^0.5.8" }, "peerDependencies": { "prettier": "^3.6.0" } }, "sha512-cW1XL27FOJQ/qGHOW6IHwdCiNWQsAgK+feA8V6+xUTaH0cD3Mh+tFAtBvEEWvuY6hTDzRV943Fzeii+qMOh7nQ=="],
"@keyv/bigmap/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="], "@keyv/bigmap/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1" } }, "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1", "@typescript-eslint/utils": "8.58.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ=="],
"@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1" } }, "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w=="],
"@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="],
"@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="],
"@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"astro-eslint-parser/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], "astro-eslint-parser/eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
"astro-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], "astro-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
@ -1672,8 +1644,6 @@
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"browserslist/caniuse-lite": ["caniuse-lite@1.0.30001784", "", {}, "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw=="],
"browserslist-to-esbuild/meow": ["meow@13.2.0", "", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="], "browserslist-to-esbuild/meow": ["meow@13.2.0", "", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="],
"cacheable/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="], "cacheable/keyv": ["keyv@5.6.0", "", { "dependencies": { "@keyv/serialize": "^1.1.1" } }, "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw=="],
@ -1702,7 +1672,7 @@
"qified/hookified": ["hookified@2.1.1", "", {}, "sha512-AHb76R16GB5EsPBE2J7Ko5kiEyXwviB9P5SMrAKcuAu4vJPZttViAbj9+tZeaQE5zjDme+1vcHP78Yj/WoAveA=="], "qified/hookified": ["hookified@2.1.1", "", {}, "sha512-AHb76R16GB5EsPBE2J7Ko5kiEyXwviB9P5SMrAKcuAu4vJPZttViAbj9+tZeaQE5zjDme+1vcHP78Yj/WoAveA=="],
"rolldown/@oxc-project/types": ["@oxc-project/types@0.123.0", "", {}, "sha512-YtECP/y8Mj1lSHiUWGSRzy/C6teUKlS87dEfuVKT09LgQbUsBW1rNg+MiJ4buGu3yuADV60gbIvo9/HplA56Ew=="], "rolldown/@oxc-project/types": ["@oxc-project/types@0.124.0", "", {}, "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg=="],
"stylelint/file-entry-cache": ["file-entry-cache@11.1.2", "", { "dependencies": { "flat-cache": "^6.1.20" } }, "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log=="], "stylelint/file-entry-cache": ["file-entry-cache@11.1.2", "", { "dependencies": { "flat-cache": "^6.1.20" } }, "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log=="],
@ -1718,44 +1688,8 @@
"table/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "table/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.58.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.58.1", "@typescript-eslint/types": "8.58.1", "@typescript-eslint/typescript-estree": "8.58.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ=="],
"vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
"@gcch/configuration-eslint/eslint/@eslint/config-array": ["@eslint/config-array@0.23.3", "", { "dependencies": { "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw=="],
"@gcch/configuration-eslint/eslint/@eslint/config-helpers": ["@eslint/config-helpers@0.5.3", "", { "dependencies": { "@eslint/core": "^1.1.1" } }, "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw=="],
"@gcch/configuration-eslint/eslint/@eslint/core": ["@eslint/core@1.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ=="],
"@gcch/configuration-eslint/eslint/@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.58.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/type-utils": "8.58.0", "@typescript-eslint/utils": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.58.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-RLkVSiNuUP1C2ROIWfqX+YcUfLaSnxGE/8M+Y57lopVwg9VTYYfhuz15Yf1IzCKgZj6/rIbYTmJCUSqr76r0Wg=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.58.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/typescript-estree": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-rLoGZIf9afaRBYsPUMtvkDWykwXwUPL60HebR4JgTI8mxfFe2cQTu3AGitANp4b9B2QlVru6WzjgB2IzJKiCSA=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.58.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.58.0", "@typescript-eslint/tsconfig-utils": "8.58.0", "@typescript-eslint/types": "8.58.0", "@typescript-eslint/visitor-keys": "8.58.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA=="],
"@gcch/configuration-prettier/prettier-plugin-sh/@reteps/dockerfmt": ["@reteps/dockerfmt@0.3.6", "", {}, "sha512-Tb5wIMvBf/nLejTQ61krK644/CEMB/cpiaIFXqGApfGqO3GwcR3qnI0DbmkFVCl2OyEp8LnLX3EkucoL0+tbFg=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="],
"@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="],
"@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="],
"@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="],
"@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"eslint-plugin-jsx-a11y/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="], "eslint-plugin-jsx-a11y/minimatch/brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="],
"stylelint/file-entry-cache/flat-cache": ["flat-cache@6.1.22", "", { "dependencies": { "cacheable": "^2.3.4", "flatted": "^3.4.2", "hookified": "^1.15.0" } }, "sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug=="], "stylelint/file-entry-cache/flat-cache": ["flat-cache@6.1.22", "", { "dependencies": { "cacheable": "^2.3.4", "flatted": "^3.4.2", "hookified": "^1.15.0" } }, "sha512-N2dnzVJIphnNsjHcrxGW7DePckJ6haPrSFqpsBUhHYgwtKGVq4JrBGielEGD2fCVnsGm1zlBVZ8wGhkyuetgug=="],
@ -1766,24 +1700,6 @@
"table/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "table/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.58.1", "", { "dependencies": { "@typescript-eslint/types": "8.58.1", "@typescript-eslint/visitor-keys": "8.58.1" } }, "sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w=="],
"typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.58.1", "", {}, "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw=="],
"@gcch/configuration-eslint/eslint/@eslint/config-array/@eslint/object-schema": ["@eslint/object-schema@3.0.3", "", {}, "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.58.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.58.0", "@typescript-eslint/types": "^8.58.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.58.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A=="],
"@gcch/configuration-eslint/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.58.0", "", { "dependencies": { "@typescript-eslint/types": "8.58.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ=="],
"eslint-plugin-jsx-a11y/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "eslint-plugin-jsx-a11y/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
} }
} }

View file

@ -1,5 +1,5 @@
import gcchConfig from "@gcch/configuration-oxlint"; import gcchConfig from "@gcch/configuration-oxlint";
import { OxlintConfig } from "oxlint"; import type { OxlintConfig } from "oxlint";
const config: OxlintConfig = { const config: OxlintConfig = {
...gcchConfig, ...gcchConfig,

View file

@ -5,7 +5,7 @@ export default defineConfig({
projects: [ projects: [
{ {
name: "desktop-chromium-1920", name: "desktop-chromium-1920",
use: { ...devices["Desktop Chrome"], viewport: { width: 1920, height: 1080 } }, use: { ...devices["Desktop Chrome"], viewport: { height: 1080, width: 1920 } },
}, },
// { // {
// name: "desktop-chromium-1536", // name: "desktop-chromium-1536",
@ -17,7 +17,7 @@ export default defineConfig({
// }, // },
{ {
name: "desktop-firefox-1920", name: "desktop-firefox-1920",
use: { ...devices["Desktop Firefox"], viewport: { width: 1920, height: 1080 } }, use: { ...devices["Desktop Firefox"], viewport: { height: 1080, width: 1920 } },
}, },
// { // {
// name: "desktop-firefox-1536", // name: "desktop-firefox-1536",
@ -51,7 +51,6 @@ export default defineConfig({
use: { use: {
/* Base URL to use in actions like `await page.goto('/')`. */ /* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "https://haikuatelier.gcch.local", baseURL: "https://haikuatelier.gcch.local",
trace: "retry-with-trace",
clientCertificates: [ clientCertificates: [
{ {
origin: "https://haikuatelier.gcch.local", origin: "https://haikuatelier.gcch.local",
@ -60,6 +59,7 @@ export default defineConfig({
}, },
], ],
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,
trace: "retry-with-trace",
}, },
workers: "100%", workers: "100%",
}); });

View file

@ -1,4 +1,4 @@
import { pipe, Array as FxArray } from "effect"; import { Array as FxArray, pipe } from "effect";
import type stylelint from "stylelint"; import type stylelint from "stylelint";
import { propertyGroups } from "stylelint-config-clean-order"; import { propertyGroups } from "stylelint-config-clean-order";

View file

@ -1,9 +1,4 @@
{ {
"autoload": {
"psr-4": {
"HaikuAtelier\\": "web/app/themes/haiku-atelier-2024/src/inc/"
}
},
"authors": [ "authors": [
{ {
"email": "scott.walkinshaw@gmail.com", "email": "scott.walkinshaw@gmail.com",
@ -16,6 +11,11 @@
"name": "Ben Word" "name": "Ben Word"
} }
], ],
"autoload": {
"psr-4": {
"HaikuAtelier\\": "web/app/themes/haiku-atelier-2024/src/inc/"
}
},
"config": { "config": {
"allow-plugins": { "allow-plugins": {
"carthage-software/mago": true, "carthage-software/mago": true,
@ -31,28 +31,45 @@
"description": "WordPress boilerplate with Composer, easier configuration, and an improved folder structure", "description": "WordPress boilerplate with Composer, easier configuration, and an improved folder structure",
"extra": { "extra": {
"installer-paths": { "installer-paths": {
"web/app/mu-plugins/{$name}/": ["type:wordpress-muplugin"], "web/app/mu-plugins/{$name}/": [
"web/app/plugins/{$name}/": ["type:wordpress-plugin"], "type:wordpress-muplugin"
"web/app/themes/{$name}/": ["type:wordpress-theme"], ],
"web/vendor/{$vendor}/{$name}": ["htmlburger/carbon-fields"] "web/app/plugins/{$name}/": [
"type:wordpress-plugin"
],
"web/app/themes/{$name}/": [
"type:wordpress-theme"
],
"web/vendor/{$vendor}/{$name}": [
"htmlburger/carbon-fields"
]
}, },
"wordpress-install-dir": "web/wp" "wordpress-install-dir": "web/wp"
}, },
"homepage": "https://roots.io/bedrock/", "homepage": "https://roots.io/bedrock/",
"keywords": ["bedrock", "composer", "roots", "wordpress", "wp", "wp-config"], "keywords": [
"bedrock",
"composer",
"roots",
"wordpress",
"wp",
"wp-config"
],
"license": "MIT", "license": "MIT",
"minimum-stability": "dev", "minimum-stability": "dev",
"name": "roots/bedrock", "name": "roots/bedrock",
"prefer-stable": true, "prefer-stable": true,
"repositories": [ "repositories": [
{ {
"only": ["wpackagist-plugin/*", "wpackagist-theme/*"], "only": [
"wpackagist-plugin/*",
"wpackagist-theme/*"
],
"type": "composer", "type": "composer",
"url": "https://wpackagist.org" "url": "https://wpackagist.org"
} }
], ],
"require": { "require": {
"php": ">=8.5",
"composer/installers": "^2.3", "composer/installers": "^2.3",
"crell/fp": "^1.0", "crell/fp": "^1.0",
"htmlburger/carbon-fields": "^3.6.9", "htmlburger/carbon-fields": "^3.6.9",
@ -63,10 +80,11 @@
"mnsami/composer-custom-directory-installer": "^2.0", "mnsami/composer-custom-directory-installer": "^2.0",
"nesbot/carbon": "^3.11.3", "nesbot/carbon": "^3.11.3",
"oscarotero/env": "^2.1.1", "oscarotero/env": "^2.1.1",
"php": ">=8.5",
"php-standard-library/php-standard-library": "^6.1.1",
"roots/bedrock-autoloader": "^1.1.0", "roots/bedrock-autoloader": "^1.1.0",
"roots/bedrock-disallow-indexing": "^2.1", "roots/bedrock-disallow-indexing": "^2.1",
"roots/wordpress": "^6.9.4", "roots/wordpress": "^6.9.4",
"php-standard-library/php-standard-library": "^6.1.1",
"roots/wp-config": "^1.0", "roots/wp-config": "^1.0",
"stripe/stripe-php": "^19.4.1", "stripe/stripe-php": "^19.4.1",
"symfony/uid": "^8.0.8", "symfony/uid": "^8.0.8",

35
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "8fa8994b91f6fdfb99db59a67eb54ac5", "content-hash": "bf6e098198b957782555eeb97479b37e",
"packages": [ "packages": [
{ {
"name": "carbonphp/carbon-doctrine-types", "name": "carbonphp/carbon-doctrine-types",
@ -5129,12 +5129,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git", "url": "https://github.com/Roave/SecurityAdvisories.git",
"reference": "7c570124dcf5c6834d78348d6817f32cd6b537d7" "reference": "d830a949e5c180e97c2245221daf8b589552cc2c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/7c570124dcf5c6834d78348d6817f32cd6b537d7", "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/d830a949e5c180e97c2245221daf8b589552cc2c",
"reference": "7c570124dcf5c6834d78348d6817f32cd6b537d7", "reference": "d830a949e5c180e97c2245221daf8b589552cc2c",
"shasum": "" "shasum": ""
}, },
"conflict": { "conflict": {
@ -5190,7 +5190,6 @@
"auth0/wordpress": "<=5.5", "auth0/wordpress": "<=5.5",
"automad/automad": "<2.0.0.0-alpha5", "automad/automad": "<2.0.0.0-alpha5",
"automattic/jetpack": "<9.8", "automattic/jetpack": "<9.8",
"avideo/avideo": "<=26",
"awesome-support/awesome-support": "<=6.0.7", "awesome-support/awesome-support": "<=6.0.7",
"aws/aws-sdk-php": "<=3.371.3", "aws/aws-sdk-php": "<=3.371.3",
"ayacoo/redirect-tab": "<2.1.2|>=3,<3.1.7|>=4,<4.0.5", "ayacoo/redirect-tab": "<2.1.2|>=3,<3.1.7|>=4,<4.0.5",
@ -5249,7 +5248,7 @@
"cesnet/simplesamlphp-module-proxystatistics": "<3.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1",
"chriskacerguis/codeigniter-restserver": "<=2.7.1", "chriskacerguis/codeigniter-restserver": "<=2.7.1",
"chrome-php/chrome": "<1.14", "chrome-php/chrome": "<1.14",
"ci4-cms-erp/ci4ms": "<=0.31.1", "ci4-cms-erp/ci4ms": "<=0.31.3",
"civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3",
"ckeditor/ckeditor": "<4.25", "ckeditor/ckeditor": "<4.25",
"clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3",
@ -5544,6 +5543,7 @@
"juzaweb/cms": "<=3.4.2", "juzaweb/cms": "<=3.4.2",
"jweiland/events2": "<8.3.8|>=9,<9.0.6", "jweiland/events2": "<8.3.8|>=9,<9.0.6",
"jweiland/kk-downloader": "<1.2.2", "jweiland/kk-downloader": "<1.2.2",
"kantorge/yaffa": "<=2",
"kazist/phpwhois": "<=4.2.6", "kazist/phpwhois": "<=4.2.6",
"kelvinmo/simplejwt": "<=1.1", "kelvinmo/simplejwt": "<=1.1",
"kelvinmo/simplexrd": "<3.1.1", "kelvinmo/simplexrd": "<3.1.1",
@ -5567,6 +5567,7 @@
"laravel/fortify": "<1.11.1", "laravel/fortify": "<1.11.1",
"laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1",
"laravel/laravel": ">=5.4,<5.4.22", "laravel/laravel": ">=5.4,<5.4.22",
"laravel/passport": "<13.7.1",
"laravel/pulse": "<1.3.1", "laravel/pulse": "<1.3.1",
"laravel/reverb": "<1.7", "laravel/reverb": "<1.7",
"laravel/socialite": ">=1,<2.0.10", "laravel/socialite": ">=1,<2.0.10",
@ -5747,7 +5748,7 @@
"phpoffice/phpexcel": "<=1.8.2", "phpoffice/phpexcel": "<=1.8.2",
"phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5",
"phppgadmin/phppgadmin": "<=7.13", "phppgadmin/phppgadmin": "<=7.13",
"phpseclib/phpseclib": "<=2.0.51|>=3,<=3.0.49", "phpseclib/phpseclib": "<2.0.53|>=3,<3.0.51",
"phpservermon/phpservermon": "<3.6", "phpservermon/phpservermon": "<3.6",
"phpsysinfo/phpsysinfo": "<3.4.3", "phpsysinfo/phpsysinfo": "<3.4.3",
"phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8", "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8",
@ -5809,11 +5810,11 @@
"rap2hpoutre/laravel-log-viewer": "<0.13", "rap2hpoutre/laravel-log-viewer": "<0.13",
"react/http": ">=0.7,<1.9", "react/http": ">=0.7,<1.9",
"really-simple-plugins/complianz-gdpr": "<6.4.2", "really-simple-plugins/complianz-gdpr": "<6.4.2",
"redaxo/source": "<=5.20.1", "redaxo/source": "<5.21",
"remdex/livehelperchat": "<4.29", "remdex/livehelperchat": "<4.29",
"renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1",
"reportico-web/reportico": "<=8.1", "reportico-web/reportico": "<=8.1",
"rhukster/dom-sanitizer": "<1.0.7", "rhukster/dom-sanitizer": "<1.0.10",
"rmccue/requests": ">=1.6,<1.8", "rmccue/requests": ">=1.6,<1.8",
"roadiz/documents": "<2.3.42|>=2.4,<2.5.44|>=2.6,<2.6.28|>=2.7,<2.7.9", "roadiz/documents": "<2.3.42|>=2.4,<2.5.44|>=2.6,<2.6.28|>=2.7,<2.7.9",
"robrichards/xmlseclibs": "<3.1.5", "robrichards/xmlseclibs": "<3.1.5",
@ -6171,7 +6172,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-04-06T23:13:58+00:00" "time": "2026-04-10T21:13:58+00:00"
}, },
{ {
"name": "sebastian/diff", "name": "sebastian/diff",
@ -7410,16 +7411,16 @@
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "2.1.6", "version": "2.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozarts/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8" "reference": "1b99650e7ffcad232624a260bc7fbdec2ffc407c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/ff31ad6efc62e66e518fbab1cde3453d389bcdc8", "url": "https://api.github.com/repos/webmozarts/assert/zipball/1b99650e7ffcad232624a260bc7fbdec2ffc407c",
"reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8", "reference": "1b99650e7ffcad232624a260bc7fbdec2ffc407c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -7466,9 +7467,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/webmozarts/assert/issues", "issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/2.1.6" "source": "https://github.com/webmozarts/assert/tree/2.2.0"
}, },
"time": "2026-02-27T10:28:38+00:00" "time": "2026-04-09T16:54:47+00:00"
} }
], ],
"aliases": [], "aliases": [],
@ -7483,5 +7484,5 @@
"php": ">=8.5" "php": ">=8.5"
}, },
"platform-dev": {}, "platform-dev": {},
"plugin-api-version": "2.9.0" "plugin-api-version": "2.6.0"
} }

View file

@ -1,49 +1,52 @@
{ {
"dictionaries": ["fr-fr", "en-gb"], "dictionaries": [
"en-gb",
"fr-fr"
],
"userWords": [ "userWords": [
"lightningcss", "codesniffer",
"curryfication",
"eilandert",
"ERRMODE",
"gcch",
"giftcard",
"haikuatelier", "haikuatelier",
"healthcheck", "healthcheck",
"traefik",
"innodb", "innodb",
"jaegertracing", "jaegertracing",
"eilandert",
"valkey",
"somaxconn",
"woocommerce",
"Squiz",
"twentytwentyfour",
"symfony",
"phpstan",
"codesniffer",
"muplugin",
"wpautop",
"ERRMODE",
"laravel", "laravel",
"multishipping", "lightningcss",
"multiformats", "multiformats",
"curryfication", "multishipping",
"giftcard", "muplugin",
"taplo",
"phpactor", "phpactor",
"gcch" "phpstan",
"somaxconn",
"Squiz",
"symfony",
"taplo",
"traefik",
"twentytwentyfour",
"valkey",
"woocommerce",
"wpautop"
], ],
"words": [ "words": [
"GLITCHTIP", "classlike",
"Vali", "Crell",
"Eles",
"fdir", "fdir",
"friendsofphp",
"GLITCHTIP",
"htmlburger",
"logtape",
"mobily", "mobily",
"oxlint", "oxlint",
"valibot",
"zstandard",
"Eles",
"logtape",
"wpackagist",
"phpdotenv", "phpdotenv",
"friendsofphp", "Vali",
"htmlburger", "valibot",
"Crell", "wpackagist",
"wpdb", "wpdb",
"classlike" "zstandard"
] ]
} }

View file

@ -105,6 +105,12 @@ lint-js:
--config cfg/oxlint.config.ts \ --config cfg/oxlint.config.ts \
--format stylish --format stylish
fix-js:
bun --bun oxlint \
--config cfg/oxlint.config.ts \
--format stylish \
--fix --fix-suggestions --fix-dangerously
# Vérifie le code Sass avec Stylelint. # Vérifie le code Sass avec Stylelint.
[group('css')] [group('css')]
[group('qualité')] [group('qualité')]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,10 @@
"baseline": { "baseline": {
"default": null, "default": null,
"description": "Path to a baseline file to ignore listed issues.", "description": "Path to a baseline file to ignore listed issues.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"baseline-variant": { "baseline-variant": {
"$ref": "#/$defs/BaselineVariant", "$ref": "#/$defs/BaselineVariant",
@ -135,7 +138,10 @@
}, },
"perform-heuristic-checks": { "perform-heuristic-checks": {
"description": "**Deprecated**: Use `check-missing-override` and `find-unused-parameters` instead.\n\nWhen set to `true`, enables both `check-missing-override` and `find-unused-parameters`.\nWhen set to `false`, disables both.\n\nThis option is kept for backwards compatibility with existing configurations.", "description": "**Deprecated**: Use `check-missing-override` and `find-unused-parameters` instead.\n\nWhen set to `true`, enables both `check-missing-override` and `find-unused-parameters`.\nWhen set to `false`, disables both.\n\nThis option is kept for backwards compatibility with existing configurations.",
"type": ["boolean", "null"], "type": [
"boolean",
"null"
],
"writeOnly": true "writeOnly": true
}, },
"performance": { "performance": {
@ -200,11 +206,18 @@
"type": "object" "type": "object"
}, },
"ArrayStyleOption": { "ArrayStyleOption": {
"enum": ["short", "long"], "enum": [
"long",
"short"
],
"type": "string" "type": "string"
}, },
"AssertionStyle": { "AssertionStyle": {
"enum": ["static", "self_", "this"], "enum": [
"self_",
"static",
"this"
],
"type": "string" "type": "string"
}, },
"BaselineVariant": { "BaselineVariant": {
@ -224,7 +237,11 @@
}, },
"BraceStyle": { "BraceStyle": {
"description": "Specifies brace placement style for various constructs.\n\n- `SameLine`: Opening brace on the same line as the declaration\n- `NextLine`: Opening brace on the next line for single-line signatures;\n on the same line when the signature breaks across multiple lines\n- `AlwaysNextLine`: Opening brace always on the next line, regardless of\n whether the signature breaks", "description": "Specifies brace placement style for various constructs.\n\n- `SameLine`: Opening brace on the same line as the declaration\n- `NextLine`: Opening brace on the next line for single-line signatures;\n on the same line when the signature breaks across multiple lines\n- `AlwaysNextLine`: Opening brace always on the next line, regardless of\n whether the signature breaks",
"enum": ["same_line", "next_line", "always_next_line"], "enum": [
"always_next_line",
"next_line",
"same_line"
],
"type": "string" "type": "string"
}, },
"DisallowedEntry": { "DisallowedEntry": {
@ -237,13 +254,18 @@
"description": "Entry with name and optional help message.", "description": "Entry with name and optional help message.",
"properties": { "properties": {
"help": { "help": {
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"name": { "name": {
"type": "string" "type": "string"
} }
}, },
"required": ["name"], "required": [
"name"
],
"type": "object" "type": "object"
} }
], ],
@ -251,7 +273,12 @@
}, },
"EndOfLine": { "EndOfLine": {
"description": "Specifies the style of line endings.", "description": "Specifies the style of line endings.",
"enum": ["auto", "lf", "crlf", "cr"], "enum": [
"auto",
"cr",
"crlf",
"lf"
],
"type": "string" "type": "string"
}, },
"FormatterConfiguration": { "FormatterConfiguration": {
@ -735,7 +762,10 @@
"baseline": { "baseline": {
"default": null, "default": null,
"description": "Path to a baseline file to ignore listed issues.", "description": "Path to a baseline file to ignore listed issues.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"baseline-variant": { "baseline-variant": {
"$ref": "#/$defs/BaselineVariant", "$ref": "#/$defs/BaselineVariant",
@ -815,7 +845,10 @@
"type": "array" "type": "array"
} }
}, },
"required": ["code", "in"], "required": [
"code",
"in"
],
"type": "object" "type": "object"
} }
], ],
@ -852,7 +885,10 @@
"baseline": { "baseline": {
"default": null, "default": null,
"description": "Path to a baseline file to ignore listed issues.", "description": "Path to a baseline file to ignore listed issues.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"baseline-variant": { "baseline-variant": {
"$ref": "#/$defs/BaselineVariant", "$ref": "#/$defs/BaselineVariant",
@ -994,11 +1030,11 @@
"level": "Help" "level": "Help"
}, },
"halstead": { "halstead": {
"difficulty-threshold": 12.0, "difficulty-threshold": 12,
"effort-threshold": 5000.0, "effort-threshold": 5000,
"enabled": true, "enabled": true,
"level": "Warning", "level": "Warning",
"volume-threshold": 1000.0 "volume-threshold": 1000
}, },
"identity-comparison": { "identity-comparison": {
"enabled": true, "enabled": true,
@ -1514,7 +1550,9 @@
}, },
"tainted-data-to-sink": { "tainted-data-to-sink": {
"enabled": true, "enabled": true,
"known-sink-functions": ["printf"], "known-sink-functions": [
"printf"
],
"level": "Error" "level": "Error"
}, },
"too-many-enum-cases": { "too-many-enum-cases": {
@ -1585,12 +1623,19 @@
"type": "object" "type": "object"
}, },
"MethodChainBreakingStyle": { "MethodChainBreakingStyle": {
"enum": ["same_line", "next_line"], "enum": [
"next_line",
"same_line"
],
"type": "string" "type": "string"
}, },
"NullTypeHint": { "NullTypeHint": {
"description": "Specifies null type hint style.", "description": "Specifies null type hint style.",
"enum": ["null_pipe", "null_pipe_last", "question"], "enum": [
"null_pipe",
"null_pipe_last",
"question"
],
"type": "string" "type": "string"
}, },
"PHPVersion": { "PHPVersion": {
@ -1697,7 +1742,10 @@
"type": "array" "type": "array"
} }
}, },
"required": ["namespace", "permit"], "required": [
"namespace",
"permit"
],
"type": "object" "type": "object"
}, },
"PerimeterSettings": { "PerimeterSettings": {
@ -1747,14 +1795,22 @@
"$ref": "#/$defs/Path" "$ref": "#/$defs/Path"
} }
}, },
"required": ["path", "kinds"], "required": [
"kinds",
"path"
],
"type": "object" "type": "object"
} }
] ]
}, },
"PermittedDependencyKind": { "PermittedDependencyKind": {
"description": "Represents the specific types of symbols allowed from a path.", "description": "Represents the specific types of symbols allowed from a path.",
"enum": ["class-like", "function", "constant", "attribute"], "enum": [
"attribute",
"class-like",
"constant",
"function"
],
"type": "string" "type": "string"
}, },
"RuleSettings": { "RuleSettings": {
@ -2654,7 +2710,9 @@
"type": "array" "type": "array"
}, },
"known-sink-functions": { "known-sink-functions": {
"default": ["printf"], "default": [
"printf"
],
"items": { "items": {
"type": "string" "type": "string"
}, },
@ -2758,7 +2816,10 @@
"description": "Maximum cyclomatic complexity allowed for a single method.\n\nWhen set, each method in a class-like is checked individually against this threshold,\nin addition to the class-level `threshold` check.\n\nDefault: `None` (methods are only checked as part of the class-level total).", "description": "Maximum cyclomatic complexity allowed for a single method.\n\nWhen set, each method in a class-like is checked individually against this threshold,\nin addition to the class-level `threshold` check.\n\nDefault: `None` (methods are only checked as part of the class-level total).",
"format": "uint", "format": "uint",
"minimum": 0, "minimum": 0,
"type": ["integer", "null"] "type": [
"integer",
"null"
]
}, },
"threshold": { "threshold": {
"default": 15, "default": 15,
@ -3308,7 +3369,10 @@
"description": "Maximum nesting depth allowed inside a single function, method, closure, or arrow function.\n\nWhen set, each function-like body is checked independently against this threshold,\nwith nesting counted from the function body (not the file root).\n\nDefault: `None` (function-like bodies are only checked against the global `threshold`).", "description": "Maximum nesting depth allowed inside a single function, method, closure, or arrow function.\n\nWhen set, each function-like body is checked independently against this threshold,\nwith nesting counted from the function body (not the file root).\n\nDefault: `None` (function-like bodies are only checked against the global `threshold`).",
"format": "uint", "format": "uint",
"minimum": 0, "minimum": 0,
"type": ["integer", "null"] "type": [
"integer",
"null"
]
}, },
"level": { "level": {
"$ref": "#/$defs/Level", "$ref": "#/$defs/Level",
@ -3331,7 +3395,10 @@
"format": "uint8", "format": "uint8",
"maximum": 255, "maximum": 255,
"minimum": 0, "minimum": 0,
"type": ["integer", "null"] "type": [
"integer",
"null"
]
}, },
"enabled": { "enabled": {
"default": true, "default": true,
@ -3401,12 +3468,12 @@
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"difficulty-threshold": { "difficulty-threshold": {
"default": 12.0, "default": 12,
"format": "double", "format": "double",
"type": "number" "type": "number"
}, },
"effort-threshold": { "effort-threshold": {
"default": 5000.0, "default": 5000,
"format": "double", "format": "double",
"type": "number" "type": "number"
}, },
@ -3425,7 +3492,7 @@
"default": "Warning" "default": "Warning"
}, },
"volume-threshold": { "volume-threshold": {
"default": 1000.0, "default": 1000,
"format": "double", "format": "double",
"type": "number" "type": "number"
} }
@ -5417,11 +5484,11 @@
"halstead": { "halstead": {
"$ref": "#/$defs/RuleSettings20", "$ref": "#/$defs/RuleSettings20",
"default": { "default": {
"difficulty-threshold": 12.0, "difficulty-threshold": 12,
"effort-threshold": 5000.0, "effort-threshold": 5000,
"enabled": true, "enabled": true,
"level": "Warning", "level": "Warning",
"volume-threshold": 1000.0 "volume-threshold": 1000
} }
}, },
"identity-comparison": { "identity-comparison": {
@ -6303,7 +6370,9 @@
"$ref": "#/$defs/RuleSettings136", "$ref": "#/$defs/RuleSettings136",
"default": { "default": {
"enabled": true, "enabled": true,
"known-sink-functions": ["printf"], "known-sink-functions": [
"printf"
],
"level": "Error" "level": "Error"
} }
}, },
@ -6423,7 +6492,9 @@
"type": "array" "type": "array"
}, },
"extensions": { "extensions": {
"default": ["php"], "default": [
"php"
],
"description": "File extensions to filter by.\n\nDefaults to `[\".php\"]`.", "description": "File extensions to filter by.\n\nDefaults to `[\".php\"]`.",
"items": { "items": {
"type": "string" "type": "string"
@ -6461,7 +6532,9 @@
"type": "string" "type": "string"
} }
}, },
"required": ["workspace"], "required": [
"workspace"
],
"type": "object" "type": "object"
}, },
"StructuralInheritanceConstraint": { "StructuralInheritanceConstraint": {
@ -6504,27 +6577,42 @@
"items": { "items": {
"$ref": "#/$defs/StructuralSymbolKind" "$ref": "#/$defs/StructuralSymbolKind"
}, },
"type": ["array", "null"] "type": [
"array",
"null"
]
}, },
"must-be-abstract": { "must-be-abstract": {
"default": null, "default": null,
"description": "If true, the symbol must be declared `abstract`.", "description": "If true, the symbol must be declared `abstract`.",
"type": ["boolean", "null"] "type": [
"boolean",
"null"
]
}, },
"must-be-final": { "must-be-final": {
"default": null, "default": null,
"description": "If true, the symbol must be declared `final`.", "description": "If true, the symbol must be declared `final`.",
"type": ["boolean", "null"] "type": [
"boolean",
"null"
]
}, },
"must-be-named": { "must-be-named": {
"default": null, "default": null,
"description": "Optional naming pattern the symbol's name must match.", "description": "Optional naming pattern the symbol's name must match.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"must-be-readonly": { "must-be-readonly": {
"default": null, "default": null,
"description": "If true, the symbol must be declared `readonly`.", "description": "If true, the symbol must be declared `readonly`.",
"type": ["boolean", "null"] "type": [
"boolean",
"null"
]
}, },
"must-extend": { "must-extend": {
"anyOf": [ "anyOf": [
@ -6577,7 +6665,10 @@
"not-on": { "not-on": {
"default": null, "default": null,
"description": "An optional exclusion pattern; if the namespace matches this, the rule is skipped.", "description": "An optional exclusion pattern; if the namespace matches this, the rule is skipped.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"on": { "on": {
"default": "", "default": "",
@ -6587,7 +6678,10 @@
"reason": { "reason": {
"default": null, "default": null,
"description": "A human-readable reason for this rule.", "description": "A human-readable reason for this rule.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"target": { "target": {
"anyOf": [ "anyOf": [
@ -6619,7 +6713,15 @@
"type": "object" "type": "object"
}, },
"StructuralSymbolKind": { "StructuralSymbolKind": {
"enum": ["class-like", "class", "interface", "trait", "enum", "constant", "function"], "enum": [
"class",
"class-like",
"constant",
"enum",
"function",
"interface",
"trait"
],
"type": "string" "type": "string"
} }
}, },
@ -6682,7 +6784,10 @@
"editor-url": { "editor-url": {
"default": null, "default": null,
"description": "Editor URL template for OSC 8 terminal hyperlinks on file paths in diagnostics.\n\nWhen set, file paths in diagnostic output become clickable links in terminals\nthat support OSC 8 hyperlinks (e.g., iTerm2, Wezterm, Kitty, Windows Terminal).\n\nSupported placeholders:\n- `%file%` — absolute file path\n- `%line%` — line number\n- `%column%` — column number\n\nCan be set via `MAGO_EDITOR_URL` environment variable or `editor-url` in `mago.toml`.", "description": "Editor URL template for OSC 8 terminal hyperlinks on file paths in diagnostics.\n\nWhen set, file paths in diagnostic output become clickable links in terminals\nthat support OSC 8 hyperlinks (e.g., iTerm2, Wezterm, Kitty, Windows Terminal).\n\nSupported placeholders:\n- `%file%` — absolute file path\n- `%line%` — line number\n- `%column%` — column number\n\nCan be set via `MAGO_EDITOR_URL` environment variable or `editor-url` in `mago.toml`.",
"type": ["string", "null"] "type": [
"null",
"string"
]
}, },
"formatter": { "formatter": {
"$ref": "#/$defs/FormatterConfiguration", "$ref": "#/$defs/FormatterConfiguration",
@ -6830,11 +6935,11 @@
"level": "Help" "level": "Help"
}, },
"halstead": { "halstead": {
"difficulty-threshold": 12.0, "difficulty-threshold": 12,
"effort-threshold": 5000.0, "effort-threshold": 5000,
"enabled": true, "enabled": true,
"level": "Warning", "level": "Warning",
"volume-threshold": 1000.0 "volume-threshold": 1000
}, },
"identity-comparison": { "identity-comparison": {
"enabled": true, "enabled": true,
@ -7350,7 +7455,9 @@
}, },
"tainted-data-to-sink": { "tainted-data-to-sink": {
"enabled": true, "enabled": true,
"known-sink-functions": ["printf"], "known-sink-functions": [
"printf"
],
"level": "Error" "level": "Error"
}, },
"too-many-enum-cases": { "too-many-enum-cases": {
@ -7434,7 +7541,9 @@
"$ref": "#/$defs/SourceConfiguration", "$ref": "#/$defs/SourceConfiguration",
"default": { "default": {
"excludes": [], "excludes": [],
"extensions": ["php"], "extensions": [
"php"
],
"glob": { "glob": {
"backslash-escape": true, "backslash-escape": true,
"case-insensitive": false, "case-insensitive": false,

View file

@ -5,7 +5,9 @@ stack-size = 0
threads = 0 threads = 0
[source] [source]
excludes = ["web/wp/wp-admin/includes/noop.php"] excludes = [
"web/wp/wp-admin/includes/noop.php",
]
extensions = ["php"] extensions = ["php"]
includes = ["config", "vendor", "web/app/plugins", "web/vendor", "web/wp"] includes = ["config", "vendor", "web/app/plugins", "web/vendor", "web/wp"]
paths = ["web/app/themes/haiku-atelier-2024"] paths = ["web/app/themes/haiku-atelier-2024"]
@ -66,3 +68,9 @@ threads = 0
negation-complexity-threshold = 8192 negation-complexity-threshold = 8192
saturation-complexity-threshold = 16384 saturation-complexity-threshold = 16384
string-combination-threshold = 256 string-combination-threshold = 256
[formatter]
excludes = [
"web/app/mu-plugins",
"web/app/plugins",
]

View file

@ -14,14 +14,14 @@
"@mobily/ts-belt": "v4.0.0-rc.5", "@mobily/ts-belt": "v4.0.0-rc.5",
"@sentry/browser": "^10.47.0", "@sentry/browser": "^10.47.0",
"a11y-dialog": "^8.1.5", "a11y-dialog": "^8.1.5",
"effect": "^4.0.0-beta.43", "effect": "^4.0.0-beta.46",
"lit-html": "^3.3.2", "lit-html": "^3.3.2",
"purify-ts": "2.1.2", "purify-ts": "2.1.2",
"ts-pattern": "^5.9.0", "ts-pattern": "^5.9.0",
"valibot": "1.1.0" "valibot": "1.1.0"
}, },
"devDependencies": { "devDependencies": {
"@effect/language-service": "^0.84.3", "@effect/language-service": "^0.85.0",
"@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274", "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#62ee424274",
"@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#0968f683", "@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#0968f683",
"@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#8de937e801", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#8de937e801",
@ -60,7 +60,7 @@
"stylelint-plugin-logical-css": "^2.1.0", "stylelint-plugin-logical-css": "^2.1.0",
"typescript": "6.0.2", "typescript": "6.0.2",
"typescript-eslint": "^8.58.1", "typescript-eslint": "^8.58.1",
"vite": "^8.0.7", "vite": "^8.0.8",
"vite-tsconfig-paths": "^6.1.1" "vite-tsconfig-paths": "^6.1.1"
}, },
"browserslist": [ "browserslist": [

View file

@ -1,12 +1,12 @@
{ {
"$schema": "https:\/\/json-schema.org\/draft-07\/schema", "$schema": "https://json-schema.org/draft-07/schema",
"properties": { "properties": {
"$schema": { "$schema": {
"default": "", "default": "",
"description": "Path to JSON schema, which can be used for config autocompletion, use phpactor config:initialize to update" "description": "Path to JSON schema, which can be used for config autocompletion, use phpactor config:initialize to update"
}, },
"behat.config_path": { "behat.config_path": {
"default": "%project_root%\/behat.yml", "default": "%project_root%/behat.yml",
"description": "Path to the main behat.yml (including the filename behat.yml)" "description": "Path to the main behat.yml (including the filename behat.yml)"
}, },
"behat.symfony.di_xml_path": { "behat.symfony.di_xml_path": {
@ -61,11 +61,19 @@
"description": "Object fill refactoring: use named parameters" "description": "Object fill refactoring: use named parameters"
}, },
"code_transform.template_paths": { "code_transform.template_paths": {
"default": ["%project_config%\/templates", "%config%\/templates"], "default": [
"%config%/templates",
"%project_config%/templates"
],
"description": "Paths in which to look for code templates" "description": "Paths in which to look for code templates"
}, },
"command": { "description": "Internal use only - name of the command which was executed" }, "command": {
"completion.dedupe": { "default": true, "description": "If results should be de-duplicated" }, "description": "Internal use only - name of the command which was executed"
},
"completion.dedupe": {
"default": true,
"description": "If results should be de-duplicated"
},
"completion.dedupe_match_fqn": { "completion.dedupe_match_fqn": {
"default": true, "default": true,
"description": "If ``completion.dedupe``, consider the class FQN in addition to the completion suggestion" "description": "If ``completion.dedupe``, consider the class FQN in addition to the completion suggestion"
@ -73,9 +81,14 @@
"completion.label_formatter": { "completion.label_formatter": {
"default": "helpful", "default": "helpful",
"description": "Definition of how to format entries in the completion list", "description": "Definition of how to format entries in the completion list",
"enum": ["helpful", "fqn"] "enum": [
"fqn",
"helpful"
]
},
"completion.limit": {
"description": "Sets a limit on the number of completion suggestions for any request"
}, },
"completion.limit": { "description": "Sets a limit on the number of completion suggestions for any request" },
"completion_worse.completor.attribute.enabled": { "completion_worse.completor.attribute.enabled": {
"default": true, "default": true,
"description": "Enable or disable the ``attribute`` completor.\n\nCompletion for attribute class names." "description": "Enable or disable the ``attribute`` completor.\n\nCompletion for attribute class names."
@ -92,7 +105,10 @@
"default": true, "default": true,
"description": "Enable or disable the ``class_member`` completor.\n\nCompletion for class members." "description": "Enable or disable the ``class_member`` completor.\n\nCompletion for class members."
}, },
"completion_worse.completor.constant.enabled": { "default": false, "description": null }, "completion_worse.completor.constant.enabled": {
"default": false,
"description": null
},
"completion_worse.completor.constructor.enabled": { "completion_worse.completor.constructor.enabled": {
"default": true, "default": true,
"description": "Enable or disable the ``constructor`` completor.\n\nCompletion for constructors." "description": "Enable or disable the ``constructor`` completor.\n\nCompletion for constructors."
@ -147,7 +163,7 @@
}, },
"completion_worse.completor.symfony.enabled": { "completion_worse.completor.symfony.enabled": {
"default": true, "default": true,
"description": "Enable\/disable the Symfony completor - depends on Symfony extension being enabled" "description": "Enable/disable the Symfony completor - depends on Symfony extension being enabled"
}, },
"completion_worse.completor.type.enabled": { "completion_worse.completor.type.enabled": {
"default": true, "default": true,
@ -161,19 +177,28 @@
"default": true, "default": true,
"description": "Enable or disable the ``worse_parameter`` completor.\n\nCompletion for method or function parameters." "description": "Enable or disable the ``worse_parameter`` completor.\n\nCompletion for method or function parameters."
}, },
"completion_worse.debug": { "default": false, "description": "Include debug info in completion results" }, "completion_worse.debug": {
"completion_worse.experimantal": { "default": false, "description": "Enable experimental functionality" }, "default": false,
"description": "Include debug info in completion results"
},
"completion_worse.experimantal": {
"default": false,
"description": "Enable experimental functionality"
},
"completion_worse.name_completion_priority": { "completion_worse.name_completion_priority": {
"default": "proximity", "default": "proximity",
"description": "Strategy to use when ordering completion results for classes and functions:\n\n- `proximity`: Classes and functions will be ordered by their proximity to the text document being edited.\n- `none`: No ordering will be applied." "description": "Strategy to use when ordering completion results for classes and functions:\n\n- `proximity`: Classes and functions will be ordered by their proximity to the text document being edited.\n- `none`: No ordering will be applied."
}, },
"completion_worse.snippets": { "default": true, "description": "Enable or disable completion snippets" }, "completion_worse.snippets": {
"default": true,
"description": "Enable or disable completion snippets"
},
"composer.autoload_deregister": { "composer.autoload_deregister": {
"default": true, "default": true,
"description": "Immediately de-register the autoloader once it has been included (prevent conflicts with Phpactor's autoloader). Some platforms may require this to be disabled" "description": "Immediately de-register the autoloader once it has been included (prevent conflicts with Phpactor's autoloader). Some platforms may require this to be disabled"
}, },
"composer.autoloader_path": { "composer.autoloader_path": {
"default": "%project_root%\/vendor\/autoload.php", "default": "%project_root%/vendor/autoload.php",
"description": "Path to project's autoloader, can be an array" "description": "Path to project's autoloader, can be an array"
}, },
"composer.class_maps_only": { "composer.class_maps_only": {
@ -186,9 +211,23 @@
}, },
"console.decorated": { "console.decorated": {
"description": "Whether to decorate messages (null for auto-guessing)", "description": "Whether to decorate messages (null for auto-guessing)",
"enum": [true, false, null] "enum": [
true,
false,
null
]
},
"console.verbosity": {
"default": 32,
"description": "Verbosity level",
"enum": [
16,
32,
64,
128,
256
]
}, },
"console.verbosity": { "default": 32, "description": "Verbosity level", "enum": [16, 32, 64, 128, 256] },
"console_dumper_default": { "console_dumper_default": {
"default": "indented", "default": "indented",
"description": "Name of the \"dumper\" (renderer) to use for some CLI commands" "description": "Name of the \"dumper\" (renderer) to use for some CLI commands"
@ -197,75 +236,131 @@
"default": 1610612736, "default": 1610612736,
"description": "Ensure that PHP has a memory_limit of at least this amount in bytes" "description": "Ensure that PHP has a memory_limit of at least this amount in bytes"
}, },
"file_path_resolver.app_name": { "default": "phpactor", "description": null }, "file_path_resolver.app_name": {
"file_path_resolver.application_root": { "description": null }, "default": "phpactor",
"file_path_resolver.enable_cache": { "default": true, "description": null }, "description": null
"file_path_resolver.enable_logging": { "default": true, "description": null }, },
"file_path_resolver.project_root": { "default": "\/opt\/phpactor", "description": null }, "file_path_resolver.application_root": {
"description": null
},
"file_path_resolver.enable_cache": {
"default": true,
"description": null
},
"file_path_resolver.enable_logging": {
"default": true,
"description": null
},
"file_path_resolver.project_root": {
"default": "/opt/phpactor",
"description": null
},
"indexer.buffer_time": { "indexer.buffer_time": {
"default": 500, "default": 500,
"description": "For real-time indexers only: the time, in milliseconds, to buffer the results", "description": "For real-time indexers only: the time, in milliseconds, to buffer the results",
"type": ["integer"] "type": [
"integer"
]
}, },
"indexer.enabled_watchers": { "indexer.enabled_watchers": {
"default": ["inotify", "watchman", "find", "php"], "default": [
"find",
"inotify",
"php",
"watchman"
],
"description": "List of allowed watchers. The first watcher that supports the current system will be used", "description": "List of allowed watchers. The first watcher that supports the current system will be used",
"type": ["object"] "type": [
"object"
]
}, },
"indexer.exclude_patterns": { "indexer.exclude_patterns": {
"default": ["\/vendor\/**\/Tests\/**\/*", "\/vendor\/**\/tests\/**\/*", "\/vendor\/composer\/**\/*"], "default": [
"/vendor/**/tests/**/*",
"/vendor/**/Tests/**/*",
"/vendor/composer/**/*"
],
"description": "Glob patterns to exclude while indexing", "description": "Glob patterns to exclude while indexing",
"type": ["object"] "type": [
"object"
]
}, },
"indexer.follow_symlinks": { "indexer.follow_symlinks": {
"default": false, "default": false,
"description": "To allow indexer to follow symlinks", "description": "To allow indexer to follow symlinks",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"indexer.implementation_finder.deep": { "indexer.implementation_finder.deep": {
"default": true, "default": true,
"description": "Recurse over class implementations to resolve all class implementations (not just the classes directly implementing the subject)", "description": "Recurse over class implementations to resolve all class implementations (not just the classes directly implementing the subject)",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"indexer.include_patterns": { "indexer.include_patterns": {
"default": ["\/**\/*.php", "\/**\/*.phar"], "default": [
"/**/*.phar",
"/**/*.php"
],
"description": "Glob patterns to include while indexing", "description": "Glob patterns to include while indexing",
"type": ["object"] "type": [
"object"
]
}, },
"indexer.index_path": { "indexer.index_path": {
"default": "%cache%\/index\/%project_id%", "default": "%cache%/index/%project_id%",
"description": "Path where the index should be saved", "description": "Path where the index should be saved",
"type": ["string"] "type": [
"string"
]
}, },
"indexer.poll_time": { "indexer.poll_time": {
"default": 5000, "default": 5000,
"description": "For polling indexers only: the time, in milliseconds, between polls (e.g. filesystem scans)", "description": "For polling indexers only: the time, in milliseconds, between polls (e.g. filesystem scans)",
"type": ["integer"] "type": [
"integer"
]
}, },
"indexer.project_root": { "indexer.project_root": {
"default": "%project_root%", "default": "%project_root%",
"description": "The root path to use for scanning the index", "description": "The root path to use for scanning the index",
"type": ["string"] "type": [
"string"
]
}, },
"indexer.reference_finder.deep": { "indexer.reference_finder.deep": {
"default": true, "default": true,
"description": "Recurse over class implementations to resolve all references", "description": "Recurse over class implementations to resolve all references",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"indexer.stub_paths": { "indexer.stub_paths": {
"default": [], "default": [],
"description": "Paths to external folders to index. They will be indexed only once, if you want to take any changes into account you will have to reindex your project manually.", "description": "Paths to external folders to index. They will be indexed only once, if you want to take any changes into account you will have to reindex your project manually.",
"type": ["object"] "type": [
"object"
]
}, },
"indexer.supported_extensions": { "indexer.supported_extensions": {
"default": ["php", "phar"], "default": [
"phar",
"php"
],
"description": "File extensions (e.g. `php`) for files that should be indexed", "description": "File extensions (e.g. `php`) for files that should be indexed",
"type": ["object"] "type": [
"object"
]
},
"language_server.catch_errors": {
"default": true,
"description": null
}, },
"language_server.catch_errors": { "default": true, "description": null },
"language_server.diagnostic_exclude_paths": { "language_server.diagnostic_exclude_paths": {
"default": [], "default": [],
"description": "List of paths to exclude from diagnostics, e.g. `vendor\/**\/*`" "description": "List of paths to exclude from diagnostics, e.g. `vendor/**/*`"
}, },
"language_server.diagnostic_outsource": { "language_server.diagnostic_outsource": {
"default": true, "default": true,
@ -296,19 +391,30 @@
}, },
"language_server.enable_workspace": { "language_server.enable_workspace": {
"default": true, "default": true,
"description": "If workspace management \/ text synchronization should be enabled (this isn't required for some language server implementations, e.g. static analyzers)" "description": "If workspace management / text synchronization should be enabled (this isn't required for some language server implementations, e.g. static analyzers)"
},
"language_server.file_event_globs": {
"default": [
"**/*.php"
],
"description": null
},
"language_server.file_events": {
"default": true,
"description": "Register to receive file events"
}, },
"language_server.file_event_globs": { "default": ["**\/*.php"], "description": null },
"language_server.file_events": { "default": true, "description": "Register to receive file events" },
"language_server.method_alias_map": { "language_server.method_alias_map": {
"default": [], "default": [],
"description": "Allow method names to be re-mapped. Useful for maintaining backwards compatibility" "description": "Allow method names to be re-mapped. Useful for maintaining backwards compatibility"
}, },
"language_server.phpactor_bin": { "language_server.phpactor_bin": {
"default": "\/opt\/phpactor\/lib\/Extension\/LanguageServer\/..\/..\/..\/bin\/phpactor", "default": "/opt/phpactor/lib/Extension/LanguageServer/../../../bin/phpactor",
"description": "Internal use only - name path to Phpactor binary" "description": "Internal use only - name path to Phpactor binary"
}, },
"language_server.profile": { "default": false, "description": "Logs timing information for incoming LSP requests" }, "language_server.profile": {
"default": false,
"description": "Logs timing information for incoming LSP requests"
},
"language_server.self_destruct_timeout": { "language_server.self_destruct_timeout": {
"default": 2500, "default": 2500,
"description": "Wait this amount of time (in milliseconds) after a shutdown request before self-destructing" "description": "Wait this amount of time (in milliseconds) after a shutdown request before self-destructing"
@ -340,22 +446,30 @@
"language_server_configuration.auto_config": { "language_server_configuration.auto_config": {
"default": true, "default": true,
"description": "Prompt to enable extensions which apply to your project on language server start", "description": "Prompt to enable extensions which apply to your project on language server start",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"language_server_indexer.reindex_timeout": { "language_server_indexer.reindex_timeout": {
"default": 300, "default": 300,
"description": "Unconditionally reindex modified files every N seconds" "description": "Unconditionally reindex modified files every N seconds"
}, },
"language_server_indexer.workspace_symbol_search_limit": { "default": 250, "description": null }, "language_server_indexer.workspace_symbol_search_limit": {
"default": 250,
"description": null
},
"language_server_php_cs_fixer.bin": { "language_server_php_cs_fixer.bin": {
"default": "%project_root%\/vendor\/bin\/php-cs-fixer", "default": "%project_root%/vendor/bin/php-cs-fixer",
"description": "Path to the php-cs-fixer executable" "description": "Path to the php-cs-fixer executable"
}, },
"language_server_php_cs_fixer.config": { "language_server_php_cs_fixer.config": {
"description": "Set custom PHP CS config path. Ex., %project_root%\/.php-cs-fixer.php" "description": "Set custom PHP CS config path. Ex., %project_root%/.php-cs-fixer.php"
}, },
"language_server_php_cs_fixer.env": { "language_server_php_cs_fixer.env": {
"default": { "PHP_CS_FIXER_IGNORE_ENV": true, "XDEBUG_MODE": "off" }, "default": {
"PHP_CS_FIXER_IGNORE_ENV": true,
"XDEBUG_MODE": "off"
},
"description": "Environment for PHP CS Fixer (e.g. to set PHP_CS_FIXER_IGNORE_ENV)" "description": "Environment for PHP CS Fixer (e.g. to set PHP_CS_FIXER_IGNORE_ENV)"
}, },
"language_server_php_cs_fixer.show_diagnostics": { "language_server_php_cs_fixer.show_diagnostics": {
@ -363,16 +477,24 @@
"description": "Whether PHP CS Fixer diagnostics are shown" "description": "Whether PHP CS Fixer diagnostics are shown"
}, },
"language_server_phpstan.bin": { "language_server_phpstan.bin": {
"default": "%project_root%\/vendor\/bin\/phpstan", "default": "%project_root%/vendor/bin/phpstan",
"description": "Path to the PHPStan executable" "description": "Path to the PHPStan executable"
}, },
"language_server_phpstan.config": { "description": "Override the PHPStan configuration file" }, "language_server_phpstan.config": {
"language_server_phpstan.level": { "description": "Override the PHPStan level" }, "description": "Override the PHPStan configuration file"
"language_server_phpstan.mem_limit": { "description": "Override the PHPStan memory limit" }, },
"language_server_phpstan.level": {
"description": "Override the PHPStan level"
},
"language_server_phpstan.mem_limit": {
"description": "Override the PHPStan memory limit"
},
"language_server_psalm.bin": { "language_server_psalm.bin": {
"default": "%project_root%\/vendor\/bin\/psalm", "default": "%project_root%/vendor/bin/psalm",
"description": "Path to psalm if different from vendor\/bin\/psalm", "description": "Path to psalm if different from vendor/bin/psalm",
"type": ["string"] "type": [
"string"
]
}, },
"language_server_psalm.error_level": { "language_server_psalm.error_level": {
"description": "Override level at which Psalm should report errors (lower => more errors)" "description": "Override level at which Psalm should report errors (lower => more errors)"
@ -380,28 +502,39 @@
"language_server_psalm.show_info": { "language_server_psalm.show_info": {
"default": true, "default": true,
"description": "If infos from psalm should be displayed", "description": "If infos from psalm should be displayed",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"language_server_psalm.threads": { "language_server_psalm.threads": {
"default": 1, "default": 1,
"description": "Set the number of threads Psalm should use. Warning: NULL will use as many as possible and may crash your computer", "description": "Set the number of threads Psalm should use. Warning: NULL will use as many as possible and may crash your computer",
"type": ["integer"] "type": [
"integer"
]
}, },
"language_server_psalm.timeout": { "language_server_psalm.timeout": {
"default": 15, "default": 15,
"description": "Kill the psalm process after this number of seconds", "description": "Kill the psalm process after this number of seconds",
"type": ["integer"] "type": [
"integer"
]
}, },
"language_server_psalm.use_cache": { "language_server_psalm.use_cache": {
"default": true, "default": true,
"description": "If the Psalm cache should be used (see the `--no-cache` option)", "description": "If the Psalm cache should be used (see the `--no-cache` option)",
"type": ["boolean"] "type": [
"boolean"
]
}, },
"language_server_reference_reference_finder.reference_timeout": { "language_server_reference_reference_finder.reference_timeout": {
"default": 60, "default": 60,
"description": "Stop searching for references after this time (in seconds) has expired" "description": "Stop searching for references after this time (in seconds) has expired"
}, },
"language_server_worse_reflection.diagnostics.enable": { "default": true, "description": "Enable diagnostics" }, "language_server_worse_reflection.diagnostics.enable": {
"default": true,
"description": "Enable diagnostics"
},
"language_server_worse_reflection.inlay_hints.enable": { "language_server_worse_reflection.inlay_hints.enable": {
"default": false, "default": false,
"description": "Enable inlay hints (experimental)" "description": "Enable inlay hints (experimental)"
@ -418,34 +551,87 @@
"default": 100, "default": 100,
"description": "Minimum interval to update the workspace index as documents are updated (in milliseconds)" "description": "Minimum interval to update the workspace index as documents are updated (in milliseconds)"
}, },
"logger.name": { "default": "logger", "description": null, "type": ["string"] }, "logger.name": {
"logging.enabled": { "default": false, "description": null, "type": ["boolean"] }, "default": "logger",
"logging.fingers_crossed": { "default": false, "description": null, "type": ["boolean"] }, "description": null,
"logging.formatter": { "description": null }, "type": [
"string"
]
},
"logging.enabled": {
"default": false,
"description": null,
"type": [
"boolean"
]
},
"logging.fingers_crossed": {
"default": false,
"description": null,
"type": [
"boolean"
]
},
"logging.formatter": {
"description": null
},
"logging.level": { "logging.level": {
"default": "warning", "default": "warning",
"description": null, "description": null,
"enum": ["emergency", "alert", "critical", "error", "warning", "notice", "info", "debug"], "enum": [
"type": ["string"] "alert",
"critical",
"debug",
"emergency",
"error",
"info",
"notice",
"warning"
],
"type": [
"string"
]
},
"logging.path": {
"default": "application.log",
"description": null,
"type": [
"string"
]
},
"navigator.autocreate": {
"default": [],
"description": null
},
"navigator.destinations": {
"default": [],
"description": null
}, },
"logging.path": { "default": "application.log", "description": null, "type": ["string"] },
"navigator.autocreate": { "default": [], "description": null },
"navigator.destinations": { "default": [], "description": null },
"object_renderer.template_paths.markdown": { "object_renderer.template_paths.markdown": {
"default": ["%project_config%\/templates\/markdown", "%config%\/templates\/markdown"], "default": [
"%config%/templates/markdown",
"%project_config%/templates/markdown"
],
"description": "Paths in which to look for templates for hover information." "description": "Paths in which to look for templates for hover information."
}, },
"php.version": { "php.version": {
"description": "Consider this value to be the project\\'s version of PHP (e.g. `7.4`). If omitted\nit will check `composer.json` (by the configured platform then the PHP requirement) before\nfalling back to the PHP version of the current process." "description": "Consider this value to be the project\\'s version of PHP (e.g. `7.4`). If omitted\nit will check `composer.json` (by the configured platform then the PHP requirement) before\nfalling back to the PHP version of the current process."
}, },
"php_code_sniffer.args": { "default": [], "description": "Additional arguments to pass to the PHPCS process" }, "php_code_sniffer.args": {
"default": [],
"description": "Additional arguments to pass to the PHPCS process"
},
"php_code_sniffer.bin": { "php_code_sniffer.bin": {
"default": "%project_root%\/vendor\/bin\/phpcs", "default": "%project_root%/vendor/bin/phpcs",
"description": "Path to the phpcs executable" "description": "Path to the phpcs executable"
}, },
"php_code_sniffer.cwd": { "description": "Working directory for PHPCS" }, "php_code_sniffer.cwd": {
"description": "Working directory for PHPCS"
},
"php_code_sniffer.env": { "php_code_sniffer.env": {
"default": { "XDEBUG_MODE": "off" }, "default": {
"XDEBUG_MODE": "off"
},
"description": "Environment for PHP_CodeSniffer (e.g. to set XDEBUG_MODE)" "description": "Environment for PHP_CodeSniffer (e.g. to set XDEBUG_MODE)"
}, },
"php_code_sniffer.show_diagnostics": { "php_code_sniffer.show_diagnostics": {
@ -456,15 +642,24 @@
"default": false, "default": false,
"description": "Only consider public services when providing analysis for the service locator" "description": "Only consider public services when providing analysis for the service locator"
}, },
"rpc.replay_path": { "default": "%cache%\/replay.json", "description": "Path where the replays should be stored" }, "rpc.replay_path": {
"rpc.store_replay": { "default": false, "description": "Should replays be stored?" }, "default": "%cache%/replay.json",
"source_code_filesystem.project_root": { "default": "%project_root%", "description": null }, "description": "Path where the replays should be stored"
},
"rpc.store_replay": {
"default": false,
"description": "Should replays be stored?"
},
"source_code_filesystem.project_root": {
"default": "%project_root%",
"description": null
},
"symfony.xml_path": { "symfony.xml_path": {
"default": "%project_root%\/var\/cache\/dev\/App_KernelDevDebugContainer.xml", "default": "%project_root%/var/cache/dev/App_KernelDevDebugContainer.xml",
"description": "Path to the Symfony container XML dump file" "description": "Path to the Symfony container XML dump file"
}, },
"worse_reflection.cache_dir": { "worse_reflection.cache_dir": {
"default": "%cache%\/worse-reflection", "default": "%cache%/worse-reflection",
"description": "Cache directory for stubs" "description": "Cache directory for stubs"
}, },
"worse_reflection.cache_lifetime": { "worse_reflection.cache_lifetime": {
@ -474,18 +669,26 @@
"worse_reflection.diagnostics.undefined_variable.suggestion_levenshtein_disatance": { "worse_reflection.diagnostics.undefined_variable.suggestion_levenshtein_disatance": {
"default": 4, "default": 4,
"description": "Levenshtein distance to use when suggesting corrections for variable names", "description": "Levenshtein distance to use when suggesting corrections for variable names",
"type": ["integer"] "type": [
"integer"
]
},
"worse_reflection.enable_cache": {
"default": true,
"description": "If reflection caching should be enabled"
}, },
"worse_reflection.enable_cache": { "default": true, "description": "If reflection caching should be enabled" },
"worse_reflection.enable_context_location": { "worse_reflection.enable_context_location": {
"default": true, "default": true,
"description": "If source code is passed to a ``Reflector`` then temporarily make it available as a\nsource location. Note this should NOT be enabled if the source code can be\nlocated in another (e.g. when running a Language Server)" "description": "If source code is passed to a ``Reflector`` then temporarily make it available as a\nsource location. Note this should NOT be enabled if the source code can be\nlocated in another (e.g. when running a Language Server)"
}, },
"worse_reflection.stub_dir": { "worse_reflection.stub_dir": {
"default": "%application_root%\/vendor\/jetbrains\/phpstorm-stubs", "default": "%application_root%/vendor/jetbrains/phpstorm-stubs",
"description": "Location of the core PHP stubs - these will be scanned and cached on the first request" "description": "Location of the core PHP stubs - these will be scanned and cached on the first request"
}, },
"xdebug_disable": { "default": true, "description": "If XDebug should be automatically disabled" } "xdebug_disable": {
"default": true,
"description": "If XDebug should be automatically disabled"
}
}, },
"title": "Phpactor Configuration Schema", "title": "Phpactor Configuration Schema",
"type": "object" "type": "object"

View file

@ -1,17 +1,18 @@
import { $ } from "bun"; import { $ } from "bun";
import { Array, Console, Effect, Layer, ManagedRuntime, Option, Order, pipe, Schema, ServiceMap } from "effect"; import type { Option } from "effect";
import { UnknownError } from "effect/Cause"; import { Array as FxArray, Console, Context, Effect, Layer, ManagedRuntime, Order, pipe, Schema } from "effect";
import type { UnknownError } from "effect/Cause";
import { readdir } from "node:fs/promises"; import { readdir } from "node:fs/promises";
class PodmanError extends Schema.TaggedErrorClass<PodmanError>()("PodmanError", { class PodmanError extends Schema.TaggedErrorClass<PodmanError>()("PodmanError", {
cause: Schema.Error, cause: Schema.Error,
}) {} }) {}
class FileSystemError extends Schema.TaggedErrorClass<FileSystemError>()("FileSystemError", { class FSError extends Schema.TaggedErrorClass<FSError>()("FSError", {
cause: Schema.Error, cause: Schema.Error,
}) {} }) {}
class Podman extends ServiceMap.Service< class Podman extends Context.Service<
Podman, Podman,
{ {
launchContainers(): Effect.Effect<string, PodmanError>; launchContainers(): Effect.Effect<string, PodmanError>;
@ -24,7 +25,7 @@ class Podman extends ServiceMap.Service<
Effect.gen(function*() { Effect.gen(function*() {
const launchContainers = Effect.fn("launchContainers")(function*() { const launchContainers = Effect.fn("launchContainers")(function*() {
return yield* pipe( return yield* pipe(
Effect.tryPromise(() => $`podman compose up -d &> /dev/null`), Effect.tryPromise(async () => $`podman compose up -d &> /dev/null`),
Effect.map((shell: $.ShellOutput) => shell.text()), Effect.map((shell: $.ShellOutput) => shell.text()),
Effect.mapError((error: UnknownError) => new PodmanError({ cause: error })), Effect.mapError((error: UnknownError) => new PodmanError({ cause: error })),
); );
@ -35,7 +36,7 @@ class Podman extends ServiceMap.Service<
) { ) {
return yield* pipe( return yield* pipe(
Effect.tryPromise( Effect.tryPromise(
() => async () =>
$`podman exec -it haikuatelier.fr-wordpress fish -c "cd web && wp --allow-root db import ${exportPath} > /dev/null"`, $`podman exec -it haikuatelier.fr-wordpress fish -c "cd web && wp --allow-root db import ${exportPath} > /dev/null"`,
), ),
Effect.map((shell: $.ShellOutput) => shell.text()), Effect.map((shell: $.ShellOutput) => shell.text()),
@ -51,47 +52,44 @@ class Podman extends ServiceMap.Service<
); );
} }
class FileSystem extends ServiceMap.Service< class FS extends Context.Service<
FileSystem, FS,
{ {
getLatestDbExport(): Effect.Effect<string, FileSystemError>; getLatestDbExport(): Effect.Effect<string, FSError>;
} }
>()("haikuatelier.fr/scripts/importe-dernier-export-bdd/FileSystem") { >()("haikuatelier.fr/scripts/importe-dernier-export-bdd/FS") {
static readonly layer = Layer.effect( static readonly layer = Layer.effect(
FileSystem, FS,
// oxlint-disable-next-line require-yield // oxlint-disable-next-line require-yield
Effect.gen(function*() { Effect.gen(function*() {
const getLatestDbExport = Effect.fn("getLatestDbExport")(function*() { const getLatestDbExport = Effect.fn("getLatestDbExport")(function*() {
return yield* pipe( return yield* pipe(
Effect.tryPromise(() => readdir(`./db`)), Effect.tryPromise(async () => readdir(`./db`)),
Effect.map((paths: ReadonlyArray<string>) => Array.sort(paths, Order.String)), Effect.map((paths: ReadonlyArray<string>) => FxArray.sort(paths, Order.String)),
Effect.map((sortedPaths: ReadonlyArray<string>) => Array.last(sortedPaths)), Effect.map((sortedPaths: ReadonlyArray<string>) => FxArray.last(sortedPaths)),
Effect.flatMap((path: Option.Option<string>) => Effect.fromOption(path)), Effect.flatMap((path: Option.Option<string>) => Effect.fromOption(path)),
Effect.mapError((_) => new FileSystemError({ cause: new Error("Aucun export de BDD n'est disponible.") })), Effect.mapError(_ => new FSError({ cause: new Error("Aucun export de BDD n'est disponible.") })),
); );
}); });
return FileSystem.of({ return FS.of({
getLatestDbExport, getLatestDbExport,
}); });
}), }),
); );
} }
const mainLayer = Layer.mergeAll(Podman.layer, FileSystem.layer); const mainLayer = Layer.mergeAll(Podman.layer, FS.layer);
const runtime = ManagedRuntime.make(mainLayer); const runtime = ManagedRuntime.make(mainLayer);
const program = Effect.fn("program")(function*() { const program = Effect.fn("program")(function*() {
yield* Podman.use((podman) => podman.launchContainers()); yield* Podman.use(podman => podman.launchContainers());
yield* Console.log("Containers are launched."); yield* Console.log("Containers are launched.");
const latestExportPath: string = pipe( const latestExportPath: string = pipe(yield* FS.use(fs => fs.getLatestDbExport()), path => `../db/${path}`);
yield* FileSystem.use((fs) => fs.getLatestDbExport()),
(path) => `../db/${path}`,
);
yield* Console.log(latestExportPath); yield* Console.log(latestExportPath);
yield* Podman.use((podman) => podman.importLatestDbInWordPressContainer(latestExportPath)); yield* Podman.use(podman => podman.importLatestDbInWordPressContainer(latestExportPath));
yield* Console.log("Import done."); yield* Console.log("Import done.");
}); });

View file

@ -1,5 +1,5 @@
import { YAML } from "bun"; import { YAML } from "bun";
import { Console, Data, Effect, Array as EffectArray, pipe, Record, Schema, SchemaIssue } from "effect"; import { Array as EffectArray, Console, Data, Effect, pipe, Record, Schema, SchemaIssue } from "effect";
import { SchemaError } from "effect/Schema"; import { SchemaError } from "effect/Schema";
const COMPOSE_PATH = "compose.yaml"; const COMPOSE_PATH = "compose.yaml";
@ -21,7 +21,7 @@ class ScriptError extends Data.TaggedError("ScriptError")<{ cause: unknown }> {}
* @param compose Le fichier _Compose_ sous forme d'objet. * @param compose Le fichier _Compose_ sous forme d'objet.
* @returns Les noms des Services sous forme de tableau. * @returns Les noms des Services sous forme de tableau.
*/ */
const getServicesFromComposeYaml: (compose: Compose) => ReadonlyArray<string> = (compose) => const getServicesFromComposeYaml: (compose: Compose) => ReadonlyArray<string> = compose =>
Record.keys(compose.services); Record.keys(compose.services);
/** /**
@ -61,7 +61,7 @@ const getComposeYaml: <ComposeSchema>(
getFileContent(path), getFileContent(path),
Effect.map((text: string): unknown => YAML.parse(text)), Effect.map((text: string): unknown => YAML.parse(text)),
Effect.flatMap((yaml: unknown) => Effect.flatMap((yaml: unknown) =>
Schema.decodeUnknownEffect(schema)(yaml, { errors: "all", onExcessProperty: "ignore" }), Schema.decodeUnknownEffect(schema)(yaml, { errors: "all", onExcessProperty: "ignore" })
), ),
Effect.mapError((error): ScriptError => { Effect.mapError((error): ScriptError => {
if (error instanceof SchemaError) { if (error instanceof SchemaError) {
@ -76,7 +76,7 @@ const getComposeYaml: <ComposeSchema>(
const program: Effect.Effect<ReadonlyArray<string>, ScriptError> = pipe( const program: Effect.Effect<ReadonlyArray<string>, ScriptError> = pipe(
getComposeYaml(COMPOSE_PATH, Compose), getComposeYaml(COMPOSE_PATH, Compose),
Effect.map((compose: Compose) => getServicesFromComposeYaml(compose)), Effect.map((compose: Compose) => getServicesFromComposeYaml(compose)),
Effect.map((keys: ReadonlyArray<string>) => EffectArray.filter(keys, (key) => key !== "wordpress")), Effect.map((keys: ReadonlyArray<string>) => EffectArray.filter(keys, key => key !== "wordpress")),
Effect.orElseSucceed(() => [""]), Effect.orElseSucceed(() => [""]),
Effect.tap((services: ReadonlyArray<string>) => { Effect.tap((services: ReadonlyArray<string>) => {
Bun.spawn({ cmd: ["podman", "compose", "pull", ...services], timeout: DEFAULT_CMD_TIMEOUT }); Bun.spawn({ cmd: ["podman", "compose", "pull", ...services], timeout: DEFAULT_CMD_TIMEOUT });

View file

@ -37,7 +37,7 @@ Array.from<TestPage>([
}, },
]).forEach(({ pageName, url }) => { ]).forEach(({ pageName, url }) => {
test.skip(pageName, async ({ page }, testInfo) => { test.skip(pageName, async ({ page }, testInfo) => {
await page.goto(url); await page["goto"](url);
const projectName = testInfo.project.name; const projectName = testInfo.project.name;
const timestamp: string = genTimestamp(); const timestamp: string = genTimestamp();

View file

@ -1,11 +1,13 @@
import { test as base, expect, Response } from "@playwright/test"; import type { Response } from "@playwright/test";
import { import { expect, test as base } from "@playwright/test";
import { pipe } from "effect";
import { not } from "effect/Boolean";
import type {
WCV3Product, WCV3Product,
WCV3Products, WCV3Products,
} from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products"; } from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products";
import { BackendHeaders, getBackendHeadersFromHtml } from "./utils.ts"; import type { BackendHeaders } from "./utils.ts";
import { pipe } from "effect"; import { getBackendHeadersFromHtml } from "./utils.ts";
import { not } from "effect/Boolean";
/* /*
* Faire un premier test simple l'on clic sur la première carte du shop * Faire un premier test simple l'on clic sur la première carte du shop
@ -30,7 +32,7 @@ type ProductsKinds = {
export const test = base.extend<ProductsFixture>({ export const test = base.extend<ProductsFixture>({
products: async ({ page, request }, use) => { products: async ({ page, request }, use) => {
await page.goto("/shop"); await page["goto"]("/shop");
const backendHeaders: BackendHeaders = await getBackendHeadersFromHtml(page); const backendHeaders: BackendHeaders = await getBackendHeadersFromHtml(page);
const response = await request.get("/wp-json/wc/v3/products?page=1&per_page=100&status=publish", { const response = await request.get("/wp-json/wc/v3/products?page=1&per_page=100&status=publish", {
@ -68,7 +70,7 @@ test("can add a Product without variation with stock to the Cart", async ({ page
} }
// Va à la page du Produit. // Va à la page du Produit.
await page.goto(randomProduct.permalink); await page["goto"](randomProduct.permalink);
// Vérifie le bon état du bouton de l'ajout au Panier. // Vérifie le bon état du bouton de l'ajout au Panier.
const addToCartButton = page.getByRole("button", { disabled: false, name: "Add to cart" }); const addToCartButton = page.getByRole("button", { disabled: false, name: "Add to cart" });
@ -101,7 +103,7 @@ test("can't add a Product without variation without stock to the Cart", async ({
} }
// Va à la page du Produit. // Va à la page du Produit.
await page.goto(randomProduct.permalink); await page["goto"](randomProduct.permalink);
// Vérifie le bon état du bouton de l'ajout au Panier. // Vérifie le bon état du bouton de l'ajout au Panier.
const outOfStockButton = page.getByRole("button", { disabled: true, name: "Out of stock" }); const outOfStockButton = page.getByRole("button", { disabled: true, name: "Out of stock" });

View file

@ -1,6 +1,8 @@
import { APIRequestContext, expect, Locator, Page, Response, test } from "@playwright/test"; import type { APIRequestContext, Locator, Page, Response } from "@playwright/test";
import { WCV3Products } from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products"; import { expect, test } from "@playwright/test";
import { BackendHeaders, getBackendHeadersFromHtml } from "./utils.ts"; import type { WCV3Products } from "../../web/app/themes/haiku-atelier-2024/src/scripts/lib/types/api/v3/products";
import type { BackendHeaders } from "./utils.ts";
import { getBackendHeadersFromHtml } from "./utils.ts";
test.describe.configure({ mode: "parallel", timeout: 60_000 }); test.describe.configure({ mode: "parallel", timeout: 60_000 });
@ -9,13 +11,13 @@ test("can scroll to the end of the grid", async ({ page }): Promise<void> => {
}); });
test.skip("can access all Products' pages", async ({ page, request }): Promise<void> => { test.skip("can access all Products' pages", async ({ page, request }): Promise<void> => {
await page.goto("https://haikuatelier.gcch.local/shop/"); await page["goto"]("https://haikuatelier.gcch.local/shop/");
const links = await getAllProductsLinks(page, request); const links = await getAllProductsLinks(page, request);
for (const link of links) { for (const link of links) {
// Vérifie que le lien de la page retourne OK. // Vérifie que le lien de la page retourne OK.
const req = await request.get(link as string); const req = await request.get(link);
expect(req, "The Product's page is accessible").toBeOK(); await expect(req, "The Product's page is accessible").toBeOK();
} }
}); });
@ -25,11 +27,11 @@ const getAllProductsLinks = async (page: Page, request: APIRequestContext): Prom
headers: { Authorization: `Basic ${backendHeaders.authString}`, Nonce: backendHeaders.nonce }, headers: { Authorization: `Basic ${backendHeaders.authString}`, Nonce: backendHeaders.nonce },
}); });
const json = (await response.json()) as WCV3Products; const json = (await response.json()) as WCV3Products;
return json.map((p) => p.permalink); return json.map(p => p.permalink);
}; };
const scrollToGridsEnd = async (page: Page): Promise<void> => { const scrollToGridsEnd = async (page: Page): Promise<void> => {
await page.goto("https://haikuatelier.gcch.local/shop/"); await page["goto"]("https://haikuatelier.gcch.local/shop/");
let hasMoreProducts = true; let hasMoreProducts = true;
let currentPageNumber = "1"; let currentPageNumber = "1";

View file

@ -1,5 +1,5 @@
import { Option, pipe } from "effect"; import { Option, pipe } from "effect";
import { Page } from "playwright/test"; import type { Page } from "playwright/test";
export type BackendHeaders = { export type BackendHeaders = {
authString: string; authString: string;
@ -12,7 +12,7 @@ export type BackendHeaders = {
export const getBackendHeadersFromHtml = async (page: Page): Promise<BackendHeaders> => { export const getBackendHeadersFromHtml = async (page: Page): Promise<BackendHeaders> => {
const backendHeaders: BackendHeaders | undefined = pipe( const backendHeaders: BackendHeaders | undefined = pipe(
Option.fromNullishOr(await page.locator("#injection-v2").textContent()), Option.fromNullishOr(await page.locator("#injection-v2").textContent()),
Option.andThen((j) => JSON.parse(j) as BackendHeaders), Option.andThen(j => JSON.parse(j) as BackendHeaders),
Option.getOrUndefined, Option.getOrUndefined,
); );

View file

@ -12,7 +12,12 @@
"exactOptionalPropertyTypes": true, "exactOptionalPropertyTypes": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"isolatedModules": true, "isolatedModules": true,
"lib": ["DOM", "DOM.Iterable", "DOM.AsyncIterable", "ESNext"], "lib": [
"DOM",
"DOM.AsyncIterable",
"DOM.Iterable",
"ESNext"
],
"libReplacement": true, "libReplacement": true,
"module": "ESNext", "module": "ESNext",
"moduleDetection": "force", "moduleDetection": "force",
@ -41,10 +46,20 @@
"strictNullChecks": true, "strictNullChecks": true,
"strictPropertyInitialization": true, "strictPropertyInitialization": true,
"target": "ESNext", "target": "ESNext",
"types": ["node", "vite/client"], "types": [
"node",
"vite/client"
],
"useDefineForClassFields": true, "useDefineForClassFields": true,
"useUnknownInCatchVariables": true "useUnknownInCatchVariables": true
}, },
"exclude": ["vendor", "web/app/plugins", "web/wp"], "exclude": [
"include": ["**/*.js", "**/*.ts"] "vendor",
"web/app/plugins",
"web/wp"
],
"include": [
"**/*.js",
"**/*.ts"
]
} }

View file

@ -22,7 +22,8 @@ $templates = ['404.twig'];
* *
* @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger * @throws Exception une exception est levée s'il est impossible d'obtenir la date de modification du fichier à charger
*/ */
function load_page_resources(): void { function load_page_resources(): void
{
Resource::enqueue_style_file( Resource::enqueue_style_file(
handle: 'haiku-atelier-2024-styles-page-a-propos', handle: 'haiku-atelier-2024-styles-page-a-propos',
path: '/assets/css/pages/page-modele-simple.css', path: '/assets/css/pages/page-modele-simple.css',

View file

@ -19,9 +19,9 @@ jQuery(document).ready(function ($) {
mediaButtons: tinyMCEMediaButtons, mediaButtons: tinyMCEMediaButtons,
quicktags: true, quicktags: true,
tinymce: { tinymce: {
wpautop: true,
toolbar1: tinyMCEToolbar1String, toolbar1: tinyMCEToolbar1String,
toolbar2: tinyMCEToolbar2String, toolbar2: tinyMCEToolbar2String,
wpautop: true,
}, },
}); });
}); });

View file

@ -22,7 +22,8 @@ use WC_Session_Handler;
header('Content-Type: application/json; charset=utf-8'); header('Content-Type: application/json; charset=utf-8');
// TODO: Appliquer le bon calcul pour les montants vs. percentages // TODO: Appliquer le bon calcul pour les montants vs. percentages
function get_discount_amount(WC_Coupon $coupon) { function get_discount_amount(WC_Coupon $coupon)
{
if ($coupon->get_discount_type() === 'fixed_cart') { if ($coupon->get_discount_type() === 'fixed_cart') {
return $coupon->get_amount() * 100; return $coupon->get_amount() * 100;
} else { } else {
@ -30,7 +31,8 @@ function get_discount_amount(WC_Coupon $coupon) {
} }
} }
function get_discount_duration(WC_Coupon $coupon): string { function get_discount_duration(WC_Coupon $coupon): string
{
if ($coupon->get_discount_type() === 'fixed_cart') { if ($coupon->get_discount_type() === 'fixed_cart') {
return 'once'; return 'once';
} else { } else {

View file

@ -45,6 +45,7 @@ $maximum_price = collect($product->variations)->max('price');
$same_collection_products = Product::get_same_collection_products($product->collection)($product->id) $same_collection_products = Product::get_same_collection_products($product->collection)($product->id)
|> function (/** @var list<WC_Product>|stdClass */ mixed $products): array { |> function (/** @var list<WC_Product>|stdClass */ mixed $products): array {
assert(is_array($products), 'Les Produits de la même collection doivent être un tableau.'); assert(is_array($products), 'Les Produits de la même collection doivent être un tableau.');
return $products; return $products;
} }
|> (static fn(/** @var list<WC_Product> */ array $products): array => Arr::map( |> (static fn(/** @var list<WC_Product> */ array $products): array => Arr::map(

View file

@ -170,6 +170,7 @@ final class StarterSite extends Site {
public function maj_environnement_twig(array $options): array { public function maj_environnement_twig(array $options): array {
return $options; return $options;
} }
// public function charge_traductions_theme(): void { // public function charge_traductions_theme(): void {
// load_theme_textdomain("haiku-atelier-2024", get_template_directory() . "/languages"); // load_theme_textdomain("haiku-atelier-2024", get_template_directory() . "/languages");
// } // }

View file

@ -9,7 +9,8 @@ declare(strict_types=1);
use Carbon_Fields\Container; use Carbon_Fields\Container;
use Carbon_Fields\Field; use Carbon_Fields\Field;
function cree_champs_personnalises_produit(): void { function cree_champs_personnalises_produit(): void
{
Container::make('post_meta', "Product's Details") Container::make('post_meta', "Product's Details")
->where('post_type', '=', 'product') ->where('post_type', '=', 'product')
->add_fields([ ->add_fields([
@ -26,7 +27,8 @@ function cree_champs_personnalises_produit(): void {
]); ]);
} }
function cree_champ_personnalise_commande($order): void { function cree_champ_personnalise_commande($order): void
{
woocommerce_wp_text_input([ woocommerce_wp_text_input([
'id' => 'tracking_number', 'id' => 'tracking_number',
'label' => 'Tracking Number:', 'label' => 'Tracking Number:',
@ -35,7 +37,8 @@ function cree_champ_personnalise_commande($order): void {
]); ]);
} }
function maj_champ_personnalise_commande($order_id): void { function maj_champ_personnalise_commande($order_id): void
{
$order = wc_get_order($order_id); $order = wc_get_order($order_id);
$order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number'])); $order->update_meta_data('tracking_number', wc_clean($_POST['tracking_number']));
$order->save(); $order->save();

View file

@ -8,7 +8,8 @@
declare(strict_types=1); declare(strict_types=1);
function enregistre_controle_personnalise_tinymce(): void { function enregistre_controle_personnalise_tinymce(): void
{
/** /**
* TinyMCE Custom Control. * TinyMCE Custom Control.
* *
@ -17,14 +18,16 @@ function enregistre_controle_personnalise_tinymce(): void {
* *
* @see https://github.com/maddisondesigns * @see https://github.com/maddisondesigns
*/ */
final class ControlesPersonnalises extends WP_Customize_Control { final class ControlesPersonnalises extends WP_Customize_Control
{
/** The type of control being rendered. */ /** The type of control being rendered. */
public $type = 'editeur_tinymce'; public $type = 'editeur_tinymce';
/** /**
* Enqueue our scripts and styles. * Enqueue our scripts and styles.
*/ */
public function enqueue(): void { public function enqueue(): void
{
wp_enqueue_script( wp_enqueue_script(
handle: 'controle-personnalise-tinymce', handle: 'controle-personnalise-tinymce',
src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js', src: get_template_directory_uri() . '/assets/vendor/controle-personnalise-tinymce.js',
@ -38,7 +41,8 @@ function enregistre_controle_personnalise_tinymce(): void {
/** /**
* Render the control in the customizer. * Render the control in the customizer.
*/ */
public function render_content(): void { ?> public function render_content(): void
{ ?>
<div class="tinymce-control"> <div class="tinymce-control">
<span class="customize-control-title"><?php echo esc_html($this->label); ?></span> <span class="customize-control-title"><?php echo esc_html($this->label); ?></span>
<?php if (!empty($this->description)) { ?> <?php if (!empty($this->description)) { ?>
@ -55,7 +59,8 @@ function enregistre_controle_personnalise_tinymce(): void {
/** /**
* Pass our TinyMCE toolbar string to JavaScript. * Pass our TinyMCE toolbar string to JavaScript.
*/ */
public function to_json(): void { public function to_json(): void
{
parent::to_json(); parent::to_json();
$this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1']) $this->json['skyrockettinymcetoolbar1'] = isset($this->input_attrs['toolbar1'])

View file

@ -11,7 +11,8 @@ use function is_float;
use function is_int; use function is_int;
use function is_string; use function is_string;
final readonly class Cart { final readonly class Cart
{
public function __construct() {} public function __construct() {}
/** La valeur par défaut d'une donnée invalide du Panier. */ /** La valeur par défaut d'une donnée invalide du Panier. */
@ -22,7 +23,8 @@ final readonly class Cart {
* *
* @return array<int,string> * @return array<int,string>
*/ */
public static function get_allowed_countries(): array { public static function get_allowed_countries(): array
{
return [ return [
'AD', 'AD',
'AL', 'AL',
@ -95,7 +97,8 @@ final readonly class Cart {
]; ];
} }
public static function parse_cart_value(int|float|string|bool $cart_value): string { public static function parse_cart_value(int|float|string|bool $cart_value): string
{
if (is_int($cart_value) || is_float($cart_value)) { if (is_int($cart_value) || is_float($cart_value)) {
return self::format_number($cart_value); return self::format_number($cart_value);
} }
@ -110,7 +113,8 @@ final readonly class Cart {
return '0.00'; return '0.00';
} }
private static function format_number(int|float $number): string { private static function format_number(int|float $number): string
{
$formatted_number = Number::format( $formatted_number = Number::format(
number: $number, number: $number,
// precision et max_precision sont mutuellement exclusifs. // precision et max_precision sont mutuellement exclusifs.

View file

@ -6,7 +6,8 @@ namespace HaikuAtelier\Data;
use WC_Product; use WC_Product;
final readonly class ProductVariation { final readonly class ProductVariation
{
/** /**
* @param int $id L'ID de la Variation * @param int $id L'ID de la Variation
* @param string $price Le prix de la Variation * @param string $price Le prix de la Variation
@ -21,7 +22,8 @@ final readonly class ProductVariation {
/** /**
* Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`. * Créé une nouvelle instance de `ProductVariation` à partir d'un `WC_Product`.
*/ */
public static function new(WC_Product $product): self { public static function new(WC_Product $product): self
{
$id = $product->get_id(); $id = $product->get_id();
$price = $product->get_price(); $price = $product->get_price();
/** @var list<ProductVariationAttribute> */ /** @var list<ProductVariationAttribute> */

View file

@ -4,7 +4,8 @@ declare(strict_types=1);
namespace HaikuAtelier\Data; namespace HaikuAtelier\Data;
final readonly class ProductVariationAttribute { final readonly class ProductVariationAttribute
{
/** /**
* @param string $attribute Le slug de l'Attribut * @param string $attribute Le slug de l'Attribut
* @param string $value Le slug de la valeur de l'Attribut * @param string $value Le slug de la valeur de l'Attribut

View file

@ -9,7 +9,8 @@ declare(strict_types=1);
namespace HaikuAtelier; namespace HaikuAtelier;
// Désactive divers transformations du contenu par WordPress // Désactive divers transformations du contenu par WordPress
function desactive_wpautop(): void { function desactive_wpautop(): void
{
remove_filter('the_content', 'wpautop'); remove_filter('the_content', 'wpautop');
} }
@ -20,7 +21,8 @@ function desactive_wpautop(): void {
* *
* @return array<string, bool> le même tableau avec des configurations en plus * @return array<string, bool> le même tableau avec des configurations en plus
*/ */
function desactive_transformation_contenu_tinymce(array $configuration): array { function desactive_transformation_contenu_tinymce(array $configuration): array
{
// Ne supprime pas les retours à la ligne // Ne supprime pas les retours à la ligne
$configuration['remove_linebreaks'] = false; $configuration['remove_linebreaks'] = false;
// Convertis les caractères de retours à la ligne en <br> // Convertis les caractères de retours à la ligne en <br>
@ -39,18 +41,21 @@ function desactive_transformation_contenu_tinymce(array $configuration): array {
* *
* @return array<string, string> le même tableau avec SVG en plus * @return array<string, string> le même tableau avec SVG en plus
*/ */
function autorise_import_svg_mediatheque(array $file_types): array { function autorise_import_svg_mediatheque(array $file_types): array
{
$new_filetypes = []; $new_filetypes = [];
$new_filetypes['svg'] = 'image/svg+xml'; $new_filetypes['svg'] = 'image/svg+xml';
return [...$file_types, ...$new_filetypes]; return [...$file_types, ...$new_filetypes];
} }
function retire_motifs_blocs_gutenberg(): void { function retire_motifs_blocs_gutenberg(): void
{
remove_theme_support('core-block-patterns'); remove_theme_support('core-block-patterns');
} }
function retire_styles_core_block(): void { function retire_styles_core_block(): void
{
wp_dequeue_style('core-block-supports'); wp_dequeue_style('core-block-supports');
} }

View file

@ -14,7 +14,8 @@ use function register_taxonomy;
/** /**
* Enregistre la Taxonomie « Collection ». * Enregistre la Taxonomie « Collection ».
*/ */
function enregistre_taxonomie_collection(): void { function enregistre_taxonomie_collection(): void
{
$labels = [ $labels = [
'add_new_item' => __('Add New Collection'), 'add_new_item' => __('Add New Collection'),
'all_items' => __('All Collections'), 'all_items' => __('All Collections'),

View file

@ -14,11 +14,13 @@ use function is_array;
use function Psl\Option\none; use function Psl\Option\none;
use function Psl\Option\some; use function Psl\Option\some;
final readonly class Post { final readonly class Post
{
/** /**
* @return Option\Option<mixed> * @return Option\Option<mixed>
*/ */
public static function get_post_meta(int $post_id, string $key): Option\Option { public static function get_post_meta(int $post_id, string $key): Option\Option
{
/** @var false|mixed|string */ /** @var false|mixed|string */
$value = get_post_meta($post_id, $key, true); $value = get_post_meta($post_id, $key, true);
@ -32,7 +34,8 @@ final readonly class Post {
/** /**
* @return Option\Option<array<mixed>> * @return Option\Option<array<mixed>>
*/ */
public static function get_post_meta_array(int $post_id, string $key): Option\Option { public static function get_post_meta_array(int $post_id, string $key): Option\Option
{
/** @var array<mixed>|false */ /** @var array<mixed>|false */
$value = get_post_meta($post_id, $key, false); $value = get_post_meta($post_id, $key, false);
@ -46,7 +49,8 @@ final readonly class Post {
/** /**
* @return Option\Option<array<mixed>> * @return Option\Option<array<mixed>>
*/ */
public static function get_terms(int $post_id, string $taxonomy_name): Option\Option { public static function get_terms(int $post_id, string $taxonomy_name): Option\Option
{
/** @var false|list<WP_Term>|WP_Error */ /** @var false|list<WP_Term>|WP_Error */
$terms = get_the_terms($post_id, $taxonomy_name); $terms = get_the_terms($post_id, $taxonomy_name);

View file

@ -7,13 +7,11 @@ import { getOptionOrThrowWithError } from "./utils.ts";
type ParentElement = Document | Element; type ParentElement = Document | Element;
const getFirstSelectorFromParent = const getFirstSelectorFromParent =
(parent: ParentElement) => (parent: ParentElement) => <E extends Element = Element>(selector: string): Option.Option<NonNullable<E>> =>
<E extends Element = Element>(selector: string): Option.Option<NonNullable<E>> =>
Option.fromNullishOr(parent.querySelector<E>(selector)); Option.fromNullishOr(parent.querySelector<E>(selector));
const getFirstSelectorFromParentOrThrow = const getFirstSelectorFromParentOrThrow =
(parent: ParentElement) => (parent: ParentElement) => <E extends Element = Element>(selector: string): NonNullable<E> =>
<E extends Element = Element>(selector: string): NonNullable<E> =>
pipe( pipe(
getFirstSelectorFromParent(parent)<E>(selector), getFirstSelectorFromParent(parent)<E>(selector),
getOptionOrThrowWithError(`Il n'y a pas d'Élément dans le parent avec le sélecteur suivant : ${selector}.`), getOptionOrThrowWithError(`Il n'y a pas d'Élément dans le parent avec le sélecteur suivant : ${selector}.`),
@ -29,8 +27,7 @@ const getFirstSelectorFromDocumentOrThrow = <E extends Element = Element>(select
); );
const getAllSelectorFromParent = const getAllSelectorFromParent =
(parent: ParentElement) => (parent: ParentElement) => <E extends Element = Element>(selector: string): Option.Option<NonEmptyReadonlyArray<E>> =>
<E extends Element = Element>(selector: string): Option.Option<NonEmptyReadonlyArray<E>> =>
pipe( pipe(
parent.querySelectorAll<E>(selector), parent.querySelectorAll<E>(selector),
// Convertis NodeListOf en Array. // Convertis NodeListOf en Array.

View file

@ -1,8 +1,6 @@
import { Option, pipe } from "effect"; import { Option, pipe } from "effect";
export const getOptionOrThrowWithError = export const getOptionOrThrowWithError = (message: string) => <T>(option: Option.Option<T>): T =>
(message: string) =>
<T>(option: Option.Option<T>): T =>
pipe( pipe(
option, option,
Option.getOrThrowWith(() => new Error(message)), Option.getOrThrowWith(() => new Error(message)),

View file

@ -1,18 +1,12 @@
export const forEach = export const forEach = <T>(fn: (_1: T) => void) => (xs: Array<T>): void => {
<T>(fn: (_1: T) => void) =>
(xs: Array<T>): void => {
xs.forEach(fn); xs.forEach(fn);
}; };
export const forEachWithIndex = export const forEachWithIndex = <T>(fn: (_1: T, _2: number) => void) => (xs: Array<T>): void => {
<T>(fn: (_1: T, _2: number) => void) =>
(xs: Array<T>): void => {
xs.forEach(fn); xs.forEach(fn);
}; };
export const map = export const map = <T>(fn: (_1: T) => void) => (xs: Array<T>): Array<T> => {
<T>(fn: (_1: T) => void) =>
(xs: Array<T>): Array<T> => {
xs.map(fn); xs.map(fn);
return xs; return xs;
}; };

View file

@ -18,26 +18,22 @@ import {
} from "./erreurs"; } from "./erreurs";
export const recupereElementAvecSelecteur = export const recupereElementAvecSelecteur =
(parent: ParentElement) => (parent: ParentElement) => <E extends Element = Element>(selecteur: string): Either<SyntaxError, E> =>
<E extends Element = Element>(selecteur: string): Either<SyntaxError, E> =>
Either Either
// Retourne une SyntaxError dans un Left si le sélecteur est invalide // Retourne une SyntaxError dans un Left si le sélecteur est invalide
.encase(() => parent.querySelector<E>(selecteur)) .encase(() => parent.querySelector<E>(selecteur))
// Transforme le Left en une erreur plus sympathique // Transforme le Left en une erreur plus sympathique
.mapLeft((_) => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur))) .mapLeft(_ => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
// Retourne une SyntaxError si l'Élément est null // Retourne une SyntaxError si l'Élément est null
.chain((e: E | null) => .chain((e: E | null) => G.isNotNullable(e) ? Right(e) : Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))));
G.isNotNullable(e) ? Right(e) : Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))),
);
export const getDOMElementsWithSelector = export const getDOMElementsWithSelector =
(parent: ParentElement) => (parent: ParentElement) => <E extends Element = Element>(selecteur: string): Either<SyntaxError, Array<E>> =>
<E extends Element = Element>(selecteur: string): Either<SyntaxError, Array<E>> =>
Either Either
// Retourne une SyntaxError dans un Left si le sélecteur est invalide // Retourne une SyntaxError dans un Left si le sélecteur est invalide
.encase(() => pipe(parent.querySelectorAll<E>(selecteur), Array.from<E>)) .encase(() => pipe(parent.querySelectorAll<E>(selecteur), Array.from<E>))
// Transforme le Left en une erreur plus sympathique // Transforme le Left en une erreur plus sympathique
.mapLeft((_) => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur))) .mapLeft(_ => creeSyntaxError(ERREUR_SYNTAXE_INVALIDE(selecteur)))
// Retourne une SyntaxError si le tableau est vide // Retourne une SyntaxError si le tableau est vide
.chain((e: Array<E>) => (A.isEmpty(e) ? Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))) : Right(e))); .chain((e: Array<E>) => (A.isEmpty(e) ? Left(creeSyntaxError(ERREUR_DOM_INEXISTANT(selecteur))) : Right(e)));
@ -55,9 +51,7 @@ export const recupereElementsOuLeve = <E extends Element = Element>(
Right: identity, Right: identity,
}); });
export const majElementInnerHtml = export const majElementInnerHtml = <T extends HTMLElement>(element: T) => (innerHtml: string) => {
<T extends HTMLElement>(element: T) =>
(innerHtml: string) => {
element.innerHTML = innerHtml; element.innerHTML = innerHtml;
return element; return element;
}; };
@ -66,9 +60,9 @@ export const majElementInnerHtml =
export const html = (strings: TemplateStringsArray, ...args: Array<string>) => export const html = (strings: TemplateStringsArray, ...args: Array<string>) =>
pipe( pipe(
document.createElement("template"), document.createElement("template"),
(template) => template =>
majElementInnerHtml(template)(args.reduce((prev, value, i) => prev + value + strings[i + 1], strings[0])), majElementInnerHtml(template)(args.reduce((prev, value, i) => prev + value + strings[i + 1], strings[0])),
(template) => template.content, template => template.content,
); );
/** /**
@ -86,10 +80,8 @@ export const safeJsonParse = (chaine: string): Either<SyntaxError, JSONValue> =>
* *
* @returns Un booléen * @returns Un booléen
*/ */
export const targetMatchesSelector = <E extends HTMLElement = HTMLElement>( export const targetMatchesSelector = (cible: EventTarget | null, selecteur: string): cible is HTMLElement =>
cible: EventTarget | null, (cible as HTMLElement)?.matches(selecteur);
selecteur: string,
): cible is E => cible !== null && (cible as HTMLElement).matches(selecteur);
export const recupereElementsDocumentEither: <E extends Element = Element>( export const recupereElementsDocumentEither: <E extends Element = Element>(
selecteur: string, selecteur: string,
@ -105,13 +97,11 @@ export const recupereElementDocumentEither: <E extends Element = Element>(select
* @throws Une SyntaxError si l'Élément n'est pas trouvé. * @throws Une SyntaxError si l'Élément n'est pas trouvé.
* @returns Un Élément. * @returns Un Élément.
*/ */
export const mustGetEleInDocument = <E extends Element = Element>(selecteur: string): E => export const mustGetEleInDocument = (selecteur: string): Element =>
pipe(recupereElementDocumentEither<E>(selecteur), recupereElementOuLeve); pipe(recupereElementDocumentEither<Element>(selecteur), recupereElementOuLeve);
export const mustGetEleInParent = export const mustGetEleInParent = (parent: ParentElement) => (selector: string) =>
(parent: ParentElement) => pipe(recupereElementAvecSelecteur(parent)<HTMLElement>(selector), recupereElementOuLeve);
<E extends HTMLElement>(selector: string) =>
pipe(recupereElementAvecSelecteur(parent)<E>(selector), recupereElementOuLeve);
/** /**
* Fonction utilitaire pour récupérer des Éléments selon un sélecteur au sein du Document. * Fonction utilitaire pour récupérer des Éléments selon un sélecteur au sein du Document.
@ -138,11 +128,11 @@ export const setButtonLoadingState = (button: HTMLButtonElement, isLoading: bool
}; };
export const estErreurHttp = (erreur: unknown) => export const estErreurHttp = (erreur: unknown) =>
erreur instanceof BadRequestError || erreur instanceof BadRequestError
erreur instanceof ForbiddenError || || erreur instanceof ForbiddenError
erreur instanceof NotFoundError || || erreur instanceof NotFoundError
erreur instanceof ServerError || || erreur instanceof ServerError
erreur instanceof UnauthorizedError; || erreur instanceof UnauthorizedError;
export const estErreurFetch = (erreur: unknown) => export const estErreurFetch = (erreur: unknown) =>
erreur instanceof DOMException || erreur instanceof TypeError || erreur instanceof Error; erreur instanceof DOMException || erreur instanceof TypeError || erreur instanceof Error;

View file

@ -78,7 +78,7 @@ export const Erreur = (message: string): Error => new Error(message);
export const ErreurInconnue = (erreur: unknown): UnknownError => new UnknownError(erreur); export const ErreurInconnue = (erreur: unknown): UnknownError => new UnknownError(erreur);
export const ErreurEntreeInexistante = (message: string): NonExistingKeyError => new NonExistingKeyError(message); export const ErreurEntreeInexistante = (message: string): NonExistingKeyError => new NonExistingKeyError(message);
export const leveErreur = <E extends Error = Error>(erreur: E): never => { export const leveErreur = (erreur: Error): never => {
throw erreur; throw erreur;
}; };
export const leveBadRequestError = (erreur: WCErrorBody): never => { export const leveBadRequestError = (erreur: WCErrorBody): never => {
@ -106,7 +106,7 @@ export const leveNonExistingKeyError = (message: string): never => {
* @param erreur * @param erreur
* @returns L'ID Sentry de l'évènement capturé. * @returns L'ID Sentry de l'évènement capturé.
*/ */
export const reporteErreur = <E extends Error>(erreur: E): string => captureException(erreur); export const reporteErreur = (erreur: Error): string => captureException(erreur);
/** /**
* Reporte une Erreur, sous forme d'erreur console et au service GlitchTip, puis la lève sous forme * Reporte une Erreur, sous forme d'erreur console et au service GlitchTip, puis la lève sous forme
@ -115,12 +115,12 @@ export const reporteErreur = <E extends Error>(erreur: E): string => captureExce
* @param erreur * @param erreur
* @returns never Lève une Erreur et ne retourne donc rien. * @returns never Lève une Erreur et ne retourne donc rien.
*/ */
export const reporteEtLeveErreur = <E extends Error>(erreur: E): never => { export const reporteEtLeveErreur = (erreur: Error): never => {
reporteErreur(erreur); reporteErreur(erreur);
throw erreur; throw erreur;
}; };
export const reporteEtJournaliseErreur = <E extends Error>(erreur: E): void => { export const reporteEtJournaliseErreur = (erreur: Error): void => {
reporteErreur(erreur); reporteErreur(erreur);
console.error(erreur); console.error(erreur);
if (erreur instanceof ValiError) { if (erreur instanceof ValiError) {

View file

@ -7,12 +7,12 @@ export const CODE_PROMO_MAJ_EVENT = new CustomEvent(CODE_PROMO_MAJ, {});
// Interfaces // Interfaces
export type UpdatedShippingRatesEvent = { export type UpdatedShippingRatesEvent = Event & {
detail: { refresh_methods: boolean; shipping_rates: ReadonlyArray<WCStoreShippingRateShippingRate> }; detail: { refresh_methods: boolean; shipping_rates: ReadonlyArray<WCStoreShippingRateShippingRate> };
} & Event; };
export type UpdatedTotalsEvent = { export type UpdatedTotalsEvent = Event & {
detail: { totals: WCStoreCartTotals }; detail: { totals: WCStoreCartTotals };
} & Event; };
// Méthodes // Méthodes

View file

@ -1,8 +1,6 @@
import type { Constructor } from "./types/classes"; import type { Constructor } from "./types/classes";
const estElement = const estElement = <T extends HTMLElement>(typeElement: Constructor<T>) => (element: unknown): element is T =>
<T extends HTMLElement>(typeElement: Constructor<T>) =>
(element: unknown): element is T =>
element instanceof typeElement; element instanceof typeElement;
export const estHTMLSelectElement = estElement<HTMLSelectElement>(HTMLSelectElement); export const estHTMLSelectElement = estElement<HTMLSelectElement>(HTMLSelectElement);

View file

@ -55,30 +55,31 @@ export const emetMessageMajContenuPanier = (args: MessageMajContenuPanierDonnees
* @param message Le message émis. * @param message Le message émis.
* @return void * @return void
*/ */
export const emetUniqueMessageBroadcastChannel = <M>(nomCanal: string, message: M): void => export const emetUniqueMessageBroadcastChannel = (nomCanal: string, message: unknown): void => {
pipe( pipe(
new BroadcastChannel(nomCanal), new BroadcastChannel(nomCanal),
(canal) => canalPostMessage(canal, message), canal => canalPostMessage(canal, message),
(canal) => canal.close(), canal => canal.close(),
); );
};
// Validations // Validations
export const valideMessageMajBoutonPanier = ( export const valideMessageMajBoutonPanier = (
evenementMessage: MessageEvent<unknown>, evenementMessage: MessageEvent<unknown>,
): Either<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier> => ): Either<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier> =>
Either.of<ValiError<typeof MessageMajBoutonPanierSchema>, MessageMajBoutonPanier>( Either.of<ValiError<typeof MessageMajBoutonPanierSchema>>(
parse(MessageMajBoutonPanierSchema, evenementMessage.data), parse(MessageMajBoutonPanierSchema, evenementMessage.data),
).ifLeft((erreur) => reporteErreur(erreur)); ).ifLeft(erreur => reporteErreur(erreur));
export const valideMessageMajContenuPanier = ( export const valideMessageMajContenuPanier = (
evenementMessage: MessageEvent<unknown>, evenementMessage: MessageEvent<unknown>,
): Either<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier> => ): Either<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier> =>
Either.of<ValiError<typeof MessageMajContenuPanierSchema>, MessageMajContenuPanier>( Either.of<ValiError<typeof MessageMajContenuPanierSchema>>(
parse(MessageMajContenuPanierSchema, evenementMessage.data), parse(MessageMajContenuPanierSchema, evenementMessage.data),
).ifLeft((erreur) => reporteErreur(erreur)); ).ifLeft(erreur => reporteErreur(erreur));
// Correspondances // Correspondances
export const reponseEstCodeErreurWC = (reponse: SimplifiedResponse, codeErreurWC: string): boolean => export const reponseEstCodeErreurWC = (reponse: SimplifiedResponse, codeErreurWC: string): boolean =>
safeSchemaParse(reponse, WCErrorSchema) safeSchemaParse(reponse, WCErrorSchema)
.map((v) => v.body.code === codeErreurWC) .map(v => v.body.code === codeErreurWC)
.orDefault(false); .orDefault(false);

View file

@ -5,10 +5,10 @@ export const estEntreDeuxNombres = (nombre: number, min: number, max: number): b
export const diviseParCent = (nombre: number | string): number => Number(nombre) / 100; export const diviseParCent = (nombre: number | string): number => Number(nombre) / 100;
export const arrondisADeuxDecimales = (nombre: number | string) => pipe(Number(nombre), (n) => n.toFixed(2)); export const arrondisADeuxDecimales = (nombre: number | string) => pipe(Number(nombre), n => n.toFixed(2));
export const arrondisAZeroOuDeuxDecimales = (nombre: number | string): string => export const arrondisAZeroOuDeuxDecimales = (nombre: number | string): string =>
pipe(Number(nombre), (n) => (n / Math.round(n) === 1 ? n.toFixed(0) : n.toFixed(2))); pipe(Number(nombre), n => (n / Math.round(n) === 1 ? n.toFixed(0) : n.toFixed(2)));
export const inverseNombre = (nombre: number | string): number => Number(nombre) * -1; export const inverseNombre = (nombre: number | string): number => Number(nombre) * -1;

View file

@ -38,7 +38,7 @@ type ArgumentsPostBackendWC = {
// Fetch // Fetch
export const getBackend = (args: ArgumentsGetBackendWC): Promise<Response> => export const getBackend = async (args: ArgumentsGetBackendWC): Promise<Response> =>
fetch(args.route, { fetch(args.route, {
credentials: "same-origin", credentials: "same-origin",
headers: { headers: {
@ -53,7 +53,7 @@ export const getBackend = (args: ArgumentsGetBackendWC): Promise<Response> =>
signal: AbortSignal.timeout(5000), signal: AbortSignal.timeout(5000),
}); });
export const getBackendAvecParametresUrl = (args: ArgumentsGetBackendWC): Promise<Response> => export const getBackendAvecParametresUrl = async (args: ArgumentsGetBackendWC): Promise<Response> =>
fetch(`${args.route}?${args.searchParams}`, { fetch(`${args.route}?${args.searchParams}`, {
credentials: "same-origin", credentials: "same-origin",
headers: { headers: {
@ -68,7 +68,7 @@ export const getBackendAvecParametresUrl = (args: ArgumentsGetBackendWC): Promis
signal: AbortSignal.timeout(5000), signal: AbortSignal.timeout(5000),
}); });
export const deleteBackend = (args: ArgumentsDeleteBackendWC): Promise<Response> => export const deleteBackend = async (args: ArgumentsDeleteBackendWC): Promise<Response> =>
fetch(args.route, { fetch(args.route, {
credentials: "same-origin", credentials: "same-origin",
headers: { headers: {
@ -83,7 +83,7 @@ export const deleteBackend = (args: ArgumentsDeleteBackendWC): Promise<Response>
signal: AbortSignal.timeout(5000), signal: AbortSignal.timeout(5000),
}); });
export const postBackend = (args: ArgumentsPostBackendWC): Promise<Response> => export const postBackend = async (args: ArgumentsPostBackendWC): Promise<Response> =>
fetch(args.route, { fetch(args.route, {
body: args.corps, body: args.corps,
credentials: "same-origin", credentials: "same-origin",
@ -101,7 +101,7 @@ export const postBackend = (args: ArgumentsPostBackendWC): Promise<Response> =>
export const prefilledPostBackend = export const prefilledPostBackend =
(nonce: string, authString?: string) => (nonce: string, authString?: string) =>
(route: string, body: BodyInit, needsAuthString: boolean): Promise<Response> => async (route: string, body: BodyInit, needsAuthString: boolean): Promise<Response> =>
fetch(route, { fetch(route, {
body: body, body: body,
credentials: "same-origin", credentials: "same-origin",
@ -127,9 +127,9 @@ export const newPartialResponse = async (reponse: Response): Promise<SimplifiedR
export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors => export const traiteErreursBackendWooCommerce = (rs: SimplifiedResponse): HttpCodeErrors =>
match(rs) match(rs)
.with({ status: 400 }, () => new BadRequestError()) ["with"]({ status: 400 }, () => new BadRequestError())
.with({ status: 401 }, () => new UnauthorizedError()) ["with"]({ status: 401 }, () => new UnauthorizedError())
.with({ status: 403 }, () => new ForbiddenError()) ["with"]({ status: 403 }, () => new ForbiddenError())
.with({ status: 404 }, () => new NotFoundError()) ["with"]({ status: 404 }, () => new NotFoundError())
.with({ status: 500 }, () => new ServerError()) ["with"]({ status: 500 }, () => new ServerError())
.otherwise((rs) => new Error(String(rs.status))); .otherwise(rs => new Error(String(rs.status)));

View file

@ -7,7 +7,5 @@ import { Maybe } from "purify-ts";
*/ */
export const first = <T>(xs: Array<T>): Maybe<T> => Maybe.fromNullable(xs.at(0)); export const first = <T>(xs: Array<T>): Maybe<T> => Maybe.fromNullable(xs.at(0));
export const find = export const find = <T>(predicateFn: (_1: T) => boolean) => (xs: Array<T>): Maybe<T> =>
<T>(predicateFn: (_1: T) => boolean) =>
(xs: Array<T>): Maybe<T> =>
Maybe.fromNullable(xs.find(predicateFn)); Maybe.fromNullable(xs.find(predicateFn));

View file

@ -20,24 +20,24 @@ export const WCStoreCartItemTotalsSchema = v.object({
}); });
export const WCStoreCartItemSchema = v.object({ export const WCStoreCartItemSchema = v.object({
backorders_allowed: v.boolean(), backorders_allowed: v["boolean"](),
catalog_visibility: v.enum(CATALOG_VISIBILITIES), catalog_visibility: v["enum"](CATALOG_VISIBILITIES),
description: v.string(), description: v.string(),
extensions: v.unknown(), extensions: v.unknown(),
id: v.number(), id: v.number(),
images: v.array(v.unknown()), images: v.array(v.unknown()),
item_data: v.array(v.unknown()), item_data: v.array(v.unknown()),
key: v.string(), key: v.string(),
low_stock_remaining: v.union([v.number(), v.null()]), low_stock_remaining: v.union([v.number(), v["null"]()]),
name: v.string(), name: v.string(),
permalink: v.pipe(v.string(), v.url()), permalink: v.pipe(v.string(), v.url()),
prices: v.unknown(), prices: v.unknown(),
quantity: v.number(), quantity: v.number(),
quantity_limits: v.unknown(), quantity_limits: v.unknown(),
short_description: v.string(), short_description: v.string(),
show_backorder_badge: v.boolean(), show_backorder_badge: v["boolean"](),
sku: v.string(), sku: v.string(),
sold_individually: v.boolean(), sold_individually: v["boolean"](),
totals: WCStoreCartItemTotalsSchema, totals: WCStoreCartItemTotalsSchema,
type: v.string(), type: v.string(),
variation: v.array(v.unknown()), variation: v.array(v.unknown()),
@ -60,10 +60,10 @@ export const WCStoreCartTotalsSchema = v.object({
total_items_tax: v.string(), total_items_tax: v.string(),
total_price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)), total_price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
total_shipping: v.pipe( total_shipping: v.pipe(
v.union([v.string(), v.number(), v.null()]), v.union([v.string(), v.number(), v["null"]()]),
v.transform((n) => (n ? Number(n) : 0)), v.transform(n => (n ? Number(n) : 0)),
), ),
total_shipping_tax: v.union([v.string(), v.null()]), total_shipping_tax: v.union([v.string(), v["null"]()]),
total_tax: v.string(), total_tax: v.string(),
}); });
@ -75,12 +75,12 @@ export const WCStoreCartSchema = v.object({
errors: v.unknown(), errors: v.unknown(),
extensions: v.unknown(), extensions: v.unknown(),
fees: v.unknown(), fees: v.unknown(),
has_calculated_shipping: v.boolean(), has_calculated_shipping: v["boolean"](),
items: v.array(WCStoreCartItemSchema), items: v.array(WCStoreCartItemSchema),
items_count: v.pipe(v.number(), v.integer()), items_count: v.pipe(v.number(), v.integer()),
items_weight: v.pipe(v.number(), v.integer()), items_weight: v.pipe(v.number(), v.integer()),
needs_payment: v.boolean(), needs_payment: v["boolean"](),
needs_shipping: v.boolean(), needs_shipping: v["boolean"](),
payment_methods: v.unknown(), payment_methods: v.unknown(),
payment_requirements: v.unknown(), payment_requirements: v.unknown(),
shipping_address: WCStoreShippingAddressSchema, shipping_address: WCStoreShippingAddressSchema,

View file

@ -26,7 +26,7 @@ export const WCStoreShippingRateShippingRateSchema = v.object({
name: v.string(), name: v.string(),
price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)), price: v.pipe(v.union([v.string(), v.number()]), v.transform(Number)),
rate_id: v.string(), rate_id: v.string(),
selected: v.boolean(), selected: v["boolean"](),
taxes: v.string(), taxes: v.string(),
}); });

View file

@ -24,14 +24,14 @@ export const WCAddressErrorSchema = v.object({
billing: v.optional( billing: v.optional(
v.object({ v.object({
code: v.string(), code: v.string(),
data: v.union([v.null(), v.string()]), data: v.union([v["null"](), v.string()]),
message: v.string(), message: v.string(),
}), }),
), ),
shipping: v.optional( shipping: v.optional(
v.object({ v.object({
code: v.string(), code: v.string(),
data: v.union([v.null(), v.string()]), data: v.union([v["null"](), v.string()]),
message: v.string(), message: v.string(),
}), }),
), ),

View file

@ -17,36 +17,36 @@ import {
export const WCProductsArgsSchema = v.object({ export const WCProductsArgsSchema = v.object({
// Date ISO8601 // Date ISO8601
after: v.optional(v.optional(v.string())), after: v.optional(v.optional(v.string())),
attribute_relation: v.optional(v.enum(ATTRIBUTES_RELATIONS)), attribute_relation: v.optional(v["enum"](ATTRIBUTES_RELATIONS)),
attributes: v.optional(v.array(v.unknown())), attributes: v.optional(v.array(v.unknown())),
// Date ISO8601 // Date ISO8601
before: v.optional(v.string()), before: v.optional(v.string()),
catalog_visibility: v.optional(v.enum(CATALOG_VISIBILITIES)), catalog_visibility: v.optional(v["enum"](CATALOG_VISIBILITIES)),
category: v.optional(v.string()), category: v.optional(v.string()),
category_operator: v.optional(v.enum(CATEGORY_OPERATORS)), category_operator: v.optional(v["enum"](CATEGORY_OPERATORS)),
context: v.optional(v.enum(PRODUCTS_CONTEXTES)), context: v.optional(v["enum"](PRODUCTS_CONTEXTES)),
date_column: v.optional(v.enum(DATE_COLUMN_VALUES)), date_column: v.optional(v["enum"](DATE_COLUMN_VALUES)),
exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))), exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))),
featured: v.optional(v.boolean()), featured: v.optional(v["boolean"]()),
include: v.optional(v.array(v.pipe(v.number(), v.integer()))), include: v.optional(v.array(v.pipe(v.number(), v.integer()))),
max_price: v.optional(v.string()), max_price: v.optional(v.string()),
min_price: v.optional(v.string()), min_price: v.optional(v.string()),
offset: v.optional(v.number()), offset: v.optional(v.number()),
on_sale: v.optional(v.boolean()), on_sale: v.optional(v["boolean"]()),
order: v.optional(v.enum(ORDER_VALUES)), order: v.optional(v["enum"](ORDER_VALUES)),
orderby: v.optional(v.enum(ORDERBY_VALUES)), orderby: v.optional(v["enum"](ORDERBY_VALUES)),
page: v.optional(v.pipe(v.number(), v.minValue(1))), page: v.optional(v.pipe(v.number(), v.minValue(1))),
parent: v.optional(v.array(v.pipe(v.number(), v.integer()))), parent: v.optional(v.array(v.pipe(v.number(), v.integer()))),
parent_exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))), parent_exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))),
per_page: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100))), per_page: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100))),
rating: v.optional(v.array(v.enum(RATINGS))), rating: v.optional(v.array(v["enum"](RATINGS))),
search: v.optional(v.string()), search: v.optional(v.string()),
sku: v.optional(v.string()), sku: v.optional(v.string()),
slug: v.optional(v.string()), slug: v.optional(v.string()),
stock_status: v.optional(v.array(v.enum(STOCK_STATUSES))), stock_status: v.optional(v.array(v["enum"](STOCK_STATUSES))),
tag: v.optional(v.string()), tag: v.optional(v.string()),
tag_operator: v.optional(v.enum(TAG_OPERATORS)), tag_operator: v.optional(v["enum"](TAG_OPERATORS)),
type: v.optional(v.enum(PRODUCT_TYPES)), type: v.optional(v["enum"](PRODUCT_TYPES)),
}); });
export const WCProductSchema = v.object({ export const WCProductSchema = v.object({
@ -70,7 +70,7 @@ export const WCProductSchema = v.object({
), ),
description: v.string(), description: v.string(),
extensions: v.unknown(), extensions: v.unknown(),
has_options: v.boolean(), has_options: v["boolean"](),
id: v.number(), id: v.number(),
images: v.array( images: v.array(
v.object({ v.object({
@ -83,12 +83,12 @@ export const WCProductSchema = v.object({
thumbnail: v.string(), thumbnail: v.string(),
}), }),
), ),
is_in_stock: v.boolean(), is_in_stock: v["boolean"](),
is_on_backorder: v.boolean(), is_on_backorder: v["boolean"](),
is_purchasable: v.boolean(), is_purchasable: v["boolean"](),
low_stock_remaining: v.union([v.number(), v.null()]), low_stock_remaining: v.union([v.number(), v["null"]()]),
name: v.string(), name: v.string(),
on_sale: v.boolean(), on_sale: v["boolean"](),
parent: v.number(), parent: v.number(),
permalink: v.string(), permalink: v.string(),
price_html: v.string(), price_html: v.string(),
@ -109,7 +109,7 @@ export const WCProductSchema = v.object({
short_description: v.string(), short_description: v.string(),
sku: v.string(), sku: v.string(),
slug: v.string(), slug: v.string(),
sold_individually: v.boolean(), sold_individually: v["boolean"](),
tags: v.array(v.string()), tags: v.array(v.string()),
type: v.string(), type: v.string(),
variation: v.unknown(), variation: v.unknown(),

View file

@ -14,7 +14,7 @@ export const WCV3OrdersCouponLineSchema = v.object({
discount: v.string(), discount: v.string(),
discount_tax: v.string(), discount_tax: v.string(),
discount_type: v.string(), discount_type: v.string(),
free_shipping: v.boolean(), free_shipping: v["boolean"](),
id: v.pipe(v.number(), v.integer()), id: v.pipe(v.number(), v.integer()),
meta_data: v.array(WCV3OrdersCouponLineMetaDataSchema), meta_data: v.array(WCV3OrdersCouponLineMetaDataSchema),
nominal_amount: v.number(), nominal_amount: v.number(),
@ -37,7 +37,7 @@ export const WCV3OrdersFeeLineSchema = v.object({
meta_data: v.array(WCV3OrdersFeeLineMetaDataSchema), meta_data: v.array(WCV3OrdersFeeLineMetaDataSchema),
name: v.string(), name: v.string(),
tax_class: v.string(), tax_class: v.string(),
tax_status: v.enum(TAX_STATUSES), tax_status: v["enum"](TAX_STATUSES),
taxes: v.array(WCV3OrdersFeeLineTaxSchema), taxes: v.array(WCV3OrdersFeeLineTaxSchema),
total: v.string(), total: v.string(),
total_tax: v.string(), total_tax: v.string(),
@ -88,7 +88,7 @@ export const WCV3OrdersLineItemSchema = v.object({
image: v.optional(WCV3OrdersLineItemImageSchema), image: v.optional(WCV3OrdersLineItemImageSchema),
meta_data: v.optional(v.array(WCV3OrdersLineItemMetaDataSchema)), meta_data: v.optional(v.array(WCV3OrdersLineItemMetaDataSchema)),
name: v.optional(v.string()), name: v.optional(v.string()),
parent_name: v.optional(v.union([v.string(), v.null()])), parent_name: v.optional(v.union([v.string(), v["null"]()])),
price: v.optional(v.number()), price: v.optional(v.number()),
product_id: v.optional(v.pipe(v.number(), v.integer())), product_id: v.optional(v.pipe(v.number(), v.integer())),
quantity: v.optional(v.pipe(v.number(), v.integer())), quantity: v.optional(v.pipe(v.number(), v.integer())),
@ -116,14 +116,14 @@ export const WCV3OrdersArgsSchema = v.object({
customer_note: v.optional(v.string()), customer_note: v.optional(v.string()),
fee_lines: v.optional(v.array(WCV3OrdersFeeLineSchema)), fee_lines: v.optional(v.array(WCV3OrdersFeeLineSchema)),
line_items: v.optional(v.array(WCV3OrdersLineItemSchema)), line_items: v.optional(v.array(WCV3OrdersLineItemSchema)),
manual_update: v.optional(v.boolean()), manual_update: v.optional(v["boolean"]()),
parent_id: v.optional(v.pipe(v.number(), v.integer())), parent_id: v.optional(v.pipe(v.number(), v.integer())),
payment_method: v.optional(v.string()), payment_method: v.optional(v.string()),
payment_method_title: v.optional(v.string()), payment_method_title: v.optional(v.string()),
set_paid: v.optional(v.boolean()), set_paid: v.optional(v["boolean"]()),
shipping: v.optional(WCStoreShippingAddressSchema), shipping: v.optional(WCStoreShippingAddressSchema),
shipping_lines: v.optional(v.array(WCV3OrdersShippingLineSchema)), shipping_lines: v.optional(v.array(WCV3OrdersShippingLineSchema)),
status: v.optional(v.enum(ORDER_STATUSES)), status: v.optional(v["enum"](ORDER_STATUSES)),
transaction_id: v.optional(v.string()), transaction_id: v.optional(v.string()),
}); });
@ -139,37 +139,37 @@ export const WCV3OrderSchema = v.object({
customer_ip_address: v.string(), customer_ip_address: v.string(),
customer_note: v.string(), customer_note: v.string(),
customer_user_agent: v.string(), customer_user_agent: v.string(),
date_completed: v.union([v.string(), v.null()]), date_completed: v.union([v.string(), v["null"]()]),
date_completed_gmt: v.union([v.string(), v.null()]), date_completed_gmt: v.union([v.string(), v["null"]()]),
// Date // Date
date_created: v.string(), date_created: v.string(),
date_created_gmt: v.string(), date_created_gmt: v.string(),
date_modified: v.string(), date_modified: v.string(),
date_modified_gmt: v.string(), date_modified_gmt: v.string(),
date_paid: v.union([v.string(), v.null()]), date_paid: v.union([v.string(), v["null"]()]),
date_paid_gmt: v.union([v.string(), v.null()]), date_paid_gmt: v.union([v.string(), v["null"]()]),
discount_tax: v.string(), discount_tax: v.string(),
discount_total: v.string(), discount_total: v.string(),
fee_lines: v.array(WCV3OrdersFeeLineSchema), fee_lines: v.array(WCV3OrdersFeeLineSchema),
id: v.pipe(v.number(), v.integer()), id: v.pipe(v.number(), v.integer()),
is_editable: v.boolean(), is_editable: v["boolean"](),
line_items: v.array(WCV3OrdersLineItemSchema), line_items: v.array(WCV3OrdersLineItemSchema),
meta_data: v.unknown(), meta_data: v.unknown(),
needs_payment: v.boolean(), needs_payment: v["boolean"](),
needs_processing: v.boolean(), needs_processing: v["boolean"](),
number: v.string(), number: v.string(),
order_key: v.string(), order_key: v.string(),
parent_id: v.pipe(v.number(), v.integer()), parent_id: v.pipe(v.number(), v.integer()),
payment_method: v.string(), payment_method: v.string(),
payment_method_title: v.string(), payment_method_title: v.string(),
payment_url: v.string(), payment_url: v.string(),
prices_include_tax: v.boolean(), prices_include_tax: v["boolean"](),
refunds: v.array(v.unknown()), refunds: v.array(v.unknown()),
shipping: WCStoreShippingAddressSchema, shipping: WCStoreShippingAddressSchema,
shipping_lines: v.array(WCV3OrdersShippingLineSchema), shipping_lines: v.array(WCV3OrdersShippingLineSchema),
shipping_tax: v.string(), shipping_tax: v.string(),
shipping_total: v.string(), shipping_total: v.string(),
status: v.enum(ORDER_STATUSES), status: v["enum"](ORDER_STATUSES),
tax_lines: v.array(v.unknown()), tax_lines: v.array(v.unknown()),
total: v.string(), total: v.string(),
total_tax: v.string(), total_tax: v.string(),

View file

@ -21,20 +21,20 @@ export const WCV3ProductsArgsSchema = v.object({
// Date ISO8601 // Date ISO8601
after: v.optional(v.string()), after: v.optional(v.string()),
attribute: v.optional(v.string()), attribute: v.optional(v.string()),
attribute_relation: v.optional(v.enum(ATTRIBUTES_RELATIONS)), attribute_relation: v.optional(v["enum"](ATTRIBUTES_RELATIONS)),
attribute_term: v.optional(v.string()), attribute_term: v.optional(v.string()),
attributes: v.optional(v.array(v.unknown())), attributes: v.optional(v.array(v.unknown())),
// Date ISO8601 // Date ISO8601
before: v.optional(v.string()), before: v.optional(v.string()),
catalog_visibility: v.optional(v.enum(CATALOG_VISIBILITIES)), catalog_visibility: v.optional(v["enum"](CATALOG_VISIBILITIES)),
category: v.optional(v.string()), category: v.optional(v.string()),
category_operator: v.optional(v.enum(CATEGORY_OPERATORS)), category_operator: v.optional(v["enum"](CATEGORY_OPERATORS)),
context: v.optional(v.enum(PRODUCTS_CONTEXTES)), context: v.optional(v["enum"](PRODUCTS_CONTEXTES)),
date_column: v.optional(v.enum(DATE_COLUMN_VALUES)), date_column: v.optional(v["enum"](DATE_COLUMN_VALUES)),
dates_are_gmt: v.optional(v.boolean()), dates_are_gmt: v.optional(v["boolean"]()),
exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))), exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))),
exclude_meta: v.optional(v.array(v.string())), exclude_meta: v.optional(v.array(v.string())),
featured: v.optional(v.boolean()), featured: v.optional(v["boolean"]()),
include: v.optional(v.array(v.pipe(v.number(), v.integer()))), include: v.optional(v.array(v.pipe(v.number(), v.integer()))),
include_meta: v.optional(v.array(v.string())), include_meta: v.optional(v.array(v.string())),
max_price: v.optional(v.string()), max_price: v.optional(v.string()),
@ -44,24 +44,24 @@ export const WCV3ProductsArgsSchema = v.object({
// Date ISO8601 // Date ISO8601
modified_before: v.optional(v.string()), modified_before: v.optional(v.string()),
offset: v.optional(v.pipe(v.number(), v.integer())), offset: v.optional(v.pipe(v.number(), v.integer())),
on_sale: v.optional(v.boolean()), on_sale: v.optional(v["boolean"]()),
order: v.optional(v.enum(ORDER_VALUES)), order: v.optional(v["enum"](ORDER_VALUES)),
orderby: v.optional(v.enum(ORDERBY_VALUES)), orderby: v.optional(v["enum"](ORDERBY_VALUES)),
page: v.optional(v.pipe(v.number(), v.minValue(1))), page: v.optional(v.pipe(v.number(), v.minValue(1))),
parent: v.optional(v.array(v.pipe(v.number(), v.integer()))), parent: v.optional(v.array(v.pipe(v.number(), v.integer()))),
parent_exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))), parent_exclude: v.optional(v.array(v.pipe(v.number(), v.integer()))),
per_page: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100))), per_page: v.optional(v.pipe(v.number(), v.minValue(0), v.maxValue(100))),
rating: v.optional(v.array(v.enum(RATINGS))), rating: v.optional(v.array(v["enum"](RATINGS))),
search: v.optional(v.string()), search: v.optional(v.string()),
search_sku: v.optional(v.string()), search_sku: v.optional(v.string()),
shipping_class: v.optional(v.string()), shipping_class: v.optional(v.string()),
sku: v.optional(v.string()), sku: v.optional(v.string()),
slug: v.optional(v.string()), slug: v.optional(v.string()),
status: v.optional(v.enum(PRODUCT_STATUTES)), status: v.optional(v["enum"](PRODUCT_STATUTES)),
stock_status: v.optional(v.array(v.enum(STOCK_STATUSES))), stock_status: v.optional(v.array(v["enum"](STOCK_STATUSES))),
tag: v.optional(v.string()), tag: v.optional(v.string()),
tag_operator: v.optional(v.enum(TAG_OPERATORS)), tag_operator: v.optional(v["enum"](TAG_OPERATORS)),
type: v.optional(v.enum(PRODUCT_TYPES)), type: v.optional(v["enum"](PRODUCT_TYPES)),
}); });
export const WCV3ProductDownloadsSchema = v.object({ export const WCV3ProductDownloadsSchema = v.object({
@ -99,8 +99,8 @@ export const WCV3ProductAttributeSchema = v.object({
name: v.string(), name: v.string(),
options: v.array(v.string()), options: v.array(v.string()),
position: v.pipe(v.number(), v.integer()), position: v.pipe(v.number(), v.integer()),
variation: v.boolean(), variation: v["boolean"](),
visible: v.boolean(), visible: v["boolean"](),
}); });
export const WCV3ProductDefaultAttributeSchema = v.object({ export const WCV3ProductDefaultAttributeSchema = v.object({
id: v.pipe(v.number(), v.integer()), id: v.pipe(v.number(), v.integer()),
@ -116,46 +116,46 @@ export const WCV3ProductMetaDataSchema = v.object({
export const WCV3ProductSchema = v.object({ export const WCV3ProductSchema = v.object({
attributes: v.array(WCV3ProductAttributeSchema), attributes: v.array(WCV3ProductAttributeSchema),
average_rating: v.string(), average_rating: v.string(),
backordered: v.boolean(), backordered: v["boolean"](),
backorders: v.enum(BACKORDERS_SETTINGS), backorders: v["enum"](BACKORDERS_SETTINGS),
backorders_allowed: v.boolean(), backorders_allowed: v["boolean"](),
button_text: v.string(), button_text: v.string(),
catalog_visibility: v.enum(CATALOG_VISIBILITIES), catalog_visibility: v["enum"](CATALOG_VISIBILITIES),
categories: v.array(WCV3ProductCategorySchema), categories: v.array(WCV3ProductCategorySchema),
cross_sell_ids: v.array(v.pipe(v.number(), v.integer())), cross_sell_ids: v.array(v.pipe(v.number(), v.integer())),
date_created: v.string(), date_created: v.string(),
date_created_gmt: v.string(), date_created_gmt: v.string(),
date_modified: v.string(), date_modified: v.string(),
date_modified_gmt: v.string(), date_modified_gmt: v.string(),
date_on_sale_from: v.union([v.string(), v.null()]), date_on_sale_from: v.union([v.string(), v["null"]()]),
date_on_sale_from_gmt: v.union([v.string(), v.null()]), date_on_sale_from_gmt: v.union([v.string(), v["null"]()]),
date_on_sale_to: v.union([v.string(), v.null()]), date_on_sale_to: v.union([v.string(), v["null"]()]),
date_on_sale_to_gmt: v.union([v.string(), v.null()]), date_on_sale_to_gmt: v.union([v.string(), v["null"]()]),
default_attributes: v.array(WCV3ProductDefaultAttributeSchema), default_attributes: v.array(WCV3ProductDefaultAttributeSchema),
description: v.string(), description: v.string(),
dimensions: WCV3ProductDimensionsSchema, dimensions: WCV3ProductDimensionsSchema,
download_expiry: v.number(), download_expiry: v.number(),
download_limit: v.number(), download_limit: v.number(),
downloadable: v.boolean(), downloadable: v["boolean"](),
downloads: v.array(WCV3ProductDownloadsSchema), downloads: v.array(WCV3ProductDownloadsSchema),
external_url: v.string(), external_url: v.string(),
featured: v.boolean(), featured: v["boolean"](),
generated_slug: v.optional(v.string()), generated_slug: v.optional(v.string()),
global_unique_id: v.string(), global_unique_id: v.string(),
grouped_products: v.array(v.pipe(v.number(), v.integer())), grouped_products: v.array(v.pipe(v.number(), v.integer())),
has_options: v.boolean(), has_options: v["boolean"](),
id: v.pipe(v.number(), v.integer()), id: v.pipe(v.number(), v.integer()),
// NOTE: Ajouté par mes soins // NOTE: Ajouté par mes soins
image_repos: v.union([v.string(), v.null()]), image_repos: v.union([v.string(), v["null"]()]),
// NOTE: Ajouté par mes soins // NOTE: Ajouté par mes soins
image_survol: v.union([v.string(), v.null()]), image_survol: v.union([v.string(), v["null"]()]),
images: v.array(WCV3ProductImageSchema), images: v.array(WCV3ProductImageSchema),
low_stock_amount: v.union([v.number(), v.null()]), low_stock_amount: v.union([v.number(), v["null"]()]),
manage_stock: v.boolean(), manage_stock: v["boolean"](),
menu_order: v.pipe(v.number(), v.integer()), menu_order: v.pipe(v.number(), v.integer()),
meta_data: v.array(WCV3ProductMetaDataSchema), meta_data: v.array(WCV3ProductMetaDataSchema),
name: v.string(), name: v.string(),
on_sale: v.boolean(), on_sale: v["boolean"](),
parent_id: v.pipe(v.number(), v.integer()), parent_id: v.pipe(v.number(), v.integer()),
permalink: v.pipe(v.string(), v.url()), permalink: v.pipe(v.string(), v.url()),
permalink_template: v.optional(v.string()), permalink_template: v.optional(v.string()),
@ -163,32 +163,32 @@ export const WCV3ProductSchema = v.object({
price: v.string(), price: v.string(),
price_html: v.string(), price_html: v.string(),
prix_maximal: v.string(), prix_maximal: v.string(),
purchasable: v.boolean(), purchasable: v["boolean"](),
purchase_note: v.string(), purchase_note: v.string(),
rating_count: v.pipe(v.number(), v.integer()), rating_count: v.pipe(v.number(), v.integer()),
regular_price: v.string(), regular_price: v.string(),
related_ids: v.array(v.pipe(v.number(), v.integer())), related_ids: v.array(v.pipe(v.number(), v.integer())),
reviews_allowed: v.boolean(), reviews_allowed: v["boolean"](),
sale_price: v.string(), sale_price: v.string(),
shipping_class: v.string(), shipping_class: v.string(),
shipping_class_id: v.pipe(v.number(), v.integer()), shipping_class_id: v.pipe(v.number(), v.integer()),
shipping_required: v.boolean(), shipping_required: v["boolean"](),
shipping_taxable: v.boolean(), shipping_taxable: v["boolean"](),
short_description: v.string(), short_description: v.string(),
sku: v.string(), sku: v.string(),
slug: v.string(), slug: v.string(),
sold_individually: v.boolean(), sold_individually: v["boolean"](),
status: v.enum(PRODUCT_STATUTES), status: v["enum"](PRODUCT_STATUTES),
stock_quantity: v.union([v.number(), v.null()]), stock_quantity: v.union([v.number(), v["null"]()]),
stock_status: v.enum(STOCK_STATUSES), stock_status: v["enum"](STOCK_STATUSES),
tags: v.array(WCV3ProductTagSchema), tags: v.array(WCV3ProductTagSchema),
tax_class: v.string(), tax_class: v.string(),
tax_status: v.enum(TAX_STATUTES), tax_status: v["enum"](TAX_STATUTES),
total_sales: v.pipe(v.number(), v.integer()), total_sales: v.pipe(v.number(), v.integer()),
type: v.enum(PRODUCT_TYPES), type: v["enum"](PRODUCT_TYPES),
upsell_ids: v.array(v.pipe(v.number(), v.integer())), upsell_ids: v.array(v.pipe(v.number(), v.integer())),
variations: v.array(v.pipe(v.number(), v.integer())), variations: v.array(v.pipe(v.number(), v.integer())),
virtual: v.boolean(), virtual: v["boolean"](),
weight: v.string(), weight: v.string(),
}); });

View file

@ -5,7 +5,7 @@ import * as v from "valibot";
import { TYPES_MESSAGES } from "../../constantes/messages.ts"; import { TYPES_MESSAGES } from "../../constantes/messages.ts";
import { WCStoreCartItemSchema } from "./api/cart.ts"; import { WCStoreCartItemSchema } from "./api/cart.ts";
export const TypesMessagesSchema = v.enum(TYPES_MESSAGES); export const TypesMessagesSchema = v["enum"](TYPES_MESSAGES);
export const MessageMajBoutonPanierDonneesSchema = v.object({ export const MessageMajBoutonPanierDonneesSchema = v.object({
quantiteProduits: v.number(), quantiteProduits: v.number(),

View file

@ -35,4 +35,4 @@ export const getSessionStorageByKey = <S extends GenericSchema>(key: string, sch
export const setSessionStorageByKey = export const setSessionStorageByKey =
<S extends GenericSchema>(key: string, schema: S) => <S extends GenericSchema>(key: string, schema: S) =>
(value: unknown): Either<DOMException | ValiError<S>, InferOutput<S>> => (value: unknown): Either<DOMException | ValiError<S>, InferOutput<S>> =>
safeSchemaParse(value, schema).chain((v) => eitherSetSessionStorage(key, v)); safeSchemaParse(value, schema).chain(v => eitherSetSessionStorage(key, v));

View file

@ -7,9 +7,7 @@ import { CleNonTrouveError } from "./erreurs";
/** /**
* TODO * TODO
*/ */
export const propEither = export const propEither = <T, K extends keyof T>(cle: K) => (donnees: T): Either<CleNonTrouveError, T[K]> =>
<T, K extends keyof T>(cle: K) =>
(donnees: T): Either<CleNonTrouveError, T[K]> =>
Maybe.fromNullable(D.getUnsafe(donnees, cle)).toEither( Maybe.fromNullable(D.getUnsafe(donnees, cle)).toEither(
new CleNonTrouveError(`La clé « ${String(cle)} » n'a pas été trouvé dans l'objet.`), new CleNonTrouveError(`La clé « ${String(cle)} » n'a pas été trouvé dans l'objet.`),
); );

View file

@ -12,6 +12,5 @@ export const safeSchemaParse = <Schema extends GenericSchema>(
): Either<ValiError<Schema>, InferOutput<Schema>> => Either.encase(() => parse(schema, valeur)); ): Either<ValiError<Schema>, InferOutput<Schema>> => Either.encase(() => parse(schema, valeur));
export const safeSchemaParseCurried = export const safeSchemaParseCurried =
<S extends GenericSchema>(schema: S) => <S extends GenericSchema>(schema: S) => (valeur: unknown): Either<ValiError<S>, InferOutput<S>> =>
(valeur: unknown): Either<ValiError<S>, InferOutput<S>> =>
Either.encase(() => parse(schema, valeur)); Either.encase(() => parse(schema, valeur));

View file

@ -8,15 +8,16 @@ import { ValiError } from "valibot";
import type { AnySchema } from "valibot"; import type { AnySchema } from "valibot";
import type { WCStoreBillingAddress, WCStoreShippingAddress } from "../lib/types/api/adresses.ts"; import type { WCStoreBillingAddress, WCStoreShippingAddress } from "../lib/types/api/adresses.ts";
import type { WCStoreCart, WCStoreShippingRate, WCStoreShippingRateShippingRate } from "../lib/types/api/cart.ts";
import type { WCStoreCartUpdateCustomerArgs } from "../lib/types/api/cart-update-customer.ts"; import type { WCStoreCartUpdateCustomerArgs } from "../lib/types/api/cart-update-customer.ts";
import type { WCStoreCart, WCStoreShippingRate, WCStoreShippingRateShippingRate } from "../lib/types/api/cart.ts";
import type { WCV3Order, WCV3OrdersArgs } from "../lib/types/api/v3/orders.ts"; import type { WCV3Order, WCV3OrdersArgs } from "../lib/types/api/v3/orders.ts";
import type { GenericPageState } from "../lib/types/pages.ts"; import type { GenericPageState } from "../lib/types/pages.ts";
import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau.ts"; import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau.ts";
import { Console, Effect, Stream } from "effect";
import { ReadonlyRecord } from "effect/Record";
import { ROUTE_API_MAJ_CLIENT, ROUTE_API_NOUVELLE_COMMANDES } from "../constantes/api.ts"; import { ROUTE_API_MAJ_CLIENT, ROUTE_API_NOUVELLE_COMMANDES } from "../constantes/api.ts";
import { ATTRIBUT_CHARGEMENT, ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom.ts"; import { ATTRIBUT_CHARGEMENT, ATTRIBUT_LIVRAISON_VALIDEE } from "../constantes/dom.ts";
import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages.ts";
import { import {
ERREUR_ADRESSE_GENERIQUE, ERREUR_ADRESSE_GENERIQUE,
ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL, ERREUR_ADRESSE_MAUVAIS_CODE_POSTAL,
@ -24,6 +25,7 @@ import {
ERREUR_GENERIQUE_RESEAU, ERREUR_GENERIQUE_RESEAU,
ERREUR_GENERIQUE_SOUMISSION_ADRESSES, ERREUR_GENERIQUE_SOUMISSION_ADRESSES,
} from "../constantes/messages-utilisateur.ts"; } from "../constantes/messages-utilisateur.ts";
import { NOM_CANAL_REVALIDATION_LIVRAISON } from "../constantes/messages.ts";
import { estErreurFetch, estErreurHttp, setButtonLoadingState } from "../lib/dom.ts"; import { estErreurFetch, estErreurHttp, setButtonLoadingState } from "../lib/dom.ts";
import { reporteEtJournaliseErreur } from "../lib/erreurs.ts"; import { reporteEtJournaliseErreur } from "../lib/erreurs.ts";
import { ErreurAdresseInvalide } from "../lib/erreurs/adresses.ts"; import { ErreurAdresseInvalide } from "../lib/erreurs/adresses.ts";
@ -36,15 +38,13 @@ import { emetUniqueMessageBroadcastChannel } from "../lib/messages.ts";
import { diviseParCent } from "../lib/nombres.ts"; import { diviseParCent } from "../lib/nombres.ts";
import { newPartialResponse, prefilledPostBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau.ts"; import { newPartialResponse, prefilledPostBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau.ts";
import { find, first } from "../lib/safe-arrays.ts"; import { find, first } from "../lib/safe-arrays.ts";
import { WCStoreCartSchema } from "../lib/schemas/api/cart.ts";
import { WCStoreCartUpdateCustomerArgsSchema } from "../lib/schemas/api/cart-update-customer.ts"; import { WCStoreCartUpdateCustomerArgsSchema } from "../lib/schemas/api/cart-update-customer.ts";
import { WCStoreCartSchema } from "../lib/schemas/api/cart.ts";
import { estWCAddressError } from "../lib/schemas/api/erreurs.ts"; import { estWCAddressError } from "../lib/schemas/api/erreurs.ts";
import { WCV3OrdersArgsSchema, WCV3OrderSchema } from "../lib/schemas/api/v3/orders.ts"; import { WCV3OrdersArgsSchema, WCV3OrderSchema } from "../lib/schemas/api/v3/orders.ts";
import { safeSchemaParse } from "../lib/validation.ts"; import { safeSchemaParse } from "../lib/validation.ts";
import { E } from "./scripts-page-panier-elements.ts"; import { E } from "./scripts-page-panier-elements.ts";
import { getShippingRatesLS } from "./scripts-page-panier-local-storage.ts"; import { getShippingRatesLS } from "./scripts-page-panier-local-storage.ts";
import { ReadonlyRecord } from "effect/Record";
import { Console, Effect, Stream } from "effect";
type Addresses = { type Addresses = {
billing_address: WCStoreBillingAddress; billing_address: WCStoreBillingAddress;
@ -125,7 +125,7 @@ export const initShippingCalculationButton = (): void => {
.fromFalsy(E.FORMULAIRE_PANIER.checkValidity()) .fromFalsy(E.FORMULAIRE_PANIER.checkValidity())
// Ne fais rien si la livraison a déjà été validée // Ne fais rien si la livraison a déjà été validée
.chainNullable((): boolean | undefined => .chainNullable((): boolean | undefined =>
E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? undefined : true, E.BOUTON_ACTIONS_FORMULAIRE.hasAttribute(ATTRIBUT_LIVRAISON_VALIDEE) ? undefined : true
) )
.ifJust((): void => { .ifJust((): void => {
event.preventDefault(); event.preventDefault();
@ -133,8 +133,8 @@ export const initShippingCalculationButton = (): void => {
/** Les données du Formulaire transformées pour la requête vers le Backend. */ /** Les données du Formulaire transformées pour la requête vers le Backend. */
const formArgs: WCStoreCartUpdateCustomerArgs = pipe( const formArgs: WCStoreCartUpdateCustomerArgs = pipe(
Object.fromEntries(new FormData(E.FORMULAIRE_PANIER)) as Record<string, string>, Object.fromEntries(new FormData(E.FORMULAIRE_PANIER)) as Record<string, string>,
(fields) => dictMap(fields, stringTrim), fields => dictMap(fields, stringTrim),
(fields) => getAddressesFromForm(fields, E.BOUTON_SEPARATION_ADRESSES.checked), fields => getAddressesFromForm(fields, E.BOUTON_SEPARATION_ADRESSES.checked),
); );
// Réalise la requête et traite sa réponse // Réalise la requête et traite sa réponse
@ -142,7 +142,7 @@ export const initShippingCalculationButton = (): void => {
// Désactive le Bouton pour empêcher des requêtes concurrentes // Désactive le Bouton pour empêcher des requêtes concurrentes
.ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true)) .ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true))
.chain((args: WCStoreCartUpdateCustomerArgs) => .chain((args: WCStoreCartUpdateCustomerArgs) =>
safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false)), safeFetch(postBackend(ROUTE_API_MAJ_CLIENT, JSON.stringify(args), false))
) )
.chain((rs: Response) => .chain((rs: Response) =>
EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>( EitherAsync<ErreurAdresseInvalide | HttpCodeErrors, unknown>(
@ -151,18 +151,18 @@ export const initShippingCalculationButton = (): void => {
.with({ status: 200 }, (rs): unknown => rs.body) .with({ status: 200 }, (rs): unknown => rs.body)
.with( .with(
{ {
body: P.when((body) => estWCAddressError(body)), body: P.when(body => estWCAddressError(body)),
status: 400, status: 400,
}, },
(rs): never => throwE(new ErreurAdresseInvalide(rs.body.data.params)), (rs): never => throwE(new ErreurAdresseInvalide(rs.body.data.params)),
) )
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))), .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))),
), )
) )
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema))) .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema)))
.ifRight((cart: WCStoreCart): void => { .ifRight((cart: WCStoreCart): void => {
/** La méthode de livraison sélectionnée dans le SessionStorage */ /** La méthode de livraison sélectionnée dans le SessionStorage */
const oldSelectedRateLS = getShippingRatesLS().chain(find((sr) => sr.selected)); const oldSelectedRateLS = getShippingRatesLS().chain(find(sr => sr.selected));
/* Les méthodes de livraison mises à jour avec le nouveau choix de l'Utilisateur. */ /* Les méthodes de livraison mises à jour avec le nouveau choix de l'Utilisateur. */
const updatedRates = first(cart.shipping_rates) const updatedRates = first(cart.shipping_rates)
@ -171,7 +171,7 @@ export const initShippingCalculationButton = (): void => {
srs.map((sr: WCStoreShippingRateShippingRate, index: number) => { srs.map((sr: WCStoreShippingRateShippingRate, index: number) => {
// Sélectionne la nouvelle méthode demandée OU la première si le SessionStorage n'a pas été défini // Sélectionne la nouvelle méthode demandée OU la première si le SessionStorage n'a pas été défini
oldSelectedRateLS.caseOf({ oldSelectedRateLS.caseOf({
Just: (sm) => { Just: sm => {
sr.selected = sr.method_id === sm.method_id; sr.selected = sr.method_id === sm.method_id;
}, },
Nothing: () => { Nothing: () => {
@ -183,7 +183,7 @@ export const initShippingCalculationButton = (): void => {
sr.price = diviseParCent(sr.price); sr.price = diviseParCent(sr.price);
return sr; return sr;
}), })
) )
.orDefault([]); .orDefault([]);
@ -191,13 +191,14 @@ export const initShippingCalculationButton = (): void => {
window.dispatchEvent(createUpdatedShippingRatesEvent(updatedRates, true)); window.dispatchEvent(createUpdatedShippingRatesEvent(updatedRates, true));
// Met à jour les Totaux // Met à jour les Totaux
const newShippingPrice = updatedRates.find((m) => m.selected)?.price ?? 0; const newShippingPrice = updatedRates.find(m => m.selected)?.price ?? 0;
const newTotals = { const newTotals = {
...cart.totals, ...cart.totals,
total_discount: diviseParCent(cart.totals.total_discount), total_discount: diviseParCent(cart.totals.total_discount),
total_items: diviseParCent(cart.totals.total_items), total_items: diviseParCent(cart.totals.total_items),
total_price: total_price: diviseParCent(cart.totals.total_items)
diviseParCent(cart.totals.total_items) - diviseParCent(cart.totals.total_discount) + newShippingPrice, - diviseParCent(cart.totals.total_discount)
+ newShippingPrice,
total_shipping: newShippingPrice, total_shipping: newShippingPrice,
}; };
@ -222,10 +223,10 @@ export const initShippingCalculationButton = (): void => {
match(e.problemes) match(e.problemes)
.when( .when(
// TODO: Créer une fonction utilitaire // TODO: Créer une fonction utilitaire
(p) => p =>
pipe( pipe(
dictValues(p), dictValues(p),
arrayFind((c) => c === "The provided postcode is not valid"), arrayFind(c => c === "The provided postcode is not valid"),
), ),
// TODO: Créer une fonction utilitaire pour fixer le texte d'un message // TODO: Créer une fonction utilitaire pour fixer le texte d'un message
(): void => { (): void => {
@ -315,14 +316,14 @@ export const initOrderCreationButton = (): void => {
}; };
// Retire toute méthode de livraison invalide. // Retire toute méthode de livraison invalide.
formArgs.shipping_lines = formArgs.shipping_lines.filter((line) => line.method_id !== undefined); formArgs.shipping_lines = formArgs.shipping_lines.filter(line => line.method_id !== undefined);
// Réalise la requête et traite sa réponse // Réalise la requête et traite sa réponse
void EitherAsync.liftEither(safeSchemaParse(formArgs, WCV3OrdersArgsSchema)) void EitherAsync.liftEither(safeSchemaParse(formArgs, WCV3OrdersArgsSchema))
// Désactive le Bouton pour empêcher des requêtes concurrentes // Désactive le Bouton pour empêcher des requêtes concurrentes
.ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true)) .ifRight((): void => setButtonLoadingState(E.BOUTON_ACTIONS_FORMULAIRE, true))
.chain((args: WCV3OrdersArgs) => .chain((args: WCV3OrdersArgs) =>
safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true)), safeFetch(postBackend(ROUTE_API_NOUVELLE_COMMANDES, JSON.stringify(args), true))
) )
.chain((rs: Response) => .chain((rs: Response) =>
EitherAsync<HttpCodeErrors, unknown>( EitherAsync<HttpCodeErrors, unknown>(
@ -330,7 +331,7 @@ export const initOrderCreationButton = (): void => {
match(await newPartialResponse(rs)) match(await newPartialResponse(rs))
.with({ status: 201 }, (rs): unknown => rs.body) .with({ status: 201 }, (rs): unknown => rs.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))), .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))),
), )
) )
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCV3OrderSchema))) .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCV3OrderSchema)))
.ifRight((order: WCV3Order): void => { .ifRight((order: WCV3Order): void => {
@ -342,9 +343,9 @@ export const initOrderCreationButton = (): void => {
// Redirige vers Stripe // Redirige vers Stripe
Maybe.fromNullable(new URL(`https://${window.location.host}/checkout`)) Maybe.fromNullable(new URL(`https://${window.location.host}/checkout`))
.ifJust((url) => url.searchParams.append("order_key", order.order_key)) .ifJust(url => url.searchParams.append("order_key", order.order_key))
.ifJust((url) => url.searchParams.append("order_id", String(order.id))) .ifJust(url => url.searchParams.append("order_id", String(order.id)))
.ifJust((url) => location.assign(url)); .ifJust(url => location.assign(url));
}) })
.ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => { .ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err) match(err)

View file

@ -54,193 +54,34 @@ export const initialiseElementsCodePromo = (): void => {
codePromoPresent: recuperePresenceCodePromo(), codePromoPresent: recuperePresenceCodePromo(),
valeurCodePromo: recupereValeurCodePromo(), valeurCodePromo: recupereValeurCodePromo(),
}) })
[
// Un code promo doit être ajouté // Un code promo doit être ajouté
// Aucun code promo n'est déjà présent et une valeur acceptable existe // Aucun code promo n'est déjà présent et une valeur acceptable existe
.with( "with"
](
{ {
cible: P.when((cible: EventTarget | null) => cible: P.when((cible: EventTarget | null) =>
targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO), targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)
), ),
codePromoPresent: false, codePromoPresent: false,
valeurCodePromo: P.string, valeurCodePromo: P.string,
}, },
({ valeurCodePromo }) => ({ valeurCodePromo }) => undefined,
void EitherAsync
// Vérifie le Schéma des arguments
.liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartApplyCouponArgsSchema))
.ifRight(() => {
// Désactive le Bouton pour empêcher des requêtes concurrentes
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_DESACTIVE, "");
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_CHARGEMENT, "");
// Réinitialise le Message à l'Utilisateur
E.MESSAGE_CODE_PROMO.textContent = "";
// Lance un cycle d'animation sur le texte de chargement
lanceAnimationCycleLoading(E.BOUTON_CODE_PROMO, 500);
})
// Réalise la requête auprès du backend
.map((args: WCStoreCartApplyCouponArgs) =>
postBackend({
corps: JSON.stringify(args),
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_APPLIQUE_COUPON,
}),
)
// Traite les cas d'Erreur
.chain((reponse: Response) =>
EitherAsync<ErreurCodePromoInvalide | ServerError, unknown>(async ({ throwE }) => {
const reponseSimplifiee: SimplifiedResponse = {
body: await reponse.json(),
status: reponse.status,
};
return match(reponseSimplifiee)
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with(
{
body: P.when(() => reponseEstCodeErreurWC(reponseSimplifiee, ERREUR_CODE_PROMO_INVALIDE)),
status: 400,
},
() => throwE(new ErreurCodePromoInvalide(recupereValeurCodePromo() ?? "")),
)
.with({ status: 200 }, () => reponseSimplifiee.body)
.run();
}),
)
// Vérifie le Schéma de la Réponse du backend
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema)))
// Déclenche les mises à jour du DOM avec les données du nouveau Panier
.ifRight((panier: WCStoreCart) => {
E.ENSEMBLE_CODE_PROMO.toggleAttribute(ATTRIBUT_CODE_PROMO_PRESENT);
E.CHAMP_CODE_PROMO.toggleAttribute(ATTRIBUT_DESACTIVE);
E.CHAMP_CODE_PROMO.value = panier.coupons[0]?.code ?? "";
E.BOUTON_CODE_PROMO.textContent = "Remove";
E.TOTAL_PANIER.textContent = pipe(
diviseParCent(panier.totals.total_price),
arrondisADeuxDecimales,
formateEnEuros,
);
E.TOTAL_REDUCTION_LIGNE.toggleAttribute(ATTRIBUT_HIDDEN);
E.TOTAL_REDUCTION_VALEUR.textContent = pipe(
diviseParCent(panier.totals.total_discount),
inverseNombre,
arrondisADeuxDecimales,
formateEnEuros,
);
window.dispatchEvent(CODE_PROMO_MAJ_EVENT);
// EmetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
.ifLeft((erreur) => {
// Rétablis le texte d'origine
E.BOUTON_CODE_PROMO.textContent = "Apply";
// Traite les Erreurs et affiche un Message à l'Utilisateur
match(erreur)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("ValiError", e.issues);
})
.with(P.instanceOf(ErreurCodePromoInvalide), (e) => {
E.MESSAGE_CODE_PROMO.textContent = "This promo code does not exist.";
reporteErreur(e);
console.error(e);
})
.with(P.instanceOf(ServerError), (e) => {
E.MESSAGE_CODE_PROMO.textContent =
"Sorry, something went wrong! Please refresh the page and try again.";
reporteErreur(e);
console.error(e);
})
.with(P.instanceOf(TypeError), (e) => {
E.MESSAGE_CODE_PROMO.textContent =
"Sorry, something went wrong! Please refresh the page and try again.";
reporteErreur(e);
console.error(e);
})
.exhaustive();
})
.finally(() => {
// Désactive l'animation de chargement et rend le Bouton de nouveau cliquable
// TODO: Créer un type d'Événement ?
E.BOUTON_CODE_PROMO.removeAttribute(ATTRIBUT_CHARGEMENT);
E.BOUTON_CODE_PROMO.removeAttribute(ATTRIBUT_DESACTIVE);
})
.run(),
) )
[
// Un code promo doit être retiré // Un code promo doit être retiré
// Un code promo est présent sous forme de chaîne // Un code promo est présent sous forme de chaîne
.with( "with"
](
{ {
cible: P.when((cible) => targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)), cible: P.when(cible => targetMatchesSelector<HTMLButtonElement>(cible, DOM_BOUTON_CODE_PROMO)),
codePromoPresent: true, codePromoPresent: true,
valeurCodePromo: P.string, valeurCodePromo: P.string,
}, },
({ valeurCodePromo }) => ({ valeurCodePromo }) => undefined,
void EitherAsync.liftEither(safeSchemaParse({ code: valeurCodePromo }, WCStoreCartRemoveCouponArgsSchema))
.ifRight(() => {
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_DESACTIVE, "");
E.BOUTON_CODE_PROMO.setAttribute(ATTRIBUT_CHARGEMENT, "");
lanceAnimationCycleLoading(E.BOUTON_CODE_PROMO, 500);
})
.map((args: WCStoreCartRemoveCouponArgs) =>
postBackend({
corps: JSON.stringify(args),
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_RETIRE_COUPON,
}),
)
.chain((reponse: Response) =>
EitherAsync<ServerError, unknown>(async ({ throwE }) => {
if (estReponse500(reponse)) {
throwE(new ServerError("500 server Error"));
}
return await reponse.json();
}),
)
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema)))
.ifRight((panier: WCStoreCart) => {
E.ENSEMBLE_CODE_PROMO.toggleAttribute(ATTRIBUT_CODE_PROMO_PRESENT);
E.ENSEMBLE_CODE_PROMO.reset();
E.CHAMP_CODE_PROMO.toggleAttribute(ATTRIBUT_DESACTIVE);
E.CHAMP_CODE_PROMO.textContent = "";
E.BOUTON_CODE_PROMO.textContent = "Apply";
E.TOTAL_PANIER.textContent = pipe(
diviseParCent(panier.totals.total_price),
arrondisADeuxDecimales,
formateEnEuros,
);
E.TOTAL_REDUCTION_LIGNE.toggleAttribute(ATTRIBUT_HIDDEN);
E.TOTAL_REDUCTION_VALEUR.textContent = "-0€";
emetUniqueMessageBroadcastChannel(NOM_CANAL_REVALIDATION_LIVRAISON, true);
})
.ifLeft((erreur) =>
match(erreur)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e.issues);
})
.with(P.instanceOf(ServerError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e);
})
.with(P.instanceOf(TypeError), (e) => {
reporteErreur(e);
console.error("retour ajout code promo", e);
})
.exhaustive(),
)
.finally(() => {
E.BOUTON_CODE_PROMO.removeAttribute(ATTRIBUT_CHARGEMENT);
E.BOUTON_CODE_PROMO.removeAttribute(ATTRIBUT_DESACTIVE);
})
.run(),
) )
[
// Ne rien faire en dehors de ces deux situations // Ne rien faire en dehors de ces deux situations
.with(P._, identity), "with"
); ](P._, identity));
}; };

View file

@ -26,20 +26,20 @@ export const reinitialiseValidationLivraison = (): void => {
* @returns void * @returns void
*/ */
export const souscrisEvenementsPanier = (): void => { export const souscrisEvenementsPanier = (): void => {
window.addEventListener(ADRESSES_MAJ, (): void => { globalThis.addEventListener(ADRESSES_MAJ, (): void => {
reinitialiseValidationLivraison(); reinitialiseValidationLivraison();
}); });
window.addEventListener(CODE_PROMO_MAJ, (): void => { globalThis.addEventListener(CODE_PROMO_MAJ, (): void => {
reinitialiseValidationLivraison(); reinitialiseValidationLivraison();
}); });
window.addEventListener(SHIPPING_RATES_UPDATED, (event: Event): void => { globalThis.addEventListener(SHIPPING_RATES_UPDATED, (event: Event): void => {
Either Either
// La vérification du schéma se fait à l'émission // La vérification du schéma se fait à l'émission
.encase(() => (event as UpdatedShippingRatesEvent).detail) .encase(() => (event as UpdatedShippingRatesEvent).detail)
// Met à jour le DOM // Met à jour le DOM
.ifRight((event) => { .ifRight(event => {
// Met à jour les Méthodes à l'Utilisateur si demandé // Met à jour les Méthodes à l'Utilisateur si demandé
// Il peut y en avoir aucune // Il peut y en avoir aucune
if (event.refresh_methods) { if (event.refresh_methods) {
@ -47,18 +47,18 @@ export const souscrisEvenementsPanier = (): void => {
} }
}) })
// Met à jour le SessionStorage // Met à jour le SessionStorage
.chain((event) => eitherSetSessionStorage("shipping_rates", event.shipping_rates)) .chain(event => eitherSetSessionStorage("shipping_rates", event.shipping_rates))
.ifLeft(reporteEtJournaliseErreur); .ifLeft(reporteEtJournaliseErreur);
}); });
window.addEventListener(TOTALS_UPDATED, (event: Event): void => { globalThis.addEventListener(TOTALS_UPDATED, (event: Event): void => {
Either Either
// La vérification du Schéma se fait à l'émission // La vérification du Schéma se fait à l'émission
.encase(() => (event as UpdatedTotalsEvent).detail.totals) .encase(() => (event as UpdatedTotalsEvent).detail.totals)
.chain((ts) => eitherSetSessionStorage("totals", ts)) .chain(ts => eitherSetSessionStorage("totals", ts))
.ifLeft(reporteEtJournaliseErreur) .ifLeft(reporteEtJournaliseErreur)
// Met à jour le DOM // Met à jour le DOM
.ifRight((ts) => { .ifRight(ts => {
E.SOUS_TOTAL_LIVRAISON_VALEUR.textContent = formateEnEuros(ts.total_shipping); E.SOUS_TOTAL_LIVRAISON_VALEUR.textContent = formateEnEuros(ts.total_shipping);
E.SOUS_TOTAL_PRODUITS_VALEUR.textContent = formateEnEuros(ts.total_items); E.SOUS_TOTAL_PRODUITS_VALEUR.textContent = formateEnEuros(ts.total_items);
E.SOUS_TOTAL_REDUCTION_VALEUR.textContent = formateEnEuros(ts.total_discount * -1); E.SOUS_TOTAL_REDUCTION_VALEUR.textContent = formateEnEuros(ts.total_discount * -1);

View file

@ -19,7 +19,7 @@ import { getShippingRatesLS } from "./scripts-page-panier-local-storage";
export const initShippingRatesChoicesActions = (): void => { export const initShippingRatesChoicesActions = (): void => {
getDOMElementsWithSelector(E.CONTENEUR_METHODES_LIVRAISON)<HTMLInputElement>("input").ifRight( getDOMElementsWithSelector(E.CONTENEUR_METHODES_LIVRAISON)<HTMLInputElement>("input").ifRight(
forEach((el: HTMLInputElement): void => forEach((el: HTMLInputElement): void => {
el.addEventListener("click", (event: MouseEvent): void => { el.addEventListener("click", (event: MouseEvent): void => {
// Récupère les méthodes du SessionStorage et les met à jour avec le nouveau choix // Récupère les méthodes du SessionStorage et les met à jour avec le nouveau choix
getShippingRatesLS() getShippingRatesLS()
@ -32,10 +32,10 @@ export const initShippingRatesChoicesActions = (): void => {
) )
// Met à jour les Méthodes de livraison dans le SessionStorage et le DOM // Met à jour les Méthodes de livraison dans le SessionStorage et le DOM
.ifJust((srs: WCStoreShippingRateShippingRates): void => { .ifJust((srs: WCStoreShippingRateShippingRates): void => {
window.dispatchEvent(createUpdatedShippingRatesEvent(srs, false)); globalThis.dispatchEvent(createUpdatedShippingRatesEvent(srs, false));
}) })
// Met à jour les totaux dans le SessionStorage et le DOM // Met à jour les totaux dans le SessionStorage et le DOM
.chain(find((sr) => sr.selected)) .chain(find(sr => sr.selected))
.ifJust((sr: WCStoreShippingRateShippingRate): void => { .ifJust((sr: WCStoreShippingRateShippingRate): void => {
getSessionStorageByKey("totals", WCStoreCartTotalsSchema) getSessionStorageByKey("totals", WCStoreCartTotalsSchema)
.ifLeft(reporteEtJournaliseErreur) .ifLeft(reporteEtJournaliseErreur)
@ -45,11 +45,11 @@ export const initShippingRatesChoicesActions = (): void => {
return ts; return ts;
}) })
.ifRight((ts: WCStoreCartTotals): void => { .ifRight((ts: WCStoreCartTotals): void => {
window.dispatchEvent(createUpdatedTotalsEvent(ts)); globalThis.dispatchEvent(createUpdatedTotalsEvent(ts));
});
}); });
}); });
}), }),
),
); );
}; };
@ -64,12 +64,17 @@ export const generateShippingRatesHTML = (
} }
// Retire les méthodes de livraison initiales // Retire les méthodes de livraison initiales
getDOMElementsWithSelector(container)("div[data-methode-initiale]").ifRight(arrayForEach((div) => div.remove())); getDOMElementsWithSelector(container)("div[data-methode-initiale]").ifRight(
arrayForEach(div => {
div.remove();
}),
);
const selectedShippingRate: string = shippingRates.find((sr) => sr.selected)?.method_id ?? ""; const selectedShippingRate: string = shippingRates.find(sr => sr.selected)?.method_id ?? "";
const shippingRatesHTML: ReadonlyArray<TemplateResult> = arrayMap( const shippingRatesHTML: ReadonlyArray<TemplateResult> = arrayMap(
shippingRates, shippingRates,
(methode) => html` <div> methode =>
html` <div>
<input <input
id="methode-livraison-${methode.method_id}" id="methode-livraison-${methode.method_id}"
name="choix-methode-livraison" name="choix-methode-livraison"

View file

@ -7,12 +7,13 @@ import { match, P } from "ts-pattern";
import { ValiError } from "valibot"; import { ValiError } from "valibot";
import type { AnySchema } from "valibot"; import type { AnySchema } from "valibot";
import type { WCStoreCart } from "../lib/types/api/cart.ts";
import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item.ts"; import type { WCStoreCartRemoveItemArgs } from "../lib/types/api/cart-remove-item.ts";
import type { WCStoreCartUpdateItemArgs } from "../lib/types/api/cart-update-item.ts"; import type { WCStoreCartUpdateItemArgs } from "../lib/types/api/cart-update-item.ts";
import type { WCStoreCart } from "../lib/types/api/cart.ts";
import type { GenericPageState } from "../lib/types/pages.ts"; import type { GenericPageState } from "../lib/types/pages.ts";
import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau.ts"; import type { FetchErrors, HttpCodeErrors } from "../lib/types/reseau.ts";
import { getFirstSelectorFromParentOrThrow } from "../../scripts-effect/lib/dom.ts";
import { ROUTE_API_MAJ_ARTICLE_PANIER, ROUTE_API_RETIRE_ARTICLE_PANIER } from "../constantes/api.ts"; import { ROUTE_API_MAJ_ARTICLE_PANIER, ROUTE_API_RETIRE_ARTICLE_PANIER } from "../constantes/api.ts";
import { import {
ATTRIBUT_CLE_PANIER, ATTRIBUT_CLE_PANIER,
@ -31,12 +32,11 @@ import {
} from "../lib/messages.ts"; } from "../lib/messages.ts";
import { diviseParCent } from "../lib/nombres.ts"; import { diviseParCent } from "../lib/nombres.ts";
import { newPartialResponse, postBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau.ts"; import { newPartialResponse, postBackend, safeFetch, traiteErreursBackendWooCommerce } from "../lib/reseau.ts";
import { WCStoreCartSchema } from "../lib/schemas/api/cart.ts";
import { WCStoreCartRemoveItemArgsSchema } from "../lib/schemas/api/cart-remove-item.ts"; import { WCStoreCartRemoveItemArgsSchema } from "../lib/schemas/api/cart-remove-item.ts";
import { WCStoreCartUpdateItemArgsSchema } from "../lib/schemas/api/cart-update-item.ts"; import { WCStoreCartUpdateItemArgsSchema } from "../lib/schemas/api/cart-update-item.ts";
import { WCStoreCartSchema } from "../lib/schemas/api/cart.ts";
import { safeSchemaParse } from "../lib/validation.ts"; import { safeSchemaParse } from "../lib/validation.ts";
import { E } from "./scripts-page-panier-elements.ts"; import { E } from "./scripts-page-panier-elements.ts";
import { getFirstSelectorFromParentOrThrow } from "../../scripts-effect/lib/dom.ts";
// @ts-expect-error -- États injectés par le modèle PHP // @ts-expect-error -- États injectés par le modèle PHP
const PAGE_STATE: GenericPageState = _etats; const PAGE_STATE: GenericPageState = _etats;
@ -65,8 +65,7 @@ const getCartEntryInteractiveEles = (entry: HTMLElement): CartEntryInteractiveEl
* @returns Rien. * @returns Rien.
*/ */
const toggleCartEntryButtons = const toggleCartEntryButtons =
(activated: boolean) => (activated: boolean) => (cartEntries: ReadonlyArray<CartEntryInteractiveElements>): void => {
(cartEntries: ReadonlyArray<CartEntryInteractiveElements>): void => {
arrayForEach(cartEntries, (e: CartEntryInteractiveElements): void => { arrayForEach(cartEntries, (e: CartEntryInteractiveElements): void => {
if (activated) { if (activated) {
// Active les Boutons // Active les Boutons
@ -121,10 +120,10 @@ const initActionsOnCartEntries = (): void => {
.fromNullable(entryButtons.quantityInput.valueAsNumber) .fromNullable(entryButtons.quantityInput.valueAsNumber)
.toEither(new Error("Quantité manquante pour cette ligne du Panier !")), .toEither(new Error("Quantité manquante pour cette ligne du Panier !")),
) )
.chain((q) => .chain(q =>
EitherAsync.liftEither( EitherAsync.liftEither(
safeSchemaParse({ key: entryKey, quantity: q + 1 }, WCStoreCartUpdateItemArgsSchema), safeSchemaParse({ key: entryKey, quantity: q + 1 }, WCStoreCartUpdateItemArgsSchema),
), )
) )
.ifRight(() => { .ifRight(() => {
pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false)); pipe(cartEntries, arrayMap(getCartEntryInteractiveEles), toggleCartEntryButtons(false));
@ -136,14 +135,14 @@ const initActionsOnCartEntries = (): void => {
nonce: PAGE_STATE.nonce, nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER, route: ROUTE_API_MAJ_ARTICLE_PANIER,
}), }),
), )
) )
.chain((r: Response) => .chain((r: Response) =>
EitherAsync<ServerError, unknown>(async ({ throwE }) => EitherAsync<ServerError, unknown>(async ({ throwE }) =>
match(await newPartialResponse(r)) match(await newPartialResponse(r))
["with"]({ status: 200 }, (r) => r.body) ["with"]({ status: 200 }, r => r.body)
.otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs))), .otherwise((rs): never => throwE(traiteErreursBackendWooCommerce(rs)))
), )
) )
.chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema))) .chain((b: unknown) => EitherAsync.liftEither(safeSchemaParse(b, WCStoreCartSchema)))
.ifRight((c: WCStoreCart): void => { .ifRight((c: WCStoreCart): void => {
@ -161,17 +160,17 @@ const initActionsOnCartEntries = (): void => {
}) })
.ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => { .ifLeft((err: FetchErrors | HttpCodeErrors | ValiError<AnySchema>): void => {
match(err) match(err)
["with"](P.instanceOf(ValiError), (e) => { ["with"](P.instanceOf(ValiError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e.issues); console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => { ["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => { ["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
@ -191,7 +190,7 @@ const initActionsOnCartEntries = (): void => {
Maybe Maybe
// Nécessaire pour que l'on ait une valeur à incrémenter // Nécessaire pour que l'on ait une valeur à incrémenter
.fromNullable(entryButtons.quantityInput.valueAsNumber) .fromNullable(entryButtons.quantityInput.valueAsNumber)
.filter((valeur) => valeur > 1) .filter(valeur => valeur > 1)
.ifJust((valeur: number) => { .ifJust((valeur: number) => {
// Réalise la requête et traite sa réponse // Réalise la requête et traite sa réponse
void EitherAsync void EitherAsync
@ -211,7 +210,7 @@ const initActionsOnCartEntries = (): void => {
nonce: PAGE_STATE.nonce, nonce: PAGE_STATE.nonce,
route: ROUTE_API_MAJ_ARTICLE_PANIER, route: ROUTE_API_MAJ_ARTICLE_PANIER,
}), }),
), )
) )
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) => .chain((reponse: Response) =>
@ -220,9 +219,9 @@ const initActionsOnCartEntries = (): void => {
match(await newPartialResponse(reponse)) match(await newPartialResponse(reponse))
["with"]({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) ["with"]({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
["with"]({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) ["with"]({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error")))
["with"]({ status: 200 }, (r) => r.body) ["with"]({ status: 200 }, r => r.body)
.otherwise((erreur) => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))), .otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`)))
), )
) )
// 5. Vérifie le Schéma de la Réponse // 5. Vérifie le Schéma de la Réponse
.chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema))) .chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema)))
@ -243,17 +242,17 @@ const initActionsOnCartEntries = (): void => {
// 7. Traite les Erreurs et affiche un message à l'Utilisateur // 7. Traite les Erreurs et affiche un message à l'Utilisateur
.ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => { .ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur) match(erreur)
["with"](P.instanceOf(ValiError), (e) => { ["with"](P.instanceOf(ValiError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e.issues); console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => { ["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => { ["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
@ -292,7 +291,7 @@ const initActionsOnCartEntries = (): void => {
nonce: PAGE_STATE.nonce, nonce: PAGE_STATE.nonce,
route: ROUTE_API_RETIRE_ARTICLE_PANIER, route: ROUTE_API_RETIRE_ARTICLE_PANIER,
}), }),
), )
) )
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) => .chain((reponse: Response) =>
@ -301,9 +300,9 @@ const initActionsOnCartEntries = (): void => {
match(await newPartialResponse(reponse)) match(await newPartialResponse(reponse))
["with"]({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) ["with"]({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
["with"]({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) ["with"]({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error")))
["with"]({ status: 200 }, (r) => r.body) ["with"]({ status: 200 }, r => r.body)
.otherwise((erreur) => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))), .otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`)))
), )
) )
// 5. Vérifie le Schéma de la Réponse // 5. Vérifie le Schéma de la Réponse
.chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema))) .chain((corps: unknown) => EitherAsync.liftEither(safeSchemaParse(corps, WCStoreCartSchema)))
@ -327,17 +326,17 @@ const initActionsOnCartEntries = (): void => {
// 7. Traite les Erreurs et affiche un message à l'Utilisateur // 7. Traite les Erreurs et affiche un message à l'Utilisateur
.ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => { .ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>): void => {
match(erreur) match(erreur)
["with"](P.instanceOf(ValiError), (e) => { ["with"](P.instanceOf(ValiError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e.issues); console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => { ["with"](P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => { ["with"](P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
@ -352,10 +351,10 @@ const initActionsOnCartEntries = (): void => {
}); });
}, },
) )
.otherwise((_) => {}); .otherwise(_ => {});
}); });
}); });
}); });
}; };
export { toggleCartEntryButtons, initActionsOnCartEntries as initialiseActionsEntreesPanier }; export { initActionsOnCartEntries as initialiseActionsEntreesPanier, toggleCartEntryButtons };

View file

@ -68,9 +68,9 @@ const initialiseObservationFenetre = (): void => {
} }
etapePlanifiee = true; etapePlanifiee = true;
requestAnimationFrame((): void => requestAnimationFrame((): void => {
majVisibiliteBouton(defilementY > window.innerHeight * RATIO_MINIMUM_PAGE_PAR_FENETRE), majVisibiliteBouton(defilementY > window.innerHeight * RATIO_MINIMUM_PAGE_PAR_FENETRE);
); });
}); });
new ResizeObserver((entrees: Array<ResizeObserverEntry>): void => { new ResizeObserver((entrees: Array<ResizeObserverEntry>): void => {

View file

@ -2,13 +2,14 @@
import { Array as EffectArray, Match, Predicate } from "effect"; import { Array as EffectArray, Match, Predicate } from "effect";
import { DOM_ENTREES_MENU_CATEGORIES_PRODUITS, DOM_MENU_CATEGORIES_PRODUITS } from "./constantes/dom.ts";
import { getAllSelectorFromDocumentOrThrow, getFirstSelectorFromDocumentOrThrow } from "../scripts-effect/lib/dom.ts"; import { getAllSelectorFromDocumentOrThrow, getFirstSelectorFromDocumentOrThrow } from "../scripts-effect/lib/dom.ts";
import { DOM_ENTREES_MENU_CATEGORIES_PRODUITS, DOM_MENU_CATEGORIES_PRODUITS } from "./constantes/dom.ts";
// Initialise les attributs HTML pour l'affichage initiale des flèches de défilement du menu de catégories de Produits. // Initialise les attributs HTML pour l'affichage initiale des flèches de défilement du menu de catégories de Produits.
document.addEventListener("DOMContentLoaded", (): void => { document.addEventListener("DOMContentLoaded", (): void => {
const productsCategoriesMenu: HTMLElement = const productsCategoriesMenu: HTMLElement = getFirstSelectorFromDocumentOrThrow<HTMLElement>(
getFirstSelectorFromDocumentOrThrow<HTMLElement>(DOM_MENU_CATEGORIES_PRODUITS); DOM_MENU_CATEGORIES_PRODUITS,
);
const menuEntries: ReadonlyArray<HTMLAnchorElement> = getAllSelectorFromDocumentOrThrow( const menuEntries: ReadonlyArray<HTMLAnchorElement> = getAllSelectorFromDocumentOrThrow(
DOM_ENTREES_MENU_CATEGORIES_PRODUITS, DOM_ENTREES_MENU_CATEGORIES_PRODUITS,
); );
@ -22,17 +23,25 @@ document.addEventListener("DOMContentLoaded", (): void => {
} }
new IntersectionObserver( new IntersectionObserver(
EffectArray.forEach((intersectionEntry) => { EffectArray.forEach(intersectionEntry => {
// Ne déclenche rien si le scroll n'est pas horizontal // Ne déclenche rien si le scroll n'est pas horizontal
if (intersectionEntry.boundingClientRect.top <= 0) { if (intersectionEntry.boundingClientRect.top <= 0) {
return; return;
} }
Match.value([intersectionEntry.isIntersecting]).pipe( Match.value([intersectionEntry.isIntersecting]).pipe(
Match.when([true, 0], () => productsCategoriesMenu.removeAttribute("data-entrees-presentes-debut")), Match.when([true, 0], () => {
Match.when([true, 1], () => productsCategoriesMenu.removeAttribute("data-entrees-presentes-fin")), productsCategoriesMenu.removeAttribute("data-entrees-presentes-debut");
Match.when([false, 0], () => productsCategoriesMenu.setAttribute("data-entrees-presentes-debut", "")), }),
Match.when([false, 1], () => productsCategoriesMenu.setAttribute("data-entrees-presentes-fin", "")), Match.when([true, 1], () => {
productsCategoriesMenu.removeAttribute("data-entrees-presentes-fin");
}),
Match.when([false, 0], () => {
productsCategoriesMenu.setAttribute("data-entrees-presentes-debut", "");
}),
Match.when([false, 1], () => {
productsCategoriesMenu.setAttribute("data-entrees-presentes-fin", "");
}),
Match.orElse(() => {}), Match.orElse(() => {}),
); );
}), }),

View file

@ -18,19 +18,19 @@ const E = {
const initialiseBoutonMenuMobile = (): void => { const initialiseBoutonMenuMobile = (): void => {
const menuMobile = new A11yDialog(E.MENU_MOBILE); const menuMobile = new A11yDialog(E.MENU_MOBILE);
new ResizeObserver((entrees) => new ResizeObserver(entrees =>
// Cache le Menu mobile pour les grandes tailles d'écrans // Cache le Menu mobile pour les grandes tailles d'écrans
pipe( pipe(
A.head(entrees), A.head(entrees),
O.filter((entree: ResizeObserverEntry) => entree.borderBoxSize[0]!.inlineSize > 1000), O.filter((entree: ResizeObserverEntry) => entree.borderBoxSize[0]!.inlineSize > 1000),
O.tap((_) => menuMobile.hide()), O.tap(_ => menuMobile.hide()),
), )
).observe(E.CORPS_HTML); ).observe(E.CORPS_HTML);
E.BOUTON_MENU_MOBILE.addEventListener("click", (): void => { E.BOUTON_MENU_MOBILE.addEventListener("click", (): void => {
// Renvoie à la Page d'accueil pour les grandes tailles d'écrans // Renvoie à la Page d'accueil pour les grandes tailles d'écrans
if (window.innerWidth > 1000) { if (window.innerWidth > 1000) {
window.location.href = "/"; globalThis.location.href = "/";
return; return;
} }
// Cache le Menu mobile s'il est actif // Cache le Menu mobile s'il est actif

View file

@ -2,7 +2,7 @@
* Scripts pour les fonctionnalités de la Page À Propos (« About »). * Scripts pour les fonctionnalités de la Page À Propos (« About »).
*/ */
import { A, pipe as beltPipe, O } from "@mobily/ts-belt"; import { A, O, pipe as beltPipe } from "@mobily/ts-belt";
import { import {
ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF, ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF,
@ -48,7 +48,11 @@ document.addEventListener("DOMContentLoaded", (): void => {
O.tap((id: string) => { O.tap((id: string) => {
beltPipe( beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)), O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))), O.tap(
A.forEach(element => {
element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF);
}),
),
); );
}), }),
); );
@ -64,7 +68,11 @@ document.addEventListener("DOMContentLoaded", (): void => {
if (cible.hasAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)) { if (cible.hasAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)) {
beltPipe( beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)), O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))), O.tap(
A.forEach(element => {
element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF);
}),
),
); );
return; return;
} }
@ -73,12 +81,14 @@ document.addEventListener("DOMContentLoaded", (): void => {
beltPipe( beltPipe(
Array.from(ENSEMBLES_EPINGLES_BOITES_TEXTE.values()), Array.from(ENSEMBLES_EPINGLES_BOITES_TEXTE.values()),
A.flat, A.flat,
A.forEach((element) => element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF)), A.forEach(element => {
element.removeAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF);
}),
); );
// Active l'Attribut sur l'Ensemble // Active l'Attribut sur l'Ensemble
beltPipe( beltPipe(
O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)), O.fromNullable(ENSEMBLES_EPINGLES_BOITES_TEXTE.get(id)),
O.tap(A.forEach((element) => element.toggleAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))), O.tap(A.forEach(element => element.toggleAttribute(ATTRIBUT_ENSEMBLE_EPINGLE_BOITE_ACTIF))),
); );
}), }),
); );

View file

@ -94,23 +94,25 @@ const initDefilementStorytelling = (): void => {
}).observe(E.STORYTELLING); }).observe(E.STORYTELLING);
// Initialise la mise à jour des images au défilement sur le Conteneur. // Initialise la mise à jour des images au défilement sur le Conteneur.
E.STORYTELLING.addEventListener("scroll", (): void => majVisibilitéImagesStorytelling()); E.STORYTELLING.addEventListener("scroll", (): void => {
majVisibilitéImagesStorytelling();
});
}; };
const initGestionAnimation = (): void => { const initGestionAnimation = (): void => {
pipe( pipe(
A.at(E.IMAGES_STORYTELLING, 0), A.at(E.IMAGES_STORYTELLING, 0),
O.tap((img) => { O.tap(img => {
const options: IntersectionObserverInit = { const options: IntersectionObserverInit = {
root: undefined, root: undefined,
rootMargin: "0px", rootMargin: "0px",
threshold: 0, threshold: 0,
}; };
const callback = (entries: Array<IntersectionObserverEntry>) => { const callback = (entries: Array<IntersectionObserverEntry>) => {
A.forEach(entries, (e) => { A.forEach(entries, e => {
e.intersectionRatio >= 0.9 e.intersectionRatio >= 0.9 ?
? E.CONTENEUR_ANIMATION.removeAttribute(ATTRIBUT_HIDDEN) E.CONTENEUR_ANIMATION.removeAttribute(ATTRIBUT_HIDDEN) :
: E.CONTENEUR_ANIMATION.setAttribute(ATTRIBUT_HIDDEN, ""); E.CONTENEUR_ANIMATION.setAttribute(ATTRIBUT_HIDDEN, "");
}); });
}; };

View file

@ -13,6 +13,7 @@ import type { WCV3Products, WCV3ProductsArgs } from "./lib/types/api/v3/products
import type { GenericPageState } from "./lib/types/pages"; import type { GenericPageState } from "./lib/types/pages";
import { ROUTE_API_NOUVELLE_PRODUCTS } from "./constantes/api.ts"; import { ROUTE_API_NOUVELLE_PRODUCTS } from "./constantes/api.ts";
import { PRODUCT_STATUTES } from "./constantes/api/products.ts";
import { import {
ATTRIBUT_CHARGEMENT, ATTRIBUT_CHARGEMENT,
ATTRIBUT_DESACTIVE, ATTRIBUT_DESACTIVE,
@ -28,7 +29,6 @@ import { BadRequestError, reporteErreur, ServerError } from "./lib/erreurs.ts";
import { getBackendAvecParametresUrl, newPartialResponse } from "./lib/reseau.ts"; import { getBackendAvecParametresUrl, newPartialResponse } from "./lib/reseau.ts";
import { WCV3ProductsArgsSchema, WCV3ProductsSchema } from "./lib/schemas/api/v3/products.ts"; import { WCV3ProductsArgsSchema, WCV3ProductsSchema } from "./lib/schemas/api/v3/products.ts";
import { safeSchemaParse } from "./lib/validation.ts"; import { safeSchemaParse } from "./lib/validation.ts";
import { PRODUCT_STATUTES } from "./constantes/api/products.ts";
type APIProductsErrors = type APIProductsErrors =
| APIFetchErrors | APIFetchErrors
@ -67,109 +67,7 @@ const initialisePageBoutique = (): void => {
...(idCategorieProduits && { category: idCategorieProduits }), ...(idCategorieProduits && { category: idCategorieProduits }),
}; };
void EitherAsync undefined;
// 1. Valide les Arguments de la Requête
.liftEither(safeSchemaParse(args, WCV3ProductsArgsSchema))
// 2. Exécute un Effet pour empêcher les requêtes concurrentes et lancer une animation de chargement
.ifRight((): void => {
// Désactive le Bouton pour empêcher des requêtes concurrentes
E.BOUTON_PLUS_DE_PRODUITS.setAttribute(ATTRIBUT_DESACTIVE, "");
E.BOUTON_PLUS_DE_PRODUITS.setAttribute(ATTRIBUT_CHARGEMENT, "");
// Lance un cycle d'animation sur le texte de chargement
lanceAnimationCycleLoading(E.BOUTON_PLUS_DE_PRODUITS, 500);
})
// 3. Exécute la requête via fetch sous forme d'EitherAsync
.chain((args: WCV3ProductsArgs) =>
EitherAsync<DOMException | Error, Response>(() =>
getBackendAvecParametresUrl({
authString: ETATS_PAGE.authString,
nonce: ETATS_PAGE.nonce,
route: ROUTE_API_NOUVELLE_PRODUCTS,
searchParams: new URLSearchParams(args).toString(),
}),
),
)
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) =>
EitherAsync<APIFetchErrors, unknown>(async ({ throwE }) =>
match(await newPartialResponse(reponse))
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({ status: 400 }, () => throwE(new BadRequestError("400 Server Error")))
.with({ status: 200 }, (r) => r.body)
.run(),
),
)
// 5. Vérifie le Schéma de la Réponse
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCV3ProductsSchema)))
// 6. Exécute un Effet pour la mise à jour du DOM avec les Résultats
.ifRight((donnees: WCV3Products) => {
// Cache le bouton s'il y a moins de PRODUCTS_PER_PAGE Produits disponibles (que l'on est à la dernière page)
if (donnees.length < PRODUCTS_PER_PAGE) {
E.BOUTON_PLUS_DE_PRODUITS.toggleAttribute(ATTRIBUT_HIDDEN);
}
// Créé un DocumentFragment qui recevra tous les nouveaux Produits
const fragment: DocumentFragment = document.createDocumentFragment();
// Créé les Éléments <article> à insérer
for (const produit of donnees.slice(0, PRODUCTS_PER_PAGE)) {
pipe(
html`
<article class="produit">
<figure>
<a href="/product/${produit.slug}">
<picture class="produit__illustration produit__illustration__principale">
${produit.image_repos ?? ""}
</picture>
<picture class="produit__illustration produit__illustration__survol">
${produit.image_survol ?? ""}
</picture>
</a>
<figcaption class="produit__textuel">
<h3 class="produit__textuel__titre">
<a href="${produit.permalink}">${produit.name}</a>
</h3>
<p class="produit__textuel__prix">
${produit.prix_maximal}
</p>
</figcaption>
</figure>
</article>
`,
tap((article) => fragment.append(article)),
);
}
// Ajoute les nouveaux Produits dans le DOM
E.GRILLE_PRODUITS.append(fragment);
E.GRILLE_PRODUITS.setAttribute(ATTRIBUT_PAGE, String(nouveauNumeroPage));
E.BOUTON_PLUS_DE_PRODUITS.textContent = "Show more";
})
// 7. Traite les Erreurs et affiche un Message à l'Utilisateur
.ifLeft((erreur: APIProductsErrors) => {
match(erreur)
.with(P.instanceOf(ValiError), (e) => {
reporteErreur(e);
console.error("ValiError", e.issues);
})
.otherwise((e) => {
reporteErreur(e);
console.error("Erreur", e);
});
E.BOUTON_PLUS_DE_PRODUITS.textContent = "Error, try again?";
})
// 8. Quel que soit le résultat, réactiver le Bouton et arrêter l'animation
.finally(() => {
// Désactive l'animation de chargement et rend le Bouton de nouveau cliquable
E.BOUTON_PLUS_DE_PRODUITS.removeAttribute(ATTRIBUT_CHARGEMENT);
E.BOUTON_PLUS_DE_PRODUITS.removeAttribute(ATTRIBUT_DESACTIVE);
})
.run();
}); });
}; };

View file

@ -8,6 +8,8 @@ import type { MessageMajContenuPanierSchema } from "./lib/schemas/messages.ts";
import type { WCStoreCartItem } from "./lib/types/api/cart"; import type { WCStoreCartItem } from "./lib/types/api/cart";
import type { MessageMajBoutonPanierDonnees, MessageMajContenuPanierDonnees } from "./lib/types/messages"; import type { MessageMajBoutonPanierDonnees, MessageMajContenuPanierDonnees } from "./lib/types/messages";
import { Effect } from "effect";
import { Effect } from "effect";
import { import {
ATTRIBUT_CLE_PANIER, ATTRIBUT_CLE_PANIER,
ATTRIBUT_CONTIENT_ARTICLES, ATTRIBUT_CONTIENT_ARTICLES,
@ -36,7 +38,6 @@ import { E } from "./page-panier/scripts-page-panier-elements.ts";
import { souscrisEvenementsPanier } from "./page-panier/scripts-page-panier-evenement.ts"; import { souscrisEvenementsPanier } from "./page-panier/scripts-page-panier-evenement.ts";
import { initShippingRatesChoicesActions } from "./page-panier/scripts-page-panier-methodes-livraison.ts"; import { initShippingRatesChoicesActions } from "./page-panier/scripts-page-panier-methodes-livraison.ts";
import { initialiseActionsEntreesPanier } from "./page-panier/scripts-page-panier-panneau-produits.ts"; import { initialiseActionsEntreesPanier } from "./page-panier/scripts-page-panier-panneau-produits.ts";
import { Effect } from "effect";
type ElementsEntreePanier = { type ElementsEntreePanier = {
boutonAddition: HTMLButtonElement; boutonAddition: HTMLButtonElement;
@ -54,7 +55,6 @@ type EtatsPage = {
// @ts-expect-error -- États injectés par le modèle PHP // @ts-expect-error -- États injectés par le modèle PHP
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP
const ETATS_PAGE: EtatsPage = _etats;
/** /**
* Fonction utilitaire pour récupérer un Élément dans une ligne (entrée) du Panier, en levant une * Fonction utilitaire pour récupérer un Élément dans une ligne (entrée) du Panier, en levant une
@ -64,13 +64,11 @@ const ETATS_PAGE: EtatsPage = _etats;
* @returns L'Élément demandé. * @returns L'Élément demandé.
* @throws Une SyntaxError si l'Élément n'est pas trouvé. * @throws Une SyntaxError si l'Élément n'est pas trouvé.
*/ */
const recupereElementDansEntreePanierOuLeve = const recupereElementDansEntreePanierOuLeve = (entree: HTMLElement) => (selecteur: string) =>
(entree: HTMLElement) => pipe(recupereElementAvecSelecteur(entree)<Element>(selecteur), recupereElementOuLeve);
<E extends Element = Element>(selecteur: string) =>
pipe(recupereElementAvecSelecteur(entree)<E>(selecteur), recupereElementOuLeve);
// NOTE: Nécessaire pour éviter une condition de course entre la réussite de la requête et l'émission effective du Message // NOTE: Nécessaire pour éviter une condition de course entre la réussite de la requête et l'émission effective du Message
const majEtatsActivationBoutons = (entrees: Array<HTMLElement>): void => const majEtatsActivationBoutons = (entrees: Array<HTMLElement>): void => {
entrees.forEach((entree: HTMLElement) => { entrees.forEach((entree: HTMLElement) => {
// Fonction utilitaire // Fonction utilitaire
const recupereElementDansEntree = recupereElementDansEntreePanierOuLeve(entree); const recupereElementDansEntree = recupereElementDansEntreePanierOuLeve(entree);
@ -82,13 +80,14 @@ const majEtatsActivationBoutons = (entrees: Array<HTMLElement>): void =>
champQuantite: recupereElementDansEntree<HTMLInputElement>(DOM_CHAMP_QUANTITE_LIGNE_PANIER), champQuantite: recupereElementDansEntree<HTMLInputElement>(DOM_CHAMP_QUANTITE_LIGNE_PANIER),
}; };
Number(elements.champQuantite?.value) === 1 Number(elements.champQuantite?.value) === 1 ?
? elements.boutonSoustraction.setAttribute(ATTRIBUT_DESACTIVE, "") elements.boutonSoustraction.setAttribute(ATTRIBUT_DESACTIVE, "") :
: elements.boutonSoustraction.removeAttribute(ATTRIBUT_DESACTIVE); elements.boutonSoustraction.removeAttribute(ATTRIBUT_DESACTIVE);
elements.boutonAddition.removeAttribute(ATTRIBUT_DESACTIVE); elements.boutonAddition.removeAttribute(ATTRIBUT_DESACTIVE);
elements.boutonSuppression.removeAttribute(ATTRIBUT_DESACTIVE); elements.boutonSuppression.removeAttribute(ATTRIBUT_DESACTIVE);
elements.boutonSuppression.textContent = "Remove"; elements.boutonSuppression.textContent = "Remove";
}); });
};
const initialiseMajConteneurPanier = (): void => { const initialiseMajConteneurPanier = (): void => {
new BroadcastChannel(NOM_CANAL_BOUTON_PANIER).onmessage = (evenementMessage: MessageEvent<unknown>): void => { new BroadcastChannel(NOM_CANAL_BOUTON_PANIER).onmessage = (evenementMessage: MessageEvent<unknown>): void => {
@ -111,7 +110,7 @@ const initialiseMajContenuPanier = (): void => {
donnees.produits.forEach((ligne: WCStoreCartItem) => { donnees.produits.forEach((ligne: WCStoreCartItem) => {
// Met à jour les entrées du Panier // Met à jour les entrées du Panier
E.ENTREES_PANIER.ifRight((entrees: Array<HTMLElement>) => { E.ENTREES_PANIER.ifRight((entrees: Array<HTMLElement>) => {
Maybe.fromNullable(entrees.find((entree) => entree.getAttribute(ATTRIBUT_CLE_PANIER) === ligne.key)).ifJust( Maybe.fromNullable(entrees.find(entree => entree.getAttribute(ATTRIBUT_CLE_PANIER) === ligne.key)).ifJust(
(entree: HTMLElement) => { (entree: HTMLElement) => {
// Fonction utilitaire // Fonction utilitaire
const recupereElementDansEntree = recupereElementDansEntreePanierOuLeve(entree); const recupereElementDansEntree = recupereElementDansEntreePanierOuLeve(entree);
@ -144,7 +143,9 @@ const initialiseMajContenuPanier = (): void => {
// Reporte tout Erreur et réactive les Boutons // Reporte tout Erreur et réactive les Boutons
.ifLeft((erreur: CleNonTrouveError | ValiError<typeof MessageMajContenuPanierSchema>) => { .ifLeft((erreur: CleNonTrouveError | ValiError<typeof MessageMajContenuPanierSchema>) => {
reporteErreur(erreur); reporteErreur(erreur);
E.ENTREES_PANIER.ifRight((entrees) => majEtatsActivationBoutons(entrees)); E.ENTREES_PANIER.ifRight(entrees => {
majEtatsActivationBoutons(entrees);
});
}); });
}; };
}; };
@ -157,7 +158,9 @@ const initialiseMajFormulairesPanier = (): void => {
// Rend visible le formulaire de facturation. // Rend visible le formulaire de facturation.
E.FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN); E.FORMULAIRE_FACTURATION.removeAttribute(ATTRIBUT_HIDDEN);
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)("input, select").ifRight( getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)("input, select").ifRight(
arrayForEach((champ) => champ.removeAttribute(ATTRIBUT_DESACTIVE)), arrayForEach(champ => {
champ.removeAttribute(ATTRIBUT_DESACTIVE);
}),
); );
}) })
// Les Adresses sont combinées. // Les Adresses sont combinées.
@ -167,7 +170,7 @@ const initialiseMajFormulairesPanier = (): void => {
getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)<HTMLInputElement | HTMLSelectElement>( getDOMElementsWithSelector(E.FORMULAIRE_FACTURATION)<HTMLInputElement | HTMLSelectElement>(
"input, select", "input, select",
).ifRight( ).ifRight(
arrayForEach((champ) => { arrayForEach(champ => {
champ.setAttribute(ATTRIBUT_DESACTIVE, ""); champ.setAttribute(ATTRIBUT_DESACTIVE, "");
champ.value = ""; champ.value = "";
}), }),

View file

@ -0,0 +1,132 @@
import { Array as FxArray, Console, Context, Effect, HashMap, Layer, ManagedRuntime, Option, pipe } from "effect";
import type { NonEmptyReadonlyArray } from "effect/Array";
import type { NoSuchElementError } from "effect/Cause";
import { getAllSelectorFromDocument, getFirstSelectorFromDocument } from "../scripts-effect/lib/dom.ts";
import {
ATTRIBUT_ARIA_CONTROLS,
ATTRIBUT_ARIA_EXPANDED,
ATTRIBUT_HIDDEN,
DOM_BOUTON_AJOUT_PANIER,
DOM_BOUTONS_ACCORDEON,
DOM_CONTENUS_ACCORDEON,
DOM_PRIX_PRODUIT,
} from "./constantes/dom.ts";
import type { WCStoreCartAddItemArgsItems } from "./lib/types/api/cart-add-item.d.ts";
/** Représente un ensemble bouton-contenu d'une Section dans la description du Produit. */
type DetailEnsemble = {
button: HTMLButtonElement;
content: HTMLDivElement;
};
class ProductPageElements extends Context.Service<
ProductPageElements,
{
AddProductButton: HTMLButtonElement;
Details: HashMap.HashMap<string, DetailEnsemble>;
DetailsButtons: NonEmptyReadonlyArray<HTMLButtonElement>;
DetailsContents: NonEmptyReadonlyArray<HTMLDivElement>;
ProductPrice: HTMLParagraphElement;
ProductRawJson: HTMLScriptElement;
VariationChoiceForm: HTMLFormElement;
VariationSelectors: ReadonlyArray<HTMLSelectElement>;
}
>()("haikuatelier.fr/Produit/ProductPageElements") {
static readonly layer = Layer.effect(
ProductPageElements,
Effect.gen(function*() {
const AddProductButton = yield* getFirstSelectorFromDocument<HTMLButtonElement>(DOM_BOUTON_AJOUT_PANIER);
const DetailsButtons = yield* getAllSelectorFromDocument<HTMLButtonElement>(DOM_BOUTONS_ACCORDEON);
const DetailsContents = yield* getAllSelectorFromDocument<HTMLDivElement>(DOM_CONTENUS_ACCORDEON);
const ProductPrice = yield* getFirstSelectorFromDocument<HTMLParagraphElement>(DOM_PRIX_PRODUIT);
const ProductRawJson = yield* getFirstSelectorFromDocument<HTMLScriptElement>("#product-json");
const VariationChoiceForm = yield* getFirstSelectorFromDocument<HTMLFormElement>("#variation-choice");
const VariationSelectors = yield* pipe(
getAllSelectorFromDocument<HTMLSelectElement>(".selecteur-produit select"),
Option.orElseSome(() => FxArray.empty<HTMLSelectElement>()),
);
const Details = yield* pipe(
DetailsButtons,
FxArray.map(
(button: HTMLButtonElement, index: number): Effect.Effect<[string, DetailEnsemble], NoSuchElementError> =>
Effect.gen(function*() {
const contentId = yield* Option.fromNullishOr(button.getAttribute(ATTRIBUT_ARIA_CONTROLS));
const content = yield* FxArray.get(DetailsContents, index);
return [contentId, { button, content } satisfies DetailEnsemble];
}),
),
Effect.all,
Effect.map(HashMap.fromIterable<string, DetailEnsemble>),
);
return ProductPageElements.of({
AddProductButton,
Details,
DetailsButtons,
DetailsContents,
ProductPrice,
ProductRawJson,
VariationChoiceForm,
VariationSelectors,
});
}),
);
}
class ProductPageDOM extends Context.Service<
ProductPageDOM,
{
/**
* Récupère les Attributs du Produit depuis les Elements au sein du DOM.
*/
getProductAttributesFromDOM: () => Effect.Effect<ReadonlyArray<WCStoreCartAddItemArgsItems>>;
/**
* Replie toutes les sections de la description du Produit.
*/
toggleAllDetails: () => Effect.Effect<void>;
}
>()("haikuatelier.fr/Produit/ProductPageDOM") {
static readonly layer = Layer.effect(
ProductPageDOM,
Effect.gen(function*() {
const { Details, VariationSelectors } = yield* ProductPageElements;
const toggleAllDetails: () => Effect.Effect<void> = () =>
Effect.sync((): void => {
pipe(
// Récupère les Sections sous forme d'Ensembles.
[...HashMap.values(Details)],
FxArray.forEach((detail: DetailEnsemble) => {
detail.button.toggleAttribute(ATTRIBUT_ARIA_EXPANDED, false);
detail.content.toggleAttribute(ATTRIBUT_HIDDEN, true);
}),
);
});
const getProductAttributesFromDOM: () => Effect.Effect<ReadonlyArray<WCStoreCartAddItemArgsItems>> = () =>
Effect.sync(() =>
FxArray.map(VariationSelectors, (select: HTMLSelectElement) => ({
attribute: select.id,
value: select.value,
}))
);
return ProductPageDOM.of({
getProductAttributesFromDOM,
toggleAllDetails,
});
}),
);
}
const ProductPageRuntime = ManagedRuntime.make(
pipe(
ProductPageDOM.layer,
Layer.provide(ProductPageElements.layer),
Layer.tapError(error => Console.error("ManagedRuntime", "Impossible de créer le Layer :", error.name)),
),
);
export { type DetailEnsemble, ProductPageDOM, ProductPageElements, ProductPageRuntime };

View file

@ -3,25 +3,14 @@
import { pipe } from "@mobily/ts-belt"; import { pipe } from "@mobily/ts-belt";
import { get as dictGet } from "@mobily/ts-belt/Dict"; import { get as dictGet } from "@mobily/ts-belt/Dict";
import { tap as optionTap } from "@mobily/ts-belt/Option"; import { tap as optionTap } from "@mobily/ts-belt/Option";
import { import { Array as FxArray, Console, Effect, HashMap, Option, pipe as epipe, Stream } from "effect";
Array as FxArray,
Effect,
pipe as epipe,
Option,
Stream,
ServiceMap,
Layer,
ManagedRuntime,
Console,
HashMap,
} from "effect";
import { EitherAsync } from "purify-ts"; import { EitherAsync } from "purify-ts";
import { match, P } from "ts-pattern"; import { match, P } from "ts-pattern";
import { ValiError } from "valibot"; import { ValiError } from "valibot";
import type { AnySchema } from "valibot"; import type { AnySchema } from "valibot";
import type { WCStoreCart } from "./lib/types/api/cart.ts";
import type { WCStoreCartAddItemArgs, WCStoreCartAddItemArgsItems } from "./lib/types/api/cart-add-item.ts"; import type { WCStoreCartAddItemArgs, WCStoreCartAddItemArgsItems } from "./lib/types/api/cart-add-item.ts";
import type { WCStoreCart } from "./lib/types/api/cart.ts";
import type { FetchErrors } from "./lib/types/reseau.ts"; import type { FetchErrors } from "./lib/types/reseau.ts";
import { ROUTE_API_AJOUTE_ARTICLE_PANIER } from "./constantes/api.ts"; import { ROUTE_API_AJOUTE_ARTICLE_PANIER } from "./constantes/api.ts";
@ -44,15 +33,8 @@ import { emetMessageMajBoutonPanier } from "./lib/messages.ts";
import { newPartialResponse, postBackend, safeFetch } from "./lib/reseau.ts"; import { newPartialResponse, postBackend, safeFetch } from "./lib/reseau.ts";
import { WCStoreCartAddItemArgsSchema } from "./lib/schemas/api/cart-add-item.ts"; import { WCStoreCartAddItemArgsSchema } from "./lib/schemas/api/cart-add-item.ts";
import { WCStoreCartSchema } from "./lib/schemas/api/cart.ts"; import { WCStoreCartSchema } from "./lib/schemas/api/cart.ts";
import { safeSchemaParse } from "./lib/validation"; import { safeSchemaParse } from "./lib/validation.ts";
import { getAllSelectorFromDocument, getFirstSelectorFromDocument } from "../scripts-effect/lib/dom.ts"; import { ProductPageElements, ProductPageRuntime } from "./scripts-page-produit-service.ts";
import { NonEmptyReadonlyArray } from "effect/Array";
import { NoSuchElementError } from "effect/Cause";
type DetailEnsemble = {
button: HTMLButtonElement;
content: HTMLDivElement;
};
/** États utiles pour les scripts de la page. */ /** États utiles pour les scripts de la page. */
type EtatsPage = { type EtatsPage = {
@ -65,109 +47,6 @@ type EtatsPage = {
// @ts-expect-error -- États injectés par le modèle PHP // @ts-expect-error -- États injectés par le modèle PHP
const ETATS_PAGE: EtatsPage = _etats; const ETATS_PAGE: EtatsPage = _etats;
class ProductPageElements extends ServiceMap.Service<
ProductPageElements,
{
AddProductButton: HTMLButtonElement;
DetailsButtons: NonEmptyReadonlyArray<HTMLButtonElement>;
DetailsContents: NonEmptyReadonlyArray<HTMLDivElement>;
Details: HashMap.HashMap<string, DetailEnsemble>;
ProductPrice: HTMLParagraphElement;
ProductRawJson: HTMLScriptElement;
VariationChoiceForm: HTMLFormElement;
VariationSelectors: ReadonlyArray<HTMLSelectElement>;
}
>()("haikuatelier.fr/Produit/ProductPageElements") {
static readonly layer = Layer.effect(
ProductPageElements,
Effect.gen(function* () {
const AddProductButton = yield* getFirstSelectorFromDocument<HTMLButtonElement>(DOM_BOUTON_AJOUT_PANIER);
const DetailsButtons = yield* getAllSelectorFromDocument<HTMLButtonElement>(DOM_BOUTONS_ACCORDEON);
const DetailsContents = yield* getAllSelectorFromDocument<HTMLDivElement>(DOM_CONTENUS_ACCORDEON);
const ProductPrice = yield* getFirstSelectorFromDocument<HTMLParagraphElement>(DOM_PRIX_PRODUIT);
const ProductRawJson = yield* getFirstSelectorFromDocument<HTMLScriptElement>("#product-json");
const VariationChoiceForm = yield* getFirstSelectorFromDocument<HTMLFormElement>("#variation-choice");
const VariationSelectors = yield* pipe(
getAllSelectorFromDocument<HTMLSelectElement>(".selecteur-produit select"),
Option.orElseSome(() => FxArray.empty<HTMLSelectElement>()),
);
const Details = yield* pipe(
DetailsButtons,
FxArray.map(
(button: HTMLButtonElement, index: number): Effect.Effect<[string, DetailEnsemble], NoSuchElementError> =>
Effect.gen(function* () {
const contentId = yield* Option.fromNullishOr(button.getAttribute(ATTRIBUT_ARIA_CONTROLS));
const content = yield* FxArray.get(DetailsContents, index);
return [contentId, { button, content } satisfies DetailEnsemble];
}),
),
Effect.all,
Effect.map(HashMap.fromIterable<string, DetailEnsemble>),
);
return {
AddProductButton,
DetailsButtons,
DetailsContents,
Details,
ProductPrice,
ProductRawJson,
VariationChoiceForm,
VariationSelectors,
};
}),
);
}
const ProductPageRuntime = ManagedRuntime.make(
pipe(
ProductPageElements.layer,
Layer.tapError((error) => Console.error("ManagedRuntime", "Impossible de créer le Layer :", error.name)),
),
);
// Éléments d'intérêt
const E = {
BOUTON_AJOUT_PANIER: mustGetEleInDocument<HTMLButtonElement>(DOM_BOUTON_AJOUT_PANIER),
BOUTONS_ACCORDEON: mustGetElesInDocument<HTMLAnchorElement>(DOM_BOUTONS_ACCORDEON),
CONTENUS_ACCORDEON: mustGetElesInDocument<HTMLDivElement>(DOM_CONTENUS_ACCORDEON),
DOM_VARIATION: recupereElementDocumentEither<HTMLSelectElement>(DOM_DOM_QUANTITE),
PRIX_PRODUIT: mustGetEleInDocument<HTMLParagraphElement>(DOM_PRIX_PRODUIT),
PRODUCT_JSON: mustGetEleInDocument<HTMLScriptElement>("#product-json"),
VARIATION_CHOICE_FORM: mustGetEleInDocument<HTMLFormElement>("#variation-choice"),
};
const toggleAllDetails = Effect.fn("toggleAllDetails")(function* () {
const PageElements = yield* ProductPageElements;
// Récupère les Ensembles sous forme de tableau.
const details = [...HashMap.values(PageElements.Details)];
FxArray.forEach(details, (detail: DetailEnsemble) => {
detail.button.toggleAttribute(ATTRIBUT_ARIA_EXPANDED, false);
detail.content.toggleAttribute(ATTRIBUT_HIDDEN, true);
});
});
// TODO: Utiliser Effect.
const getAttributesFromDom = (): ReadonlyArray<WCStoreCartAddItemArgsItems> => {
const selectElements = epipe(
document.querySelectorAll<HTMLSelectElement>(".selecteur-produit select"),
Array.from<HTMLSelectElement>,
);
if (selectElements.length === 0) {
return [];
}
const attributes = selectElements.map((select: HTMLSelectElement) => ({
attribute: select.id,
value: select.value,
}));
return attributes;
};
const areArraysEqual = <T>(array1: Array<T>, array2: Array<T>): boolean => { const areArraysEqual = <T>(array1: Array<T>, array2: Array<T>): boolean => {
if (array1 !== array2) { if (array1 !== array2) {
const a1 = JSON.stringify(array1.toSorted()); const a1 = JSON.stringify(array1.toSorted());
@ -186,7 +65,7 @@ const updatePriceOnAttributeChange = (): void => {
const productVariations: Array<unknown> = epipe(E.PRODUCT_JSON.textContent, JSON.parse)?.variations; const productVariations: Array<unknown> = epipe(E.PRODUCT_JSON.textContent, JSON.parse)?.variations;
const chosenAttributes = getAttributesFromDom(); const chosenAttributes = getAttributesFromDom();
const chosenVariation = productVariations.find((v) => areArraysEqual(v.attributes, chosenAttributes)); const chosenVariation = productVariations.find(v => areArraysEqual(v.attributes, chosenAttributes));
const newPrice: string = chosenVariation.price; const newPrice: string = chosenVariation.price;
E.PRIX_PRODUIT.textContent = `${newPrice}`; E.PRIX_PRODUIT.textContent = `${newPrice}`;
@ -227,7 +106,7 @@ const ajouteProduitAuPanier = (event: MouseEvent): void => {
nonce: ETATS_PAGE.nonce, nonce: ETATS_PAGE.nonce,
route: ROUTE_API_AJOUTE_ARTICLE_PANIER, route: ROUTE_API_AJOUTE_ARTICLE_PANIER,
}), }),
), )
) )
// 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse // 4. Traite les cas d'Erreurs et récupère le Corps de la Réponse
.chain((reponse: Response) => .chain((reponse: Response) =>
@ -236,9 +115,9 @@ const ajouteProduitAuPanier = (event: MouseEvent): void => {
match(await newPartialResponse(reponse)) match(await newPartialResponse(reponse))
.with({ status: 500 }, () => throwE(new ServerError("500 Server Error"))) .with({ status: 500 }, () => throwE(new ServerError("500 Server Error")))
.with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error"))) .with({ status: 400 }, () => throwE(new BadRequestError("400 Bad Request Error")))
.with({ status: 201 }, (r) => r.body) .with({ status: 201 }, r => r.body)
.otherwise((erreur) => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`))), .otherwise(erreur => throwE(new Error(`Erreur inconnue ${String(erreur.status)}`)))
), )
) )
// 5. Vérifie le Schéma de la Réponse // 5. Vérifie le Schéma de la Réponse
.chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema))) .chain((corpsReponse: unknown) => EitherAsync.liftEither(safeSchemaParse(corpsReponse, WCStoreCartSchema)))
@ -250,21 +129,21 @@ const ajouteProduitAuPanier = (event: MouseEvent): void => {
E.BOUTON_AJOUT_PANIER.textContent = "Added to cart!"; E.BOUTON_AJOUT_PANIER.textContent = "Added to cart!";
emetMessageMajBoutonPanier({ quantiteProduits: totalArticles }); emetMessageMajBoutonPanier({ quantiteProduits: totalArticles });
}), }),
), )
) )
.ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>) => { .ifLeft((erreur: BadRequestError | FetchErrors | ServerError | ValiError<AnySchema>) => {
match(erreur) match(erreur)
.with(P.instanceOf(ValiError), (e) => { .with(P.instanceOf(ValiError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e.issues); console.error(e.issues);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
.with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), (e) => { .with(P.instanceOf(ServerError), P.instanceOf(BadRequestError), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_SOUMISSION_ADRESSES;
}) })
.with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), (e) => { .with(P.instanceOf(DOMException), P.instanceOf(TypeError), P.instanceOf(Error), e => {
reporteErreur(e); reporteErreur(e);
console.error(e); console.error(e);
// E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU; // E.MESSAGE_ADRESSES.textContent = ERREUR_GENERIQUE_RESEAU;
@ -304,10 +183,10 @@ const initAddToCartButton = Effect.fn("initAddToCartButton")(function* () {
return yield* Effect.void; return yield* Effect.void;
}); });
const onFormChange = Effect.fnUntraced(function* (event: Event) { const onFormChange = Effect.fnUntraced(function*(evt: Event) {
const { AddProductButton } = yield* ProductPageElements; const { AddProductButton } = yield* ProductPageElements;
// La cible ne peut qu'être un Formulaire. // La cible ne peut qu'être un Formulaire.
const target = event.target as HTMLFormElement; const target: HTMLFormElement = evt.target as HTMLFormElement;
const isClickAllowed = target.checkValidity() === false; const isClickAllowed = target.checkValidity() === false;
// Active/désactive le Bouton en fonction de la validité du Formulaire du Produit. // Active/désactive le Bouton en fonction de la validité du Formulaire du Produit.
@ -327,13 +206,13 @@ const initAddToCartInteractionUpdates = Effect.fn("initAddToCartInteractionUpdat
); );
}); });
const onDetailButtonClick = Effect.fnUntraced(function* (event: Event) { const onDetailButtonClick = Effect.fnUntraced(function*(evt: Event) {
const { Details } = yield* ProductPageElements; const { Details } = yield* ProductPageElements;
// Empêche la pollution de l'historique de navigation // Empêche la pollution de l'historique de navigation
event.preventDefault(); evt.preventDefault();
// La cible est connue. // La cible est connue.
const target = event.target as HTMLButtonElement; const target = evt.target as HTMLButtonElement;
// Récupère le contenu correspondant. // Récupère le contenu correspondant.
const linkedSection = yield* pipe( const linkedSection = yield* pipe(
Option.fromNullishOr(target.getAttribute(ATTRIBUT_ARIA_CONTROLS)), Option.fromNullishOr(target.getAttribute(ATTRIBUT_ARIA_CONTROLS)),
@ -361,14 +240,32 @@ const initDetailInteractions = Effect.fn("initDetailInteractions")(function* ()
const PageElements = yield* ProductPageElements; const PageElements = yield* ProductPageElements;
return yield* pipe( return yield* pipe(
FxArray.map(PageElements.DetailsButtons, (button: HTMLButtonElement) => FxArray.map(
pipe(Stream.fromEventListener(button, "click"), Stream.tap(onDetailButtonClick)), PageElements.DetailsButtons,
(button: HTMLButtonElement) => pipe(Stream.fromEventListener(button, "click"), Stream.tap(onDetailButtonClick)),
), ),
Stream.mergeAll({ concurrency: "unbounded" }), Stream.mergeAll({ concurrency: "unbounded" }),
Stream.runDrain, Stream.runDrain,
); );
}); });
const getAttributesFromDom = (): ReadonlyArray<WCStoreCartAddItemArgsItems> => {
const selectElements = epipe(
document.querySelectorAll<HTMLSelectElement>(".selecteur-produit select"),
Array.from<HTMLSelectElement>,
);
if (selectElements.length === 0) {
return [];
}
const attributes = selectElements.map((select: HTMLSelectElement) => ({
attribute: select.id,
value: select.value,
}));
return attributes;
};
document.addEventListener("DOMContentLoaded", (): void => { document.addEventListener("DOMContentLoaded", (): void => {
ProductPageRuntime.runFork(pipe(initAddToCartButton(), Effect.tapCause(Console.error))); ProductPageRuntime.runFork(pipe(initAddToCartButton(), Effect.tapCause(Console.error)));
ProductPageRuntime.runFork(pipe(initAddToCartInteractionUpdates(), Effect.tapCause(Console.error))); ProductPageRuntime.runFork(pipe(initAddToCartInteractionUpdates(), Effect.tapCause(Console.error)));

View file

@ -1,7 +1,7 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
type ImportMeta = { type ImportMeta = Readonly<{
readonly env: ImportMetaEnv; env: ImportMetaEnv;
}; }>;
type ImportMetaEnv = {}; type ImportMetaEnv = {};

View file

@ -37,6 +37,7 @@ $products = wc_get_products([
]) ])
|> function (/** @var list<WC_Product>|stdClass */ mixed $products): array { |> function (/** @var list<WC_Product>|stdClass */ mixed $products): array {
assert(is_array($products), 'Les Produits de la Catégorie doivent être un tableau.'); assert(is_array($products), 'Les Produits de la Catégorie doivent être un tableau.');
return $products; return $products;
} }
|> (static fn(/** @var list<WC_Product> */ array $products): array => Arr::map( |> (static fn(/** @var list<WC_Product> */ array $products): array => Arr::map(

View file

@ -31,7 +31,10 @@ $commande = $order;
$date = new Carbon($commande->get_date_created()); $date = new Carbon($commande->get_date_created());
$email = [ $email = [
'adresses' => ['facturation' => $commande->get_address('billing'), 'livraison' => $commande->get_address('shipping')], 'adresses' => [
'facturation' => $commande->get_address('billing'),
'livraison' => $commande->get_address('shipping'),
],
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
'livraison' => [ 'livraison' => [
'methode' => $commande->get_shipping_method(), 'methode' => $commande->get_shipping_method(),
@ -62,7 +65,9 @@ $email = [
]; ];
}), }),
'totaux' => [ 'totaux' => [
'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€', 'sous_total_livraison' => '0' === $commande->get_shipping_total()
? 'Free'
: $commande->get_shipping_total() . '€',
'sous_total_produits' => $commande->get_subtotal() . '€', 'sous_total_produits' => $commande->get_subtotal() . '€',
'sous_total_reduction' => '0.00' === $commande->get_discount_total() 'sous_total_reduction' => '0.00' === $commande->get_discount_total()
? '0' ? '0'

View file

@ -31,7 +31,10 @@ $commande = $order;
$date = new Carbon($commande->get_date_created()); $date = new Carbon($commande->get_date_created());
$email = [ $email = [
'adresses' => ['facturation' => $commande->get_address('billing'), 'livraison' => $commande->get_address('shipping')], 'adresses' => [
'facturation' => $commande->get_address('billing'),
'livraison' => $commande->get_address('shipping'),
],
'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()], 'commande' => ['date' => $date->toDateString(), 'id' => $commande->get_id()],
'paiement' => ['methode' => ''], 'paiement' => ['methode' => ''],
'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) { 'produits' => collect($commande->get_items())->map(static function (WC_Order_Item_Product $article) {
@ -58,7 +61,9 @@ $email = [
]; ];
}), }),
'totaux' => [ 'totaux' => [
'sous_total_livraison' => '0' === $commande->get_shipping_total() ? 'Free' : $commande->get_shipping_total() . '€', 'sous_total_livraison' => '0' === $commande->get_shipping_total()
? 'Free'
: $commande->get_shipping_total() . '€',
'sous_total_produits' => $commande->get_subtotal() . '€', 'sous_total_produits' => $commande->get_subtotal() . '€',
'sous_total_reduction' => '0.00' === $commande->get_discount_total() 'sous_total_reduction' => '0.00' === $commande->get_discount_total()
? '0' ? '0'