diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c970e488d7a4..c9a819637e83 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -35,7 +35,6 @@ updates: - '@oxlint/*' - 'oxfmt' - 'oxlint' - - 'oxlint-plugin-eslint' - 'oxlint-tsgolint' proxy-agent: patterns: @@ -46,15 +45,6 @@ updates: patterns: - '@typescript-eslint/*' - - package-ecosystem: 'nix' - directory: '/' - schedule: - interval: daily - time: '08:00' - open-pull-requests-limit: 100 - labels: - - dependencies - - package-ecosystem: 'github-actions' directory: '/' schedule: diff --git a/.github/workflows/comment-on-issue.yml b/.github/workflows/comment-on-issue.yml index 255336571baf..78371364a547 100644 --- a/.github/workflows/comment-on-issue.yml +++ b/.github/workflows/comment-on-issue.yml @@ -22,7 +22,7 @@ jobs: - name: Install dependencies (pnpm) # import remark-parse and unified run: pnpm i - name: Generate feedback - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index c019b02ffb9e..0f2789c862fd 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -74,13 +74,13 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Log in to Docker Hub - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: username: ${{ vars.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the Container registry - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -207,13 +207,13 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Log in to Docker Hub - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: username: ${{ vars.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the Container registry - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: registry: ghcr.io username: ${{ github.actor }} diff --git a/.github/workflows/docker-test-cont.yml b/.github/workflows/docker-test-cont.yml index 84b324214961..7b4418845554 100644 --- a/.github/workflows/docker-test-cont.yml +++ b/.github/workflows/docker-test-cont.yml @@ -58,7 +58,7 @@ jobs: - name: Fetch affected routes id: fetch-route - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: PULL_REQUEST: ${{ steps.pr-data.outputs.data }} with: @@ -74,7 +74,7 @@ jobs: - name: Fetch Docker image if: (env.TEST_CONTINUE) - uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 + uses: dawidd6/action-download-artifact@8a338493df3d275e4a7a63bcff3b8fe97e51a927 # v19 with: workflow: ${{ github.event.workflow_run.workflow_id }} run_id: ${{ github.event.workflow_run.id }} @@ -127,7 +127,7 @@ jobs: if: (env.TEST_CONTINUE) id: generate-feedback timeout-minutes: 10 - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: TEST_BASEURL: http://localhost:1200 TEST_ROUTES: ${{ steps.fetch-route.outputs.result }} diff --git a/.github/workflows/issue-command.yml b/.github/workflows/issue-command.yml index 6fed306bcfb0..d98c74af6f49 100644 --- a/.github/workflows/issue-command.yml +++ b/.github/workflows/issue-command.yml @@ -81,7 +81,7 @@ jobs: - name: Fetch affected routes id: fetch-route - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: EVENT: ${{ toJson(github.event) }} with: @@ -109,7 +109,7 @@ jobs: - name: Generate feedback if: env.TEST_CONTINUE - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: TEST_BASEURL: http://localhost:1200 TEST_ROUTES: ${{ steps.fetch-route.outputs.result }} diff --git a/.github/workflows/pr-review.yml b/.github/workflows/pr-review.yml index 39db57eb3edd..1bf60cacc649 100644 --- a/.github/workflows/pr-review.yml +++ b/.github/workflows/pr-review.yml @@ -134,20 +134,6 @@ jobs: - Otherwise create a new PR comment. - If there are no findings and marker comment exists, edit marker comment to a short pass status. - gh command reference (PR_NUMBER and GITHUB_REPOSITORY are available as env vars): - - Create a new PR comment: - gh pr comment \"\$PR_NUMBER\" --repo \"\$GITHUB_REPOSITORY\" --body \" - ## Auto Review - ...\" - - List existing marker comments to find the one to update: - gh pr view \"\$PR_NUMBER\" --repo \"\$GITHUB_REPOSITORY\" --json comments \\ - --jq '.comments[] | select(.body | startswith(\"\")) | {id: .id, body: .body}' - - Update an existing marker comment (use the numeric id from the URL, not the node id): - gh api \"repos/\$GITHUB_REPOSITORY/issues/comments/\" -X PATCH -f body=\" - ## Auto Review - ...\" - - Prefer --body-file - with a heredoc when the body contains quotes or many lines. - Suggested comment format: ## Auto Review diff --git a/.github/workflows/similar-issues.yml b/.github/workflows/similar-issues.yml index 95372a91e63f..5af8b404b1d1 100644 --- a/.github/workflows/similar-issues.yml +++ b/.github/workflows/similar-issues.yml @@ -50,7 +50,7 @@ jobs: Issue number: $ISSUE_NUMBER - Lookup this issue and search through existing issues (excluding #$ISSUE_NUMBER) in this repository (DIYgod/RSSHub) to find any potential duplicates of this new issue. + Lookup this issue and search through existing issues (excluding #$ISSUE_NUMBER) in this repository to find any potential duplicates of this new issue. Consider: 1. Similar titles or descriptions 2. Same error messages or symptoms diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 567b235ffdbb..2a7dd45c31b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -145,7 +145,7 @@ jobs: pull-requests: write contents: write steps: - - uses: fastify/github-action-merge-dependabot@30c3f8f14a4f7b315ba38dbc1b793d27128fef82 # v3.12.0 + - uses: fastify/github-action-merge-dependabot@1b2ed42db8f9d81a46bac83adedfc03eb5149dff # v3.11.2 with: github-token: ${{ secrets.GITHUB_TOKEN }} target: patch diff --git a/.github/workflows/update-nix-hash.yml b/.github/workflows/update-nix-hash.yml index fb9ba223a0b6..8207658baed2 100644 --- a/.github/workflows/update-nix-hash.yml +++ b/.github/workflows/update-nix-hash.yml @@ -5,7 +5,7 @@ on: branches: - master paths: - - 'flake.lock' + - 'pnpm-lock.yaml' permissions: contents: write @@ -20,11 +20,9 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Nix - uses: cachix/install-nix-action@616559265b40713947b9c190a8ff4b507b5df49b # v31.10.4 + uses: cachix/install-nix-action@96951a368ba55167b55f1c916f7d416bac6505fe # v31.10.3 with: nix_path: nixpkgs=channel:nixos-unstable - - name: Cache Nix store - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13 - name: Update Nix flake hash id: update-hash @@ -49,7 +47,7 @@ jobs: fi # Update with correct hash - sed -i "s#hash = \"sha256-[^\"]*\";#hash = \"sha256-$NEW_HASH\";#" flake.nix + sed -i "s/hash = \"sha256-[^\"]*\";/hash = \"sha256-$NEW_HASH\";/" flake.nix if [ "$CURRENT_HASH" = "$NEW_HASH" ]; then echo "Hash unchanged" diff --git a/.oxlintrc.json b/.oxlintrc.json index 505d3386edbe..62b6dd4b4855 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -12,12 +12,10 @@ }, "plugins": ["eslint", "typescript", "node", "unicorn", "import"], "jsPlugins": [ + "@stylistic/eslint-plugin", { "name": "import-x-js", "specifier": "eslint-plugin-import-x" }, { "name": "n", "specifier": "eslint-plugin-n" }, - { "name": "unicorn-js", "specifier": "eslint-plugin-unicorn" }, - "@stylistic/eslint-plugin", "eslint-plugin-simple-import-sort", - "oxlint-plugin-eslint", "./eslint-plugins/no-then.js", "./eslint-plugins/nsfw-flag.js" ], @@ -149,22 +147,21 @@ "n/process-exit-as-throw": "error", // #endregion - // #region --- unicorn recommended --- + // #region --- unicorn --- "unicorn/catch-error-name": "error", "unicorn/consistent-assert": "error", "unicorn/consistent-date-clone": "error", "unicorn/consistent-empty-array-spread": "error", "unicorn/consistent-existence-index-check": "error", // "unicorn/consistent-function-scoping": "error", - "unicorn-js/consistent-template-literal-escape": "error", // use jsPlugins "unicorn/empty-brace-spaces": "error", "unicorn/error-message": "error", "unicorn/escape-case": "error", // "unicorn/expiring-todo-comments": "error", // not yet implemented // "unicorn/explicit-length-check": "error", // "unicorn/filename-case": "error", - "unicorn-js/import-style": "error", // use jsPlugins - "unicorn-js/isolated-functions": "error", // use jsPlugins + // "unicorn/import-style": "error", // not yet implemented + // "unicorn/isolated-functions": "error", // not yet implemented "unicorn/new-for-builtins": "error", "unicorn/no-abusive-eslint-disable": "error", "unicorn/no-accessor-recursion": "error", @@ -207,14 +204,13 @@ "unicorn/no-unnecessary-array-flat-depth": "error", "unicorn/no-unnecessary-array-splice-count": "error", "unicorn/no-unnecessary-await": "error", - "unicorn-js/no-unnecessary-polyfills": "error", // use jsPlugins + // "unicorn/no-unnecessary-polyfills": "error", // not yet implemented "unicorn/no-unnecessary-slice-end": "error", "unicorn/no-unreadable-array-destructuring": "error", "unicorn/no-unreadable-iife": "error", "unicorn/no-useless-collection-argument": "error", "unicorn/no-useless-error-capture-stack-trace": "error", "unicorn/no-useless-fallback-in-spread": "error", - // "unicorn/no-useless-iterator-to-array": "error", "unicorn/no-useless-length-check": "error", "unicorn/no-useless-promise-resolve-reject": "error", "unicorn/no-useless-spread": "error", @@ -242,7 +238,7 @@ "unicorn/prefer-dom-node-remove": "error", "unicorn/prefer-dom-node-text-content": "error", "unicorn/prefer-event-target": "error", - "unicorn-js/prefer-export-from": "error", // use jsPlugins + // "unicorn/prefer-export-from": "error", // not yet implemented // "unicorn/prefer-global-this": "error", "unicorn/prefer-includes": "error", "unicorn/prefer-keyboard-event-key": "error", @@ -265,8 +261,7 @@ "unicorn/prefer-response-static-json": "error", "unicorn/prefer-set-has": "error", "unicorn/prefer-set-size": "error", - "unicorn-js/prefer-simple-condition-first": "error", // use jsPlugins - "unicorn-js/prefer-single-call": "error", // use jsPlugins + // "unicorn/prefer-single-call": "error", // not yet implemented // "unicorn/prefer-spread": "error", "unicorn/prefer-string-raw": "error", "unicorn/prefer-string-replace-all": "error", @@ -274,19 +269,18 @@ "unicorn/prefer-string-starts-ends-with": "error", "unicorn/prefer-string-trim-start-end": "error", "unicorn/prefer-structured-clone": "error", - // "unicorn/prefer-switch": "error", // use jsPlugins + // "unicorn/prefer-switch": "error", // not yet implemented "unicorn/prefer-ternary": "error", // "unicorn/prefer-top-level-await": "error", "unicorn/prefer-type-error": "error", - // "unicorn/prevent-abbreviations": "error", + // "unicorn/prevent-abbreviations": "error", // not yet implemented "unicorn/relative-url-style": "error", "unicorn/require-array-join-separator": "error", "unicorn/require-module-attributes": "error", "unicorn/require-module-specifiers": "error", "unicorn/require-number-to-fixed-digits-argument": "error", // "unicorn/switch-case-braces": "error", - "unicorn-js/switch-case-break-position": "error", // use jsPlugins - "unicorn-js/template-indent": "error", // use jsPlugins + // "unicorn/template-indent": "error", // not yet implemented // "unicorn/text-encoding-identifier-case": "error", "unicorn/throw-new-error": "error", // #endregion @@ -326,60 +320,27 @@ } ], - "eslint-js/no-implicit-globals": "error", // use jsPlugins + // "no-implicit-globals": "error", // not yet implemented "no-labels": "error", "no-lonely-if": "error", "no-multi-str": "error", "no-new-func": "error", - - "eslint-js/no-restricted-syntax": [ - "error", // use jsPlugins - { - "selector": "CallExpression[callee.property.name='get'][arguments.length=0]", - "message": "Please use .toArray() instead." - }, - { - "selector": "CallExpression[callee.property.name='toArray'] MemberExpression[object.callee.property.name='map']", - "message": "Please use .toArray() before .map()." - }, - { - "selector": "CallExpression[callee.property.name=\"catch\"] > ArrowFunctionExpression[params.length=0][body.value=null]", - "message": "Usage of .catch(() => null) is not allowed. Please handle the error appropriately." - }, - { - "selector": "CallExpression[callee.property.name=\"catch\"] > ArrowFunctionExpression[params.length=0][body.type=\"Identifier\"][body.name=\"undefined\"]", - "message": "Usage of .catch(() => undefined) is not allowed. Please handle the error appropriately." - }, - { - "selector": "CallExpression[callee.property.name=\"catch\"] > ArrowFunctionExpression[params.length=0] > ArrayExpression[elements.length=0]", - "message": "Usage of .catch(() => []) is not allowed. Please handle the error appropriately." - }, - { - "selector": "CallExpression[callee.property.name=\"catch\"] > ArrowFunctionExpression[params.length=0] > BlockStatement[body.length=0]", - "message": "Usage of .catch(() => {}) is not allowed. Please handle the error appropriately." - }, - { - "selector": "CallExpression[callee.name=\"load\"] AwaitExpression > CallExpression", - "message": "Do not use await in call expressions. Extract the result into a variable first." - } - ], - "no-unneeded-ternary": "error", "no-useless-computed-key": "error", "no-useless-concat": "warn", "no-useless-rename": "error", "no-var": "error", - "eslint-js/object-shorthand": "error", // use jsPlugins - "eslint-js/prefer-arrow-callback": "error", // use jsPlugins + // "object-shorthand": "error", // not yet implemented + // "prefer-arrow-callback'": "error", // not yet implemented "prefer-const": "error", "prefer-object-has-own": "error", - "eslint-js/prefer-regex-literals": [ - "error", // use jsPlugins - { - "disallowRedundantWrapping": true - } - ], "require-await": "error", + // "prefer-regex-literals": [ // not yet implemented + // "error", + // { + // "disallowRedundantWrapping": true + // } + // ], // #endregion // #region --- TypeScript --- @@ -388,7 +349,6 @@ "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/consistent-indexed-object-style": "off", // stylistic "@typescript-eslint/consistent-type-definitions": "off", // stylistic - "@typescript-eslint/dot-notation": "error", // type-aware "@typescript-eslint/no-empty-function": "off", // stylistic && tests "@typescript-eslint/no-explicit-any": "off", @@ -432,7 +392,6 @@ "unicorn/no-null": "off", "unicorn/no-object-as-default-parameter": "warn", "unicorn/no-process-exit": "off", - "unicorn/no-useless-iterator-to-array": "off", "unicorn/no-useless-switch-case": "off", "unicorn/no-useless-undefined": ["error", { "checkArguments": false }], @@ -464,7 +423,7 @@ "unicorn/prefer-code-point": "warn", "unicorn/prefer-global-this": "off", - "unicorn-js/prefer-import-meta-properties": "warn", + "unicorn/prefer-import-meta-properties": "warn", "unicorn/prefer-module": "off", "unicorn/prefer-number-properties": ["error", { "checkInfinity": false, "checkNaN": false }], @@ -472,15 +431,15 @@ "unicorn/prefer-spread": "warn", "unicorn/prefer-string-slice": "warn", - "unicorn-js/prefer-switch": [ - "warn", - { - "emptyDefaultCase": "do-nothing-comment" - } - ], + // "unicorn/prefer-switch": [ // not yet implemented + // "warn", + // { + // "emptyDefaultCase": "do-nothing-comment" + // } + // ], "unicorn/prefer-top-level-await": "off", - // "unicorn/prevent-abbreviations": "off", + "unicorn/prevent-abbreviations": "off", "unicorn/switch-case-braces": ["error", "avoid"], "unicorn/text-encoding-identifier-case": "off", // #endregion @@ -510,12 +469,12 @@ // #region --- import sorting --- // oxfmt also handles import sorting "sort-imports": "off", - // "import-x/order": "off", + "import-x/order": "off", "simple-import-sort/imports": "error", // oxc doesn't sort named imports yet https://github.com/oxc-project/oxc/issues/13610 "simple-import-sort/exports": "error", "import-x/first": "error", - "import-x-js/newline-after-import": "error", // use jsPlugins + "import-x-js/newline-after-import": "error", // oxc native not yet implemented "no-duplicate-imports": "off", "import-x/no-duplicates": "error", diff --git a/eslint.config.mjs b/eslint.config.mjs index e1637cb97180..76ce19cbefdd 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,26 +1,43 @@ import js from '@eslint/js'; +import stylistic from '@stylistic/eslint-plugin'; import typescriptEslint from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; // import { importX } from 'eslint-plugin-import-x'; +import n from 'eslint-plugin-n'; // import simpleImportSort from 'eslint-plugin-simple-import-sort'; +import unicorn from 'eslint-plugin-unicorn'; import eslintPluginYml from 'eslint-plugin-yml'; import { defineConfig } from 'eslint/config'; import globals from 'globals'; +// import github from './eslint-plugins/no-then.js'; +// import nsfwFlagPlugin from './eslint-plugins/nsfw-flag.js'; + const SOURCE_FILES_GLOB = '**/*.?([cm])[jt]s?(x)'; export default defineConfig([ + // { + // plugins: { + // '@rsshub/nsfw-flag': nsfwFlagPlugin, + // }, + // rules: { + // '@rsshub/nsfw-flag/add-nsfw-flag': 'error', + // }, + // }, { ignores: ['**/coverage', '**/.vscode', '**/docker-compose.yml', '!.github', 'assets/build', 'lib/routes-deprecated', 'lib/router.js', 'dist', 'dist-lib', 'dist-worker'], }, { files: [SOURCE_FILES_GLOB], plugins: { + '@stylistic': stylistic, '@typescript-eslint': typescriptEslint, // github, js, + n, + unicorn, }, - // extends: [typescriptEslint.configs['flat/recommended'], typescriptEslint.configs['flat/stylistic'], n.configs['flat/recommended-script']], + // extends: [js.configs.recommended, typescriptEslint.configs['flat/recommended'], typescriptEslint.configs['flat/stylistic'], n.configs['flat/recommended-script'], unicorn.configs.recommended], languageOptions: { globals: { @@ -38,6 +55,101 @@ export default defineConfig([ }, rules: { + // #region possible problems + /* + 'array-callback-return': ['error', { allowImplicit: true }], + + 'no-await-in-loop': 'error', + 'no-control-regex': 'off', + 'no-prototype-builtins': 'off', + */ + // #endregion + + // #region suggestions + /* + 'arrow-body-style': 'error', + 'block-scoped-var': 'error', + curly: 'error', + 'dot-notation': 'error', + eqeqeq: 'error', + + 'default-case': ['warn', { commentPattern: '^no default$' }], + + 'default-case-last': 'error', + 'no-console': 'error', + 'no-eval': 'error', + 'no-extend-native': 'error', + 'no-extra-label': 'error', + + 'no-implicit-coercion': [ + 'error', + { + boolean: false, + number: false, + string: false, + disallowTemplateShorthand: true, + }, + ], + + 'no-implicit-globals': 'error', + 'no-labels': 'error', + 'no-lonely-if': 'error', + 'no-multi-str': 'error', + 'no-new-func': 'error', + */ + 'no-restricted-syntax': [ + 'error', + { + selector: "CallExpression[callee.property.name='get'][arguments.length=0]", + message: 'Please use .toArray() instead.', + }, + { + selector: "CallExpression[callee.property.name='toArray'] MemberExpression[object.callee.property.name='map']", + message: 'Please use .toArray() before .map().', + }, + { + selector: 'CallExpression[callee.property.name="catch"] > ArrowFunctionExpression[params.length=0][body.value=null]', + message: 'Usage of .catch(() => null) is not allowed. Please handle the error appropriately.', + }, + { + selector: 'CallExpression[callee.property.name="catch"] > ArrowFunctionExpression[params.length=0][body.type="Identifier"][body.name="undefined"]', + message: 'Usage of .catch(() => undefined) is not allowed. Please handle the error appropriately.', + }, + { + selector: 'CallExpression[callee.property.name="catch"] > ArrowFunctionExpression[params.length=0] > ArrayExpression[elements.length=0]', + message: 'Usage of .catch(() => []) is not allowed. Please handle the error appropriately.', + }, + { + selector: 'CallExpression[callee.property.name="catch"] > ArrowFunctionExpression[params.length=0] > BlockStatement[body.length=0]', + message: 'Usage of .catch(() => {}) is not allowed. Please handle the error appropriately.', + }, + { + selector: 'CallExpression[callee.name="load"] AwaitExpression > CallExpression', + message: 'Do not use await in call expressions. Extract the result into a variable first.', + }, + ], + /* + 'no-unneeded-ternary': 'error', + 'no-useless-computed-key': 'error', + 'no-useless-concat': 'warn', + 'no-useless-rename': 'error', + 'no-var': 'error', + 'object-shorthand': 'error', + 'prefer-arrow-callback': 'error', + 'prefer-const': 'error', + 'prefer-object-has-own': 'error', + + 'prefer-regex-literals': [ + 'error', + { + disallowRedundantWrapping: true, + }, + ], + + 'require-await': 'error', + */ + // #endregion + // #region typescript /* '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], @@ -53,6 +165,136 @@ export default defineConfig([ '@typescript-eslint/no-unused-vars': ['error', { args: 'after-used', argsIgnorePattern: '^_' }], */ // #endregion + + // #region unicorn + /* + 'unicorn/consistent-function-scoping': 'warn', + 'unicorn/explicit-length-check': 'off', + + 'unicorn/filename-case': [ + 'error', + { + case: 'kebabCase', + ignore: [String.raw`.*\.(yaml|yml)$`, String.raw`RequestInProgress\.js$`], + }, + ], + + 'unicorn/no-array-callback-reference': 'warn', + 'unicorn/no-array-reduce': 'warn', + 'unicorn/no-array-sort': 'warn', + 'unicorn/no-await-expression-member': 'off', + 'unicorn/no-empty-file': 'warn', + 'unicorn/no-for-loop': 'off', + 'unicorn/no-hex-escape': 'warn', + 'unicorn/no-nested-ternary': 'off', + 'unicorn/no-null': 'off', + 'unicorn/no-object-as-default-parameter': 'warn', + 'unicorn/no-process-exit': 'off', + 'unicorn/no-useless-switch-case': 'off', + + 'unicorn/no-useless-undefined': ['error', { checkArguments: false }], + + 'unicorn/number-literal-case': 'off', + + 'unicorn/numeric-separators-style': [ + 'warn', + { + onlyIfContainsSeparator: false, + + number: { + minimumDigits: 7, + groupLength: 3, + }, + + binary: { + minimumDigits: 9, + groupLength: 4, + }, + + octal: { + minimumDigits: 9, + groupLength: 4, + }, + + hexadecimal: { + minimumDigits: 5, + groupLength: 2, + }, + }, + ], + + 'unicorn/prefer-code-point': 'warn', + 'unicorn/prefer-global-this': 'off', + 'unicorn/prefer-import-meta-properties': 'warn', + 'unicorn/prefer-module': 'off', + + 'unicorn/prefer-number-properties': ['error', { checkInfinity: false, checkNaN: false }], + + 'unicorn/prefer-spread': 'warn', + 'unicorn/prefer-string-slice': 'warn', + + 'unicorn/prefer-switch': [ + 'warn', + { + emptyDefaultCase: 'do-nothing-comment', + }, + ], + + 'unicorn/prefer-top-level-await': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/switch-case-braces': ['error', 'avoid'], + 'unicorn/text-encoding-identifier-case': 'off', + */ + // #endregion + + // #region stylistic + /* + '@stylistic/arrow-parens': 'error', + '@stylistic/arrow-spacing': 'error', + '@stylistic/comma-spacing': 'error', + '@stylistic/comma-style': 'error', + '@stylistic/function-call-spacing': 'error', + '@stylistic/keyword-spacing': 'off', + '@stylistic/linebreak-style': 'error', + + '@stylistic/lines-around-comment': ['error', { beforeBlockComment: false }], + + '@stylistic/no-multiple-empty-lines': 'error', + '@stylistic/no-trailing-spaces': 'error', + '@stylistic/rest-spread-spacing': 'error', + '@stylistic/semi': 'error', + '@stylistic/space-before-blocks': 'error', + '@stylistic/space-in-parens': 'error', + '@stylistic/space-infix-ops': 'error', + '@stylistic/space-unary-ops': 'error', + '@stylistic/spaced-comment': 'error', + */ + // #endregion + + // #region node specific rules + /* + 'n/no-extraneous-require': 'error', + 'n/no-deprecated-api': 'warn', + 'n/no-missing-import': 'off', + 'n/no-missing-require': 'off', + 'n/no-process-exit': 'off', + 'n/no-unpublished-import': 'off', + + 'n/no-unpublished-require': ['error', { allowModules: ['tosource'] }], + + 'n/no-unsupported-features/node-builtins': [ + 'error', + { + version: '^22.20.0 || ^24', + allowExperimental: true, + ignores: [], + }, + ], + */ + // #endregion + + // github + // 'github/no-then': 'warn', }, }, { diff --git a/flake.lock b/flake.lock index 5589a4b9f522..cdfc46ed3ba8 100644 --- a/flake.lock +++ b/flake.lock @@ -19,11 +19,11 @@ ] }, "locked": { - "lastModified": 1767714506, - "narHash": "sha256-WaTs0t1CxhgxbIuvQ97OFhDTVUGd1HA+KzLZUZBhe0s=", + "lastModified": 1760971495, + "narHash": "sha256-IwnNtbNVrlZIHh7h4Wz6VP0Furxg9Hh0ycighvL5cZc=", "owner": "cachix", "repo": "cachix", - "rev": "894c649f0daaa38bbcfb21de64be47dfa7cd0ec9", + "rev": "c5bfd933d1033672f51a863c47303fc0e093c2d2", "type": "github" }, "original": { @@ -33,141 +33,21 @@ "type": "github" } }, - "cachix_2": { - "inputs": { - "devenv": [ - "devenv", - "crate2nix" - ], - "flake-compat": [ - "devenv", - "crate2nix" - ], - "git-hooks": "git-hooks", - "nixpkgs": "nixpkgs" - }, - "locked": { - "lastModified": 1767714506, - "narHash": "sha256-WaTs0t1CxhgxbIuvQ97OFhDTVUGd1HA+KzLZUZBhe0s=", - "owner": "cachix", - "repo": "cachix", - "rev": "894c649f0daaa38bbcfb21de64be47dfa7cd0ec9", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "cachix_3": { - "inputs": { - "devenv": [ - "devenv", - "crate2nix", - "crate2nix_stable" - ], - "flake-compat": [ - "devenv", - "crate2nix", - "crate2nix_stable" - ], - "git-hooks": "git-hooks_2", - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1767714506, - "narHash": "sha256-WaTs0t1CxhgxbIuvQ97OFhDTVUGd1HA+KzLZUZBhe0s=", - "owner": "cachix", - "repo": "cachix", - "rev": "894c649f0daaa38bbcfb21de64be47dfa7cd0ec9", - "type": "github" - }, - "original": { - "owner": "cachix", - "ref": "latest", - "repo": "cachix", - "type": "github" - } - }, - "crate2nix": { - "inputs": { - "cachix": "cachix_2", - "crate2nix_stable": "crate2nix_stable", - "devshell": "devshell_2", - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts_2", - "nix-test-runner": "nix-test-runner_2", - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "pre-commit-hooks": "pre-commit-hooks_2" - }, - "locked": { - "lastModified": 1772186516, - "narHash": "sha256-8s28pzmQ6TOIUzznwFibtW1CMieMUl1rYJIxoQYor58=", - "owner": "rossng", - "repo": "crate2nix", - "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e", - "type": "github" - }, - "original": { - "owner": "rossng", - "repo": "crate2nix", - "rev": "ba5dd398e31ee422fbe021767eb83b0650303a6e", - "type": "github" - } - }, - "crate2nix_stable": { - "inputs": { - "cachix": "cachix_3", - "crate2nix_stable": [ - "devenv", - "crate2nix", - "crate2nix_stable" - ], - "devshell": "devshell", - "flake-compat": "flake-compat", - "flake-parts": "flake-parts", - "nix-test-runner": "nix-test-runner", - "nixpkgs": "nixpkgs_3", - "pre-commit-hooks": "pre-commit-hooks" - }, - "locked": { - "lastModified": 1769627083, - "narHash": "sha256-SUuruvw1/moNzCZosHaa60QMTL+L9huWdsCBN6XZIic=", - "owner": "nix-community", - "repo": "crate2nix", - "rev": "7c33e664668faecf7655fa53861d7a80c9e464a2", - "type": "github" - }, - "original": { - "owner": "nix-community", - "ref": "0.15.0", - "repo": "crate2nix", - "type": "github" - } - }, "devenv": { "inputs": { "cachix": "cachix", - "crate2nix": "crate2nix", - "flake-compat": "flake-compat_3", - "flake-parts": "flake-parts_3", - "git-hooks": "git-hooks_3", + "flake-compat": "flake-compat", + "flake-parts": "flake-parts", + "git-hooks": "git-hooks", "nix": "nix", - "nixd": "nixd", - "nixpkgs": "nixpkgs_4", - "rust-overlay": "rust-overlay" + "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1775803833, - "narHash": "sha256-mx/CJShwE4b5CyU106ls3Jiw9fK4kyPoTLmta/cV5iM=", + "lastModified": 1764368166, + "narHash": "sha256-FktN7dtYlC/sgLGBCGFXzNOvwgB7MSujp6cooJE48Ac=", "owner": "cachix", "repo": "devenv", - "rev": "d4410df5bf2213111d3c7598b09e49176cd772d9", + "rev": "47a243b97499bfe5d5783d1fc86d9fe776b2497f", "type": "github" }, "original": { @@ -176,87 +56,14 @@ "type": "github" } }, - "devshell": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1768818222, - "narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=", - "owner": "numtide", - "repo": "devshell", - "rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, - "devshell_2": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1768818222, - "narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=", - "owner": "numtide", - "repo": "devshell", - "rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, "flake-compat": { - "locked": { - "lastModified": 1733328505, - "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", - "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", - "revCount": 69, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_2": { - "locked": { - "lastModified": 1733328505, - "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", - "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", - "revCount": 69, - "type": "tarball", - "url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.1.0/01948eb7-9cba-704f-bbf3-3fa956735b52/source.tar.gz" - }, - "original": { - "type": "tarball", - "url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz" - } - }, - "flake-compat_3": { "flake": false, "locked": { - "lastModified": 1767039857, - "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "lastModified": 1761588595, + "narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=", "owner": "edolstra", "repo": "flake-compat", - "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5", "type": "github" }, "original": { @@ -269,60 +76,15 @@ "inputs": { "nixpkgs-lib": [ "devenv", - "crate2nix", - "crate2nix_stable", "nixpkgs" ] }, "locked": { - "lastModified": 1768135262, - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", + "lastModified": 1760948891, + "narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_2": { - "inputs": { - "nixpkgs-lib": [ - "devenv", - "crate2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1768135262, - "narHash": "sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "80daad04eddbbf5a4d883996a73f3f542fa437ac", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "flake-parts_3": { - "inputs": { - "nixpkgs-lib": [ - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1772408722, - "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04", "type": "github" }, "original": { @@ -353,82 +115,20 @@ "inputs": { "flake-compat": [ "devenv", - "crate2nix", - "cachix", "flake-compat" ], "gitignore": "gitignore", "nixpkgs": [ "devenv", - "crate2nix", - "cachix", "nixpkgs" ] }, "locked": { - "lastModified": 1765404074, - "narHash": "sha256-+ZDU2d+vzWkEJiqprvV5PR26DVFN2vgddwG5SnPZcUM=", + "lastModified": 1760663237, + "narHash": "sha256-BflA6U4AM1bzuRMR8QqzPXqh8sWVCNDzOdsxXEguJIc=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "2d6f58930fbcd82f6f9fd59fb6d13e37684ca529", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "git-hooks_2": { - "inputs": { - "flake-compat": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "cachix", - "flake-compat" - ], - "gitignore": "gitignore_2", - "nixpkgs": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "cachix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1765404074, - "narHash": "sha256-+ZDU2d+vzWkEJiqprvV5PR26DVFN2vgddwG5SnPZcUM=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "2d6f58930fbcd82f6f9fd59fb6d13e37684ca529", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "git-hooks_3": { - "inputs": { - "flake-compat": [ - "devenv", - "flake-compat" - ], - "gitignore": "gitignore_5", - "nixpkgs": [ - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1772893680, - "narHash": "sha256-JDqZMgxUTCq85ObSaFw0HhE+lvdOre1lx9iI6vYyOEs=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "8baab586afc9c9b57645a734c820e4ac0a604af9", + "rev": "ca5b894d3e3e151ffc1db040b6ce4dcc75d31c37", "type": "github" }, "original": { @@ -438,102 +138,6 @@ } }, "gitignore": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "cachix", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_2": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "cachix", - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_3": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_4": { - "inputs": { - "nixpkgs": [ - "devenv", - "crate2nix", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_5": { "inputs": { "nixpkgs": [ "devenv", @@ -581,153 +185,27 @@ ] }, "locked": { - "lastModified": 1775657489, - "narHash": "sha256-v1KwZrIMGpteHPwxXvbapc7o3iduhU61phPUfyrnjM8=", + "lastModified": 1761648602, + "narHash": "sha256-H97KSB/luq/aGobKRuHahOvT1r7C03BgB6D5HBZsbN8=", "owner": "cachix", "repo": "nix", - "rev": "5c0da4397902105a84611c6d49e9d39a618ca025", + "rev": "3e5644da6830ef65f0a2f7ec22830c46285bfff6", "type": "github" }, "original": { "owner": "cachix", - "ref": "devenv-2.34", + "ref": "devenv-2.30.6", "repo": "nix", "type": "github" } }, - "nix-test-runner": { - "flake": false, - "locked": { - "lastModified": 1588761593, - "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=", - "owner": "stoeffel", - "repo": "nix-test-runner", - "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2", - "type": "github" - }, - "original": { - "owner": "stoeffel", - "repo": "nix-test-runner", - "type": "github" - } - }, - "nix-test-runner_2": { - "flake": false, - "locked": { - "lastModified": 1588761593, - "narHash": "sha256-FKJykltAN/g3eIceJl4SfDnnyuH2jHImhMrXS2KvGIs=", - "owner": "stoeffel", - "repo": "nix-test-runner", - "rev": "c45d45b11ecef3eb9d834c3b6304c05c49b06ca2", - "type": "github" - }, - "original": { - "owner": "stoeffel", - "repo": "nix-test-runner", - "type": "github" - } - }, - "nixd": { - "inputs": { - "flake-parts": [ - "devenv", - "flake-parts" - ], - "nixpkgs": [ - "devenv", - "nixpkgs" - ], - "treefmt-nix": "treefmt-nix" - }, - "locked": { - "lastModified": 1773634079, - "narHash": "sha256-49qb4QNMv77VOeEux+sMd0uBhPvvHgVc0r938Bulvbo=", - "owner": "nix-community", - "repo": "nixd", - "rev": "8ecf93d4d93745e05ea53534e8b94f5e9506e6bd", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixd", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1765186076, - "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-src": { - "flake": false, - "locked": { - "lastModified": 1773597492, - "narHash": "sha256-hQ284SkIeNaeyud+LS0WVLX+WL2rxcVZLFEaK0e03zg=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "a07d4ce6bee67d7c838a8a5796e75dff9caa21ef", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1765186076, - "narHash": "sha256-hM20uyap1a0M9d344I692r+ik4gTMyj60cQWO+hAYP8=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "addf7cf5f383a3101ecfba091b98d0a1263dc9b8", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_3": { - "locked": { - "lastModified": 1769433173, - "narHash": "sha256-Gf1dFYgD344WZ3q0LPlRoWaNdNQq8kSBDLEWulRQSEs=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "13b0f9e6ac78abbbb736c635d87845c4f4bee51b", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_4": { - "inputs": { - "nixpkgs-src": "nixpkgs-src" - }, - "locked": { - "lastModified": 1773704619, - "narHash": "sha256-LKtmit8Sr81z8+N2vpIaN/fyiQJ8f7XJ6tMSKyDVQ9s=", + "lastModified": 1761313199, + "narHash": "sha256-wCIACXbNtXAlwvQUo1Ed++loFALPjYUA3dpcUJiXO44=", "owner": "cachix", "repo": "devenv-nixpkgs", - "rev": "906534d75b0e2fe74a719559dfb1ad3563485f43", + "rev": "d1c30452ebecfc55185ae6d1c983c09da0c274ff", "type": "github" }, "original": { @@ -737,13 +215,13 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_2": { "locked": { - "lastModified": 1775710090, - "narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=", + "lastModified": 1764242076, + "narHash": "sha256-sKoIWfnijJ0+9e4wRvIgm/HgE27bzwQxcEmo2J/gNpI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4c1018dae018162ec878d42fec712642d214fdfa", + "rev": "2fad6eac6077f03fe109c4d4eb171cf96791faa4", "type": "github" }, "original": { @@ -753,90 +231,11 @@ "type": "github" } }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "flake-compat" - ], - "gitignore": "gitignore_3", - "nixpkgs": [ - "devenv", - "crate2nix", - "crate2nix_stable", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1769069492, - "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "pre-commit-hooks_2": { - "inputs": { - "flake-compat": [ - "devenv", - "crate2nix", - "flake-compat" - ], - "gitignore": "gitignore_4", - "nixpkgs": [ - "devenv", - "crate2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1769069492, - "narHash": "sha256-Efs3VUPelRduf3PpfPP2ovEB4CXT7vHf8W+xc49RL/U=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "a1ef738813b15cf8ec759bdff5761b027e3e1d23", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, "root": { "inputs": { "devenv": "devenv", "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs_5" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": [ - "devenv", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1773630837, - "narHash": "sha256-zJhgAGnbVKeBMJOb9ctZm4BGS/Rnrz+5lfSXTVah4HQ=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "f600ea449c7b5bb596fa1cf21c871cc5b9e31316", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" + "nixpkgs": "nixpkgs_2" } }, "systems": { @@ -853,28 +252,6 @@ "repo": "default", "type": "github" } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "devenv", - "nixd", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1772660329, - "narHash": "sha256-IjU1FxYqm+VDe5qIOxoW+pISBlGvVApRjiw/Y/ttJzY=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "3710e0e1218041bbad640352a0440114b1e10428", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b2422bf5d285..563a42c91332 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,7 @@ deps = pkgs.fetchPnpmDeps { pname = "rsshub"; src = ./.; - hash = "sha256-Q7plMp6xtB7tnTyRu2/ik8pY0kXt82BLNBQ3lG3dHSo="; + hash = "sha256-QG1cIkZh+qBA5Dipt0iDLuQpEOI45wdFhuG/CTcRVU8="; fetcherVersion = 2; }; in diff --git a/lib/app-bootstrap.test.tsx b/lib/app-bootstrap.test.tsx index 980c9355ec50..69facc57e574 100644 --- a/lib/app-bootstrap.test.tsx +++ b/lib/app-bootstrap.test.tsx @@ -8,14 +8,6 @@ vi.mock('@/utils/logger', () => ({ }, })); -vi.mock('@honeybadger-io/js', () => ({ - default: { - configure: vi.fn(), - notify: vi.fn(), - setContext: vi.fn(), - }, -})); - describe('app-bootstrap', () => { it('logs uncaught exceptions', async () => { const before = new Set(process.listeners('uncaughtException')); diff --git a/lib/app-bootstrap.tsx b/lib/app-bootstrap.tsx index 25468be6864f..c1bd50bc1811 100644 --- a/lib/app-bootstrap.tsx +++ b/lib/app-bootstrap.tsx @@ -10,7 +10,6 @@ import antiHotlink from '@/middleware/anti-hotlink'; import cache from '@/middleware/cache'; import debug from '@/middleware/debug'; import header from '@/middleware/header'; -import honeybadger from '@/middleware/honeybadger'; import mLogger from '@/middleware/logger'; import parameter from '@/middleware/parameter'; import sentry from '@/middleware/sentry'; @@ -36,7 +35,6 @@ app.use( ); app.use(mLogger); app.use(trace); -app.use(honeybadger); app.use(sentry); app.use(accessControl); app.use(debug); diff --git a/lib/app.test.ts b/lib/app.test.ts index 88ba65138338..185cc6f620f1 100644 --- a/lib/app.test.ts +++ b/lib/app.test.ts @@ -3,6 +3,8 @@ import { describe, expect, it, vi } from 'vitest'; import app from '@/app'; +const { config } = await import('@/config'); + describe('index', () => { it('serve index', async () => { const res = await app.request('/'); @@ -18,6 +20,6 @@ describe('request-rewriter', () => { // headers const headers: Headers = fetchSpy.mock.lastCall?.[0].headers; - expect(headers.get('user-agent')).toMatch(/Chrome/); + expect(headers.get('user-agent')).toBe(config.ua); }); }); diff --git a/lib/app.worker.tsx b/lib/app.worker.tsx index cd704587579c..d8c96848d56f 100644 --- a/lib/app.worker.tsx +++ b/lib/app.worker.tsx @@ -52,7 +52,6 @@ app.use(mLogger); app.use(trace); // Heavy middleware excluded in Worker build: -// - honeybadger: @honeybadger-io/js // - sentry: @sentry/node // - antiHotlink: cheerio // - parameter: cheerio, sanitize-html, @jocmp/mercury-parser diff --git a/lib/config.test.ts b/lib/config.test.ts index 02010cb5d417..c5f79d68d1ea 100644 --- a/lib/config.test.ts +++ b/lib/config.test.ts @@ -84,11 +84,9 @@ describe('config', () => { delete process.env.NO_RANDOM_UA; }); - it('default ua from preset', async () => { + it('random ua', async () => { const { config } = await import('./config'); - expect(config.ua).toContain('Chrome'); - expect(config.ua).toContain('Macintosh'); - expect(config.isDefaultUA).toBe(true); + expect(config.ua).not.toBe('RSSHub/1.0 (+http://github.com/DIYgod/RSSHub; like FeedFetcher-Google)'); }); it('remote config', async () => { diff --git a/lib/config.ts b/lib/config.ts index 9ba567508c9e..61e5204f8872 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -48,8 +48,6 @@ type ConfigEnvKeys = | 'OTEL_SECONDS_BUCKET' | 'OTEL_MILLISECONDS_BUCKET' | 'SHOW_LOGGER_TIMESTAMP' - | 'HONEYBADGER_API_KEY' - | 'ERROR_TRACKING_ROUTE_TIMEOUT' | 'SENTRY' | 'SENTRY_ROUTE_TIMEOUT' | 'ENABLE_REMOTE_DEBUGGING' @@ -133,7 +131,7 @@ type ConfigEnvKeys = | 'JUMEILI_COOKIE' | 'KEYLOL_COOKIE' | 'LASTFM_API_KEY' - | 'LOCALS_SESSION' + | 'SECURITY_KEY' | 'LOFTER_COOKIE' | 'LORIENTLEJOUR_TOKEN' | 'LORIENTLEJOUR_USERNAME' @@ -184,7 +182,6 @@ type ConfigEnvKeys = | 'SCIHUB_HOST' | 'SDO_FF14RISINGSTONES' | 'SDO_UA' - | 'SECURITY_KEY' | 'SIS001_BASE_URL' | 'SKEB_BEARER_TOKEN' | 'SORRYCC_COOKIES' @@ -266,7 +263,6 @@ export type Config = { requestRetry: number; requestTimeout: number; ua: string; - isDefaultUA: boolean; trueUA: string; allowOrigin?: string; // cache @@ -308,13 +304,10 @@ export type Config = { milliseconds_bucket?: string; }; showLoggerTimestamp?: boolean; - honeybadger: { - apiKey?: string; - }; sentry: { dsn?: string; + routeTimeout: number; }; - errorTrackingRouteTimeout: number; enableRemoteDebugging?: boolean; // feed config hotlink: { @@ -476,9 +469,6 @@ export type Config = { lightnovel: { cookie?: string; }; - locals: { - session?: string; - }; lofter: { cookies?: string; }; @@ -754,8 +744,7 @@ const calculateValue = () => { listenInaddrAny: toBoolean(envs.LISTEN_INADDR_ANY, true), // 是否允许公网连接,取值 0 1 requestRetry: toInt(envs.REQUEST_RETRY, 2), // 请求失败重试次数 requestTimeout: toInt(envs.REQUEST_TIMEOUT, 30000), // Milliseconds to wait for the server to end the response before aborting the request - ua: envs.UA || (toBoolean(envs.NO_RANDOM_UA, false) ? TRUE_UA : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 15_6_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'), - isDefaultUA: !envs.UA && !toBoolean(envs.NO_RANDOM_UA, false), + ua: envs.UA ?? (toBoolean(envs.NO_RANDOM_UA, false) ? TRUE_UA : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 15_6_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'), trueUA: TRUE_UA, allowOrigin: envs.ALLOW_ORIGIN, // cache @@ -803,13 +792,10 @@ const calculateValue = () => { milliseconds_bucket: envs.OTEL_MILLISECONDS_BUCKET || '10,20,50,100,250,500,1000,5000,15000', }, showLoggerTimestamp: toBoolean(envs.SHOW_LOGGER_TIMESTAMP, false), - honeybadger: { - apiKey: envs.HONEYBADGER_API_KEY, - }, sentry: { dsn: envs.SENTRY, + routeTimeout: toInt(envs.SENTRY_ROUTE_TIMEOUT, 30000), }, - errorTrackingRouteTimeout: toInt(envs.ERROR_TRACKING_ROUTE_TIMEOUT || envs.SENTRY_ROUTE_TIMEOUT, 30000), enableRemoteDebugging: toBoolean(envs.ENABLE_REMOTE_DEBUGGING, false), // feed config hotlink: { @@ -971,9 +957,6 @@ const calculateValue = () => { lightnovel: { cookie: envs.SECURITY_KEY, }, - locals: { - session: envs.LOCALS_SESSION, - }, lofter: { cookies: envs.LOFTER_COOKIE, }, diff --git a/lib/errors/honeybadger.test.ts b/lib/errors/honeybadger.test.ts deleted file mode 100644 index c59d26ceb60c..000000000000 --- a/lib/errors/honeybadger.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { describe, expect, it, vi } from 'vitest'; - -const notify = vi.fn(); - -vi.mock('@honeybadger-io/js', () => ({ - default: { notify }, -})); - -vi.mock('@sentry/node', () => ({ - withScope: vi.fn(), - captureException: vi.fn(), -})); - -vi.mock('hono/route', () => ({ - routePath: () => '/test/path', -})); - -vi.mock('@/utils/logger', () => ({ - default: { - error: vi.fn(), - }, -})); - -vi.mock('@/utils/otel', () => ({ - requestMetric: { - error: vi.fn(), - }, -})); - -describe('error handler honeybadger', () => { - it('sends errors to honeybadger when enabled', async () => { - process.env.HONEYBADGER_API_KEY = 'hbp_test_key'; - vi.resetModules(); - - // Re-mock after resetModules - vi.doMock('@honeybadger-io/js', () => ({ - default: { notify }, - })); - vi.doMock('@sentry/node', () => ({ - withScope: vi.fn(), - captureException: vi.fn(), - })); - vi.doMock('hono/route', () => ({ - routePath: () => '/test/path', - })); - vi.doMock('@/utils/logger', () => ({ - default: { error: vi.fn() }, - })); - vi.doMock('@/utils/otel', () => ({ - requestMetric: { error: vi.fn() }, - })); - - const { errorHandler } = await import('@/errors'); - - const ctx = { - req: { - path: '/test/path', - method: 'GET', - query: () => 'json', - }, - res: { - status: 500, - headers: new Headers(), - }, - status: vi.fn(), - header: vi.fn(), - json: (payload: unknown) => payload, - html: (payload: unknown) => payload, - }; - - errorHandler(new Error('boom'), ctx as any); - - expect(notify).toHaveBeenCalledWith(expect.any(Error), { - context: { name: 'test' }, - }); - - delete process.env.HONEYBADGER_API_KEY; - }); -}); diff --git a/lib/errors/index.tsx b/lib/errors/index.tsx index b78603815c00..c8ae927edb5f 100644 --- a/lib/errors/index.tsx +++ b/lib/errors/index.tsx @@ -1,4 +1,3 @@ -import Honeybadger from '@honeybadger-io/js'; import * as Sentry from '@sentry/node'; import type { ErrorHandler, NotFoundHandler } from 'hono'; import { routePath } from 'hono/route'; @@ -37,12 +36,6 @@ export const errorHandler: ErrorHandler = (error, ctx) => { hasMatchedRoute && debug.errorRoutes[matchedRoute]++; setDebugInfo(debug); - if (config.honeybadger.apiKey) { - Honeybadger.notify(error, { - context: { name: requestPath.split('/')[1] }, - }); - } - if (config.sentry.dsn) { Sentry.withScope((scope) => { scope.setTag('name', requestPath.split('/')[1]); diff --git a/lib/middleware/honeybadger.test.ts b/lib/middleware/honeybadger.test.ts deleted file mode 100644 index 5c20ea4b7a85..000000000000 --- a/lib/middleware/honeybadger.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest'; - -afterEach(() => { - vi.resetModules(); - vi.restoreAllMocks(); - vi.unmock('@/config'); - vi.unmock('@/utils/helpers'); - vi.unmock('@/utils/logger'); - vi.unmock('@honeybadger-io/js'); -}); - -describe('honeybadger middleware', () => { - const loadMiddleware = async () => { - const honeybadger = { - configure: vi.fn(), - setContext: vi.fn(), - notify: vi.fn(), - }; - const logger = { - info: vi.fn(), - }; - const getRouteNameFromPath = vi.fn((path: string) => `route:${path}`); - - vi.doMock('@honeybadger-io/js', () => ({ - default: honeybadger, - })); - vi.doMock('@/utils/logger', () => ({ - default: logger, - })); - vi.doMock('@/utils/helpers', () => ({ - getRouteNameFromPath, - })); - vi.doMock('@/config', () => ({ - config: { - honeybadger: { - apiKey: 'hbp_test_key', - }, - errorTrackingRouteTimeout: 50, - nodeName: 'node-a', - }, - })); - - const { default: middleware } = await import('@/middleware/honeybadger'); - - return { middleware, honeybadger, logger, getRouteNameFromPath }; - }; - - it('initializes honeybadger and captures slow routes', async () => { - const { middleware, honeybadger, logger, getRouteNameFromPath } = await loadMiddleware(); - - expect(honeybadger.configure).toHaveBeenCalledWith({ - apiKey: 'hbp_test_key', - enableUncaught: false, - }); - expect(honeybadger.setContext).toHaveBeenCalledWith({ node_name: 'node-a' }); - expect(logger.info).toHaveBeenCalledWith('Honeybadger inited.'); - - const nowSpy = vi.spyOn(Date, 'now'); - nowSpy.mockReturnValueOnce(0).mockReturnValueOnce(100); - - await middleware({ req: { path: '/test/slow' } } as any, async () => {}); - - expect(getRouteNameFromPath).toHaveBeenCalledWith('/test/slow'); - expect(honeybadger.notify).toHaveBeenCalledTimes(1); - expect(honeybadger.notify).toHaveBeenCalledWith(expect.any(Error), { - context: { name: 'route:/test/slow' }, - }); - }); -}); diff --git a/lib/middleware/honeybadger.ts b/lib/middleware/honeybadger.ts deleted file mode 100644 index bf7675f6e8cb..000000000000 --- a/lib/middleware/honeybadger.ts +++ /dev/null @@ -1,28 +0,0 @@ -import Honeybadger from '@honeybadger-io/js'; -import type { MiddlewareHandler } from 'hono'; - -import { config } from '@/config'; -import { getRouteNameFromPath } from '@/utils/helpers'; -import logger from '@/utils/logger'; - -if (config.honeybadger.apiKey) { - Honeybadger.configure({ - apiKey: config.honeybadger.apiKey, - enableUncaught: false, - }); - Honeybadger.setContext({ node_name: config.nodeName }); - - logger.info('Honeybadger inited.'); -} - -const middleware: MiddlewareHandler = async (ctx, next) => { - const time = Date.now(); - await next(); - if (config.honeybadger.apiKey && Date.now() - time >= config.errorTrackingRouteTimeout) { - Honeybadger.notify(new Error('Route Timeout'), { - context: { name: getRouteNameFromPath(ctx.req.path) }, - }); - } -}; - -export default middleware; diff --git a/lib/middleware/sentry.test.ts b/lib/middleware/sentry.test.ts index 50c88bac0050..1b72733710f7 100644 --- a/lib/middleware/sentry.test.ts +++ b/lib/middleware/sentry.test.ts @@ -36,8 +36,8 @@ describe('sentry middleware', () => { config: { sentry: { dsn: 'https://sentry.example/123', + routeTimeout: 50, }, - errorTrackingRouteTimeout: 50, nodeName: 'node-a', }, })); diff --git a/lib/middleware/sentry.ts b/lib/middleware/sentry.ts index efc6f1679e7b..8c2952bbb951 100644 --- a/lib/middleware/sentry.ts +++ b/lib/middleware/sentry.ts @@ -17,7 +17,7 @@ if (config.sentry.dsn) { const middleware: MiddlewareHandler = async (ctx, next) => { const time = Date.now(); await next(); - if (config.sentry.dsn && Date.now() - time >= config.errorTrackingRouteTimeout) { + if (config.sentry.dsn && Date.now() - time >= config.sentry.routeTimeout) { Sentry.withScope((scope) => { scope.setTag('name', getRouteNameFromPath(ctx.req.path)); Sentry.captureException(new Error('Route Timeout')); diff --git a/lib/routes/18comic/album.ts b/lib/routes/18comic/album.ts index e7d423b7db85..575c71d72548 100644 --- a/lib/routes/18comic/album.ts +++ b/lib/routes/18comic/album.ts @@ -24,7 +24,7 @@ export const route: Route = { }, ], name: '专辑', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, url: 'jmcomic.group/', description: `::: tip diff --git a/lib/routes/18comic/blogs.ts b/lib/routes/18comic/blogs.ts index 0f127d966982..fff7f43756c1 100644 --- a/lib/routes/18comic/blogs.ts +++ b/lib/routes/18comic/blogs.ts @@ -27,7 +27,7 @@ export const route: Route = { }, ], name: '文庫', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, url: 'jmcomic.group/', description: `分类 diff --git a/lib/routes/18comic/index.ts b/lib/routes/18comic/index.ts index 433be226d3c8..d33f21dd680e 100644 --- a/lib/routes/18comic/index.ts +++ b/lib/routes/18comic/index.ts @@ -22,7 +22,7 @@ export const route: Route = { }, ], name: '成人 A 漫', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, url: 'jmcomic.group/', description: `分类 diff --git a/lib/routes/18comic/search.ts b/lib/routes/18comic/search.ts index 09ff46b5a1c5..3ada20123e9b 100644 --- a/lib/routes/18comic/search.ts +++ b/lib/routes/18comic/search.ts @@ -32,7 +32,7 @@ export const route: Route = { }, ], name: '搜索', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, url: 'jmcomic.group/', description: `::: tip diff --git a/lib/routes/8kcos/utils.ts b/lib/routes/8kcos/utils.ts index 237317eaec81..9bb08bc5b04c 100644 --- a/lib/routes/8kcos/utils.ts +++ b/lib/routes/8kcos/utils.ts @@ -19,7 +19,7 @@ export const getPosts = async (limit: number, options?: { categories?: number; t description: item.content.rendered, link: item.link, pubDate: parseDate(item.date_gmt), - author: item._embedded?.author?.map((a) => a.name).join(', '), + author: item._embedded?.['author']?.map((a) => a.name).join(', '), category: item._embedded?.['wp:term']?.flatMap((terms) => terms.map((t) => t.name)), })) satisfies DataItem[]; }; diff --git a/lib/routes/acfun/bangumi.ts b/lib/routes/acfun/bangumi.ts index 01be818d10df..b83c04319c1e 100644 --- a/lib/routes/acfun/bangumi.ts +++ b/lib/routes/acfun/bangumi.ts @@ -1,16 +1,14 @@ import type { Route } from '@/types'; import { ViewType } from '@/types'; -import ofetch from '@/utils/ofetch'; +import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; -import { renderDescription } from './templates/description'; - export const route: Route = { - path: '/bangumi/:id/:embed?', + path: '/bangumi/:id', categories: ['anime'], view: ViewType.Videos, - example: '/acfun/bangumi/6000617', - parameters: { id: '番剧 id', embed: '默认为开启内嵌视频, 任意值为关闭' }, + example: '/acfun/bangumi/5022158', + parameters: { id: '番剧 id' }, features: { requireConfig: false, requirePuppeteer: false, @@ -24,28 +22,31 @@ export const route: Route = { handler, description: `::: tip 番剧 id 不包含开头的 aa。 -例如:\`https://www.acfun.cn/bangumi/aa6000617\` 的番剧 id 是 6000617,不包括开头的 aa。 +例如:\`https://www.acfun.cn/bangumi/aa5022158\` 的番剧 id 是 5022158,不包括开头的 aa。 :::`, }; async function handler(ctx) { const id = ctx.req.param('id'); - const embed = !ctx.req.param('embed'); - const link = `https://www.acfun.cn/bangumi/aa${id}`; + const url = `https://www.acfun.cn/bangumi/aa${id}`; - const bangumiPage = await ofetch(link); - const bangumiData = JSON.parse(bangumiPage.match(/window.bangumiData = (.*?);\n/)[1]); - const bangumiList = JSON.parse(bangumiPage.match(/window.bangumiList = (.*?);\n/)[1]); + const bangumiPage = await got(url, { + headers: { + Referer: 'https://www.acfun.cn', + }, + }); + const bangumiData = JSON.parse(bangumiPage.data.match(/window.bangumiData = (.*?);\n/)[1]); + const bangumiList = JSON.parse(bangumiPage.data.match(/window.bangumiList = (.*?);\n/)[1]); return { title: bangumiData.bangumiTitle, - link, + link: url, description: bangumiData.bangumiIntro, image: bangumiData.belongResource.coverImageV, item: bangumiList.items.map((item) => ({ - title: `${item.episodeName}${item.title ? ` - ${item.title}` : ''}`, - description: renderDescription({ embed, aid: `ac${item.itemId}`, img: item.imgInfo.thumbnailImage.cdnUrls[0].url.split('?')[0] }), - link: `https://www.acfun.cn/bangumi/aa${id}_36188_${item.itemId}`, + title: `${item.episodeName} - ${item.title}`, + description: ``, + link: `http://www.acfun.cn/bangumi/aa${id}_36188_${item.itemId}`, pubDate: parseDate(item.updateTime, 'x'), })), }; diff --git a/lib/routes/acfun/templates/description.tsx b/lib/routes/acfun/templates/description.tsx deleted file mode 100644 index 04d48f07c198..000000000000 --- a/lib/routes/acfun/templates/description.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { renderToString } from 'hono/jsx/dom/server'; - -type DescriptionProps = { - embed: boolean; - aid: string; - img?: string; -}; - -const Description = ({ embed, aid, img }: DescriptionProps) => ( - <> - {embed ? ( - <> - -
- - ) : null} - {img ? : null} - -); - -export const renderDescription = (props: DescriptionProps): string => renderToString(); diff --git a/lib/routes/acfun/video.ts b/lib/routes/acfun/video.ts index 39ca0200be73..1c105702a3f0 100644 --- a/lib/routes/acfun/video.ts +++ b/lib/routes/acfun/video.ts @@ -2,13 +2,11 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import { ViewType } from '@/types'; -import ofetch from '@/utils/ofetch'; +import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; -import { renderDescription } from './templates/description'; - export const route: Route = { - path: '/user/video/:uid/:embed?', + path: '/user/video/:uid', radar: [ { source: ['www.acfun.cn/u/:id'], @@ -18,7 +16,6 @@ export const route: Route = { name: '用户投稿', parameters: { uid: '用户 UID', - embed: '默认为开启内嵌视频, 任意值为关闭', }, categories: ['anime'], example: '/acfun/user/video/6102', @@ -29,37 +26,39 @@ export const route: Route = { async function handler(ctx) { const uid = ctx.req.param('uid'); - const embed = !ctx.req.param('embed'); + const url = `https://www.acfun.cn/u/${uid}`; const host = 'https://www.acfun.cn'; - const link = `${host}/u/${uid}`; - const response = await ofetch(link); + const response = await got(url, { + headers: { + Referer: host, + }, + }); + const data = response.data; - const $ = load(response); + const $ = load(data); const title = $('title').text(); const description = $('.signature .complete').text(); const list = $('#ac-space-video-list a').toArray(); - const image = $('head style:contains("user-photo")') + const image = $('head style') .text() - .match(/.user-photo{\n\s*background:url\((.*)\) 0% 0% \/ 100% no-repeat;/)?.[1]; + .match(/.user-photo{\n\s*background:url\((.*)\) 0% 0% \/ 100% no-repeat;/)[1]; return { title, - link, + link: url, description, image, item: list.map((item) => { - const $item = $(item); + item = $(item); - const itemTitle = $item.find('p.title').text(); - const itemImg = $item.find('figure img').attr('src'); - const itemUrl = $item.attr('href')!; - const itemDate = $item.find('.date').text(); - const wbInfo = JSON.parse(($item.data('wb-info') as string) || '{}'); - const aid = wbInfo.atmid || wbInfo.mediaId || itemUrl.match(/\/v\/(ac\d+)/)?.[1]; + const itemTitle = item.find('p.title').text(); + const itemImg = item.find('figure img').attr('src'); + const itemUrl = item.attr('href'); + const itemDate = item.find('.date').text(); return { title: itemTitle, - description: renderDescription({ embed, aid, img: itemImg?.split('?')[0] }), + description: ``, link: host + itemUrl, pubDate: parseDate(itemDate, 'YYYY/MM/DD'), }; diff --git a/lib/routes/anthropic/research.ts b/lib/routes/anthropic/research.ts index cfba01932e4d..55961d98a8d3 100644 --- a/lib/routes/anthropic/research.ts +++ b/lib/routes/anthropic/research.ts @@ -68,7 +68,8 @@ async function handler() { }); const sections = fd.flatMap((d) => (Array.isArray(d.data) ? d.data : [])).flatMap((item) => item?.page?.sections ?? []); - const publicationSections = sections.filter((section) => section?.title === 'Publications'); + const tabPages = sections.flatMap((section) => section?.tabPages ?? []).filter((tabPage) => tabPage?.label === 'Overview'); + const publicationSections = tabPages.flatMap((tabPage) => tabPage.sections).filter((section) => section?.title === 'Publications'); const posts = publicationSections .flatMap((section) => section?.posts ?? []) .map((post) => ({ @@ -84,10 +85,7 @@ async function handler() { const response = await ofetch(item.link); const $ = load(response); - const content = $('#main-content > article'); - content - .find('[class$="__header"], [class$="__sidebar-container"], [class$="__controls"], [class$="__socialShare"], [class^="LandingPageSection-module-scss-module__"], [class^="SubjectNewsletter-module-scss-module__"]') - .remove(); + const content = $('div[class*="PostDetail_post-detail__"]'); content.find('img').each((_, e) => { const $e = $(e); $e.removeAttr('style srcset'); diff --git a/lib/routes/bilibili/cache.ts b/lib/routes/bilibili/cache.ts index e4add3e2226c..63c3a201f601 100644 --- a/lib/routes/bilibili/cache.ts +++ b/lib/routes/bilibili/cache.ts @@ -38,7 +38,7 @@ const getCookie = (disableConfig = false) => { let waitForRequest = new Promise((resolve) => { resolve(''); }); - const { destroy } = await getPuppeteerPage('https://space.bilibili.com/1/dynamic', { + const { destory } = await getPuppeteerPage('https://space.bilibili.com/1/dynamic', { onBeforeLoad: (page) => { waitForRequest = new Promise((resolve) => { page.on('requestfinished', async (request) => { @@ -54,7 +54,7 @@ const getCookie = (disableConfig = false) => { }); const cookieString = await waitForRequest; logger.debug(`Got bilibili cookie: ${cookieString}`); - await destroy(); + await destory(); return cookieString; }); }; diff --git a/lib/routes/castanet/namespace.ts b/lib/routes/castanet/namespace.ts deleted file mode 100644 index 02f37eae4eab..000000000000 --- a/lib/routes/castanet/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'Castanet', - url: 'www.castanet.net', - lang: 'en', -}; diff --git a/lib/routes/castanet/news.ts b/lib/routes/castanet/news.ts deleted file mode 100644 index d9f4894a6e8f..000000000000 --- a/lib/routes/castanet/news.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import parser from '@/utils/rss-parser'; - -const feeds = { - 'Top Headlines': 'topheadlines', - 'Recent Headlines': 'mostrecent', - Kelowna: 'page-1', - 'West-Kelowna': 'page-101', - Peachland: 'page-86', - Vernon: 'page-2', - 'Salmon-Arm': 'page-61', - Penticton: 'page-21', - 'Oliver-Osoyoos': 'page-87', - Kamloops: 'page-48', - Nelson: 'page-91', - BC: 'page-3', - Canada: 'page-4', - World: 'page-5', - Business: 'page-6', - Sports: 'page-7', - ShowBiz: 'page-8', -}; - -export const route: Route = { - path: '/:category?', - categories: ['traditional-media'], - example: '/castanet/Kelowna', - parameters: { - category: { - options: Object.keys(feeds).map((k) => ({ - value: k, - label: k, - })), - description: 'Category', - default: 'Recent Headlines', - }, - }, - radar: [ - { - source: ['www.castanet.net/news/:category/'], - target: '/:category', - }, - { - source: ['www.castanet.net/'], - target: '/', - }, - ], - name: 'News', - maintainers: ['TonyRL'], - handler, - url: 'www.castanet.net', -}; - -async function handler(ctx) { - const category = ctx.req.param('category') ?? 'Recent Headlines'; - const baseUrl = 'https://www.castanet.net'; - const feedFile = feeds[category] ?? category; - const feedUrl = `${baseUrl}/rss/${feedFile}.xml`; - - const feed = await parser.parseURL(feedUrl); - - const items = await Promise.all( - feed.items.map((item) => - cache.tryGet(item.link as string, async () => { - const response = await ofetch(item.link as string); - const $ = load(response); - - delete item.content; - delete item.contentSnippet; - delete item.isoDate; - - const content = $('.newsstory'); - content.find('.newsheadlinefull, .newsheadline, .byline, .click_gallery').remove(); - if (content.find('.gallery_img1').length) { - const a = content.find('.gallery_img1 a').toArray(); - content.find('.gallery_img1').next().remove(); - for (const ele of a) { - const $ele = $(ele); - const href = $ele.attr('href'); - const figure = `
${$ele.text().trim()}
${$ele.attr('title')?.trim() ?? ''}
`; - $ele.replaceWith(figure); - } - } - - item.description = content.html()?.trim(); - - return item; - }) - ) - ); - - return { - title: feed.title, - link: feed.link, - description: feed.description, - image: feed.image?.url, - language: feed.language, - item: items, - }; -} diff --git a/lib/routes/caus/index.ts b/lib/routes/caus/index.ts index 46d055d4bc53..d93a108da17e 100644 --- a/lib/routes/caus/index.ts +++ b/lib/routes/caus/index.ts @@ -1,18 +1,32 @@ import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; -// Reason: preserve original category numbers for backward compatibility. -// WordPress category ids from REST API (GET /wp-json/wp/v2/categories). -// Old categories "商业"(2) and "快讯"(3) no longer exist on the new site, -// mapped to closest equivalents: 2→财富(finance), 3→社会(lifestyle). const categories = { - 0: { title: '全部', slug: '', id: 0 }, - 1: { title: '要闻', slug: 'news', id: 101 }, - 2: { title: '商业', slug: 'finance', id: 108 }, - 3: { title: '快讯', slug: 'lifestyle', id: 106 }, - 8: { title: '财富', slug: 'finance', id: 108 }, - 6: { title: '生活', slug: 'lifestyle', id: 106 }, + 0: { + title: '全部', + link: 'home?id=0', + }, + 1: { + title: '要闻', + link: 'focus_news?id=1', + }, + 2: { + title: '商业', + link: 'business?id=2', + }, + 3: { + title: '快讯', + link: 'hours?id=3', + }, + 8: { + title: '财富', + link: 'fortune?id=8', + }, + 6: { + title: '生活', + link: 'life?id=6', + }, }; export const route: Route = { @@ -29,7 +43,7 @@ export const route: Route = { supportScihub: false, }, name: '分类', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| 全部 | 要闻 | 商业 | 快讯 | 财富 | 生活 | | ---- | ---- | ---- | ---- | ---- | ---- | @@ -38,35 +52,59 @@ export const route: Route = { async function handler(ctx) { const category = ctx.req.param('category') || '0'; - const cat = categories[category] || categories[0]; - const rootUrl = 'https://caus.com'; - const apiUrl = `${rootUrl}/wp-json/wp/v2/posts`; + const isHome = category === '0'; - const query: Record = { - per_page: 20, - // Reason: using _embed=1 with many posts produces responses too large for ofetch to parse as JSON - _embed: 'author,wp:term', - }; - if (cat.id) { - query.categories = cat.id; - } + const rootUrl = 'https://www.caus.com'; + const apiRootUrl = 'https://api.caus.money'; + + const currentUrl = `${rootUrl}/${categories[category].link}`; + const searchUrl = `${apiRootUrl}/toronto/display/searchList`; + const listUrl = `${apiRootUrl}/toronto/display/lanmuArticlelistNew`; - const data = await ofetch(apiUrl, { query }); + const response = await got({ + method: 'post', + url: isHome ? searchUrl : listUrl, + json: isHome + ? { + pageQ: { + pageSize: 10, + sortFiled: 'id', + sortType: 'DESC', + }, + types: ['ARTICLE', 'VIDEO'], + } + : { + filterIds: [], + lanmuId: Number.parseInt(category), + }, + }); - const items = data.map((item) => ({ - title: item.title.rendered, - link: item.link, - description: item.content.rendered, - pubDate: parseDate(item.date_gmt), - author: item._embedded?.author?.[0]?.name, - category: item._embedded?.['wp:term']?.[0]?.map((t) => t.name), + const list = (isHome ? response.data.data : response.data.data.articleList).map((item) => ({ + title: item.title, + link: `${rootUrl}/detail/${item.contentId}`, + contentId: item.contentId, + pubDate: new Date(item.createTime), + category: [...new Set([...item.lanmus.map((lanmu) => lanmu.name), ...item.tags.map((tag) => tag.name)])], })); - const currentUrl = cat.slug ? `${rootUrl}/category/${cat.slug}/` : rootUrl; + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const detailResponse = await got({ + method: 'get', + url: `${apiRootUrl}/toronto/display/contentWithRelate?contentId=${item.contentId}`, + }); + + item.description = detailResponse.data.data.content.content; + + return item; + }) + ) + ); return { - title: `${cat.title} - 加美财经`, + title: `${categories[category].title} - 加美财经`, link: currentUrl, item: items, }; diff --git a/lib/routes/changba/user.tsx b/lib/routes/changba/user.tsx index 26e6210ebec0..c601b2d9e972 100644 --- a/lib/routes/changba/user.tsx +++ b/lib/routes/changba/user.tsx @@ -5,7 +5,8 @@ import type { Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; + +const headers = { 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1' }; export const route: Route = { path: '/:userid', @@ -37,7 +38,7 @@ async function handler(ctx) { const response = await got({ method: 'get', url, - headerGeneratorOptions: PRESETS.MODERN_IOS, + headers, }); const data = response.data; const $ = load(data); @@ -53,7 +54,7 @@ async function handler(ctx) { const result = await got({ method: 'get', url: link, - headerGeneratorOptions: PRESETS.MODERN_IOS, + headers, }); const re = /workid: '\d+'/; diff --git a/lib/routes/cjlu/yjsy/index.ts b/lib/routes/cjlu/yjsy/index.ts index 894e488bfdce..1b333b623d12 100644 --- a/lib/routes/cjlu/yjsy/index.ts +++ b/lib/routes/cjlu/yjsy/index.ts @@ -86,7 +86,7 @@ async function handler(ctx) { const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 10; const url = `${host}index/${cate}.htm`; - const { page, destroy, browser } = await getPuppeteerPage(url, { + const { page, destory, browser } = await getPuppeteerPage(url, { onBeforeLoad: async (page) => { await page.setExtraHTTPHeaders(headers); await page.setUserAgent(headers['User-Agent']); @@ -102,7 +102,7 @@ async function handler(ctx) { const cookieString = cookies.map((c) => `${c.name}=${c.value}`).join('; '); const response = await page.content(); - await destroy(); + await destory(); const $ = load(response); diff --git a/lib/routes/claude/code-changelog.ts b/lib/routes/claude/code-changelog.ts index 7d8483231530..c5697ac52bc9 100644 --- a/lib/routes/claude/code-changelog.ts +++ b/lib/routes/claude/code-changelog.ts @@ -4,7 +4,6 @@ import type { Context } from 'hono'; import type { Data, DataItem, Route } from '@/types'; import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; const handler = async (ctx: Context): Promise => { const limit = Number.parseInt(ctx.req.query('limit') ?? '25', 10); @@ -15,27 +14,29 @@ const handler = async (ctx: Context): Promise => { const response = await ofetch(targetUrl); const $: CheerioAPI = load(response); - const items: DataItem[] = $('div.update-container') + const items: DataItem[] = $('div.markdown-heading') .slice(0, limit) .toArray() .map((el): DataItem => { - const $entry = $(el); - const version = $entry.find('[data-component-part="update-label"]').text().trim(); + const $heading = $(el); + const version = $heading.find('h2.heading-element').text().trim(); if (!version) { return null as unknown as DataItem; } - const dateText = $entry.find('[data-component-part="update-description"]').text().trim(); - const description = $entry.find('[data-component-part="update-content"]').html() ?? ''; + const descriptionParts: string[] = []; + $heading.nextUntil('div.markdown-heading').each((_, sibling) => { + descriptionParts.push($(sibling).prop('outerHTML') ?? ''); + }); + const description = descriptionParts.join(''); - const anchor = $entry.attr('id') ?? version.replaceAll('.', '-'); - const link = `${targetUrl}#${anchor}`; + const anchor = $heading.find('a.anchor').attr('href') ?? `#${version.replaceAll('.', '')}`; + const link = `${targetUrl}${anchor}`; return { title: version, description, link, - pubDate: dateText ? parseDate(dateText) : undefined, guid: `claude-code-${version}`, id: `claude-code-${version}`, }; diff --git a/lib/routes/dailypush/all.ts b/lib/routes/dailypush/all.ts index d15bb923de9a..8e0ed6fa3baa 100644 --- a/lib/routes/dailypush/all.ts +++ b/lib/routes/dailypush/all.ts @@ -1,9 +1,9 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; -import puppeteer from '@/utils/puppeteer'; +import ofetch from '@/utils/ofetch'; -import { BASE_URL, enhanceItemsWithSummaries, fetchPageHtml, parseArticles } from './utils'; +import { BASE_URL, enhanceItemsWithSummaries, parseArticles } from './utils'; export const route: Route = { path: '/:sort?', @@ -21,7 +21,7 @@ export const route: Route = { }, features: { requireConfig: false, - requirePuppeteer: true, + requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, @@ -42,21 +42,17 @@ async function handler(ctx) { const { sort = '' } = ctx.req.param(); const url = sort ? `${BASE_URL}/${sort}` : BASE_URL; - const browser = await puppeteer(); - try { - const html = await fetchPageHtml(browser, url, 'article'); - const $ = load(html); - const list = parseArticles($, BASE_URL); - const items = await enhanceItemsWithSummaries(browser, list); - - const pageTitle = $('title').text() || 'DailyPush - All'; - - return { - title: pageTitle, - link: url, - item: items, - }; - } finally { - await browser.close(); - } + const response = await ofetch(url); + const $ = load(response); + + const list = parseArticles($, BASE_URL); + const items = await enhanceItemsWithSummaries(list); + + const pageTitle = $('title').text() || 'DailyPush - All'; + + return { + title: pageTitle, + link: url, + item: items, + }; } diff --git a/lib/routes/dailypush/tags.ts b/lib/routes/dailypush/tags.ts index da50a1556210..1c4e8bf58387 100644 --- a/lib/routes/dailypush/tags.ts +++ b/lib/routes/dailypush/tags.ts @@ -1,9 +1,9 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; -import puppeteer from '@/utils/puppeteer'; +import ofetch from '@/utils/ofetch'; -import { BASE_URL, enhanceItemsWithSummaries, fetchPageHtml, parseArticles } from './utils'; +import { BASE_URL, enhanceItemsWithSummaries, parseArticles } from './utils'; export const route: Route = { path: '/tag/:tag/:sort?', @@ -22,7 +22,7 @@ export const route: Route = { }, features: { requireConfig: false, - requirePuppeteer: true, + requirePuppeteer: false, antiCrawler: false, supportBT: false, supportPodcast: false, @@ -43,21 +43,17 @@ async function handler(ctx) { const { tag, sort = 'trending' } = ctx.req.param(); const url = `${BASE_URL}/${tag}/${sort}`; - const browser = await puppeteer(); - try { - const html = await fetchPageHtml(browser, url, 'article'); - const $ = load(html); - const list = parseArticles($, BASE_URL); - const items = await enhanceItemsWithSummaries(browser, list); - - const pageTitle = $('title').text() || `DailyPush - ${tag.charAt(0).toUpperCase() + tag.slice(1)}`; - - return { - title: pageTitle, - link: url, - item: items, - }; - } finally { - await browser.close(); - } + const response = await ofetch(url); + const $ = load(response); + + const list = parseArticles($, BASE_URL); + const items = await enhanceItemsWithSummaries(list); + + const pageTitle = $('title').text() || `DailyPush - ${tag.charAt(0).toUpperCase() + tag.slice(1)}`; + + return { + title: pageTitle, + link: url, + item: items, + }; } diff --git a/lib/routes/dailypush/utils.ts b/lib/routes/dailypush/utils.ts index 2854207eae8c..041eaa600ed0 100644 --- a/lib/routes/dailypush/utils.ts +++ b/lib/routes/dailypush/utils.ts @@ -1,10 +1,9 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; -import type { Browser, Page } from 'rebrowser-puppeteer'; import type { DataItem } from '@/types'; import cache from '@/utils/cache'; -import logger from '@/utils/logger'; +import ofetch from '@/utils/ofetch'; import { parseRelativeDate } from '@/utils/parse-date'; export const BASE_URL = 'https://www.dailypush.dev'; @@ -20,38 +19,6 @@ export interface ArticleItem { dailyPushUrl?: string; } -const allowedRequestTypes = new Set(['document']); - -async function preparePage(page: Page) { - await page.setRequestInterception(true); - page.on('request', (request) => { - if (allowedRequestTypes.has(request.resourceType())) { - request.continue(); - return; - } - - request.abort(); - }); -} - -export async function fetchPageHtml(browser: Browser, url: string, waitForSelector?: string): Promise { - const page = await browser.newPage(); - await preparePage(page); - - try { - logger.http(`Requesting ${url}`); - await page.goto(url, { waitUntil: 'domcontentloaded' }); - - if (waitForSelector) { - await page.waitForSelector(waitForSelector); - } - - return await page.content(); - } finally { - await page.close(); - } -} - /** * Try to parse text as a date. Returns the Date if parsing succeeds and is valid, undefined otherwise. */ @@ -73,14 +40,14 @@ function extractAuthor(article: ReturnType): DataItem['author'] { return undefined; } - // Get all content spans (exclude separator spans with "•") + // Get all content spans (exclude separator spans with '•') const allSpans = container.find('span'); const contentSpans: string[] = []; for (let i = 0; i < allSpans.length; i++) { const $span = allSpans.eq(i); const text = $span.text().trim(); - // Skip separator spans (contain only "•" or have separator classes) + // Skip separator spans (contain only '•' or have separator classes) if (text !== '•' && !$span.hasClass('text-slate-300') && !$span.hasClass('dark:text-slate-600')) { contentSpans.push(text); } @@ -160,14 +127,14 @@ function extractPubDate(article: ReturnType): Date | undefined { return undefined; } - // Get all content spans (exclude separator spans with "•") + // Get all content spans (exclude separator spans with '•') const allSpans = container.find('span'); const contentSpans: string[] = []; for (let i = 0; i < allSpans.length; i++) { const $span = allSpans.eq(i); const text = $span.text().trim(); - // Skip separator spans (contain only "•" or have separator classes) + // Skip separator spans (contain only '•' or have separator classes) if (text !== '•' && !$span.hasClass('text-slate-300') && !$span.hasClass('dark:text-slate-600')) { contentSpans.push(text); } @@ -258,20 +225,23 @@ export function parseArticles($: CheerioAPI, baseUrl: string): ArticleItem[] { } /** - * Enhance items with full summaries from dailypush article pages. - * Uses the provided browser; opens a new tab per URL (document requests only). Caller must close the browser. + * Enhance items with full summaries from dailypush article pages */ -export async function enhanceItemsWithSummaries(browser: Browser, items: ArticleItem[]): Promise { +export async function enhanceItemsWithSummaries(items: ArticleItem[]): Promise { const itemsWithUrl = items.filter((item) => item.dailyPushUrl !== undefined); const itemsWithoutUrl: DataItem[] = items.filter((item) => item.dailyPushUrl === undefined); - const enhancedItems = await Promise.all( + const enhancedItems: DataItem[] = await Promise.all( itemsWithUrl.map((item) => cache.tryGet(item.dailyPushUrl!, async () => { + // If we have a dailypush article URL, fetch it for the longer summary try { - const html = await fetchPageHtml(browser, item.dailyPushUrl!, 'p.font-ibm-plex-sans.leading-relaxed'); - const $ = load(html); + const articleResponse = await ofetch(item.dailyPushUrl!); + const $ = load(articleResponse); + + // Find the longer summary/description on the article page const summary = $('p.font-ibm-plex-sans.leading-relaxed').first(); + if (summary.length > 0 && summary.text().trim()) { item.description = summary.text().trim(); } @@ -284,5 +254,6 @@ export async function enhanceItemsWithSummaries(browser: Browser, items: Article ) ); + // Include items without dailyPushUrl as-is return [...enhancedItems, ...itemsWithoutUrl]; } diff --git a/lib/routes/ddosi/category.ts b/lib/routes/ddosi/category.ts index 9e1015e0e924..5c8ee1a93c6e 100644 --- a/lib/routes/ddosi/category.ts +++ b/lib/routes/ddosi/category.ts @@ -1,8 +1,8 @@ import { load } from 'cheerio'; +import { config } from '@/config'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; import { parseDate } from '@/utils/parse-date'; export const route: Route = { @@ -25,21 +25,22 @@ export const route: Route = { }, ], name: '分类', - maintainers: ['XinRoom'], + maintainers: [], handler, url: 'ddosi.org/', }; async function handler(ctx) { const url = 'https://www.ddosi.org/category'; + const userAgent = config.ua || 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'; const category = ctx.req.param('category'); const response = await got({ method: 'get', url: `${url}/${category}/`, headers: { + 'User-Agent': userAgent, Referer: url, }, - headerGeneratorOptions: PRESETS.MODERN_IOS, }); const $ = load(response.data); const list = $('main>article').toArray(); diff --git a/lib/routes/ddosi/index.ts b/lib/routes/ddosi/index.ts index 5e7ec5b9f7af..c93a8db9fbfa 100644 --- a/lib/routes/ddosi/index.ts +++ b/lib/routes/ddosi/index.ts @@ -1,20 +1,19 @@ import { load } from 'cheerio'; +import { config } from '@/config'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; import { parseDate } from '@/utils/parse-date'; export const route: Route = { path: '/', - example: '/ddosi', radar: [ { source: ['ddosi.org/'], target: '', }, ], - name: '首页', + name: 'Unknown', maintainers: ['XinRoom'], handler, url: 'ddosi.org/', @@ -22,13 +21,14 @@ export const route: Route = { async function handler() { const url = 'https://www.ddosi.org/'; + const userAgent = config.ua || 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'; const response = await got({ method: 'get', url: String(url), headers: { + 'User-Agent': userAgent, Referer: url, }, - headerGeneratorOptions: PRESETS.MODERN_IOS, }); const $ = load(response.data); const list = $('main>article').toArray(); diff --git a/lib/routes/dianping/user.ts b/lib/routes/dianping/user.ts index 6698f1aaeb0c..3503b66027e1 100644 --- a/lib/routes/dianping/user.ts +++ b/lib/routes/dianping/user.ts @@ -1,6 +1,5 @@ import { config } from '@/config'; import type { Route } from '@/types'; -import { PRESETS } from '@/utils/header-generator'; import ofetch from '@/utils/ofetch'; export const route: Route = { @@ -59,10 +58,12 @@ const starMap: Record = { async function handler(ctx) { const id = ctx.req.param('id'); + const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'; const userPage = `https://m.dianping.com/userprofile/${id}`; const cookie = config.dianping.cookie; const headers: Record = { + 'User-Agent': userAgent, Referer: userPage, }; @@ -72,7 +73,6 @@ async function handler(ctx) { const pageResponse = await ofetch(userPage, { headers, - headerGeneratorOptions: PRESETS.MODERN_IOS, }); const nickNameReg = /window\.nickName = "(.*?)"/g; @@ -80,7 +80,6 @@ async function handler(ctx) { const response = await ofetch(`https://m.dianping.com/member/ajax/NobleUserFeeds?userId=${id}`, { headers, - headerGeneratorOptions: PRESETS.MODERN_IOS, }); const data = response.data; diff --git a/lib/routes/digitalpolicyalert/activity-tracker.ts b/lib/routes/digitalpolicyalert/activity-tracker.ts index 0d4529925321..ad8042148b0d 100644 --- a/lib/routes/digitalpolicyalert/activity-tracker.ts +++ b/lib/routes/digitalpolicyalert/activity-tracker.ts @@ -30,23 +30,17 @@ export const handler = async (ctx: Context): Promise => { const baseUrl = 'https://digitalpolicyalert.org'; const apiBaseUrl = 'https://api.globaltradealert.org'; const targetUrl: string = new URL(`activity-tracker?${params.toString()}`, baseUrl).href; - // Reason: trailing slash avoids a 301 redirect from the API server - const apiUrl: string = new URL('dpa/intervention/', apiBaseUrl).href; + const apiUrl: string = new URL('dpa/intervention', apiBaseUrl).href; - // Reason: explicit Accept header needed because RSSHub's ofetch auto-generates - // browser-like Accept headers, causing the API to return HTML via content negotiation const response = await ofetch(apiUrl, { query: searchParamsToObject(params), - headers: { - Accept: 'application/json', - }, }); const targetResponse = await ofetch(targetUrl); const $: CheerioAPI = load(targetResponse); const language = $('html').attr('lang') ?? 'en'; - const items: DataItem[] = (response.results ?? []).slice(0, limit).map((item): DataItem => { + const items: DataItem[] = response.results.slice(0, limit).map((item): DataItem => { const title: string = item.title; const description: string | undefined = item.latest_event?.description ?? undefined; const pubDate: number | string = item.latest_event?.date; @@ -103,7 +97,7 @@ export const route: Route = { path: '/activity-tracker/:filters?', name: 'Activity Tracker', url: 'digitalpolicyalert.org', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, example: '/digitalpolicyalert/activity-tracker', parameters: { diff --git a/lib/routes/discuz/discuz.ts b/lib/routes/discuz/discuz.ts index e39d4f063eed..359dd9bf73cc 100644 --- a/lib/routes/discuz/discuz.ts +++ b/lib/routes/discuz/discuz.ts @@ -20,38 +20,16 @@ function fixUrl(itemLink, baseUrl) { return itemLink; } -// Reason: some Discuz forums use a "page reload" anti-bot mechanism that sets cookies -// on the first request; this helper detects it and retries with the received cookies -async function fetchWithAntiBot(url: string, header: Record) { - let response = await ofetch.raw(url, { +// discuz 7.x 与 discuz x系列 通用文章内容抓取 +async function loadContent(itemLink, charset, header) { + // 处理编码问题 + const response = await ofetch.raw(itemLink, { method: 'get', responseType: 'arrayBuffer', headers: header, }); - let responseData = Buffer.from(response._data); - const initialHtml = iconv.decode(responseData, 'utf-8'); - - if (initialHtml.includes('document.location.reload()')) { - const setCookies = response.headers.getSetCookie?.() ?? []; - const cookieStr = setCookies.map((c) => c.split(';')[0]).join('; '); - if (cookieStr) { - response = await ofetch.raw(url, { - method: 'get', - responseType: 'arrayBuffer', - headers: { ...header, Cookie: [header.Cookie, cookieStr].filter(Boolean).join('; ') }, - }); - responseData = Buffer.from(response._data); - } - } - - return { response, responseData }; -} - -// discuz 7.x 与 discuz x系列 通用文章内容抓取 -async function loadContent(itemLink, charset, header) { - const { responseData: rawData } = await fetchWithAntiBot(itemLink, header); - const responseData = iconv.decode(rawData, charset ?? 'utf-8'); + const responseData = iconv.decode(Buffer.from(response._data), charset ?? 'utf-8'); if (!responseData) { const description = '获取详细内容失败'; return { description }; @@ -80,7 +58,7 @@ async function loadContent(itemLink, charset, header) { export const route: Route = { path: ['/:ver{[7x]}/:cid{[0-9]{2}}/:link{.+}', '/:ver{[7x]}/:link{.+}', '/:link{.+}'], name: 'Unknown', - maintainers: ['pseudoyu'], + maintainers: [], handler, }; @@ -99,8 +77,13 @@ async function handler(ctx) { Cookie: cookie, }; - const { response, responseData } = await fetchWithAntiBot(link, header); + const response = await ofetch.raw(link, { + method: 'get', + responseType: 'arrayBuffer', + headers: header, + }); + const responseData = Buffer.from(response._data); // 若没有指定编码,则默认utf-8 const contentType = response.headers['content-type'] || ''; let $ = load(iconv.decode(responseData, 'utf-8')); @@ -111,10 +94,6 @@ async function handler(ctx) { const version = ver ? `DISCUZ! ${ver}` : $('head > meta[name=generator]').attr('content'); - if (!version) { - throw new InvalidParameterError('无法检测 Discuz 版本,请在路由中指定版本参数,如 /discuz/x/ 或 /discuz/7/'); - } - let items; if (version.toUpperCase().startsWith('DISCUZ! 7')) { // discuz 7.x 系列 diff --git a/lib/routes/eastmoney/report/index.tsx b/lib/routes/eastmoney/report/index.tsx index 9b9c31cf8a29..f7839c753ed4 100644 --- a/lib/routes/eastmoney/report/index.tsx +++ b/lib/routes/eastmoney/report/index.tsx @@ -151,7 +151,7 @@ async function handler(ctx) { ); } else { item.link = $('.pdf-link').attr('href'); - item.description = $('.ctx-content').html(); + item.description = $('.ctx-content').text(); } return item; } catch { diff --git a/lib/routes/fanbox/index.ts b/lib/routes/fanbox/index.ts index 487b5bc98e41..58782586eed5 100644 --- a/lib/routes/fanbox/index.ts +++ b/lib/routes/fanbox/index.ts @@ -13,7 +13,7 @@ export const route: Route = { categories: ['social-media'], example: '/fanbox/official', parameters: { creator: 'fanbox user name' }, - maintainers: ['KarasuShin', 'pseudoyu'], + maintainers: ['KarasuShin'], name: 'Creator', handler, features: { diff --git a/lib/routes/fcbayern/namespace.ts b/lib/routes/fcbayern/namespace.ts deleted file mode 100644 index b80ae577724a..000000000000 --- a/lib/routes/fcbayern/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'FC Bayern München', - url: 'fcbayern.com', - lang: 'en', -}; diff --git a/lib/routes/fcbayern/news-cn.ts b/lib/routes/fcbayern/news-cn.ts deleted file mode 100644 index 2fd69ce1ef54..000000000000 --- a/lib/routes/fcbayern/news-cn.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { Data } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; -import timezone from '@/utils/timezone'; - -export const cnNewsHander = async (limit: number) => { - const response = await ofetch('https://www.fcbayern.cn/api2018/news/list', { - method: 'POST', - headers: { - accept: 'application/json', - 'content-type': 'application/x-www-form-urlencoded', - }, - body: new URLSearchParams({ - page: '1', - pageSize: String(limit), - totalPage: '1', - tagId: '', - year: '-1', - month: '-1', - type: '1', - }), - }); - - const items = response.data.map((item) => ({ - title: item.title, - link: item.url, - pubDate: timezone(parseDate(item.time), 8), - image: item.pic?.split('?')[0], - })); - - return { - title: '拜仁慕尼黑俱乐部中文官方网站 - 新闻', - link: 'https://www.fcbayern.cn/news', - item: items, - } satisfies Data; -}; diff --git a/lib/routes/fcbayern/news.ts b/lib/routes/fcbayern/news.ts deleted file mode 100644 index 2a3d7c8d50f6..000000000000 --- a/lib/routes/fcbayern/news.ts +++ /dev/null @@ -1,207 +0,0 @@ -import type { Context } from 'hono'; - -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import { cnNewsHander } from './news-cn'; - -const languages = { - en: 'fcbayern.com-en-gb', - es: 'fcbayern.com-es-es', - de: 'fcbayern.com-de-de', -}; - -const query = /* GraphQL */ ` - query Web_NewsSearch($channelId: String!, $query: String!, $filterTags: [String!], $filterSections: [String!], $filterTypes: [String!], $count: Int!, $offset: Int, $excludeHeroStageResultFromPageId: String) { - newsSearch( - channelId: $channelId - query: $query - filterTags: $filterTags - filterSections: $filterSections - filterTypes: $filterTypes - count: $count - offset: $offset - excludeHeroStageResultFromPageId: $excludeHeroStageResultFromPageId - ) { - total - offset - count - results { - ...Teaser - __typename - } - __typename - } - } - fragment Teaser on Teaser { - __typename - id - pageType - teaserTitle - teaserShortTitle - teaserSubtitle - teaserText - tag - publicationDate - teaserImage { - ...ImageFragment - __typename - } - teaserLink { - ...Link - __typename - } - teamEmblems { - ...TeamEmblems - __typename - } - teaserAppendix { - ... on GalleryTeaserAppendix { - galleryImages { - ...ImageFragment - __typename - } - __typename - } - ... on VideoTeaserAppendix { - documentId - kalturaId - __typename - } - __typename - } - markers - adMarker - channelId - } - fragment Link on Link { - __typename - newTabOrWindow - title - target { - ... on ExternalLink { - url - __typename - } - ... on InternalLink { - id - path - channelId - channelPath - differentChannelDomain - locale - pageType - __typename - } - __typename - } - } - fragment ImageFragment on ImageFragment { - __typename - url - alt - caption - copyright - origWidth - origHeight - aspectRatioImageOverrides { - ...AspectRatioImageOverride - __typename - } - } - fragment AspectRatioImageOverride on AspectRatioImageOverride { - aspectRatio - url - __typename - } - fragment TeamEmblems on TeamEmblems { - ownTeam - emblem { - ...ImageFragment - __typename - } - __typename - } -`; - -export const route: Route = { - path: '/news/:language?', - categories: ['new-media'], - example: '/fcbayern/news', - parameters: { - language: { - description: 'Language', - options: [ - { value: 'en', label: 'English' }, - { value: 'es', label: 'Español' }, - { value: 'de', label: 'Deutsch' }, - { value: 'zh', label: '中文' }, - ], - default: 'en', - }, - }, - radar: [ - { - source: ['fcbayern.com/:language/news', 'fcbayern.com/:language'], - target: '/news/:language', - }, - { - source: ['www.fcbayern.cn/news', 'www.fcbayern.cn'], - target: '/news/zh', - }, - ], - name: 'News', - maintainers: ['TonyRL'], - handler, - url: 'fcbayern.com', -}; - -async function handler(ctx: Context) { - const { language = 'en' } = ctx.req.param(); - const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')!, 10) : 20; - - if (language === 'zh') { - return cnNewsHander(limit); - } - - const baseUrl = 'https://fcbayern.com'; - const channelId = languages[language] ?? languages.en; - - const response = await ofetch(`${baseUrl}/graphql`, { - method: 'POST', - query: { - client: 'fcbwebsite', - }, - body: { - operationName: 'Web_NewsSearch', - variables: { - query: '', - filterTags: ['tag_club', 'tag_team_women', 'tag_team_campus', 'tag_article_news', 'tag_competitions_bundesliga', 'tag_competitions_champions-league', 'tag_column_saebener-stories', 'tag_club_magazin-51'], - offset: 0, - count: limit, - channelId, - filterSections: ['section_professionals', 'section_club', 'section_women', 'section_campus', 'section_aroundtheworld'], - filterTypes: ['fcbhippo:ArticleDocument', 'fcbhippo:ImageGalleryDocument', 'fcbhippo:TeaserDocument'], - }, - query, - }, - }); - - const items = response.data.newsSearch.results.map((item) => ({ - title: item.teaserTitle, - description: item.teaserText, - link: `${baseUrl}${item.teaserLink.target.path}`, - pubDate: item.publicationDate ? parseDate(item.publicationDate) : undefined, - image: item.teaserImage?.url, - category: item.tag ? [item.tag] : undefined, - })); - - return { - title: 'FC Bayern München - News', - link: `${baseUrl}/${language}/news`, - language, - image: `${baseUrl}/favicon.ico`, - item: items, - }; -} diff --git a/lib/routes/gameapps/index.tsx b/lib/routes/gameapps/index.tsx index 1b2b25c3502e..f8268e1a676e 100644 --- a/lib/routes/gameapps/index.tsx +++ b/lib/routes/gameapps/index.tsx @@ -37,19 +37,41 @@ async function handler() { const $ = load(response); item.title = $('meta[property="og:title"]').attr('content') ?? $('.news-title h1').text(); - item.category = $('.tags-wrap .tag-item') + + const nextPages = $('.pagination li') + .not('.disabled') + .not('.active') + .find('a') .toArray() - .map((el) => $(el).text().trim().replace(/^#/, '')); + .map((a) => `${baseUrl}${a.attribs.href}`); + + $('.pages').remove(); - $('.pages, .article-ad, .social-actions, .news-footer').remove(); + const content = $('.news-content'); // remove unwanted key value delete item.content; delete item.contentSnippet; delete item.isoDate; + if (nextPages.length) { + const pages = await Promise.all( + nextPages.map(async (url) => { + const response = await ofetch(url, { + headers: { + referer: item.link, + }, + }); + const $ = load(response); + $('.pages').remove(); + return $('.news-content').html(); + }) + ); + content.append(pages); + } + const intro = $('div.introduction.media.news-intro div.media-body').html()?.trim(); - const desc = $('.article-content').html()?.trim(); + const desc = content.html()?.trim(); item.description = renderToString( <> {intro ? raw(intro) : null} diff --git a/lib/routes/github/topic.ts b/lib/routes/github/topic.ts index 3be582428c1f..74d1b96160aa 100644 --- a/lib/routes/github/topic.ts +++ b/lib/routes/github/topic.ts @@ -46,7 +46,7 @@ async function handler(ctx) { title: $('title').text(), description: $('.markdown-body').text().trim(), link: url, - item: $('article.border') + item: $('article.my-4') .toArray() .map((item) => { item = $(item); diff --git a/lib/routes/hyperdash/utils.ts b/lib/routes/hyperdash/utils.ts index b3e9c0fecb6b..f36f29798010 100644 --- a/lib/routes/hyperdash/utils.ts +++ b/lib/routes/hyperdash/utils.ts @@ -21,6 +21,7 @@ export async function fetchTopTraders(): Promise { const traders: TraderData[] = await ofetch(apiUrl, { headers: { 'x-api-key': 'hyperdash_public_7vN3mK8pQ4wX2cL9hF5tR1bY6gS0jD', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36', }, }); diff --git a/lib/routes/iapp/namespace.ts b/lib/routes/iapp/namespace.ts deleted file mode 100644 index e4c3fac1cc1c..000000000000 --- a/lib/routes/iapp/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'IAPP', - url: 'iapp.org', - lang: 'en', -}; diff --git a/lib/routes/iapp/news.ts b/lib/routes/iapp/news.ts deleted file mode 100644 index 1af11e5d7d5e..000000000000 --- a/lib/routes/iapp/news.ts +++ /dev/null @@ -1,101 +0,0 @@ -import crypto from 'node:crypto'; - -import { load } from 'cheerio'; -import type { Context } from 'hono'; - -import type { Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/news', - categories: ['new-media'], - example: '/iapp/news', - radar: [ - { - source: ['iapp.org/news'], - }, - ], - name: 'News', - maintainers: ['TonyRL'], - handler, - url: 'iapp.org/news', -}; - -async function handler(ctx: Context) { - const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')!, 10) : 20; - const baseUrl = 'https://iapp.org'; - const link = `${baseUrl}/news`; - - const { appId, apiKey, description } = await cache.tryGet('iapp:algolia-credentials', async () => { - const html = await ofetch(link); - const $ = load(html); - let appId: string | undefined; - let apiKey: string | undefined; - $('script').each((_, el) => { - const text = $(el).text(); - const match = text.match(/\\"appID\\":\\"(\w+)\\",\\"apiKey\\":\\"(\w+)\\"/); - if (match) { - appId = match[1]; - apiKey = match[2]; - return false; - } - }); - if (!appId || !apiKey) { - throw new Error('Failed to extract Algolia credentials from iapp.org'); - } - return { - appId, - apiKey, - description: $('meta[name="description"]').attr('content'), - }; - }); - - const response = await ofetch(`https://${appId.toLowerCase()}-dsn.algolia.net/1/indexes/*/queries`, { - method: 'POST', - query: { - 'x-algolia-api-key': apiKey, - 'x-algolia-application-id': appId, - }, - headers: { - Referer: `${baseUrl}/`, - }, - body: { - requests: [ - { - indexName: 'all_article_date_desc', - clickAnalytics: true, - facets: ['news_tags.domains.domains', 'news_tags.industry.industry', 'news_tags.law_and_regulation.law_and_regulation', 'news_tags.subject.subject'], - filters: '_content_type:news_article', - highlightPostTag: '__/ais-highlight__', - highlightPreTag: '__ais-highlight__', - hitsPerPage: limit, - maxValuesPerFacet: 200, - page: 0, - query: '', - userToken: `anonymous-${crypto.randomUUID()}`, - }, - ], - }, - }); - - const items = response.results[0].hits.map((hit) => ({ - title: hit.article_details.headline, - description: hit.article_body?.map((block) => block.rte?.rich_text_editor).join('') || hit.entry_summary, - link: new URL(hit.url, baseUrl).href, - pubDate: parseDate(hit.article_details.date), - author: hit.article_details.author?.map((a) => a.title).join(', '), - category: [...(hit.news_tags?.domains?.domains || []), ...(hit.news_tags?.subject?.subject || []), ...(hit.tags_group?.internal_class || [])], - image: hit.main_image?.url, - })); - - return { - title: 'IAPP - News', - description, - link, - language: 'en' as const, - image: `${baseUrl}/favicon.ico`, - item: items, - }; -} diff --git a/lib/routes/infoq/utils.ts b/lib/routes/infoq/utils.ts index c862eb48f8a8..7e09f3575286 100644 --- a/lib/routes/infoq/utils.ts +++ b/lib/routes/infoq/utils.ts @@ -22,11 +22,10 @@ const ProcessFeed = async (list, cache) => { const author = data.author ? data.author.map((p) => p.nickname).join(',') : data.no_author; const category = [...e.topic.map((t) => t.name), ...e.label.map((l) => l.name)]; const content = data.content_url ? (await got(data.content_url)).body : data.content; - const description = addCoverToDescription(parseContent(content), data.article_cover); return { title: data.article_title, - description, + description: parseContent(content), pubDate: parseDate(e.publish_time, 'x'), category, author, @@ -98,10 +97,6 @@ const parseToSimpleTexts = (content) => return parseToSimpleText(i.content); }); -function addCoverToDescription(content, cover) { - return `

${content}`; -} - function parseContent(content) { const isRichContent = content.startsWith(`{"`); if (!isRichContent) { diff --git a/lib/routes/iwara/ranking.ts b/lib/routes/iwara/ranking.ts index 4ff2fa022e70..b2969e31b05e 100644 --- a/lib/routes/iwara/ranking.ts +++ b/lib/routes/iwara/ranking.ts @@ -58,7 +58,7 @@ async function handler(ctx) { const items = await cache.tryGet( `iwara:ranking:${type}:${sort}:${rating}`, async () => { - const { page, destroy } = await getPuppeteerPage(url, { + const { page, destory } = await getPuppeteerPage(url, { onBeforeLoad: async (page) => { await page.setRequestInterception(true); page.on('request', (request) => { @@ -83,7 +83,7 @@ async function handler(ctx) { pubDate: parseDate(item.createdAt), })); } finally { - await destroy(); + await destory(); } }, config.cache.routeExpire, diff --git a/lib/routes/iwara/subscriptions.ts b/lib/routes/iwara/subscriptions.ts index 3f44add670be..77b058370362 100644 --- a/lib/routes/iwara/subscriptions.ts +++ b/lib/routes/iwara/subscriptions.ts @@ -69,7 +69,7 @@ async function handler() { const username = config.iwara.username; const password = config.iwara.password; - const { page, destroy } = await getPuppeteerPage(rootUrl, { + const { page, destory } = await getPuppeteerPage(rootUrl, { gotoConfig: { waitUntil: 'domcontentloaded', }, @@ -113,10 +113,7 @@ async function handler() { async () => { const result = await fetchApi(`${apiqRootUrl}/user/token`, { method: 'POST', - headers: { - ...apiHeaders, - Authorization: refreshHeaders.authorization, - }, + headers: { ...apiHeaders, Authorization: refreshHeaders.authorization }, }); return { authorization: 'Bearer ' + result.accessToken }; }, @@ -124,10 +121,7 @@ async function handler() { false ); - const authedHeaders = { - ...apiHeaders, - Authorization: authHeaders.authorization, - }; + const authedHeaders = { ...apiHeaders, Authorization: authHeaders.authorization }; // fetch subscriptions const [videoResponse, imageResponse] = await Promise.all([ @@ -183,9 +177,7 @@ async function handler() { } const apiUrl = item.link.replace('www.iwara.tv', 'apiq.iwara.tv'); - const response = await fetchApi(apiUrl, { - headers: authedHeaders, - }); + const response = await fetchApi(apiUrl, { headers: authedHeaders }); description = renderSubscriptionImages(response.files ? response.files.filter((f) => f.type === 'image').map((f) => `${imageRootUrl}/image/original/${f.id}/${f.name}`) : [item.imageUrl]); @@ -210,6 +202,6 @@ async function handler() { item: items, }; } finally { - await destroy(); + await destory(); } } diff --git a/lib/routes/jable/index.ts b/lib/routes/jable/index.ts deleted file mode 100644 index 361fc240f066..000000000000 --- a/lib/routes/jable/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import got from '@/utils/got'; - -export const route: Route = { - path: '/search/:query', - categories: ['multimedia'], - example: '/jable/search/みなみ羽琉', - parameters: { - query: 'Search keyword', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - nsfw: true, - }, - radar: [ - { - source: ['jable.tv/search/:query'], - target: '/search/:query', - }, - ], - name: 'Jable 搜索结果', - maintainers: ['eve2ptp'], - handler, -}; - -interface VideoThumb { - title: string; - link: string; - thumb: string; - preview: string; -} - -function renderDescription(video: VideoThumb): string { - return `${video.title}`.trim(); -} - -async function handler(ctx) { - const { query } = ctx.req.param(); - - const params = new URLSearchParams({ - mode: 'async', - function: 'get_block', - block_id: 'list_videos_videos_list_search_result', - q: query, - sort_by: 'post_date', - }); - - const encodedQuery = encodeURIComponent(query); - const baseUrl = `https://jable.tv/search/${encodedQuery}/`; - const apiUrl = `${baseUrl}?${params.toString()}`; - - const response = await got(apiUrl); - const $ = load(response.data); - - const videos: VideoThumb[] = $('.video-img-box') - .toArray() - .map((el) => { - const $el = $(el); - const $titleLink = $el.find('.detail h6.title a'); - const $img = $el.find('img'); - - return { - title: $titleLink.text().trim(), - link: $titleLink.attr('href') ?? '', - thumb: $img.attr('data-src') ?? '', - preview: $img.attr('data-preview') ?? '', - }; - }); - - const items = videos.map((video) => ({ - title: video.title, - link: video.link, - author: query, - description: renderDescription(video), - media: { - content: { - url: video.preview || video.link, - type: 'video/mp4', - }, - thumbnail: { - url: video.thumb, - }, - }, - })); - - return { - title: `${query} - Search | Jable`, - link: baseUrl, - description: `Search results for ${query}`, - item: items, - }; -} diff --git a/lib/routes/jable/namaspace.ts b/lib/routes/jable/namaspace.ts deleted file mode 100644 index f0a3ace67e5d..000000000000 --- a/lib/routes/jable/namaspace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'jable', - url: 'jable.tv', - lang: 'zh', -}; diff --git a/lib/routes/jandan/utils.ts b/lib/routes/jandan/utils.ts index c2b702c5bc0c..1b37789c0208 100644 --- a/lib/routes/jandan/utils.ts +++ b/lib/routes/jandan/utils.ts @@ -4,12 +4,15 @@ import type { DataItem } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; +export const USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36'; + /** * Extract page ID from script tags in HTML */ export const extractPageId = async (url: string, referer: string): Promise => { const response = await ofetch(url, { headers: { + 'User-Agent': USER_AGENT, Referer: referer, Accept: 'application/json, text/plain, */*', }, @@ -36,6 +39,7 @@ export const handleTopSection = async (rootUrl: string, type: string): Promise<{ const apiUrl = `${rootUrl}/api/top/${type}`; const response = await ofetch(apiUrl, { headers: { + 'User-Agent': USER_AGENT, Referer: rootUrl, Accept: 'application/json, text/plain, */*', }, @@ -110,6 +114,7 @@ export const handleForumSection = async (rootUrl: string): Promise<{ title: stri const apiUrl = `${rootUrl}/api/forum/posts/${forumId}?page=1`; const forumData = await ofetch(apiUrl, { headers: { + 'User-Agent': USER_AGENT, Referer: currentUrl, Accept: 'application/json, text/plain, */*', }, @@ -169,6 +174,7 @@ export const handleCommentSection = async (rootUrl: string, category: string): P const response = await ofetch(currentUrl, { headers: { + 'User-Agent': USER_AGENT, Referer: rootUrl, Accept: 'application/json, text/plain, */*', }, @@ -194,6 +200,7 @@ export const handleCommentSection = async (rootUrl: string, category: string): P const apiUrl = `${rootUrl}/api/comment/post/${pageId}?order=desc&page=1`; const commentsData = await ofetch(apiUrl, { headers: { + 'User-Agent': USER_AGENT, Referer: currentUrl, Accept: 'application/json, text/plain, */*', }, diff --git a/lib/routes/javdb/utils.ts b/lib/routes/javdb/utils.ts index 983a99dea7d8..133a22a148f2 100644 --- a/lib/routes/javdb/utils.ts +++ b/lib/routes/javdb/utils.ts @@ -7,7 +7,7 @@ import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; -const allowDomain = new Set(['javdb.com', 'javdb571.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']); +const allowDomain = new Set(['javdb.com', 'javdb36.com', 'javdb007.com', 'javdb521.com']); const ProcessItems = async (ctx, currentUrl, title) => { const domain = ctx.req.query('domain') ?? 'javdb.com'; diff --git a/lib/routes/jiemian/account.ts b/lib/routes/jiemian/account.ts index 2b1ae3c830b1..fc12165f60dd 100644 --- a/lib/routes/jiemian/account.ts +++ b/lib/routes/jiemian/account.ts @@ -7,7 +7,7 @@ export const route: Route = { parameters: { id: '分类 id,见下表,可在对应分类页 URL 中找到' }, name: '界面号', example: '/jiemian/account/main/1', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| [财经号](https://www.jiemian.com/account/main/1.html) | [城市号](https://www.jiemian.com/account/main/2.html) | [媒体号](https://www.jiemian.com/account/main/3.html) | | ----------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | diff --git a/lib/routes/jiemian/common.tsx b/lib/routes/jiemian/common.tsx index c81333161fd3..586760366324 100644 --- a/lib/routes/jiemian/common.tsx +++ b/lib/routes/jiemian/common.tsx @@ -92,7 +92,8 @@ export const handler = async (ctx): Promise => { const title = $('title').text(); const titleSplits = title.split(/_/); - const image = new URL($('link[rel="icon"]').prop('href'), rootUrl).href; + const image = $('div.logo img').prop('src'); + const icon = new URL($('link[rel="icon"]').prop('href'), rootUrl).href; return { item: items, @@ -101,8 +102,8 @@ export const handler = async (ctx): Promise => { description: $('meta[name="description"]').prop('content'), language: $('html').prop('lang'), image, - icon: image, - logo: image, + icon, + logo: icon, subtitle: titleSplits[0], author: titleSplits.pop(), }; diff --git a/lib/routes/jiemian/lists.ts b/lib/routes/jiemian/lists.ts index b1205f6c5fda..60c2d5c67a08 100644 --- a/lib/routes/jiemian/lists.ts +++ b/lib/routes/jiemian/lists.ts @@ -7,7 +7,7 @@ export const route: Route = { parameters: { id: '分类 id,见下表,可在对应分类页 URL 中找到' }, name: '栏目', example: '/jiemian/lists/65', - maintainers: ['WenhuWee', 'nczitzk', 'pseudoyu'], + maintainers: ['WenhuWee', 'nczitzk'], handler, description: `| [首页](https://www.jiemian.com) | [商业](https://www.jiemian.com/lists/2.html) | [财经](https://www.jiemian.com/lists/800.html) | [新闻](https://www.jiemian.com/lists/801.html) | [文化生活](https://www.jiemian.com/lists/130.html) | [快报](https://www.jiemian.com/lists/4.html) | | ------------------------------- | -------------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | -------------------------------------------------- | -------------------------------------------- | diff --git a/lib/routes/jiemian/special.ts b/lib/routes/jiemian/special.ts index 782221141cab..44aca401eb7c 100644 --- a/lib/routes/jiemian/special.ts +++ b/lib/routes/jiemian/special.ts @@ -7,6 +7,6 @@ export const route: Route = { parameters: { id: '分类 id,见下表,可在对应分类页 URL 中找到' }, name: '专题', example: '/jiemian/special/1192', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, }; diff --git a/lib/routes/jiemian/video.ts b/lib/routes/jiemian/video.ts index b853b0379464..24e000f40fad 100644 --- a/lib/routes/jiemian/video.ts +++ b/lib/routes/jiemian/video.ts @@ -7,7 +7,7 @@ export const route: Route = { parameters: { id: '分类 id,见下表,可在对应分类页 URL 中找到' }, name: '视频', example: '/jiemian/video/lists/258_1', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| [界面 Vnews](https://www.jiemian.com/video/lists/258_1.html) | [直播](https://www.jiemian.com/videoLive/lists_1.html) | [箭厂](https://www.jiemian.com/video/lists/195_1.html) | [面谈](https://www.jiemian.com/video/lists/111_1.html) | [品牌创酷](https://www.jiemian.com/video/lists/226_1.html) | [番 茄社](https://www.jiemian.com/video/lists/567_1.html) | | ------------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | ---------------------------------------------------------- | --------------------------------------------------------- | diff --git a/lib/routes/jiemian/vip.ts b/lib/routes/jiemian/vip.ts index a3c7307f304b..a044a9ca5d1e 100644 --- a/lib/routes/jiemian/vip.ts +++ b/lib/routes/jiemian/vip.ts @@ -7,7 +7,7 @@ export const route: Route = { parameters: { id: '分类 id,见下表,可在对应分类页 URL 中找到' }, name: 'VIP', example: '/jiemian/pro/lists/12', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| [投资早晚报](https://www.jiemian.com/pro/lists/12.html) | [宏观晚 6 点](https://www.jiemian.com/pro/lists/20.html) | [打新早报](https://www.jiemian.com/pro/lists/21.html) | [盘前机会前瞻](https://www.jiemian.com/pro/lists/13.html) | [公告快评](https://www.jiemian.com/pro/lists/14.html) | [盘中必读](https://www.jiemian.com/pro/lists/15.html) | | ------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | diff --git a/lib/routes/jinse/catalogue.ts b/lib/routes/jinse/catalogue.ts index 87349171eb16..9f532467bc37 100644 --- a/lib/routes/jinse/catalogue.ts +++ b/lib/routes/jinse/catalogue.ts @@ -34,7 +34,7 @@ export const route: Route = { supportScihub: false, }, name: '分类', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| 政策 | 行情 | DeFi | 矿业 | 以太坊 2.0 | | ------- | ------------ | ---- | ----- | ---------- | diff --git a/lib/routes/jinse/lives.ts b/lib/routes/jinse/lives.ts index 78ea8421835b..12c2070e9f8d 100644 --- a/lib/routes/jinse/lives.ts +++ b/lib/routes/jinse/lives.ts @@ -37,7 +37,7 @@ export const route: Route = { supportScihub: false, }, name: '快讯', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| 全部 | 精选 | 政策 | 数据 | NFT | 项目 | | ---- | ---- | ---- | ---- | --- | ---- | diff --git a/lib/routes/jinse/timeline.ts b/lib/routes/jinse/timeline.ts index 237fd86a60d5..52271274fcee 100644 --- a/lib/routes/jinse/timeline.ts +++ b/lib/routes/jinse/timeline.ts @@ -44,7 +44,7 @@ export const route: Route = { supportScihub: false, }, name: '首页', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| 头条 | 独家 | 铭文 | 产业 | 项目 | | ------ | ---- | ------- | ---------- | ---- | diff --git a/lib/routes/joneslanglasalle/index.ts b/lib/routes/joneslanglasalle/index.ts index fb33b7003c08..1d9ca7c9c95a 100644 --- a/lib/routes/joneslanglasalle/index.ts +++ b/lib/routes/joneslanglasalle/index.ts @@ -1,96 +1,188 @@ +import type { Cheerio, CheerioAPI } from 'cheerio'; +import { load } from 'cheerio'; +import type { Element } from 'domhandler'; import type { Context } from 'hono'; import type { Data, DataItem, Route } from '@/types'; import { ViewType } from '@/types'; +import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; -const searchApiUrl = 'https://www.jll.com/api/search/template'; -const subscriptionKey = '8f6a4de5b0144673acaa89b03aac035e'; +import { renderDescription } from './templates/description'; -interface LocaleConfig { - apiLang: string; - countries: string[]; - insightsUrl: string; - title: string; -} +const cleanHtml = (html: string, preservedTags: string[]): string => { + const $ = load(html); -// Reason: each locale maps to a different country filter, API language code, and site URL -const localeMap: Record = { - zh: { - apiLang: 'zh-CN', - countries: ['China Mainland'], - insightsUrl: 'https://www.joneslanglasalle.com.cn/zh-cn/insights', - title: '洞察 - 仲量联行JLL', - }, - en: { - apiLang: 'en-GB', - countries: ['China Mainland'], - insightsUrl: 'https://www.joneslanglasalle.com.cn/en-cn/insights', - title: 'Insights - JLL China', - }, - 'zh-hk': { - apiLang: 'zh-HK', - countries: ['Hong Kong'], - insightsUrl: 'https://www.jll.com/zh-hk/insights', - title: '洞察 - 仲量聯行JLL 香港', - }, - 'en-hk': { - apiLang: 'en-GB', - countries: ['Hong Kong'], - insightsUrl: 'https://www.jll.com/en-hk/insights', - title: 'Insights - JLL Hong Kong', - }, + $('div.informationbox').remove(); + $('div.contributors').remove(); + + $('*') + .not(preservedTags.join(', ')) + .contents() + .filter((_, el) => el.type === 'text') + .remove(); + + $('*') + .not(preservedTags.join(', ')) + .filter((_, el) => $(el).children().length === 0) + .remove(); + + return $.html() || ''; }; export const handler = async (ctx: Context): Promise => { - const { language: lang = 'zh' } = ctx.req.param(); + const { language: lang = 'zh', category = 'trends-and-insights' } = ctx.req.param(); + // default limit is 12 const limit: number = Number.parseInt(ctx.req.query('limit') ?? '12', 10); - const locale = localeMap[lang] || localeMap.zh; + const rootUrl = 'https://www.joneslanglasalle.com.cn'; + const targetUrl: string = new URL(`${lang}/${category}`, rootUrl).href; - // Reason: site rebuilt with search API; old HTML scraping no longer works. - // Using the public search API (Elasticsearch-backed) with subscription key from page JS. - const response = await ofetch(searchApiUrl, { - method: 'POST', - headers: { - 'Subscription-Key': subscriptionKey, - 'Content-Type': 'application/json', - }, - body: { - id: 'jll_dynamic_list_search_template_v2', - params: { - size: limit, - from: 0, - countries: locale.countries, - language: locale.apiLang, - sort_by_relevance: false, - includeGlobalPeople: false, - boostCountry: '', - }, - }, - }); - - const items: DataItem[] = (response.hits?.hits || []).map((hit) => { - const source = hit._source; - return { - title: source.title, - description: source.description || source.subTitle || '', - link: source.pageUrl, - pubDate: source.datePublished ? parseDate(source.datePublished) : undefined, - category: [...(source.topics || []), ...(source.industries || [])], - image: source.imageUrl, - banner: source.imageUrl, - language: source.language, - }; - }); + const response = await ofetch(targetUrl); + const $: CheerioAPI = load(response); + const language: string = $('html').prop('lang') ?? 'en'; + + let items: DataItem[] = $('div.ti-title') + .slice(0, limit) + .toArray() + .map((item): DataItem => { + const $item: Cheerio = $(item); + const aEl = $item.closest('a'); + + const title: string = $item.text(); + const link: string | undefined = aEl.prop('href'); + + const description: string = renderDescription({ + intro: aEl.find('p.ti-teaser').text(), + }); + + const image: string | undefined = aEl.find('div.ti-image-container img').prop('src') ? new URL(aEl.find('div.ti-image-container img').prop('src') as string, rootUrl).href : undefined; + + return { + title, + description, + pubDate: parseDate(aEl.find('span.ti-date').text(), ['MM月DD日', 'MMMM DD']), + link: link ? new URL(link, rootUrl).href : undefined, + category: [aEl.find('span.ti-type').text()].filter(Boolean), + content: { + html: description, + text: aEl.find('p.ti-teaser').text(), + }, + image, + banner: image, + language, + }; + }); + + items = ( + await Promise.all( + items.map((item) => { + if (!item.link && typeof item.link !== 'string') { + return item; + } + + return cache.tryGet(item.link, async (): Promise => { + try { + const detailResponse = await ofetch(item.link); + const $$: CheerioAPI = load(detailResponse); + + const title: string = $$('meta[property="og:title"]').prop('content'); + const guid: string = $$('meta[property="og:url"]').prop('content'); + const image: string | undefined = $$('meta[property="og:image"]').prop('content'); + + const pubDate: Date = parseDate($$('div.publicationdate').text().trim(), ['YYYY 年MM 月DD 日', 'MMMM DD, YYYY']); + + const author: DataItem['author'] = $$('div.contributors ul li') + .toArray() + .map((el) => ({ + name: $$(el).text(), + })); + + const media: Record> = {}; + + $$('picture').each((_, el) => { + const $$el = $$(el); + + const src = $$el.find('source').last().prop('srcset') ? new URL($$el.find('source').last().prop('srcset') as string, rootUrl).href : undefined; + + if (src) { + $$el.replaceWith( + renderDescription({ + images: [ + { + src, + }, + ], + }) + ); + + const mediaType: string | undefined = src.split(/\./).pop(); + + if (mediaType) { + media[mediaType] = { url: src }; + } + } + }); + + const extraLinks = $$('div.related-content a.content-card') + .toArray() + .map((el) => { + const $$el: Cheerio = $$(el); + + return { + url: new URL($$el.prop('href') as string, rootUrl).href, + type: 'related', + content_html: $$el.find('div.content-card__body').html(), + }; + }) + .filter((_link): _link is { url: string; type: string; content_html: string } => true); + + const description: string = renderDescription({ + description: cleanHtml($$('div.page-section').eq(1).html() ?? $$('div.copy-block').html() ?? '', ['div.richtext p', 'h3', 'h4', 'h5', 'h6', 'figure', 'img', 'ul', 'li', 'span', 'b']), + }); + + return { + title, + description, + pubDate, + category: $$('meta[property="article:tag"]').prop('content').split(/,\s/), + author, + guid, + id: guid, + content: { + html: description, + text: description, + }, + image, + banner: image, + language, + media: Object.keys(media).length > 0 ? media : undefined, + _extra: { + links: extraLinks.length > 0 ? extraLinks : undefined, + }, + }; + } catch { + return item; + } + }); + }) + ) + ).filter((_): _ is DataItem => true); + + const title = $('title').text(); + const feedImage = $('img.logo').prop('src') ? new URL($('img.logo').prop('src') as string, rootUrl).href : undefined; return { - title: locale.title, - link: locale.insightsUrl, + title, + description: $('meta[property="og:description"]').prop('content'), + link: targetUrl, item: items, allowEmpty: true, - language: locale.apiLang, + image: feedImage, + author: title.split(/\|/).pop(), + language, + id: $('meta[property="og:url"]').prop('content'), }; }; @@ -102,25 +194,26 @@ export const route: Route = { handler, example: '/joneslanglasalle/en/trends-and-insights', parameters: { - language: 'Language, `zh` for China Mainland Chinese, `en` for China Mainland English, `zh-hk` for Hong Kong Chinese, `en-hk` for Hong Kong English, `zh` by default', + language: 'Language, `zh` by default', category: 'Category, `trends-and-insights` by default', }, description: `::: tip -If you subscribe to [Trends & Insights (China)](https://www.joneslanglasalle.com.cn/en-cn/insights), use \`en\` as the language. For [Hong Kong Insights](https://www.jll.com/zh-hk/insights), use \`zh-hk\` as the language. +If you subscribe to [Trends & Insights](https://www.joneslanglasalle.com.cn/en/trends-and-insights),where the URL is \`https://www.joneslanglasalle.com.cn/en/trends-and-insights\`, extract the part \`https://joneslanglasalle.com.cn/\` to the end. Use \`zh\` and \`trends-and-insights\` as the parameters to fill in. Therefore, the route will be [\`/joneslanglasalle/en/trends-and-insights\`](https://rsshub.app/joneslanglasalle/en/trends-and-insights). ::: -| Region | Language | Parameter | -| -------------- | -------- | --------- | -| China Mainland | 中文 | zh | -| China Mainland | English | en | -| Hong Kong | 中文 | zh-hk | -| Hong Kong | English | en-hk | +| Category | ID | +| --------- | ----------------------------- | +| Latest | trends-and-insights | +| Workplace | trends-and-insights/workplace | +| Investor | trends-and-insights/investor | +| Cities | trends-and-insights/cities | +| Research | trends-and-insights/research | `, categories: ['new-media'], features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportRadar: true, supportBT: false, supportPodcast: false, @@ -138,21 +231,53 @@ If you subscribe to [Trends & Insights (China)](https://www.joneslanglasalle.com }, { title: 'Latest', - source: ['joneslanglasalle.com.cn/en-cn/insights'], + source: ['joneslanglasalle.com.cn/en/trends-and-insights'], target: '/en/trends-and-insights', }, + { + title: 'Workplace', + source: ['joneslanglasalle.com.cn/en/trends-and-insights/workplace'], + target: '/en/trends-and-insights/workplace', + }, + { + title: 'Investor', + source: ['joneslanglasalle.com.cn/en/trends-and-insights/investor'], + target: '/en/trends-and-insights/investor', + }, + { + title: 'Cities', + source: ['joneslanglasalle.com.cn/en/trends-and-insights/cities'], + target: '/en/trends-and-insights/cities', + }, + { + title: 'Research', + source: ['joneslanglasalle.com.cn/en/trends-and-insights/research'], + target: '/en/trends-and-insights/research', + }, { title: '房地产趋势与洞察', - source: ['joneslanglasalle.com.cn/zh-cn/insights'], + source: ['joneslanglasalle.com.cn/zh/trends-and-insights'], target: '/zh/trends-and-insights', }, { - source: ['jll.com/zh-hk/insights'], - target: '/zh-hk/trends-and-insights', + title: '办公空间', + source: ['joneslanglasalle.com.cn/zh/trends-and-insights/workplace'], + target: '/zh/trends-and-insights/workplace', + }, + { + title: '投资者', + source: ['joneslanglasalle.com.cn/zh/trends-and-insights/investor'], + target: '/zh/trends-and-insights/investor', + }, + { + title: '城市', + source: ['joneslanglasalle.com.cn/zh/trends-and-insights/cities'], + target: '/zh/trends-and-insights/cities', }, { - source: ['jll.com/en-hk/insights'], - target: '/en-hk/trends-and-insights', + title: '研究报告', + source: ['joneslanglasalle.com.cn/zh/trends-and-insights/research'], + target: '/zh/trends-and-insights/research', }, ], view: ViewType.Articles, @@ -161,23 +286,24 @@ If you subscribe to [Trends & Insights (China)](https://www.joneslanglasalle.com path: '/:language?/:category{.+}?', name: '房地产趋势与洞察', url: 'joneslanglasalle.com.cn', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, example: '/joneslanglasalle/zh/trends-and-insights', parameters: { - language: '语言,`zh` 为中国大陆中文,`en` 为中国大陆英文,`zh-hk` 为香港中文,`en-hk` 为香港英文,默认为 `zh`', - category: '分类,默认为 `trends-and-insights`', + language: '语言,默认为 `zh`,可在对应分类页 URL 中找到', + category: '分类,默认为 `trends-and-insights`,可在对应分类页 URL 中找到', }, description: `::: tip -若订阅 [中国大陆洞察](https://www.joneslanglasalle.com.cn/zh-cn/insights),语言参数为 \`zh\`。若订阅 [香港洞察](https://www.jll.com/zh-hk/insights),语言参数为 \`zh-hk\`。 +若订阅 [房地产趋势与洞察](https://www.joneslanglasalle.com.cn/zh/trends-and-insights),网址为 \`https://www.joneslanglasalle.com.cn/zh/trends-and-insights\`,请截取 \`https://joneslanglasalle.com.cn/\` 到末尾的部分 \`zh\` 和 \`trends-and-insights\` 作为 \`language\` 和 \`category\` 参数填入,此时目标路由为 [\`/joneslanglasalle/zh/trends-and-insights\`](https://rsshub.app/joneslanglasalle/zh/trends-and-insights)。 ::: -| 地区 | 语言 | 参数 | -| ------ | ------- | ----- | -| 中国大陆 | 中文 | zh | -| 中国大陆 | English | en | -| 香港 | 中文 | zh-hk | -| 香港 | English | en-hk | +| 分类名称 | 分类 ID | +| ---------- | ----------------------------- | +| 趋势及洞察 | trends-and-insights | +| 办公空间 | trends-and-insights/workplace | +| 投资者 | trends-and-insights/investor | +| 城市 | trends-and-insights/cities | +| 研究报告 | trends-and-insights/research | `, }, }; diff --git a/lib/routes/joneslanglasalle/templates/description.tsx b/lib/routes/joneslanglasalle/templates/description.tsx new file mode 100644 index 000000000000..7a40f8331d6c --- /dev/null +++ b/lib/routes/joneslanglasalle/templates/description.tsx @@ -0,0 +1,27 @@ +import { raw } from 'hono/html'; +import { renderToString } from 'hono/jsx/dom/server'; + +type DescriptionImage = { + src?: string; + alt?: string; +}; + +type DescriptionVideo = { + src?: string; +}; + +type DescriptionData = { + images?: DescriptionImage[]; + videos?: DescriptionVideo[]; + intro?: string; + description?: string; +}; + +export const renderDescription = ({ images, videos, intro, description }: DescriptionData) => + renderToString( + <> + {images?.length ? images.map((image) => (!videos?.[0]?.src && image?.src ?
{image.alt ? {image.alt} : }
: null)) : null} + {intro ?
{intro}
: null} + {description ? raw(description) : null} + + ); diff --git a/lib/routes/kuaidi100/utils.ts b/lib/routes/kuaidi100/utils.ts index 9fa3132798dd..7d6bd38ac830 100644 --- a/lib/routes/kuaidi100/utils.ts +++ b/lib/routes/kuaidi100/utils.ts @@ -230,6 +230,7 @@ export default { headers: { Referer: 'https://www.kuaidi100.com/', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36', Cookie: `${cookie.globacsrftoken}; ${cookie.csrf}; ${cookie.wwwid}; ${cookie.dasddocHref}; ${cookie.dasddocReferrer}; ${ cookie.dasddocTitl }; addcom=${number}; addnu=${id}; snt_query_meta=${queryMeta}; sortStatus=0; Hm_lpvt_22ea01af58ba2be0fec7c11b25e88e6c=${timestamp}; Hm_lvt_22ea01af58ba2be0fec7c11b25e88e6c=${timestamp - 1642}`, diff --git a/lib/routes/kyodonews/index.tsx b/lib/routes/kyodonews/index.tsx index 1918bfc68ccb..070d9d80b38f 100644 --- a/lib/routes/kyodonews/index.tsx +++ b/lib/routes/kyodonews/index.tsx @@ -2,6 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; +import ConfigNotFoundError from '@/errors/types/config-not-found'; import InvalidParameterError from '@/errors/types/invalid-parameter'; import type { Route } from '@/types'; import cache from '@/utils/cache'; @@ -24,16 +25,6 @@ export const route: Route = { supportPodcast: false, supportScihub: false, }, - radar: [ - { - source: ['china.kyodonews.net/news/:keyword', 'china.kyodonews.net/'], - target: '/china/:keyword?', - }, - { - source: ['tchina.kyodonews.net/news/:keyword', 'tchina.kyodonews.net/'], - target: '/tchina/:keyword?', - }, - ], name: '最新报道', maintainers: ['Rongronggg9'], handler, @@ -46,11 +37,11 @@ async function handler(ctx) { // raise error for invalid languages if (!['china', 'tchina'].includes(language)) { - throw new InvalidParameterError('Invalid language'); + throw new ConfigNotFoundError('Invalid language'); } const rootUrl = `https://${language}.kyodonews.net`; - const currentUrl = `${rootUrl}/${keyword ? (keyword === 'rss' ? 'list/feed/rss4news' : `news/${keyword}`) : ''}`; + const currentUrl = `${rootUrl}/${keyword ? (keyword === 'rss' ? 'rss/news.xml' : `news/${keyword}`) : ''}`; let response; try { @@ -62,7 +53,7 @@ async function handler(ctx) { const $ = load(response.data, { xmlMode: keyword === 'rss' }); let title, description, image, items; - image = `https://${language}-kyodo.ismcdn.jp/common/images/apple-touch-icon-180x180.png`; + image = `${rootUrl}/apple-touch-icon-180x180.png`; if (keyword === 'rss') { title = $('channel > title').text(); @@ -82,11 +73,11 @@ async function handler(ctx) { title = $('head > title').text(); description = $('meta[name="description"]').attr('content'); image = resolveRelativeLink($('head > link[rel="apple-touch-icon"]').attr('href'), rootUrl) || image; - items = $('.m-article-wrap:first-of-type .m-article-item__link') + items = $('div.sec-latest > ul > li') .toArray() .map((item) => { item = $(item); - const link = item.attr('href'); + const link = item.find('a').attr('href'); return { link: resolveRelativeLink(link, rootUrl), }; @@ -103,7 +94,18 @@ async function handler(ctx) { item.author = $('meta[name="author"]').attr('content'); // add main pic - const mainPicArea = $('.article-header-img'); + const mainPicArea = $('div.mainpic'); + mainPicArea.find('div').each((_, elem) => { + elem = $(elem); + elem.css('text-align', 'center'); + }); + // moving `data-src` to `src` + mainPicArea.find('img').each((_, img) => { + img = $(img); + img.attr('src', img.attr('data-src')); + img.removeAttr('data-src'); + img.wrap('
'); + }); let mainPic = mainPicArea.html(); mainPic = mainPic ? mainPic.trim() : ''; @@ -114,22 +116,28 @@ async function handler(ctx) { // render description item.description = renderToString( <> - {mainPic ? raw(mainPic) : null} + {mainPic ? ( + <> + {raw(mainPic)} +
+
+ + ) : null} {articleBody ? raw(articleBody) : null} ); - const ldJson = JSON.parse($('script[type="application/ld+json"]').text() || '[]').find((obj) => obj['@type'] === 'NewsArticle'); - const pubDateMatch = ldJson && ldJson.datePublished; - const updatedMatch = ldJson && ldJson.dateModified; - if (pubDateMatch) { - item.pubDate = timezone(parseDate(pubDateMatch), 9); + const ldJson = $('script[type="application/ld+json"]').html(); + const pubDate_match = ldJson && ldJson.match(/"datePublished":"([\d\s-:]*?)"/); + const updated_match = ldJson && ldJson.match(/"dateModified":"([\d\s-:]*?)"/); + if (pubDate_match) { + item.pubDate = timezone(parseDate(pubDate_match[1]), 9); } - if (updatedMatch) { - item.updated = timezone(parseDate(updatedMatch), 9); + if (updated_match) { + item.updated = timezone(parseDate(updated_match[1]), 9); } - item.category = $('.article-header-cate__link') + item.category = $('p.credit > a') .toArray() .map((a) => $(a).text()); return item; diff --git a/lib/routes/locals/feed.ts b/lib/routes/locals/feed.ts deleted file mode 100644 index c0e428c90be4..000000000000 --- a/lib/routes/locals/feed.ts +++ /dev/null @@ -1,436 +0,0 @@ -import vm from 'node:vm'; - -import { config } from '@/config'; -import ConfigNotFoundError from '@/errors/types/config-not-found'; -import type { DataItem, Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -const contentFilterMap = { - nonplus: 'regular_content', - plus: 'content_plus', -} as const; - -const contentTypeMap = { - article: 'article', - audio: 'audio', - document: 'document', - live: 'live_stream', - live_stream: 'live_stream', - pdf: 'document', - podcast: 'audio', - podcasts: 'audio', - video: 'video', -} as const; - -const rootUrl = 'https://locals.com'; - -type ContentFilter = keyof typeof contentFilterMap; -type ContentType = keyof typeof contentTypeMap; - -type LocalsPost = { - audios?: Array<{ - preview?: string; - }>; - author_name?: string; - author_username?: string; - content_plus?: { - enabled?: boolean; - }; - content_type?: string; - photos?: Array<{ - sizes?: { - full?: { - url?: string; - }; - thumb?: { - url?: string; - }; - }; - }>; - post_date?: string; - published?: string; - previews?: Array<{ - first_frame_url?: string; - url?: string; - }>; - share_url?: string; - subtitle?: string; - text?: string; - title?: string; - is_content?: boolean; - videos?: Array<{ - preview?: string; - source?: string; - }>; -}; - -type LocalsResponse = { - code: string; - data: LocalsPost[]; -}; - -type LocalsCommunityInfo = { - description?: string; - design?: { - image?: { - big?: string; - thumb?: string; - }; - }; - hashtag: string; - id: number; - title: string; -}; - -export const route: Route = { - path: '/content/:community/:option1?/:option2?', - categories: ['social-media'], - example: '/locals/content/mattfradd/video', - parameters: { - community: 'Community slug from `locals.com/:community/feed?mode=content`', - option1: 'Filter or content type. Filters: `plus`, `nonplus`. Content types: `video`, `live`, `audio`, `podcast`, `article`, `document`, `pdf`', - option2: 'Content type when `option1` is a filter', - }, - description: 'Fetches the Locals content library with an authenticated session cookie. By default it merges regular content and content+ posts, and it can be filtered by access tier and media type.', - features: { - requireConfig: [ - { - name: 'LOCALS_SESSION', - description: 'The value of the `locals2.v3.session` cookie after logging in to Locals', - }, - ], - requirePuppeteer: false, - antiCrawler: true, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['locals.com/:community/feed'], - target: '/content/:community', - }, - ], - name: 'Content Feed', - maintainers: ['luckycold'], - handler, -}; - -function getCookieHeader(session: string) { - return [`locals2.v3.session=${session}`, 'locals.preferLocals2=false', 'locals2.v3.locale.actual=en-us%2Cen', 'locals2.v3.locale.inferred=en'].join('; '); -} - -function getRequestHeaders(session: string) { - return { - Cookie: getCookieHeader(session), - }; -} - -function extractAssetUrls(html: string) { - return [...new Set([...html.matchAll(/\/_build\/assets\/[^"'\s>]+\.js/g)].map((match) => match[0]))]; -} - -function extractFeedActionId(asset: string) { - const symbol = asset.match(/getFeedPosts:([A-Za-z_$][\w$]*)/)?.[1]; - if (!symbol) { - return; - } - - const match = asset.match(new RegExp(`${symbol}=s\\(\\(\\)=>\\{\\},"([^"]+)","([^"]+)"\\)`)); - if (!match) { - return; - } - - return `${match[1]}#${match[2]}`; -} - -function createRequestBody(value: unknown) { - let nextIndex = 0; - - const encode = (input: unknown): object => { - if (typeof input === 'number') { - return { t: 0, s: input }; - } - - if (typeof input === 'string') { - return { t: 1, s: input }; - } - - if (Array.isArray(input)) { - const i = nextIndex++; - return { - a: input.map((item) => encode(item)), - i, - l: input.length, - o: 0, - t: 9, - }; - } - - if (input && typeof input === 'object') { - const i = nextIndex++; - const entries = Object.entries(input).filter(([, item]) => item !== undefined); - - return { - i, - o: 0, - p: { - k: entries.map(([key]) => key), - s: entries.length, - v: entries.map(([, item]) => encode(item)), - }, - t: 10, - }; - } - - throw new Error('Unsupported Locals request payload.'); - }; - - return JSON.stringify({ - f: 31, - m: [], - t: encode(value), - }); -} - -function parseUnknownResponse(body: string, instanceId: string): T { - const sandbox = { - $R: {}, - self: {}, - } as { - $R: Record; - self: { - $R?: Record; - }; - }; - - sandbox.self.$R = sandbox.$R; - - vm.createContext(sandbox); - vm.runInContext(body, sandbox, { timeout: 5000 }); - - const value = sandbox.self.$R?.[instanceId]?.[0] as T | undefined; - if (!value) { - throw new Error('Unable to decode the Locals server response.'); - } - - return value; -} - -function extractCommunityInfo(html: string, community: string) { - const markerIndex = html.indexOf(`hashtag:"${community}"`); - if (markerIndex === -1) { - throw new Error('Unable to resolve the Locals community metadata.'); - } - - const context = html.slice(Math.max(0, markerIndex - 200), markerIndex + 1200); - const idMatch = context.match(/id:(\d+)/); - const titleMatch = context.match(/title:"([^"]+)"/); - const descriptionMatch = context.match(/description:"([^"]*)"/); - const imageMatch = context.match(/image:\$R\[\d+\]=\{big:"([^"]*)",thumb:"([^"]*)"/); - - if (!idMatch || !titleMatch) { - throw new Error('Unable to resolve the Locals community metadata.'); - } - - return { - description: descriptionMatch?.[1], - design: { - image: { - big: imageMatch?.[1] || undefined, - thumb: imageMatch?.[2] || undefined, - }, - }, - hashtag: community, - id: Number(idMatch[1]), - title: titleMatch[1], - } satisfies LocalsCommunityInfo; -} - -function fetchContentPage(community: string, session: string) { - return cache.tryGet(`locals:content-page:${community}`, () => ofetch(`${rootUrl}/${community}/feed?mode=content`, { headers: getRequestHeaders(session) })); -} - -function resolveActionIds(community: string, session: string) { - return cache.tryGet(`locals:action-ids:${community}`, async () => { - const html = await fetchContentPage(community, session); - const serverApiAsset = extractAssetUrls(html).find((assetUrl) => assetUrl.includes('/serverApi-')); - if (!serverApiAsset) { - throw new Error('Unable to locate the current Locals serverApi asset.'); - } - - const assetContent = await ofetch(new URL(serverApiAsset, rootUrl).href, { - headers: getRequestHeaders(session), - }); - const serverId = extractFeedActionId(assetContent); - - if (!serverId) { - throw new Error('Unable to discover the current Locals feed action id.'); - } - - return serverId; - }); -} - -function getImage(post: LocalsPost) { - return post.photos?.[0]?.sizes?.full?.url || post.photos?.[0]?.sizes?.thumb?.url || post.previews?.[0]?.url || post.previews?.[0]?.first_frame_url || post.videos?.[0]?.preview || post.audios?.[0]?.preview; -} - -function getTitle(post: LocalsPost) { - const textFallback = post.text - ?.replaceAll(/<[^>]+>/g, '\n') - .split('\n') - .map((line) => line.trim()) - .find(Boolean); - return post.title || post.subtitle || textFallback || post.share_url || 'Locals post'; -} - -function renderDescription(image: string | undefined, description: string | undefined) { - if (image && description) { - return `

${description}`; - } - - if (image) { - return `

`; - } - - return description; -} - -function mapPostToItem(post: LocalsPost): DataItem | null { - const image = getImage(post); - const hasBodyContent = Boolean(post.text || image || post.photos?.length || post.videos?.length || post.audios?.length); - - if (!post.share_url || (!post.is_content && post.content_type === 'no_content' && !hasBodyContent)) { - return null; - } - - const contentType = post.content_type && post.content_type !== 'no_content' ? [post.content_type] : []; - const accessType = post.content_plus?.enabled ? ['content_plus'] : ['content']; - - return { - author: post.author_name || post.author_username, - category: [...accessType, ...contentType], - description: renderDescription(image, post.text), - image, - itunes_item_image: image, - link: post.share_url, - pubDate: post.published ? parseDate(post.published) : post.post_date ? parseDate(post.post_date) : undefined, - title: getTitle(post), - }; -} - -function parseOptions(option1: string | undefined, option2: string | undefined) { - const values = [option1, option2].filter(Boolean) as string[]; - const hasFilter = (value: string): value is ContentFilter => Object.hasOwn(contentFilterMap, value); - const hasContentType = (value: string): value is ContentType => Object.hasOwn(contentTypeMap, value); - const filter = values.find((value) => hasFilter(value)); - const contentType = values.find((value) => hasContentType(value)); - const unknown = values.find((value) => !hasFilter(value) && !hasContentType(value)); - - if (unknown) { - throw new Error('Invalid Locals content route option. Supported filters are `plus` and `nonplus`, and supported content types are `video`, `live`, `audio`, `podcast`, `article`, `document`, and `pdf`.'); - } - - return { - contentType: contentType ? contentTypeMap[contentType] : undefined, - filter, - }; -} - -async function requestServerFunction(session: string, id: string, key: string, args: unknown[]) { - const response = await ofetch.raw(`${rootUrl}/_server`, { - body: createRequestBody(args), - headers: { - 'Content-Type': 'application/json', - ...getRequestHeaders(session), - 'X-Server-Id': id, - 'X-Server-Instance': key, - }, - method: 'POST', - responseType: 'text', - }); - - if (!response.ok) { - throw new Error(`Unable to access the Locals server function (${response.status}).`); - } - - return parseUnknownResponse(response._data, key); -} - -function fetchCommunityInfo(community: string, session: string) { - return cache.tryGet(`locals:community:${community}`, async () => { - const html = await fetchContentPage(community, session); - return extractCommunityInfo(html, community); - }); -} - -async function fetchFeedData(communityId: number, community: string, session: string, serverId: string, filter: ContentFilter | undefined, contentType: string | undefined) { - const requestFilter = filter ? contentFilterMap[filter] : undefined; - const filters = requestFilter ? [requestFilter] : Object.values(contentFilterMap); - - const responses = await Promise.all( - filters.map((currentFilter) => - cache.tryGet(`locals:data:${communityId}:${community}:${currentFilter}:${contentType ?? 'all'}`, () => - requestServerFunction(session, serverId, `server-fn:rsshub-${community}-${currentFilter}-${contentType ?? 'all'}`, [ - { - communityId, - contentType, - filter: currentFilter, - order: 'recent', - page: 1, - pageSize: 20, - }, - ]) - ) - ) - ); - - const items = new Map(); - - for (const response of responses) { - for (const post of response.data) { - const item = mapPostToItem(post); - if (!item?.link) { - continue; - } - - if (!items.has(item.link)) { - items.set(item.link, item); - continue; - } - - const existing = items.get(item.link); - if (existing) { - existing.category = [...new Set([...(existing.category ?? []), ...(item.category ?? [])])]; - existing.description = existing.description || item.description; - existing.itunes_item_image = existing.itunes_item_image || item.itunes_item_image; - } - } - } - - return [...items.values()]; -} - -async function handler(ctx) { - const { community, option1, option2 } = ctx.req.param(); - - if (!config.locals?.session) { - throw new ConfigNotFoundError('Locals RSS is disabled due to the lack of relevant config'); - } - - const { contentType, filter } = parseOptions(option1, option2); - const serverId = await resolveActionIds(community, config.locals.session); - const communityInfo = await fetchCommunityInfo(community, config.locals.session); - const items = await fetchFeedData(communityInfo.id, community, config.locals.session, serverId, filter, contentType); - - return { - description: `Locals content feed for ${communityInfo.title}${filter ? ` (${filter})` : ''}${contentType ? ` (${contentType})` : ''}`, - image: communityInfo.design?.image?.big || communityInfo.design?.image?.thumb, - item: items, - link: `https://locals.com/${community}/feed?mode=content${contentType ? `&content=${contentType}` : ''}`, - title: `Locals - ${communityInfo.title}`, - }; -} diff --git a/lib/routes/locals/namespace.ts b/lib/routes/locals/namespace.ts deleted file mode 100644 index d40c25890ed5..000000000000 --- a/lib/routes/locals/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'Locals', - url: 'locals.com', - lang: 'en', -}; diff --git a/lib/routes/nanhua/namespace.ts b/lib/routes/nanhua/namespace.ts deleted file mode 100644 index 53dd19eee902..000000000000 --- a/lib/routes/nanhua/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: '南华期货', - url: 'mall.nanhua.net', - lang: 'zh-CN', -}; diff --git a/lib/routes/nanhua/report.ts b/lib/routes/nanhua/report.ts deleted file mode 100644 index a34dcbac25a4..000000000000 --- a/lib/routes/nanhua/report.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { Context } from 'hono'; - -import type { DataItem, Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; -import timezone from '@/utils/timezone'; - -export const route: Route = { - path: '/report/:type1/:type2', - categories: ['finance'], - example: '/nanhua/report/WEEK/WEEK_black', - parameters: { - type1: '一级分类代码,如 `WEEK`(周度报告)、`SEASON`(季年报告)、`HOT`(热点报告)等,需要使用 `encodeURIComponent` 编码', - type2: '二级分类代码,如 `WEEK_black`(黑色)、`WEEK_enchem`(能化)等,需要使用 `encodeURIComponent` 编码', - }, - radar: [ - { - source: ['mall.nanhua.net/mall/r/w/reportNew/report-list.html'], - target: (_, url) => { - const params = new URL(url).searchParams; - const type1 = params.get('type1'); - const type2 = params.get('type2'); - return type1 && type2 ? `/nanhua/report/${encodeURIComponent(type1)}/${encodeURIComponent(type2)}` : ''; - }, - }, - ], - name: '研报', - maintainers: ['TonyRL'], - handler, - url: 'mall.nanhua.net/mall/r/w/reportNew/report-list.html', -}; - -async function handler(ctx: Context) { - const { type1, type2 } = ctx.req.param(); - const baseUrl = 'https://mall.nanhua.net'; - const apiBase = `${baseUrl}/mall/nh/api`; - const link = `${baseUrl}/mall/r/w/reportNew/report-list.html?type1=${type1}&type2=${type2}`; - - const treeList = await cache.tryGet('nanhua:treeList', async () => { - const response = await ofetch(`${apiBase}/reportType/getTreeList.json`, { - method: 'POST', - body: {}, - }); - return response.data; - }); - - const response = await ofetch(`${apiBase}/report/getPage.json`, { - method: 'POST', - body: { - type1Code: type1, - type2Code: type2, - pageSize: ctx.req.query('limit') || '20', - }, - }); - - const parent = treeList.find((item) => item.type === type1); - const child = parent?.children?.find((item) => item.type === type2); - - const items: DataItem[] = response.data.result.map((item) => ({ - title: item.title, - description: item.content || item.summary || item.desc, - link: item.fileName ? `${apiBase}/report/getReportFile?reportId=${item.id}&filetitle=${item.fileName}` : /^\d+$/.test(item.id) ? item.detailUrl : `${baseUrl}/mall/r/w/reportNew/report-list-page.html?id=${item.id}`, - pubDate: timezone(parseDate(item.createTime), 8), - author: item.personName, - category: [item.type1Name, item.type2Name, item.typeName].filter(Boolean), - image: item.iconUrl, - })); - - return { - title: `南华期货 - ${parent?.name ?? type1} - ${child?.name ?? type2}`, - link, - language: 'zh-CN' as const, - image: `${baseUrl}/favicon.ico`, - item: items, - }; -} diff --git a/lib/routes/nhentai/index.ts b/lib/routes/nhentai/index.ts index 63f87caf56f3..043f0fe1078a 100644 --- a/lib/routes/nhentai/index.ts +++ b/lib/routes/nhentai/index.ts @@ -15,7 +15,6 @@ export const route: Route = { mode: 'mode, `simple` to only show cover, `detail` to show all pages, `torrent` to include Magnet URI, need login, refer to [Route-specific Configurations](https://docs.rsshub.app/deploy/config#route-specific-configurations), default to `simple`', }, features: { - requirePuppeteer: false, antiCrawler: true, supportBT: true, nsfw: true, @@ -27,7 +26,7 @@ export const route: Route = { }, ], name: 'Filter', - maintainers: ['MegrezZhu', 'hoilc', 'pseudoyu'], + maintainers: ['MegrezZhu', 'hoilc'], handler, }; diff --git a/lib/routes/nhentai/search.ts b/lib/routes/nhentai/search.ts index a550356735ec..9d354e225ae1 100644 --- a/lib/routes/nhentai/search.ts +++ b/lib/routes/nhentai/search.ts @@ -11,7 +11,6 @@ export const route: Route = { mode: 'mode, `simple` to only show cover, `detail` to show all pages, `torrent` to include Magnet URI, need login, refer to [Route-specific Configurations](https://docs.rsshub.app/deploy/config#route-specific-configurations), default to `simple`', }, features: { - requirePuppeteer: false, antiCrawler: true, supportBT: true, nsfw: true, @@ -23,7 +22,7 @@ export const route: Route = { }, ], name: 'Advanced Search', - maintainers: ['MegrezZhu', 'hoilc', 'pseudoyu'], + maintainers: ['MegrezZhu', 'hoilc'], handler, }; diff --git a/lib/routes/nhentai/util.tsx b/lib/routes/nhentai/util.tsx index 50fc28432294..3201a4158eb1 100644 --- a/lib/routes/nhentai/util.tsx +++ b/lib/routes/nhentai/util.tsx @@ -6,7 +6,6 @@ import ConfigNotFoundError from '@/errors/types/config-not-found'; import got from '@/utils/got'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; -import { getPuppeteerPage } from '@/utils/puppeteer'; const baseUrl = 'https://nhentai.net'; @@ -66,32 +65,16 @@ const getCookie = async (username, password, cache) => { return userTokenCookie; }; -// Reason: try ofetch first for speed, fall back to puppeteer on 403 (anti-bot protection) -const fetchPage = async (url: string): Promise => { - try { - return await ofetch(url); - } catch (error: unknown) { - const status = (error as { status?: number; statusCode?: number }).status ?? (error as { status?: number; statusCode?: number }).statusCode; - if (status === 403) { - const { page, destroy } = await getPuppeteerPage(url, { - onBeforeLoad: async (page) => { - const allowedTypes = new Set(['document', 'script', 'xhr', 'fetch']); - await page.setRequestInterception(true); - page.on('request', (request) => { - allowedTypes.has(request.resourceType()) ? request.continue() : request.abort(); - }); - }, - }); - const content = await page.content(); - await destroy(); - return content; - } - throw error; - } -}; +const oFetch = (url, ...options) => + ofetch(url, { + ...options, + headers: { + host: 'nhentai.net', + }, + }); const getSimple = async (url) => { - const data = await fetchPage(url); + const data = await oFetch(url); const $ = load(data); return $('.gallery a.cover') @@ -130,9 +113,7 @@ const parseSimpleDetail = ($ele) => { const getTorrent = async (simple, cookie) => { const { link } = simple; - const response = await ofetch(link + 'download', { - headers: { Cookie: cookie }, - }); + const response = await oFetch(link + 'download', { followRedirect: false, responseType: 'buffer', headers: { Cookie: cookie } }); return { ...simple, enclosure_url: response, @@ -142,7 +123,7 @@ const getTorrent = async (simple, cookie) => { const getDetail = async (simple) => { const { link } = simple; - const data = await fetchPage(link); + const data = await oFetch(link); const $ = load(data); const galleryImgs = $('.gallerythumb img') diff --git a/lib/routes/perplexity/blog.ts b/lib/routes/perplexity/blog.ts index c55ebac1a57c..98f3f61cd096 100644 --- a/lib/routes/perplexity/blog.ts +++ b/lib/routes/perplexity/blog.ts @@ -38,7 +38,7 @@ async function handler(ctx: Context) { const limit = Number.parseInt(ctx.req.query('limit') ?? '20', 10); const rootUrl = 'https://www.perplexity.ai/hub'; - const { page, destroy, browser } = await getPuppeteerPage(rootUrl, { + const { page, destory, browser } = await getPuppeteerPage(rootUrl, { onBeforeLoad: async (page) => { await page.setRequestInterception(true); page.on('request', (request) => { @@ -119,9 +119,7 @@ async function handler(ctx: Context) { request.resourceType() === 'document' ? request.continue() : request.abort(); }); - await contentPage.goto(item.link!, { - waitUntil: 'domcontentloaded', - }); + await contentPage.goto(item.link!, { waitUntil: 'domcontentloaded' }); const contentHtml = await contentPage.evaluate(() => document.documentElement.innerHTML); await contentPage.close(); @@ -150,7 +148,7 @@ async function handler(ctx: Context) { }) ); - await destroy(); + await destory(); return { title: 'Perplexity Blog', diff --git a/lib/routes/perplexity/changelog.ts b/lib/routes/perplexity/changelog.ts index 9d4698e5e497..b6dd5ecd0e21 100644 --- a/lib/routes/perplexity/changelog.ts +++ b/lib/routes/perplexity/changelog.ts @@ -16,7 +16,7 @@ export const handler = async (ctx: Context): Promise => { logger.http(`Fetching Perplexity changelog from ${targetUrl}`); - const { page, destroy, browser } = await getPuppeteerPage(targetUrl, { + const { page, destory, browser } = await getPuppeteerPage(targetUrl, { onBeforeLoad: async (page) => { await page.setRequestInterception(true); page.on('request', (request) => { @@ -131,7 +131,7 @@ export const handler = async (ctx: Context): Promise => { ); // Close the browser session after all requests are done - await destroy(); + await destory(); return { title: $('title').text() || 'Perplexity Changelog', diff --git a/lib/routes/peterwunder/achievements.ts b/lib/routes/peterwunder/achievements.ts deleted file mode 100644 index 3ba06d5d61c8..000000000000 --- a/lib/routes/peterwunder/achievements.ts +++ /dev/null @@ -1,138 +0,0 @@ -import type { CheerioAPI } from 'cheerio'; -import { load } from 'cheerio'; - -import type { DataItem, Route } from '@/types'; -import { ViewType } from '@/types'; -import cache from '@/utils/cache'; -import got from '@/utils/got'; -import { parseDate } from '@/utils/parse-date'; - -const author = 'Peter Wunder'; -const rootUrl = 'https://projects.peterwunder.de'; -const currentUrl = new URL('/achievements/', rootUrl).href; -const icon = new URL('/achievements/images/touchicon.png', rootUrl).href; -const defaultLimit = 20; - -type BadgeItem = DataItem & { - link: string; - title: string; -}; - -function absolutizeImageSource($: CheerioAPI, itemUrl: string) { - $('article') - .first() - .find('[src]') - .each((_, element) => { - const value = $(element).attr('src'); - - if (value) { - $(element).attr('src', new URL(value, itemUrl).href); - } - }); -} - -function extractBadgeDescription($: CheerioAPI) { - const article = $('article').first(); - - if (!article.length) { - return; - } - - article.find('h1, script, style, noscript').remove(); - - return article.html() ?? undefined; -} - -function extractListItems($: CheerioAPI, limit: number): BadgeItem[] { - return $('section.badges a.badge') - .slice(0, limit) - .toArray() - .map((element) => { - const badge = $(element); - const href = badge.attr('href'); - const title = badge.find('.title').text().trim(); - - if (!href || !title) { - return null; - } - - const image = badge.find('img').attr('src'); - const visibleStart = badge.attr('data-vis-start'); - - return { - title, - link: new URL(href, rootUrl).href, - pubDate: visibleStart ? parseDate(visibleStart) : undefined, - image: image ? new URL(image, rootUrl).href : undefined, - }; - }) - .filter(Boolean) as BadgeItem[]; -} - -function fetchBadge(item: BadgeItem) { - return cache.tryGet(item.link, async () => { - const { data: response } = await got(item.link); - const $: CheerioAPI = load(response); - - const title = $('article h1').first().text().trim(); - const visibleStart = $('ul.metadata li').first().find('time.date').first().attr('datetime'); - const image = $('meta[property="og:image"]').attr('content'); - absolutizeImageSource($, item.link); - - return { - ...item, - title: title || item.title, - description: extractBadgeDescription($), - pubDate: visibleStart ? parseDate(visibleStart) : item.pubDate, - author, - image: image ? new URL(image, rootUrl).href : item.image, - }; - }); -} - -const handler: Route['handler'] = async (ctx) => { - const limit = Math.max(Number.parseInt(ctx.req.query('limit') ?? '', 10) || defaultLimit, 1); - - const { data: response } = await got(currentUrl); - const $: CheerioAPI = load(response); - - const items = await Promise.all(extractListItems($, limit).map((item) => fetchBadge(item))); - - return { - title: 'All Activity Challenges - New Badges', - description: "Latest badge pages from Peter Wunder's All Activity Challenges catalog. The website's own Atom feed was discontinued on August 20, 2024, so this route follows the latest entries directly from the site.", - link: currentUrl, - item: items, - language: 'en', - author, - icon, - logo: icon, - image: icon, - }; -}; - -export const route: Route = { - path: '/achievements', - categories: ['other'], - view: ViewType.Pictures, - example: '/peterwunder/achievements', - parameters: {}, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['projects.peterwunder.de/achievements'], - }, - ], - name: 'New Badges', - maintainers: ['LinxHex'], - description: "Latest badge pages from Peter Wunder's All Activity Challenges catalog. `pubDate` uses the first 'Visible in the app' date because the site does not expose a publication timestamp.", - handler, - url: 'projects.peterwunder.de/achievements', -}; diff --git a/lib/routes/peterwunder/namespace.ts b/lib/routes/peterwunder/namespace.ts deleted file mode 100644 index 52e07a75e2fd..000000000000 --- a/lib/routes/peterwunder/namespace.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'Peter Wunder', - url: 'projects.peterwunder.de', - categories: ['other'], - description: 'Projects and catalogs maintained by Peter Wunder.', - lang: 'en', -}; diff --git a/lib/routes/picnob/utils.ts b/lib/routes/picnob/utils.ts index 1a849f0c2ba1..94cda7c887c3 100644 --- a/lib/routes/picnob/utils.ts +++ b/lib/routes/picnob/utils.ts @@ -2,7 +2,7 @@ import { getPuppeteerPage } from '@/utils/puppeteer'; const puppeteerGet = async (url) => { let data; - const { destroy } = await getPuppeteerPage(url, { + const { destory } = await getPuppeteerPage(url, { onBeforeLoad: async (page) => { await page.setRequestInterception(true); page.on('request', (request) => { @@ -13,7 +13,7 @@ const puppeteerGet = async (url) => { }); }, }); - await destroy(); + await destory(); return data; }; diff --git a/lib/routes/picuki/profile.ts b/lib/routes/picuki/profile.ts index 17aadadc819f..92c1653fddec 100644 --- a/lib/routes/picuki/profile.ts +++ b/lib/routes/picuki/profile.ts @@ -85,7 +85,7 @@ async function handler(ctx) { }); } catch (error) { if (error.status === 403) { - const { page, destroy } = await getPuppeteerPage(profileUrl, { + const { page, destory } = await getPuppeteerPage(profileUrl, { onBeforeLoad: async (page) => { const expectResourceTypes = new Set(['document', 'script', 'xhr', 'fetch']); await page.setRequestInterception(true); @@ -96,7 +96,7 @@ async function handler(ctx) { }); await page.waitForSelector('.content'); response = await page.content(); - await destroy(); + await destory(); } else { throw new NotFoundError(error.message); } diff --git a/lib/routes/polymarket/event.ts b/lib/routes/polymarket/event.ts deleted file mode 100644 index a107e710c919..000000000000 --- a/lib/routes/polymarket/event.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import type { Event } from './types'; -import { GAMMA_API } from './types'; -import { formatOddsDisplay } from './utils'; - -export const route: Route = { - path: '/event/:slug', - categories: ['finance'], - example: '/polymarket/event/presidential-election-winner-2024', - parameters: { - slug: 'Event slug from the URL (e.g. presidential-election-winner-2024)', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['polymarket.com/event/:slug'], - target: '/event/:slug', - }, - ], - name: 'Event', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const slug = ctx.req.param('slug'); - - const event = await ofetch(`${GAMMA_API}/events/slug/${slug}`); - - if (!event) { - throw new Error('Event not found'); - } - - const items = event.markets.map((market) => ({ - title: market.question, - description: ` -

Odds: ${formatOddsDisplay(market)}

-

Volume: $${Number(market.volume || 0).toLocaleString()}

- ${market.oneDayPriceChange ? `

24h Change: ${(market.oneDayPriceChange * 100).toFixed(1)}%

` : ''} - ${market.image ? `${market.question}` : ''} - `, - link: `https://polymarket.com/event/${event.slug}`, - pubDate: market.startDate || event.startDate ? parseDate(market.startDate || event.startDate!) : undefined, - category: event.tags?.map((t) => t.label).filter(Boolean) as string[], - })); - - return { - title: event.title, - link: `https://polymarket.com/event/${event.slug}`, - item: items, - description: event.description, - }; -} diff --git a/lib/routes/polymarket/events.ts b/lib/routes/polymarket/events.ts deleted file mode 100644 index df8c726ea065..000000000000 --- a/lib/routes/polymarket/events.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import type { EventsPagination } from './types'; -import { GAMMA_API } from './types'; -import { formatEventDescription } from './utils'; - -export const route: Route = { - path: '/events/:tagSlug?', - categories: ['finance'], - example: '/polymarket/events', - parameters: { - tagSlug: 'Tag slug to filter events, e.g. politics, sports, crypto. Omit for all events.', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['polymarket.com', 'polymarket.com/:tagSlug'], - target: '/events/:tagSlug', - }, - ], - name: 'Events', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const tagSlug = ctx.req.param('tagSlug'); - const limit = 30; - - const query: Record = { - active: true, - closed: false, - limit, - order: 'volume', - ascending: false, - }; - - if (tagSlug) { - query.tag_slug = tagSlug; - } - - const response = await ofetch(`${GAMMA_API}/events/pagination`, { query }); - - const data = response.data || []; - - const items = data.map((event) => ({ - title: event.title, - description: formatEventDescription(event), - link: `https://polymarket.com/event/${event.slug}`, - pubDate: event.startDate ? parseDate(event.startDate) : undefined, - category: event.tags?.map((t) => t.label).filter(Boolean) as string[], - })); - - return { - title: `Polymarket Events${tagSlug ? ` - ${tagSlug}` : ''}`, - link: tagSlug ? `https://polymarket.com/${tagSlug}` : 'https://polymarket.com', - item: items, - }; -} diff --git a/lib/routes/polymarket/leaderboard.ts b/lib/routes/polymarket/leaderboard.ts deleted file mode 100644 index 6bdef90b5e55..000000000000 --- a/lib/routes/polymarket/leaderboard.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; - -import type { LeaderboardEntry } from './types'; -import { DATA_API } from './types'; - -export const route: Route = { - path: '/leaderboard/:category?/:timePeriod?', - categories: ['finance'], - example: '/polymarket/leaderboard', - parameters: { - category: { - description: 'Market category: OVERALL, POLITICS, SPORTS, CRYPTO, CULTURE, MENTIONS, WEATHER, ECONOMICS, TECH, FINANCE', - default: 'OVERALL', - }, - timePeriod: { - description: 'Time period: DAY, WEEK, MONTH, ALL', - default: 'DAY', - }, - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - name: 'Leaderboard', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const category = ctx.req.param('category') || 'OVERALL'; - const timePeriod = ctx.req.param('timePeriod') || 'DAY'; - - const data = await ofetch(`${DATA_API}/v1/leaderboard`, { - query: { - category, - timePeriod, - orderBy: 'PNL', - limit: 50, - }, - }); - - const items = data.map((entry) => ({ - title: `#${entry.rank} ${entry.userName || entry.proxyWallet}`, - description: ` -

Rank: #${entry.rank}

-

PnL: $${Number(entry.pnl).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}

-

Volume: $${Number(entry.vol).toLocaleString()}

- ${entry.xUsername ? `

X: @${entry.xUsername}

` : ''} - ${entry.verifiedBadge ? '

✅ Verified

' : ''} - ${entry.profileImage ? `${entry.userName || 'Trader'}` : ''} - `, - link: `https://polymarket.com/portfolio?address=${entry.proxyWallet}`, - author: entry.userName || entry.proxyWallet, - })); - - const categoryName = category.charAt(0).toUpperCase() + category.slice(1).toLowerCase(); - const periodName = timePeriod.charAt(0).toUpperCase() + timePeriod.slice(1).toLowerCase(); - - return { - title: `Polymarket Leaderboard - ${categoryName} (${periodName})`, - link: 'https://polymarket.com/leaderboard', - item: items, - }; -} diff --git a/lib/routes/polymarket/namespace.ts b/lib/routes/polymarket/namespace.ts deleted file mode 100644 index 19454d16db35..000000000000 --- a/lib/routes/polymarket/namespace.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'Polymarket', - url: 'polymarket.com', - description: `Polymarket is a prediction market platform where you can bet on real-world events.`, - lang: 'en', -}; diff --git a/lib/routes/polymarket/positions.ts b/lib/routes/polymarket/positions.ts deleted file mode 100644 index de9aa1b94aef..000000000000 --- a/lib/routes/polymarket/positions.ts +++ /dev/null @@ -1,78 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; - -import type { Position, PublicProfile } from './types'; -import { DATA_API, GAMMA_API } from './types'; - -export const route: Route = { - path: '/positions/:address', - categories: ['finance'], - example: '/polymarket/positions/0x7c3db723f1d4d8cb9c550095203b686cb11e5c6b', - parameters: { - address: 'Wallet address (0x...)', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - name: 'User Positions', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const address = ctx.req.param('address'); - - // Fetch profile and positions - let profile: PublicProfile | null = null; - let positions: Position[] = []; - - try { - profile = await ofetch(`${GAMMA_API}/public-profile`, { - query: { address }, - }); - } catch { - // Profile not found, continue without it - } - - try { - positions = await ofetch(`${DATA_API}/positions`, { - query: { - user: address, - limit: 50, - sortBy: 'CURRENT', - sortDirection: 'DESC', - }, - }); - } catch { - // Positions not found, continue with empty array - } - - const displayName = profile?.name || profile?.pseudonym || address; - - const items = positions.map((pos) => ({ - title: pos.title || `Position #${pos.conditionId.slice(0, 8)}`, - description: ` -

Outcome: ${pos.outcome || `#${pos.outcomeIndex}`}

-

Size: ${Number(pos.size).toLocaleString()}

-

Avg Price: $${Number(pos.avgPrice).toFixed(4)}

-

Current Price: $${Number(pos.curPrice).toFixed(4)}

-

Current Value: $${Number(pos.currentValue).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}

-

PnL: ${pos.cashPnl >= 0 ? '+' : ''}$${Number(pos.cashPnl).toFixed(2)} (${pos.percentPnl >= 0 ? '+' : ''}${Number(pos.percentPnl).toFixed(1)}%)

- ${pos.title || 'Position'} - `, - link: pos.eventSlug ? `https://polymarket.com/event/${pos.eventSlug}` : pos.slug ? `https://polymarket.com/event/${pos.slug}` : 'https://polymarket.com', - author: displayName, - })); - - return { - title: `Polymarket Positions - ${displayName}`, - link: `https://polymarket.com/portfolio?address=${address}`, - item: items, - }; -} diff --git a/lib/routes/polymarket/search.ts b/lib/routes/polymarket/search.ts deleted file mode 100644 index add5c719caad..000000000000 --- a/lib/routes/polymarket/search.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import type { SearchResult } from './types'; -import { GAMMA_API } from './types'; -import { formatEventDescription } from './utils'; - -export const route: Route = { - path: '/search/:query', - categories: ['finance'], - example: '/polymarket/search/trump', - parameters: { - query: 'Search query', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - name: 'Search', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const query = ctx.req.param('query'); - - const data = await ofetch(`${GAMMA_API}/public-search`, { - query: { - q: query, - limit_per_type: 30, - }, - }); - - const items = (data.events || []).map((event) => ({ - title: event.title, - description: formatEventDescription(event), - link: `https://polymarket.com/event/${event.slug}`, - pubDate: event.startDate ? parseDate(event.startDate) : undefined, - category: event.tags?.map((t) => t.label).filter(Boolean) as string[], - })); - - return { - title: `Polymarket Search - ${query}`, - link: `https://polymarket.com/search?q=${encodeURIComponent(query)}`, - item: items, - }; -} diff --git a/lib/routes/polymarket/series.ts b/lib/routes/polymarket/series.ts deleted file mode 100644 index f1c77f023c16..000000000000 --- a/lib/routes/polymarket/series.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import type { Event, Series } from './types'; -import { GAMMA_API } from './types'; -import { formatEventDescription } from './utils'; - -export const route: Route = { - path: '/series/:slug?', - categories: ['finance'], - example: '/polymarket/series', - parameters: { - slug: { - description: 'Series slug, e.g. nfl, nba, mlb. If omitted, lists all series.', - default: 'all', - }, - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - radar: [ - { - source: ['polymarket.com/series/:slug'], - target: '/series/:slug', - }, - ], - name: 'Series', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const slug = ctx.req.param('slug'); - const limit = 20; - - if (slug) { - // Get specific series by slug - const data = await ofetch(`${GAMMA_API}/series`, { - query: { - slug, - limit: 1, - }, - }); - - if (!data.length) { - throw new Error('Series not found'); - } - - const series = data[0]; - const events = series.events || []; - - const items = events.map((event: Event) => ({ - title: event.title, - description: formatEventDescription(event), - link: `https://polymarket.com/event/${event.slug}`, - pubDate: event.startDate ? parseDate(event.startDate) : undefined, - category: event.tags?.map((t) => t.label).filter(Boolean) as string[], - })); - - return { - title: `Polymarket Series - ${series.title}`, - link: `https://polymarket.com/series/${series.slug}`, - item: items, - }; - } else { - // List all series - const data = await ofetch(`${GAMMA_API}/series`, { - query: { - limit, - order: 'volume', - ascending: false, - }, - }); - - const items = data.map((series) => ({ - title: series.title, - description: ` - ${series.description ? `

${series.description}

` : ''} -

Volume: $${Number(series.volume || 0).toLocaleString()}

-

Liquidity: $${Number(series.liquidity || 0).toLocaleString()}

- ${series.image ? `${series.title}` : ''} - `, - link: `https://polymarket.com/series/${series.slug}`, - pubDate: series.createdAt ? parseDate(series.createdAt) : undefined, - })); - - return { - title: 'Polymarket - Series', - link: 'https://polymarket.com', - item: items, - }; - } -} diff --git a/lib/routes/polymarket/types.ts b/lib/routes/polymarket/types.ts deleted file mode 100644 index fac5dff2131f..000000000000 --- a/lib/routes/polymarket/types.ts +++ /dev/null @@ -1,114 +0,0 @@ -// API Constants -export const GAMMA_API = 'https://gamma-api.polymarket.com'; -export const DATA_API = 'https://data-api.polymarket.com'; - -// Common Interfaces - -export interface Market { - id: string; - question: string; - slug?: string; - outcomes?: string; - outcomePrices?: string; - volume?: string; - image?: string; - oneDayPriceChange?: number; - endDate?: string; - startDate?: string; -} - -export interface Event { - id: string; - title: string; - slug: string; - description?: string; - volume?: number; - image?: string; - startDate?: string; - endDate?: string; - liquidity?: number; - live?: boolean; - markets?: Market[]; - tags?: Array<{ label?: string }>; -} - -export interface Series { - id: string; - title: string; - slug: string; - description?: string; - image?: string; - volume?: number; - liquidity?: number; - startDate?: string; - createdAt?: string; - updatedAt?: string; - events?: Event[]; -} - -export interface PublicProfile { - name?: string; - pseudonym?: string; - bio?: string; - proxyWallet?: string; - profileImage?: string; -} - -export interface Position { - conditionId: string; - size: number; - avgPrice: number; - currentValue: number; - cashPnl: number; - percentPnl: number; - curPrice: number; - title?: string; - slug?: string; - eventSlug?: string; - outcome?: string; - outcomeIndex?: number; - icon: string; - endDate?: string; -} - -export interface Activity { - timestamp: number; - type: 'TRADE' | 'SPLIT' | 'MERGE' | 'REDEEM' | 'REWARD' | 'CONVERSION' | 'MAKER_REBATE'; - size?: number; - usdcSize?: number; - price?: number; - side?: 'BUY' | 'SELL'; - outcomeIndex?: number; - title?: string; - slug?: string; - eventSlug?: string; - outcome?: string; - icon?: string; - transactionHash?: string; - name?: string; - pseudonym?: string; -} - -export interface LeaderboardEntry { - rank: string; - proxyWallet: string; - userName?: string; - vol: number; - pnl: number; - profileImage?: string; - xUsername?: string; - verifiedBadge?: boolean; -} - -export interface EventsPagination { - data: Event[]; - pagination?: { - hasMore: boolean; - totalResults: number; - }; -} - -export interface SearchResult { - events?: Event[]; - tags?: Array<{ id: string; label: string; slug: string; event_count?: number }>; -} diff --git a/lib/routes/polymarket/user.ts b/lib/routes/polymarket/user.ts deleted file mode 100644 index c285c2961d03..000000000000 --- a/lib/routes/polymarket/user.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -import type { Activity, PublicProfile } from './types'; -import { DATA_API, GAMMA_API } from './types'; - -export const route: Route = { - path: '/user/:address', - categories: ['finance'], - example: '/polymarket/user/0x7c3db723f1d4d8cb9c550095203b686cb11e5c6b', - parameters: { - address: 'Wallet address (0x...)', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - }, - name: 'User Activity', - url: 'polymarket.com', - maintainers: ['heqi201255'], - handler, -}; - -async function handler(ctx) { - const address = ctx.req.param('address'); - - // Fetch profile and activity - let profile: PublicProfile | null = null; - let activity: Activity[] = []; - - try { - profile = await ofetch(`${GAMMA_API}/public-profile`, { - query: { address }, - }); - } catch { - // Profile not found, continue without it - } - - try { - activity = await ofetch(`${DATA_API}/activity`, { - query: { - user: address, - limit: 50, - sortBy: 'TIMESTAMP', - sortDirection: 'DESC', - }, - }); - } catch { - // Activity not found, continue with empty array - } - - const displayName = profile?.name || profile?.pseudonym || address; - - const items = activity.map((act) => { - const typeEmoji: Record = { - TRADE: '💱', - SPLIT: '✂️', - MERGE: '🔗', - REDEEM: '💰', - REWARD: '🎁', - CONVERSION: '🔄', - MAKER_REBATE: '💵', - }; - - const typeLabel = `${typeEmoji[act.type] || '📝'} ${act.type}`; - - return { - title: act.title ? `${act.title} - ${act.outcome || `Outcome ${act.outcomeIndex}`}` : typeLabel, - description: ` -

Type: ${typeLabel}

- ${act.side ? `

Side: ${act.side}

` : ''} - ${act.price === undefined ? '' : `

Price: $${act.price.toFixed(4)}

`} - ${act.size === undefined ? '' : `

Size: ${act.size.toLocaleString()}

`} - ${act.usdcSize === undefined ? '' : `

USDC: $${act.usdcSize.toLocaleString()}

`} - ${act.icon ? `${act.title || 'Market'}` : ''} - `, - link: act.eventSlug ? `https://polymarket.com/event/${act.eventSlug}` : act.slug ? `https://polymarket.com/event/${act.slug}` : 'https://polymarket.com', - pubDate: parseDate(act.timestamp * 1000), - author: displayName, - }; - }); - - return { - title: `Polymarket User - ${displayName}`, - link: `https://polymarket.com/portfolio?address=${address}`, - item: items, - description: profile?.bio || undefined, - }; -} diff --git a/lib/routes/polymarket/utils.ts b/lib/routes/polymarket/utils.ts deleted file mode 100644 index 4af4b5a8835a..000000000000 --- a/lib/routes/polymarket/utils.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Event, Market } from './types'; - -export function formatOddsDisplay(market: Market): string { - const outcomes = market.outcomes ? JSON.parse(market.outcomes) : []; - const prices = market.outcomePrices ? JSON.parse(market.outcomePrices) : []; - return prices.length > 0 ? outcomes.map((o: string, i: number) => `${o}: ${(Number(prices[i]) * 100).toFixed(1)}%`).join(' | ') : outcomes.join(' | ') || 'N/A'; -} - -export function formatEventDescription(event: Event): string { - const marketsHtml = (event.markets || []) - .slice(0, 3) - .map((market) => `
  • ${market.question}
    ${formatOddsDisplay(market)}
  • `) - .join(''); - - return ` - ${event.description ? `

    ${event.description}

    ` : ''} -

    Volume: $${Number(event.volume || 0).toLocaleString()}

    - ${marketsHtml ? `

    Markets:

      ${marketsHtml}
    ` : ''} - ${event.image ? `${event.title}` : ''} - `; -} diff --git a/lib/routes/projectjav/actress.ts b/lib/routes/projectjav/actress.ts new file mode 100644 index 000000000000..4c9b9a94e7d7 --- /dev/null +++ b/lib/routes/projectjav/actress.ts @@ -0,0 +1,36 @@ +import type { Route } from '@/types'; + +import { processItems, rootUrl } from './utils'; + +export const route: Route = { + path: '/actress/:id', + categories: ['multimedia'], + example: '/projectjav/actress/rima-arai-22198', + parameters: { id: 'Actress ID or slug, can be found in the actress page URL' }, + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + nsfw: true, + }, + radar: [ + { + source: ['projectjav.com/actress/:id'], + target: '/actress/:id', + }, + ], + name: 'Actress', + maintainers: ['Exat1979'], + handler, + url: 'projectjav.com/', + description: 'Fetches the latest movies from a specific actress page on ProjectJAV.', +}; + +async function handler(ctx) { + const id = ctx.req.param('id').replace(/\/$/, ''); + const currentUrl = `${rootUrl}/actress/${id}`; + return await processItems(currentUrl); +} diff --git a/lib/routes/projectjav/namespace.ts b/lib/routes/projectjav/namespace.ts new file mode 100644 index 000000000000..9581f6264ed0 --- /dev/null +++ b/lib/routes/projectjav/namespace.ts @@ -0,0 +1,8 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'ProjectJAV', + url: 'projectjav.com', + description: 'ProjectJAV provides adult video content information and streaming.', + lang: 'en', +}; diff --git a/lib/routes/projectjav/utils.ts b/lib/routes/projectjav/utils.ts new file mode 100644 index 000000000000..d863ebc7bebd --- /dev/null +++ b/lib/routes/projectjav/utils.ts @@ -0,0 +1,97 @@ +import { load } from 'cheerio'; + +import type { DataItem } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; + +const rootUrl = 'https://projectjav.com'; +const processItems = async (currentUrl: string) => { + const response = await got({ + method: 'get', + url: currentUrl, + }); + + const $ = load(response.data); + + let items: DataItem[] = $('div.video-item') + .toArray() + .map((element) => { + const item = $(element); + const link = item.find('a').attr('href'); + return { + title: item.find('div.name span').text() || '', + link: link?.startsWith('http') ? link : `${rootUrl}${link}`, + }; + }) + .filter((item) => item.link && /\/movie\/.*/.test(item.link)); + + items = await Promise.all( + items.map((item) => + cache.tryGet(item.link!, async () => { + const detailResponse = await got({ + method: 'get', + url: item.link, + }); + + const content = load(detailResponse.data); + + // Remove ads + content('div.top-banner-ads, div.bottom-content-ads').remove(); + + // Get main content + const mainContent = content('main'); + + // Extract title + const h1Title = mainContent.find('h1').text().trim(); + if (h1Title) { + item.title = h1Title; + } + + // Extract categories + const categories = mainContent + .find('div.badge a') + .toArray() + .map((v) => content(v).text().trim()) + .filter(Boolean); + if (categories.length > 0) { + item.category = categories; + } + + // Extract author/actress (support multiple actresses) + const actresses = mainContent + .find('div.actress-item a') + .toArray() + .map((v) => content(v).text().trim()) + .filter(Boolean); + if (actresses.length > 0) { + item.author = actresses.join(', '); + } + + // Extract date + const dateEl = mainContent + .find('div.second-main~div.row>div.col-3') + .toArray() + .find((el) => content(el).text().includes('Date added')); + const dateText = dateEl ? content(dateEl).next().text().trim() : null; + if (dateText) { + // ProjectJAV uses DD/MM/YYYY format + item.pubDate = parseDate(dateText, 'DD/MM/YYYY'); + } + + // Get description + item.description = mainContent.html() || ''; + + return item; + }) + ) + ); + + return { + title: $('title').text() || 'ProjectJAV', + link: currentUrl, + item: items, + }; +}; + +export { processItems, rootUrl }; diff --git a/lib/routes/qbittorrent/news.ts b/lib/routes/qbittorrent/news.ts index 7acd5338a237..85f0e909c384 100644 --- a/lib/routes/qbittorrent/news.ts +++ b/lib/routes/qbittorrent/news.ts @@ -52,7 +52,6 @@ async function handler(ctx) { const item = $('.stretcher') .find('h3') .toArray() - // oxlint-disable-next-line array-callback-return .map((item) => { item = $(item); const pubDate = item diff --git a/lib/routes/qiche365/recall.ts b/lib/routes/qiche365/recall.ts index c1a49d266903..397d447822ab 100644 --- a/lib/routes/qiche365/recall.ts +++ b/lib/routes/qiche365/recall.ts @@ -16,34 +16,19 @@ export const route: Route = { | ------------ | ------------ | ------------ | ------------ | | 1 | 2 | 3 | 4 |`, categories: ['government'], - features: { - antiCrawler: true, - }, - maintainers: ['huanfe1', 'pseudoyu'], + maintainers: ['huanfe1'], handler, url: 'qiche365.org.cn/index/recall/index.html', }; async function handler(ctx): Promise { const { channel } = ctx.req.param(); - const targetUrl = `${baseUrl}/index/recall/index/item/${channel}.html?loadmore=1`; - // Reason: site uses cookie-based anti-bot — first request returns 403 with set-cookie, - // second request with those cookies returns the actual JSON data. - const initResponse = await ofetch.raw(targetUrl, { + const { html } = await ofetch(`${baseUrl}/index/recall/index/item/${channel}.html?loadmore=1`, { + method: 'get', headers: { 'Accept-Language': 'zh-CN,zh;q=0.9', }, - ignoreResponseError: true, - }); - - const cookies = (initResponse.headers.getSetCookie?.() || []).map((c) => c.split(';')[0]).join('; '); - - const { html } = await ofetch(targetUrl, { - headers: { - 'Accept-Language': 'zh-CN,zh;q=0.9', - Cookie: cookies, - }, }); const $ = load(html as string); @@ -61,7 +46,7 @@ async function handler(ctx): Promise { }; }); return { - title: ['国内召回新闻', '国内召回公告', '国外召回新闻', '国外召回公告'][Number(channel) - 1], + title: ['国内召回公告', '国内召回新闻', '国外召回公告', '国外召回新闻'][channel - 1], link: `${baseUrl}/index/recall/index.html`, item: items, language: 'zh-CN', diff --git a/lib/routes/qidian/author.tsx b/lib/routes/qidian/author.tsx index 8dee269a19a3..f3827d73fc24 100644 --- a/lib/routes/qidian/author.tsx +++ b/lib/routes/qidian/author.tsx @@ -1,8 +1,10 @@ import { load } from 'cheerio'; +import { renderToString } from 'hono/jsx/dom/server'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; +import { parseDate, parseRelativeDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; export const route: Route = { path: '/author/:id', @@ -12,7 +14,7 @@ export const route: Route = { features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, @@ -23,34 +25,48 @@ export const route: Route = { }, ], name: '作者', - maintainers: ['miles170', 'pseudoyu'], + maintainers: ['miles170'], handler, }; async function handler(ctx) { const id = ctx.req.param('id'); - const currentUrl = `https://my.qidian.com/author/${id}/`; - - // Reason: PC site (my.qidian.com) returns anti-bot JS challenge; mobile site has SSR data - const response = await got(`https://m.qidian.com/author/${id}/`, { headerGeneratorOptions: PRESETS.MODERN_IOS }); + const rootUrl = 'https://my.qidian.com'; + const currentUrl = `${rootUrl}/author/${id}/`; + const response = await got(currentUrl); const $ = load(response.data); - const { pageContext } = JSON.parse($('#vite-plugin-ssr_pageContext').text()); - const pageData = pageContext.pageProps.pageData; - - const authorName = pageData.info.name; + const authorName = $('.header-msg h1').contents().first().text().trim(); + const items = $('.author-work .author-item') + .toArray() + .map((item) => { + item = $(item); + const messageItem = item.find('.author-item-msg'); + const updatedDate = messageItem.find('.author-item-update span').text().replace('·', '').trim(); - const items = (pageData.allBook || []).map((book) => ({ - title: book.bName, - author: authorName, - category: book.cat, - description: book.desc, - link: `https://book.qidian.com/info/${book.bid}/`, - })); + return { + title: messageItem.find('.author-item-title').text().trim(), + author: authorName, + category: messageItem.find('.author-item-exp a').first().text().trim(), + description: renderDescription(messageItem.find('.author-item-update a').attr('title'), item.find('a img').attr('src')), + pubDate: timezone(/(今|昨)/.test(updatedDate) ? parseRelativeDate(updatedDate) : parseDate(updatedDate, 'YYYY-MM-DD HH:mm'), +8), + link: messageItem.find('.author-item-update a').attr('href'), + }; + }); return { title: `${authorName} - 起点中文网`, - description: pageData.info.desc, + description: $('.header-msg-desc').text().trim(), link: currentUrl, item: items, }; } + +const renderDescription = (description?: string, image?: string, author?: string) => renderToString(); + +const QidianDescription = ({ description, image, author }: { description?: string; image?: string; author?: string }) => ( + <> +

    {description}

    + {image ? : null} + {author ?? null} + +); diff --git a/lib/routes/qidian/chapter.ts b/lib/routes/qidian/chapter.ts index 9389c799cf9b..7cf1f7488d30 100644 --- a/lib/routes/qidian/chapter.ts +++ b/lib/routes/qidian/chapter.ts @@ -3,7 +3,6 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import { ViewType } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; import { parseDate } from '@/utils/parse-date'; export const route: Route = { @@ -15,7 +14,7 @@ export const route: Route = { features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, @@ -26,20 +25,25 @@ export const route: Route = { }, ], name: '作品章节', - maintainers: ['fuzy112', 'pseudoyu'], + maintainers: ['fuzy112'], handler, }; async function handler(ctx) { const id = ctx.req.param('id'); - const response = await got(`https://m.qidian.com/book/${id}.html`, { headerGeneratorOptions: PRESETS.MODERN_IOS }); + const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1'; + const headers = { + 'User-Agent': userAgent, + }; + + const response = await got(`https://m.qidian.com/book/${id}.html`, { headers }); const $ = load(response.data); const name = $('meta[property="og:title"]').attr('content'); const coverUrl = `https:${$('.detail__header-cover__img').attr('src')}`; - const { data: catalog } = await got(`https://m.qidian.com/book/${id}/catalog/`, { headerGeneratorOptions: PRESETS.MODERN_IOS }); + const { data: catalog } = await got(`https://m.qidian.com/book/${id}/catalog/`, { headers }); const $c = load(catalog); const { pageContext } = JSON.parse($c('#vite-plugin-ssr_pageContext').text()); diff --git a/lib/routes/qidian/forum.ts b/lib/routes/qidian/forum.ts index 3c7bdb686c5b..3d80969548c5 100644 --- a/lib/routes/qidian/forum.ts +++ b/lib/routes/qidian/forum.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; +import { parseRelativeDate } from '@/utils/parse-date'; export const route: Route = { path: '/forum/:id', @@ -12,7 +12,7 @@ export const route: Route = { features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, @@ -23,33 +23,41 @@ export const route: Route = { }, ], name: '讨论区', - maintainers: ['fuzy112', 'pseudoyu'], + maintainers: ['fuzy112'], handler, }; async function handler(ctx) { const id = ctx.req.param('id'); - // Reason: forum.qidian.com redirects and PC site has anti-bot JS challenge; - // mobile book page embeds forum posts via seoBookCirclePost - const response = await got(`https://m.qidian.com/book/${id}.html`, { headerGeneratorOptions: PRESETS.MODERN_IOS }); - const $ = load(response.data); - const { pageContext } = JSON.parse($('#vite-plugin-ssr_pageContext').text()); - const pageData = pageContext.pageProps.pageData; + const url = `https://forum.qidian.com/NewForum/List.aspx?BookId=${id}`; - const bookName = pageData.bookInfo?.bookName || ''; - const posts = pageData.seoBookCirclePost?.bookCirclePostList || []; + const forum_response = await got(url, { + headers: { + Referer: `https://book.qidian.com/info/${id}`, + }, + }); + + const $ = load(forum_response.data); + const name = $('.main-header>h1').text(); + const cover_url = $('img.forum_book').attr('src'); + const list = $('li.post-wrap>.post'); - const items = posts.map((post) => ({ - title: post.title, - link: `https://book.qidian.com/info/${id}/`, - description: post.circleReviewDesc, - author: post.userName, - })); + const items = []; + for (const el of list) { + const title = $(el).children().eq(1).find('a'); + items.push({ + title: title.text(), + link: `https:${title.attr('href')}`, + description: $(el).text(), + pubDate: parseRelativeDate($(el).find('.post-info>span').text()), + }); + } return { - title: `起点 《${bookName}》讨论区`, - link: `https://book.qidian.com/info/${id}/`, + title: `起点 《${name}》讨论区`, + link: url, + image: cover_url, item: items, }; } diff --git a/lib/routes/qidian/free-next.ts b/lib/routes/qidian/free-next.ts index 05722cd15661..0f5bd46ef36c 100644 --- a/lib/routes/qidian/free-next.ts +++ b/lib/routes/qidian/free-next.ts @@ -2,7 +2,6 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; export const route: Route = { path: '/free-next/:type?', @@ -12,7 +11,7 @@ export const route: Route = { features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, @@ -24,7 +23,7 @@ export const route: Route = { }, ], name: '限时免费下期预告', - maintainers: ['LogicJake', 'pseudoyu'], + maintainers: ['LogicJake'], handler, url: 'www.qidian.com/free', }; @@ -32,27 +31,37 @@ export const route: Route = { async function handler(ctx) { const type = ctx.req.param('type'); - const isMM = type === 'mm'; - const link = isMM ? 'https://www.qidian.com/mm/free' : 'https://www.qidian.com/free'; - const title = isMM ? '起点女生网' : '起点中文网'; + let link, title; + if (type === 'mm') { + link = 'https://www.qidian.com/mm/free'; + title = '起点女生网'; + } else { + link = 'https://www.qidian.com/free'; + title = '起点中文网'; + } - // Reason: PC site (www.qidian.com) returns anti-bot JS challenge; mobile site has SSR data - const response = await got('https://m.qidian.com/free', { headerGeneratorOptions: PRESETS.MODERN_IOS }); + const response = await got(link); const $ = load(response.data); - const { pageContext } = JSON.parse($('#vite-plugin-ssr_pageContext').text()); - const pageData = pageContext.pageProps.pageData; - const items = (pageData.nxtFree || []).map((book) => ({ - title: book.bName, - link: `https://book.qidian.com/info/${book.bid}/`, - author: book.bAuth, - description: `评分:${book.score === -1 ? '暂无' : book.score}`, - })); + const list = $('div.other-rec-wrap li'); + const out = list.toArray().map((item) => { + item = $(item); + + const img = ``; + const rank = `

    评分:${item.find('.img-box span').text()}

    `; + + return { + title: item.find('.book-info h4 a').text(), + description: img + rank + item.find('p.intro').html(), + link: 'https:' + item.find('.book-info h4 a').attr('href'), + author: item.find('p.author a').text(), + }; + }); return { title, description: `限时免费下期预告-${title}`, link, - item: items, + item: out, }; } diff --git a/lib/routes/qidian/free.ts b/lib/routes/qidian/free.ts index 10a19f0f6bba..ede85968cf95 100644 --- a/lib/routes/qidian/free.ts +++ b/lib/routes/qidian/free.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; +import { parseRelativeDate } from '@/utils/parse-date'; export const route: Route = { path: '/free/:type?', @@ -12,7 +12,7 @@ export const route: Route = { features: { requireConfig: false, requirePuppeteer: false, - antiCrawler: true, + antiCrawler: false, supportBT: false, supportPodcast: false, supportScihub: false, @@ -24,7 +24,7 @@ export const route: Route = { }, ], name: '限时免费', - maintainers: ['LogicJake', 'pseudoyu'], + maintainers: ['LogicJake'], handler, url: 'www.qidian.com/free', }; @@ -32,27 +32,39 @@ export const route: Route = { async function handler(ctx) { const type = ctx.req.param('type'); - const isMM = type === 'mm'; - const link = isMM ? 'https://www.qidian.com/mm/free' : 'https://www.qidian.com/free'; - const title = isMM ? '起点女生网' : '起点中文网'; + let link, title; + if (type === 'mm') { + link = 'https://www.qidian.com/mm/free'; + title = '起点女生网'; + } else { + link = 'https://www.qidian.com/free'; + title = '起点中文网'; + } - // Reason: PC site (www.qidian.com) returns anti-bot JS challenge; mobile site has SSR data - const response = await got('https://m.qidian.com/free', { headerGeneratorOptions: PRESETS.MODERN_IOS }); + const response = await got(link); const $ = load(response.data); - const { pageContext } = JSON.parse($('#vite-plugin-ssr_pageContext').text()); - const pageData = pageContext.pageProps.pageData; - const items = (pageData.curFree || []).map((book) => ({ - title: book.bName, - link: `https://book.qidian.com/info/${book.bid}/`, - author: book.bAuth, - description: `评分:${book.score === -1 ? '暂无' : book.score}`, - })); + const list = $('#limit-list li'); + const out = list.toArray().map((item) => { + item = $(item); + + const img = ``; + const rank = `

    评分:${item.find('.score').text()}

    `; + const update = ` a').attr('href')}>${item.find('p.update > a').text()}`; + + return { + title: item.find('.book-mid-info h4 a').text(), + description: img + rank + update + '
    ' + item.find('p.intro').html(), + pubDate: parseRelativeDate(item.find('p.update span').text()), + link: 'https:' + item.find('.book-mid-info h4 a').attr('href'), + author: item.find('p.author a.name').text(), + }; + }); return { title, description: `限时免费-${title}`, link, - item: items, + item: out, }; } diff --git a/lib/routes/qq/news/user.ts b/lib/routes/qq/news/user.ts index aad163a1c138..191542514e2a 100644 --- a/lib/routes/qq/news/user.ts +++ b/lib/routes/qq/news/user.ts @@ -64,12 +64,10 @@ async function handler(ctx) { news = await Promise.all( response.newslist.map((item) => cache.tryGet(item.id, async () => { - let description = `

    ${item.abstract}

    文章包含非文本内容,请在浏览器中打开查看

    `; - if (item.articletype === '0') { - const article = await ofetch(`https://news.qq.com/rain/a/${item.id}`); - const $ = load(article); - description = $('.rich_media_content').html()!; - } + const description = + item.articletype === '0' + ? load(await ofetch(`https://news.qq.com/rain/a/${item.id}`))('.rich_media_content').html()! + : `

    ${item.abstract}

    文章包含非文本内容,请在浏览器中打开查看

    `; return { title: item.longtitle, description, diff --git a/lib/routes/rfi/news.ts b/lib/routes/rfi/news.ts index cdc00ef35bfe..d1fe744ccc3d 100644 --- a/lib/routes/rfi/news.ts +++ b/lib/routes/rfi/news.ts @@ -14,7 +14,7 @@ export const route: Route = { }, ], name: 'Generic News', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, url: 'rfi.fr', example: '/rfi', @@ -59,38 +59,22 @@ async function handler(ctx) { content('.m-interstitial, .m-em-quote svg, .o-self-promo').remove(); - // Reason: pages may have multiple ld+json script tags; iterating separately - // avoids concatenation that produces invalid JSON like "{...}{...}" - let ldJson; - for (const el of content('script[type="application/ld+json"]').toArray()) { - try { - const parsed = JSON.parse(content(el).text()); - const candidates = Array.isArray(parsed) ? parsed : [parsed]; - ldJson = candidates.find((x) => x['@type'] === 'NewsArticle'); - if (ldJson) { - break; - } - } catch { - // skip malformed ld+json blocks - } - } + const ldJson = JSON.parse(content('script[type="application/ld+json"]').text() || '[]').find((x) => x['@type'] === 'NewsArticle'); item.description = content('.t-content__chapo').prop('outerHTML') + content('.t-content__main-media').prop('outerHTML') + content('.t-content__body').html(); - item.pubDate = ldJson?.datePublished ? parseDate(ldJson.datePublished) : undefined; - item.updated = ldJson?.dateModified ? parseDate(ldJson.dateModified) : undefined; - item.author = ldJson?.author?.map((author) => author.name).join(', '); + item.pubDate = parseDate(ldJson?.datePublished); + item.updated = parseDate(ldJson?.dateModified); + item.author = ldJson?.author.map((author) => author.name).join(', '); item.category = ldJson?.keywords; if (ldJson?.audio) { item.itunes_item_image = ldJson.audio.thumbnailUrl; // TODO: Use Temporal.Duration when https://tc39.es/proposal-temporal/ is GA - const durationMatch = ldJson.audio.duration?.match(/P0DT(\d+)H(\d+)M(\d+)S/); - if (durationMatch) { - item.itunes_duration = durationMatch - .slice(1) - .map((x) => Number.parseInt(x)) - .reduce((a, b) => a * 60 + b); - } + item.itunes_duration = ldJson.audio.duration + .match(/P0DT(\d+)H(\d+)M(\d+)S/) + .slice(1) + .map((x) => Number.parseInt(x)) + .reduce((a, b) => a * 60 + b); item.enclosure_url = ldJson.audio.contentUrl; item.enclosure_type = 'audio/mpeg'; } diff --git a/lib/routes/sciencedirect/call-for-paper.tsx b/lib/routes/sciencedirect/call-for-paper.tsx index 4729c5132428..f1903b0b46bb 100644 --- a/lib/routes/sciencedirect/call-for-paper.tsx +++ b/lib/routes/sciencedirect/call-for-paper.tsx @@ -26,7 +26,11 @@ export const route: Route = { async function handler(ctx) { const { subject = '' } = ctx.req.param(); const apiUrl = `https://www.sciencedirect.com/browse/calls-for-papers?subject=${subject}`; - const response = await got(apiUrl); + const headers = { + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36', // need this to avoid 403, 503 error + }; + const response = await got(apiUrl, { headers }); const $ = load(response.body); const scriptJSON = $('script[data-iso-key="_0"]').text(); diff --git a/lib/routes/sohu/mp.tsx b/lib/routes/sohu/mp.tsx index 45a4ae41e935..a99761c50e67 100644 --- a/lib/routes/sohu/mp.tsx +++ b/lib/routes/sohu/mp.tsx @@ -218,7 +218,7 @@ async function handler(ctx) { title: `搜狐号 - ${globalConst.title}`, description: briefIntroductionCard.column_9_text, link: originalRequest.url, - image: briefIntroductionCard.column_2_image.startsWith('http') ? briefIntroductionCard.column_2_image.replace('http:', 'https:') : `https:${briefIntroductionCard.column_2_image}`, + image: `https:${briefIntroductionCard.column_2_image}`, item: items, }; } diff --git a/lib/routes/telecompaper/news.ts b/lib/routes/telecompaper/news.ts index 822e9f4c74af..04038c90df5a 100644 --- a/lib/routes/telecompaper/news.ts +++ b/lib/routes/telecompaper/news.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import FormData from 'form-data'; import { CookieJar } from 'tough-cookie'; import type { Route } from '@/types'; @@ -57,7 +58,7 @@ async function handler(ctx) { form.append('__EVENTTARGET', 'ctl00$MainPlaceHolder$ddlContentType'); form.append('__EVENTARGUMENT', ''); form.append('__LASTFOCUS', ''); - form.append('__VIEWSTATE', $('#__VIEWSTATE').attr('value') ?? ''); + form.append('__VIEWSTATE', $('#__VIEWSTATE').attr('value')); form.append('__VIEWSTATEGENERATOR', 'E4EF4CD1'); form.append('ctl00$header$searchText', ctx.req.param('keyword') || ''); form.append('ctl00$header$searchTextMobile', ctx.req.param('keyword') || ''); @@ -65,26 +66,26 @@ async function handler(ctx) { form.append( 'ctl00$MainPlaceHolder$ddlYears', year && year !== 'all' - ? ($('select[name="ctl00$MainPlaceHolder$ddlYears"] option') + ? $('select[name="ctl00$MainPlaceHolder$ddlYears"] option') .filter((index, element) => $(element).text().split(' (')[0] === ctx.req.param('year')) - .attr('value') ?? '0') + .attr('value') : '0' ); form.append( 'ctl00$MainPlaceHolder$ddlCountries', country && country !== 'all' - ? ($('select[name="ctl00$MainPlaceHolder$ddlCountries"] option') + ? $('select[name="ctl00$MainPlaceHolder$ddlCountries"] option') .filter((index, element) => $(element).text().split(' (')[0] === country) - .attr('value') ?? '0') + .attr('value') : '0' ); } form.append( 'ctl00$MainPlaceHolder$ddlContentType', type && type !== 'all' - ? ($('select[name="ctl00$MainPlaceHolder$ddlContentType"] option') + ? $('select[name="ctl00$MainPlaceHolder$ddlContentType"] option') .filter((index, element) => $(element).text().split(' (')[0] === type) - .attr('value') ?? '') + .attr('value') : '' ); diff --git a/lib/routes/telegram/tglib/channel.ts b/lib/routes/telegram/tglib/channel.ts index 1c63528bce2c..6863cd07fa40 100644 --- a/lib/routes/telegram/tglib/channel.ts +++ b/lib/routes/telegram/tglib/channel.ts @@ -35,26 +35,6 @@ export async function getPollResults(client, message, m: Api.MessageMediaPoll) { return txt; } -export function withSearchParams(src: string, params: Record) { - const url = new URL(src); - for (const [key, value] of Object.entries(params)) { - url.searchParams.set(key, value); - } - return url.toString(); -} - -export function getMessageMediaUrl(requestUrl: string, username: string, messageId: number) { - const request = new URL(requestUrl); - const url = new URL(`/telegram/media/${username}/${messageId}`, request.origin); - for (const key of ['key', 'code']) { - const value = request.searchParams.get(key); - if (value) { - url.searchParams.set(key, value); - } - } - return url.toString(); -} - export function getMediaLink(src: string, m: Api.TypeMessageMedia) { const doc = getDocument(m); const mime = doc ? doc.mimeType : ''; @@ -64,7 +44,7 @@ export function getMediaLink(src: string, m: Api.TypeMessageMedia) { } if (doc && mime.startsWith('video/')) { const vid = (doc.attributes.find((t) => t instanceof Api.DocumentAttributeVideo) ?? { w: 1080, h: 720 }) as { w: number; h: number }; - return ``; + return ``; } if (doc && mime.startsWith('audio/')) { return `
    ${getAudioTitle(m)}
    `; @@ -76,7 +56,7 @@ export function getMediaLink(src: string, m: Api.TypeMessageMedia) { linkText = ''; // remove filename, it's only an animated sticker } if ((doc.thumbs?.length ?? 0) > 0) { - linkText = `
    ${linkText}
    `; + linkText = `
    ${linkText}
    `; } return `${linkText}`; } @@ -175,7 +155,7 @@ export default async function handler(ctx: Context) { } // messages that have no text are shown as if they're one post // because in TG only 1 attachment per message is possible - const src = getMessageMediaUrl(ctx.req.url, username, message.id); + const src = `${new URL(ctx.req.url).origin}/telegram/media/${username}/${message.id}`; attachments.push(getMediaLink(src, media)); } if (message.replyMarkup instanceof Api.ReplyInlineMarkup) { diff --git a/lib/routes/the/index.ts b/lib/routes/the/index.ts index 94f7c9295afc..2012302e2b6d 100644 --- a/lib/routes/the/index.ts +++ b/lib/routes/the/index.ts @@ -1,275 +1,136 @@ -import type { Cheerio, CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; -import type { Element } from 'domhandler'; -import type { Data, DataItem, Route } from '@/types'; +import type { Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; import { renderDescription } from './templates/description'; +import { apiSlug, bakeFilterSearchParams, bakeFiltersWithPair, bakeUrl, fetchData, getFilterParamsForUrl, parseFilterStr } from './util'; -const baseUrl = 'https://river.to/occasus'; -// Reason: the main homepage (/occasus) is severely outdated; -// this sub-page is the real full-site latest feed, updated daily -const defaultFeedPath = 'vncwdhq2xje7wp/rawzi0ruu6p6a1'; - -export const handler = async (ctx): Promise => { +export const handler = async (ctx) => { const { filter } = ctx.req.param(); const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 40; - // Reason: filter supports category/slug or just a slug directly for backward compatibility - const slug = parseSlug(filter); - const targetUrl = slug ? `${baseUrl}/${slug}` : `${baseUrl}/${defaultFeedPath}`; - - const { data: response } = await got(targetUrl); - - const $ = load(response); - - const title = $('title').first().text() || '江河日下'; - - const items = [...extractFromStreamItems($), ...extractFromMaterialBlocks($, targetUrl), ...extractFromPostPreviews($, targetUrl)]; - - // Reason: deduplicate by guid and enforce limit - const seen = new Set(); - const deduped = items.filter((item) => { - const key = item.guid || item.title; - if (seen.has(key)) { - return false; - } - seen.add(key); - return true; - }); - - return { - title: `${title} - 江河日下`, - description: $('meta[property="og:description"]').attr('content') || $('meta[name="description"]').attr('content') || '', - link: targetUrl, - allowEmpty: true, - image: $('meta[property="og:image"]').attr('content') || '', - language: 'zh-CN', - item: deduped.slice(0, limit), - }; -}; + const rootUrl = 'https://the.bi/s'; + const filters = parseFilterStr(filter); + const filtersWithPair = await bakeFiltersWithPair(filters, rootUrl); -/** - * Parse filter string to get the target slug. - * Supports: category/slug, tag/slug, or just slug directly. - */ -function parseSlug(filter: string | undefined): string | undefined { - if (!filter) { - return undefined; - } + const searchParams = bakeFilterSearchParams(filters, 'name', false); + const apiSearchParams = bakeFilterSearchParams(filtersWithPair, 'id', true); - const parts = filter.split('/').filter(Boolean); + apiSearchParams.append('_embed', 'true'); + apiSearchParams.append('per_page', String(limit)); + apiSearchParams.append('page', '1'); - // Reason: for backward compatibility, /the/category/rawXXX maps to /occasus/rawXXX - if (parts.length >= 2 && (parts[0] === 'category' || parts[0] === 'tag')) { - return parts[1]; - } + const apiUrl = bakeUrl(`${apiSlug}/posts`, rootUrl, apiSearchParams); + const currentUrl = bakeUrl(getFilterParamsForUrl(filtersWithPair) ?? '', rootUrl, searchParams); - // Direct slug access: /the/rawXXX - if (parts.length === 1) { - return parts[0]; - } + const { data: response } = await got(apiUrl); - return parts[1] || parts[0]; -} + const items = response.slice(0, limit).map((item) => { + const terminologies = item._embedded['wp:term']; + const guid = item.guid?.rendered ?? item.guid; -/** - * Find the first real article link in an element. - * Reason: only links inside h3/h4 (article title) or wrapping the main image are real article links. - * Links in author/publication areas (.postMetaInline, .uiScale, avatar containers) are excluded. - */ -function findArticleLink($: CheerioAPI, block: Cheerio): string | undefined { - let link: string | undefined; + const $$ = load(item.content?.rendered ?? item.content); - // Reason: look for links that contain h3 (title) — these are actual article links - block.find('a').each((_, el) => { - const $el = $(el); - const href = $el.attr('href'); + const publication = $$("a[id='publication']").text(); // Must be obtained before being removed - if (!href || href === '#Unauthorized' || href === baseUrl || href === `${baseUrl}/` || !href.startsWith('https://river.to/occasus/')) { - return; - } + const image = $$('img#poster').prop('data-srcset'); - // Only consider links that wrap article titles (h3) or the main image - const hasTitle = $el.find('h3').length > 0; - const isMainImage = $el.hasClass('u-block') && $el.find('.graf-image').length > 0; + $$('figure.graf').each((_, el) => { + el = $$(el); - if (hasTitle || isMainImage) { - link = href; - return false; - } - }); + const imgEl = el.find('img'); - return link; -} - -/** - * Extract articles from extremePostPreview sections (list items on homepage). - */ -function extractFromStreamItems($: CheerioAPI): DataItem[] { - const items: DataItem[] = []; - - $('section.extremePostPreview').each((_, el) => { - const section = $(el); - const link = findArticleLink($, section); - - if (!link) { - return; - } - - const title = section.find('h3 div').first().text().trim(); - const summary = section.find('.u-contentSansThin div, .ui-summary').first().text().trim(); - const dateStr = section.find('time').attr('datetime'); - const tag = section.find('.TagName').attr('title') || ''; - const author = section.find('.uiScale a').first().text().trim(); - const image = section.find('img.graf-image--src').attr('data-srcset'); - - if (!title) { - return; - } - - const description = renderDescription({ - images: image ? [{ src: image }] : undefined, - intro: summary || undefined, + el.replaceWith( + renderDescription({ + images: imgEl + ? [ + { + src: imgEl.prop('src'), + width: imgEl.prop('width'), + height: imgEl.prop('height'), + }, + ] + : undefined, + }) + ); }); - items.push({ - title, - description, - pubDate: dateStr ? parseDate(dateStr) : undefined, - link, - category: tag ? [tag] : [], - author, - guid: link, - }); - }); - - return items; -} + const title = $$('h1').text(); + const intro = $$('h2').text(); -/** - * Extract articles from material5* blocks (featured cards on category/publication pages). - * Reason: on category pages, article links are often #Unauthorized (subscriber-only). - * We still extract the metadata and use the page URL + title hash as guid. - */ -function extractFromMaterialBlocks($: CheerioAPI, pageUrl: string): DataItem[] { - const items: DataItem[] = []; - - $('[class^="material5"]').each((_, el) => { - const block = $(el); - - const title = block.find('h3').first().text().trim(); - if (!title) { - return; - } - - const summary = block.find('.ui-summary, h4.ui-summary, p.ui-summary').first().text().trim(); - const dateStr = block.find('time').first().attr('datetime'); - const tag = block.find('.TagName').attr('title') || ''; - const author = block.find('.postMetaInline--author').first().text().trim(); - const image = block.find('img.graf-image--src').first().attr('data-srcset'); - - // Reason: try to find a real article link; fall back to page URL for subscriber-only content - const articleLink = findArticleLink($, block); - const link = articleLink || pageUrl; - const guid = articleLink || `${pageUrl}#${encodeURIComponent(title)}`; + $$('h1').parent().remove(); const description = renderDescription({ - images: image ? [{ src: image }] : undefined, - intro: summary || undefined, + images: image + ? [ + { + src: image, + }, + ] + : undefined, + intro, + description: $$.html(), }); - items.push({ - title, + return { + title: item.title?.rendered ?? item.title ?? title, description, - pubDate: dateStr ? parseDate(dateStr) : undefined, - link, - category: tag ? [tag] : [], - author, + pubDate: timezone(parseDate(item.date_gmt), 0), + updated: timezone(parseDate(item.modified_gmt), 0), + link: item.link, + category: [...new Set(terminologies.flat().map((c) => c.name))], + author: [...item._embedded.author, { name: publication }], guid, - }); + id: guid, + content: { + html: description, + text: $$.text(), + }, + }; }); - return items; -} + const data = await fetchData(currentUrl, rootUrl); -/** - * Extract articles from material6Lite streamItem--postPreview blocks. - * Reason: some category pages (e.g. Beijing) use this list format instead of material5 or extremePostPreview. - * These are typically subscriber-only articles with #Unauthorized links. - */ -function extractFromPostPreviews($: CheerioAPI, pageUrl: string): DataItem[] { - const items: DataItem[] = []; - - $('.streamItem--postPreview').each((_, el) => { - const block = $(el); - - const title = block.find('h3.graf--title').first().text().trim(); - if (!title) { - return; - } - - const summary = block.find('h4.ui-summary, .graf--subtitle').first().text().trim(); - const dateStr = block.find('time').first().attr('datetime'); - const author = block.find('.postMetaInline-authorLockup a').first().text().trim(); - const tag = block.find('.TagName').attr('title') || ''; - const image = block.find('img.graf-image--src').not('.avatar-image img').first().attr('data-srcset'); - - // Reason: these blocks typically have #Unauthorized links; use page URL as fallback - const articleLink = findArticleLink($, block); - const link = articleLink || pageUrl; - const guid = articleLink || `${pageUrl}#${encodeURIComponent(title)}`; - - const description = renderDescription({ - images: image ? [{ src: image }] : undefined, - intro: summary || undefined, - }); - - items.push({ - title, - description, - pubDate: dateStr ? parseDate(dateStr) : undefined, - link, - category: tag ? [tag] : [], - author, - guid, - }); - }); - - return items; -} + return { + ...data, + item: items, + }; +}; export const route: Route = { path: '/:filter{.+}?', name: '分类', - url: 'river.to', - maintainers: ['nczitzk', 'pseudoyu'], + url: 'the.bi', + maintainers: ['nczitzk'], handler, example: '/the', parameters: { filter: '过滤器,见下方描述' }, description: `::: tip - 如果你想订阅特定类别或出版物,可以在路由中填写 filter 参数。 + 如果你想订阅特定类别或标签,可以在路由中填写 filter 参数。\`/category/rawmw7dsta2jew\` 可以实现订阅 [剩余价值](https://the.bi/s/rawmw7dsta2jew) 类别。此时,路由是 [\`/the/category/rawmw7dsta2jew/\`](https://rsshub.app/the/category/rawmw7dsta2jew). + + 你还可以订阅多个类别。\`/category/rawmw7dsta2jew,rawbcvxkktdkq8/\` 可以实现同时订阅 [剩余价值](https://the.bi/s/rawmw7dsta2jew) 和 [打江山](https://the.bi/s/rawbcvxkktdkq8) 两个类别。此时,路由是 [\`/the/category/rawmw7dsta2jew,rawbcvxkktdkq8\`](https://rsshub.app/the/category/rawmw7dsta2jew,rawbcvxkktdkq8). - \`/category/rawj7o4ypewv94\` 可以实现订阅 [时局](https://river.to/occasus/rawj7o4ypewv94) 类别。此时,路由是 [\`/the/category/rawj7o4ypewv94/\`](https://rsshub.app/the/category/rawj7o4ypewv94). + 类别和标签也可以合并订阅。\`/category/rawmw7dsta2jew/tag/raweekl3na8trq\` 订阅 [剩余价值](https://the.bi/s/rawmw7dsta2jew) 类别和 [动物](https://the.bi/s/raweekl3na8trq) 标签。此时,路由是 [\`/the/category/rawmw7dsta2jew/tag/raweekl3na8trq\`](https://rsshub.app/the/category/rawmw7dsta2jew/tag/raweekl3na8trq). - 也可以直接使用 slug:[\`/the/rawj7o4ypewv94\`](https://rsshub.app/the/rawj7o4ypewv94) + 你还可以搜索关键字。\`/search/中国\` 搜索关键字 [中国](https://the.bi/s/?s=中国)。在这种情况下,路径是 [\`/the/search/中国\`](https://rsshub.app/the/search/中国). ::: -| 分类 | ID | -| --------------------------------------------------------- | ---------------------------------------------------------------- | -| [时局](https://river.to/occasus/rawj7o4ypewv94) | [rawj7o4ypewv94](https://rsshub.app/the/category/rawj7o4ypewv94) | -| [剩余价值](https://river.to/occasus/rawmw7dsta2jew) | [rawmw7dsta2jew](https://rsshub.app/the/category/rawmw7dsta2jew) | -| [Beijing](https://river.to/occasus/rawbcvxkktdkq8) | [rawbcvxkktdkq8](https://rsshub.app/the/category/rawbcvxkktdkq8) | -| [稳中向好](https://river.to/occasus/raw4krvx85dh27) | [raw4krvx85dh27](https://rsshub.app/the/category/raw4krvx85dh27) | -| [水深火热](https://river.to/occasus/rawtn8jpsc6uvv) | [rawtn8jpsc6uvv](https://rsshub.app/the/category/rawtn8jpsc6uvv) | -| [东升西降](https://river.to/occasus/rawai5kd4z15il) | [rawai5kd4z15il](https://rsshub.app/the/category/rawai5kd4z15il) | -| [大局](https://river.to/occasus/raw2efkzejrsx8) | [raw2efkzejrsx8](https://rsshub.app/the/category/raw2efkzejrsx8) | -| [境外势力](https://river.to/occasus/rawmpalhnlphuc) | [rawmpalhnlphuc](https://rsshub.app/the/category/rawmpalhnlphuc) | -| [副刊](https://river.to/occasus/rawxght2jr2u5z) | [rawxght2jr2u5z](https://rsshub.app/the/category/rawxght2jr2u5z) | -| [天高地厚](https://river.to/occasus/rawrsnh9zakqdx) | [rawrsnh9zakqdx](https://rsshub.app/the/category/rawrsnh9zakqdx) | -| [Oyster](https://river.to/occasus/rawdhl9hugdfn9) | [rawdhl9hugdfn9](https://rsshub.app/the/category/rawdhl9hugdfn9) | +| 分类 | ID | +| ---------------------------------------------- | ---------------------------------------------------------------- | +| [时局图](https://the.bi/s/rawj7o4ypewv94) | [rawj7o4ypewv94](https://rsshub.app/the/category/rawj7o4ypewv94) | +| [剩余价值](https://the.bi/s/rawmw7dsta2jew) | [rawmw7dsta2jew](https://rsshub.app/the/category/rawmw7dsta2jew) | +| [打江山](https://the.bi/s/rawbcvxkktdkq8) | [rawbcvxkktdkq8](https://rsshub.app/the/category/rawbcvxkktdkq8) | +| [中国经济](https://the.bi/s/raw4krvx85dh27) | [raw4krvx85dh27](https://rsshub.app/the/category/raw4krvx85dh27) | +| [水深火热](https://the.bi/s/rawtn8jpsc6uvv) | [rawtn8jpsc6uvv](https://rsshub.app/the/category/rawtn8jpsc6uvv) | +| [东升西降](https://the.bi/s/rawai5kd4z15il) | [rawai5kd4z15il](https://rsshub.app/the/category/rawai5kd4z15il) | +| [大局 & 大棋](https://the.bi/s/raw2efkzejrsx8) | [raw2efkzejrsx8](https://rsshub.app/the/category/raw2efkzejrsx8) | +| [境外势力](https://the.bi/s/rawmpalhnlphuc) | [rawmpalhnlphuc](https://rsshub.app/the/category/rawmpalhnlphuc) | +| [副刊](https://the.bi/s/rawxght2jr2u5z) | [rawxght2jr2u5z](https://rsshub.app/the/category/rawxght2jr2u5z) | +| [天高地厚](https://the.bi/s/rawrsnh9zakqdx) | [rawrsnh9zakqdx](https://rsshub.app/the/category/rawrsnh9zakqdx) | +| [Oyster](https://the.bi/s/rawdhl9hugdfn9) | [rawdhl9hugdfn9](https://rsshub.app/the/category/rawdhl9hugdfn9) | `, categories: ['new-media'], @@ -284,7 +145,7 @@ export const route: Route = { }, radar: [ { - source: ['river.to/occasus/:category?'], + source: ['the.bi/s/:category?'], target: (params) => { const category = params.category; @@ -292,59 +153,59 @@ export const route: Route = { }, }, { - title: '时局', - source: ['river.to/occasus/rawj7o4ypewv94'], - target: '/the/category/rawj7o4ypewv94', + title: '时局图', + source: ['the.bi/s/rawj7o4ypewv94'], + target: '/category/rawj7o4ypewv94', }, { title: '剩余价值', - source: ['river.to/occasus/rawmw7dsta2jew'], - target: '/the/category/rawmw7dsta2jew', + source: ['the.bi/s/rawmw7dsta2jew'], + target: '/category/rawmw7dsta2jew', }, { - title: 'Beijing', - source: ['river.to/occasus/rawbcvxkktdkq8'], - target: '/the/category/rawbcvxkktdkq8', + title: '打江山', + source: ['the.bi/s/rawbcvxkktdkq8'], + target: '/category/rawbcvxkktdkq8', }, { - title: '稳中向好', - source: ['river.to/occasus/raw4krvx85dh27'], - target: '/the/category/raw4krvx85dh27', + title: '中国经济', + source: ['the.bi/s/raw4krvx85dh27'], + target: '/category/raw4krvx85dh27', }, { title: '水深火热', - source: ['river.to/occasus/rawtn8jpsc6uvv'], - target: '/the/category/rawtn8jpsc6uvv', + source: ['the.bi/s/rawtn8jpsc6uvv'], + target: '/category/rawtn8jpsc6uvv', }, { title: '东升西降', - source: ['river.to/occasus/rawai5kd4z15il'], - target: '/the/category/rawai5kd4z15il', + source: ['the.bi/s/rawai5kd4z15il'], + target: '/category/rawai5kd4z15il', }, { - title: '大局', - source: ['river.to/occasus/raw2efkzejrsx8'], - target: '/the/category/raw2efkzejrsx8', + title: '大局 & 大棋', + source: ['the.bi/s/raw2efkzejrsx8'], + target: '/category/raw2efkzejrsx8', }, { title: '境外势力', - source: ['river.to/occasus/rawmpalhnlphuc'], - target: '/the/category/rawmpalhnlphuc', + source: ['the.bi/s/rawmpalhnlphuc'], + target: '/category/rawmpalhnlphuc', }, { title: '副刊', - source: ['river.to/occasus/rawxght2jr2u5z'], - target: '/the/category/rawxght2jr2u5z', + source: ['the.bi/s/rawxght2jr2u5z'], + target: '/category/rawxght2jr2u5z', }, { title: '天高地厚', - source: ['river.to/occasus/rawrsnh9zakqdx'], - target: '/the/category/rawrsnh9zakqdx', + source: ['the.bi/s/rawrsnh9zakqdx'], + target: '/category/rawrsnh9zakqdx', }, { title: 'Oyster', - source: ['river.to/occasus/rawdhl9hugdfn9'], - target: '/the/category/rawdhl9hugdfn9', + source: ['the.bi/s/rawdhl9hugdfn9'], + target: '/category/rawdhl9hugdfn9', }, ], }; diff --git a/lib/routes/the/namespace.ts b/lib/routes/the/namespace.ts index 2ea88c9d6f9c..7e1491bc1035 100644 --- a/lib/routes/the/namespace.ts +++ b/lib/routes/the/namespace.ts @@ -1,9 +1,9 @@ import type { Namespace } from '@/types'; export const namespace: Namespace = { - name: 'River.to (江河日下)', - url: 'river.to', + name: 'The.bi', + url: 'the.bi', categories: ['new-media'], description: '', - lang: 'zh-CN', + lang: 'en', }; diff --git a/lib/routes/the/util.ts b/lib/routes/the/util.ts index ab6947a1ce76..1e7960cdbd1e 100644 --- a/lib/routes/the/util.ts +++ b/lib/routes/the/util.ts @@ -1,2 +1,308 @@ -// This file is intentionally left minimal after migration from the.bi (WordPress) to river.to (custom SSR). -// The WordPress REST API utilities are no longer needed. +import { load } from 'cheerio'; + +import got from '@/utils/got'; + +const apiSlug = 'wp-json/wp/v2'; + +interface Filter { + id: string; + name: string; + slug: string; +} + +const filterKeys: Record = { + search: 's', +}; + +const filterApiKeys: Record = { + category: 'categories', + tag: 'tags', + search: undefined, +}; + +const filterApiKeysWithNoId = new Set(['search']); + +/** + * Bake filter search parameters. + * + * @param filterPairs - The filter pairs object. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + * @param pairKey - The filter pair key. + * e.g. `{ id: ..., name: ..., slug: ... }`. + * @param isApi - Indicates if the search parameters are for API. + * @returns The baked filter search parameters. + */ +const bakeFilterSearchParams = (filterPairs: Record, pairKey: string, isApi: boolean = false): URLSearchParams => { + /** + * Bake filters recursively. + * + * @param filterPairs - The filter pairs object. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + * @param filterSearchParams - The filter search parameters. + * e.g. `category=a,b&tag=c`. + * @returns The baked filter search parameters. + * e.g. `category=a,b&tag=c`. + */ + const bakeFilters = (filterPairs: Record, filterSearchParams: URLSearchParams): URLSearchParams => { + const keys = Object.keys(filterPairs).filter((key) => filterPairs[key]?.length > 0 && (isApi ? Object.hasOwn(filterApiKeys, key) : Object.hasOwn(filterKeys, key))); + + if (keys.length === 0) { + return filterSearchParams; + } + + const key = keys[0]; + const pairs = filterPairs[key]; + + const originalFilters = { ...filterPairs }; + delete originalFilters[key]; + + const filterKey = getFilterKeyForSearchParams(key, isApi); + const pairValues = pairs.map((pair) => (Object.hasOwn(pair, pairKey) ? pair[pairKey] : pair)); + + if (filterKey) { + filterSearchParams.append(filterKey, pairValues.join(',')); + } + + return bakeFilters(originalFilters, filterSearchParams); + }; + + return bakeFilters(filterPairs, new URLSearchParams()); +}; + +/** + * Bake filters with pair. + * + * @param filters - The filters object. + * e.g. `{ category: [ a, b ], tag: [ c ] }`. + * @returns The baked filters. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + */ +const bakeFiltersWithPair = async (filters: Record, rootUrl: string) => { + /** + * Bake keywords recursively. + * + * @param key - The key. + * e.g. `category` or `tag`. + * @param keywords - The keywords. + * e.g. `[ a, b ]`. + * @returns The baked keywords. + * e.g. `[ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ]`. + */ + const bakeKeywords = async (key: string, keywords: string[]) => { + if (keywords.length === 0) { + return []; + } + + const [keyword, ...rest] = keywords; + + const filter = await getFilterByKeyAndKeyword(key, keyword, rootUrl); + + return [ + ...(filter?.id && filter?.slug + ? [ + { + id: filter.id, + name: filter.name, + slug: filter.slug, + }, + ] + : []), + ...(await bakeKeywords(key, rest)), + ]; + }; + + /** + * Bake filters recursively. + * + * @param filters - The filters object. + * e.g. `{ category: [ a, b ], tag: [ c ] }`. + * @param filtersWithPair - The filters with pairs. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + * @returns The baked filters. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + */ + const bakeFilters = async (filters: Record, filtersWithPair: Record) => { + const keys = Object.keys(filters); + + if (keys.length === 0) { + return filtersWithPair; + } + + const key = keys[0]; + const keywords = filters[key]; + + const originalFilters = { ...filters }; + delete originalFilters[key]; + + return bakeFilters(originalFilters, { + ...filtersWithPair, + [key]: filterApiKeysWithNoId.has(key) ? keywords : await bakeKeywords(key, keywords), + }); + }; + + return await bakeFilters(filters, {}); +}; + +/** + * Bake URL with search parameters. + * + * @param url - The URL. + * @param rootUrl - The root URL. + * @param searchParams - The search parameters. + * @returns The baked URL. + */ +const bakeUrl = (url: string, rootUrl: string, searchParams: URLSearchParams = new URLSearchParams()): string => { + const searchParamsStr = searchParams.toString(); + const searchParamsSuffix = searchParamsStr ? `?${searchParamsStr}` : ''; + + return `${rootUrl}/${url}${searchParamsSuffix}`; +}; + +/** + * Fetch data from the specified URL. + * + * @param url - The URL to fetch data from. + * @param rootUrl - The root URL. + * @returns A promise that resolves to an object containing the fetched data to be added into `ctx.state.data`. + */ +const fetchData = async (url: string, rootUrl: string): Promise => { + /** + * Request URLs recursively. + * + * @param urls - The URLs to request. + * @returns A promise that resolves to the response data or undefined if no response is available. + */ + const requestUrls = async (urls: string[]): Promise => { + if (urls.length === 0) { + return; + } + + const [currentUrl, ...remainingUrls] = urls; + try { + const { data: response } = await got.get(currentUrl); + return response; + } catch { + return requestUrls(remainingUrls); + } + }; + + const response = await requestUrls([url, rootUrl]); + + if (!response) { + return {}; + } + + const $ = load(response); + + const title = $('title').first().text(); + const image = new URL('wp-content/uploads/site_logo.png', rootUrl).href; + + return { + title, + description: $('meta[property="og:description"]').attr('content') || $('meta[name="description"]').attr('content'), + link: url, + allowEmpty: true, + image, + author: $('meta[property="og:site_name"]').attr('content'), + language: $('html').attr('lang'), + }; +}; + +/** + * Get filter by key and keyword. + * + * @param key - The key. + * e.g. `category` or `tag`. + * @param keyword - The keywords. + * e.g. `keyword1`. + * @returns A promise that resolves to the filter object if found, or undefined if not found. + */ +const getFilterByKeyAndKeyword = async (key: string, keyword: string, rootUrl: string): Promise => { + const apiFilterUrl = `${rootUrl}/${apiSlug}/${getFilterKeyForSearchParams(key, true)}`; + + const { data: response } = await got(apiFilterUrl, { + searchParams: { + search: keyword, + }, + }); + + return response.length > 0 ? response[0] : undefined; +}; + +/** + * Get filter key for search parameters. + * + * @param key - The key. e.g. `category` or `tag`. + * @param isApi - Indicates whether the key is for the API. + * @returns The filter key for search parameters, or undefined if not found. + * e.g. `categories` or `tags`. + */ +const getFilterKeyForSearchParams = (key: string, isApi: boolean = false): string | undefined => { + const keys = isApi ? filterApiKeys : filterKeys; + + return Object.hasOwn(keys, key) ? (keys[key] ?? key) : undefined; +}; + +/** + * Get filter parameters for URL. + * + * @param filterPairs - The filter pairs object. + * e.g. `{ category: [ { id: ..., name: ..., slug: ... }, { id: ..., name: ..., slug: ... } ], tag: [ { id: ..., name: ..., slug: ... } ] }`. + * @returns The filter parameters for the URL, or undefined if no filters are available. + */ +const getFilterParamsForUrl = (filterPairs: Record): string | undefined => { + const keys = Object.keys(filterPairs).filter((key) => filterPairs[key].length > 0 && !Object.hasOwn(filterKeys, key)); + + if (keys.length === 0) { + return; + } + + const key = keys[0]; + + return filterPairs[key].map((pair) => pair.slug).join('/'); +}; + +/** + * Parses a filter string into a filters object. + * + * @param filterStr - The filter string to parse. + * e.g. `category/a,b/tag/c`. + * @returns The parsed filters object. + * e.g. `{ category: [ 'a', 'b' ], tag: [ 'c' ] }`. + */ +const parseFilterStr = (filterStr: string | undefined): Record => { + /** + * Recursively parses a filter string. + * + * @param remainingStr - The remaining filter string to parse. + * e.g. `category/a,b/tag/c`. + * @param filters - The accumulated filters object. + * e.g. `{ category: [ a, b ], tag: [ c ] }`. + * @param currentKey - The current filter key. + * e.g. `category` or `tag`. + * @returns The parsed filters object. + */ + const parseStr = (remainingStr: string | undefined, filters: Record = {}, currentKey?: string): Record => { + if (!remainingStr) { + return filters; + } + + const [word, ...rest] = remainingStr.split(/\/|,/); + + const isKey = Object.hasOwn(filterApiKeys, word); + const key = isKey ? word : currentKey; + + const newFilters = key + ? { + ...filters, + [key]: [...(filters[key] || []), ...(isKey ? [] : [word])], + } + : filters; + + return parseStr(rest.join('/'), newFilters, key); + }; + + return parseStr(filterStr, {}); +}; + +export { apiSlug, bakeFilterSearchParams, bakeFiltersWithPair, bakeUrl, fetchData, getFilterParamsForUrl, parseFilterStr }; diff --git a/lib/routes/theinitium/app.ts b/lib/routes/theinitium/app.ts index 955e24a8e8da..5aa27897358f 100644 --- a/lib/routes/theinitium/app.ts +++ b/lib/routes/theinitium/app.ts @@ -69,7 +69,7 @@ export const route: Route = { supportScihub: false, }, name: 'App', - maintainers: ['quiniapiezoelectricity', 'pseudoyu'], + maintainers: ['quiniapiezoelectricity'], radar: [ { source: ['theinitium.com/latest/'], diff --git a/lib/routes/theinitium/author.ts b/lib/routes/theinitium/author.ts index 3b8a5b1955c2..d4e43d8a2162 100644 --- a/lib/routes/theinitium/author.ts +++ b/lib/routes/theinitium/author.ts @@ -8,7 +8,7 @@ export const route: Route = { path: '/author/:type/:language?', name: '作者', url: 'theinitium.com', - maintainers: ['AgFlore', 'pseudoyu'], + maintainers: ['AgFlore'], parameters: { type: '作者 slug,可从作者主页 URL 中获取,如 `https://theinitium.com/author/initium-newsroom/`', language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为不限', diff --git a/lib/routes/theinitium/channel.ts b/lib/routes/theinitium/channel.ts index 1f1ab3bda9ae..df91102c153e 100644 --- a/lib/routes/theinitium/channel.ts +++ b/lib/routes/theinitium/channel.ts @@ -8,7 +8,7 @@ export const route: Route = { path: '/channel/:type?/:language?', name: '栏目', url: 'theinitium.com', - maintainers: ['prnake', 'mintyfrankie', 'pseudoyu'], + maintainers: ['prnake', 'mintyfrankie'], parameters: { type: '栏目,缺省为最新(latest)', language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为不限', diff --git a/lib/routes/theinitium/follow.ts b/lib/routes/theinitium/follow.ts index 7f6245c848f4..ef56fef97c61 100644 --- a/lib/routes/theinitium/follow.ts +++ b/lib/routes/theinitium/follow.ts @@ -3,7 +3,7 @@ import type { Route } from '@/types'; export const route: Route = { path: '/follow/articles/:language?', name: '个人订阅追踪动态(已停用)', - maintainers: ['AgFlore', 'pseudoyu'], + maintainers: ['AgFlore'], parameters: { language: '语言', }, diff --git a/lib/routes/theinitium/tags.ts b/lib/routes/theinitium/tags.ts index e90cda35f248..37155f1983c7 100644 --- a/lib/routes/theinitium/tags.ts +++ b/lib/routes/theinitium/tags.ts @@ -8,7 +8,7 @@ export const route: Route = { path: '/tags/:type/:language?', name: '话题・标签', url: 'theinitium.com', - maintainers: ['AgFlore', 'pseudoyu'], + maintainers: ['AgFlore'], parameters: { type: '标签 slug,可从标签页 URL 中获取,如 `https://theinitium.com/tag/south-korea/` 则为 `south-korea`', language: '语言,简体`zh-hans`,繁体`zh-hant`,缺省为不限', diff --git a/lib/routes/thepaper/sidebar.ts b/lib/routes/thepaper/sidebar.ts index 86b12b97ae8e..3b3bdedc5c59 100644 --- a/lib/routes/thepaper/sidebar.ts +++ b/lib/routes/thepaper/sidebar.ts @@ -1,13 +1,12 @@ import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; +import got from '@/utils/got'; import utils from './utils'; const sections = { hotNews: '澎湃热榜', - financialInformationNews: '澎湃快讯', + financialInformationNews: '澎湃财讯', morningEveningNews: '早晚报', - editorHandpicked: '要闻精选', }; export const route: Route = { @@ -21,12 +20,7 @@ export const route: Route = { name: '侧边栏', categories: ['new-media'], example: '/thepaper/sidebar', - parameters: { - sec: { - description: '侧边栏 id', - options: Object.entries(sections).map(([key, value]) => ({ label: value, value: key })), - }, - }, + parameters: { sec: '侧边栏 id,可选 `hotNews` 即 澎湃热榜、`financialInformationNews` 即 澎湃财讯、`morningEveningNews` 即 早晚报,默认为 `hotNews`' }, maintainers: ['bigfei'], handler, url: 'thepaper.cn/', @@ -35,13 +29,14 @@ export const route: Route = { async function handler(ctx) { const { sec = 'hotNews' } = ctx.req.param(); - const sidebarUrl = 'https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar'; - const sidebarUrlData = await ofetch(sidebarUrl); - const list = sidebarUrlData.data[sec]; + const sidebar_url = `https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar`; + const sidebar_url_resp = await got(sidebar_url); + const sidebar_url_data = sidebar_url_resp.data; + const list = sidebar_url_data.data[sec]; const items = await Promise.all(list.filter((item) => item.contId).map((item) => utils.ProcessItem(item, ctx))); return { - title: `澎湃新闻 - ${sections[sec] ?? sec}`, + title: `澎湃新闻 - ${sections[sec]}`, item: items, link: 'https://www.thepaper.cn', }; diff --git a/lib/routes/thinkingmachines/namespace.ts b/lib/routes/thinkingmachines/namespace.ts deleted file mode 100644 index 6fdeafc03c48..000000000000 --- a/lib/routes/thinkingmachines/namespace.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'Thinking Machines Lab', - url: 'thinkingmachines.ai', -}; diff --git a/lib/routes/thinkingmachines/news.ts b/lib/routes/thinkingmachines/news.ts deleted file mode 100644 index f9b7ae6f2eee..000000000000 --- a/lib/routes/thinkingmachines/news.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/news', - name: 'News', - url: 'thinkingmachines.ai/news', - maintainers: ['w3nhao'], - example: '/thinkingmachines/news', - categories: ['programming'], - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - }, - radar: [ - { - source: ['thinkingmachines.ai/news', 'thinkingmachines.ai/news/'], - target: '/news', - }, - ], - handler, -}; - -async function handler() { - const baseUrl = 'https://thinkingmachines.ai'; - const listUrl = `${baseUrl}/news/`; - - const response = await ofetch(listUrl); - const $ = load(response); - - const items = $('main li a') - .toArray() - .map((el) => { - const $el = $(el); - const title = $el.find('.post-title').text().trim(); - const dateStr = $el.find('time.desktop-time').text().trim(); - const href = $el.attr('href') || ''; - const link = href.startsWith('http') ? href : `${baseUrl}${href}`; - - return { title, dateStr, link }; - }) - .filter((item) => item.title && item.link); - - const fullItems = await Promise.all( - items.map((item) => - cache.tryGet(item.link, async () => { - const articleResponse = await ofetch(item.link); - const $article = load(articleResponse); - - // Remove non-content elements - $article('nav, footer, header, script, style').remove(); - // Remove heading (title, author, pubDate) and paginator - $article('.post-heading, #post-prev-link, #post-next-link').remove(); - - const description = $article('main').html()?.trim() || ''; - - return { - title: item.title, - link: item.link, - pubDate: parseDate(item.dateStr, 'MMM D, YYYY'), - description, - }; - }) - ) - ); - - return { - title: 'Thinking Machines Lab - News', - link: listUrl, - item: fullItems, - }; -} diff --git a/lib/routes/trendforce/namespace.ts b/lib/routes/trendforce/namespace.ts index 78b1bf4296c7..b52d0094a236 100644 --- a/lib/routes/trendforce/namespace.ts +++ b/lib/routes/trendforce/namespace.ts @@ -6,8 +6,4 @@ export const namespace: Namespace = { categories: ['new-media'], description: '', lang: 'en', - zh: { - name: '集邦咨询', - url: 'trendforce.cn', - }, }; diff --git a/lib/routes/trendforce/news-cn.ts b/lib/routes/trendforce/news-cn.ts deleted file mode 100644 index b10979cea88f..000000000000 --- a/lib/routes/trendforce/news-cn.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/cn/presscenter/news', - categories: ['new-media'], - example: '/trendforce/cn/presscenter/news', - radar: [ - { - source: ['www.trendforce.cn/presscenter/news'], - }, - ], - name: '产业洞察', - maintainers: ['TonyRL'], - handler, - url: 'www.trendforce.cn/presscenter/news', -}; - -async function handler() { - const baseUrl = 'https://www.trendforce.cn'; - const link = `${baseUrl}/presscenter/news`; - - const response = await ofetch(link); - const $ = load(response); - - const list = $('.list-items .list-item') - .toArray() - .map((item) => { - const $item = $(item); - const a = $item.find('h3 a.title-link'); - return { - title: a.find('strong').text().trim(), - link: new URL(a.attr('href')!, baseUrl).href, - description: $item.find('p').text()?.trim(), - pubDate: parseDate($item.find('h4').text().trim()), - }; - }); - - const items = await Promise.all( - list.map((item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); - const $ = load(response); - - const pressCenter = $('.presscenter'); - const tagRow = pressCenter.find('.tag-row'); - - item.category = tagRow - .find('.fa-bookmark') - .parent() - .find('a') - .toArray() - .map((a) => $(a).text().trim()); - item.author = tagRow.find('.fa-user').parent().find('a').text().trim(); - - pressCenter.find('h1, .tag-row, .press-choose-post, hr').remove(); - - item.description = pressCenter.html()?.trim(); - - return item; - }) - ) - ); - - return { - title: $('head title').text().trim(), - description: $('meta[name="description"]').attr('content'), - link, - language: $('html').attr('lang'), - image: `${baseUrl}${$('link[rel="apple-touch-icon-precomposed"][sizes="152x152"]').attr('href')}`, - item: items, - }; -} diff --git a/lib/routes/tw-nongmu/market.ts b/lib/routes/tw-nongmu/market.ts deleted file mode 100644 index 1167ed7858fa..000000000000 --- a/lib/routes/tw-nongmu/market.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; -import { finishArticleItem } from '@/utils/wechat-mp'; - -export const route: Route = { - path: '/market', - categories: ['other'], - example: '/tw-nongmu/market', - radar: [ - { - source: ['www.tw-nongmu.com/market.html', 'www.tw-nongmu.com/'], - }, - ], - name: '鱼价行情', - maintainers: ['TonyRL'], - handler, - url: 'www.tw-nongmu.com/market.html', -}; - -async function handler() { - const baseUrl = 'https://www.tw-nongmu.com'; - const link = `${baseUrl}/market.html`; - - const response = await ofetch(link); - const $ = load(response); - - const list = $('.list-list li') - .toArray() - .map((item) => { - const $item = $(item); - const a = $item.find('a'); - return { - title: a.text(), - link: a.attr('href')!, - pubDate: parseDate($item.find('.date').text(), 'YYYY年MM月DD日'), - }; - }); - - const items = await Promise.all(list.map((item) => finishArticleItem(item))); - - return { - title: $('head title').text(), - link, - language: $('html').attr('lang') as const, - image: `${baseUrl}/favicon.ico`, - item: items, - }; -} diff --git a/lib/routes/tw-nongmu/namespace.ts b/lib/routes/tw-nongmu/namespace.ts deleted file mode 100644 index 8953d24bdca8..000000000000 --- a/lib/routes/tw-nongmu/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: '通威农业发展', - url: 'www.tw-nongmu.com', - lang: 'zh-CN', -}; diff --git a/lib/routes/twitter/api/web-api/api.ts b/lib/routes/twitter/api/web-api/api.ts index b412517badef..be9c908cc42b 100644 --- a/lib/routes/twitter/api/web-api/api.ts +++ b/lib/routes/twitter/api/web-api/api.ts @@ -3,7 +3,7 @@ import InvalidParameterError from '@/errors/types/invalid-parameter'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; -import { baseUrl, gqlFeatures, gqlMap, initGqlMap } from './constants'; +import { baseUrl, gqlFeatures, gqlMap } from './constants'; import { gatherLegacyFromData, paginationTweets, twitterGot } from './utils'; const getUserData = (id) => @@ -216,5 +216,5 @@ export default { getList, getHomeTimeline, getHomeLatestTimeline, - init: initGqlMap, + init: () => {}, }; diff --git a/lib/routes/twitter/api/web-api/constants.ts b/lib/routes/twitter/api/web-api/constants.ts index ea58af273d5e..b1ca1d46a1af 100644 --- a/lib/routes/twitter/api/web-api/constants.ts +++ b/lib/routes/twitter/api/web-api/constants.ts @@ -1,14 +1,19 @@ -import { buildGqlMap, fallbackIds, resolveQueryIds } from './gql-id-resolver'; - const baseUrl = 'https://x.com/i/api'; -// Initial gqlMap from fallback IDs, updated dynamically via initGqlMap() -let gqlMap: Record = buildGqlMap(fallbackIds); +const graphQLEndpointsPlain = [ + '/graphql/E3opETHurmVJflFsUBVuUQ/UserTweets', + '/graphql/Yka-W8dz7RaEuQNkroPkYw/UserByScreenName', + '/graphql/HJFjzBgCs16TqxewQOeLNg/HomeTimeline', + '/graphql/DiTkXJgLqBBxCs7zaYsbtA/HomeLatestTimeline', + '/graphql/bt4TKuFz4T7Ckk-VvQVSow/UserTweetsAndReplies', + '/graphql/dexO_2tohK86JDudXXG3Yw/UserMedia', + '/graphql/Qw77dDjp9xCpUY-AXwt-yQ/UserByRestId', + '/graphql/UN1i3zUiCWa-6r-Uaho4fw/SearchTimeline', + '/graphql/Pa45JvqZuKcW1plybfgBlQ/ListLatestTweetsTimeline', + '/graphql/QuBlQ6SxNAQCt6-kBiCXCQ/TweetDetail', +]; -const initGqlMap = async () => { - const queryIds = await resolveQueryIds(); - gqlMap = buildGqlMap(queryIds); -}; +const gqlMap = Object.fromEntries(graphQLEndpointsPlain.map((endpoint) => [endpoint.split('/')[3].replace(/V2$|Query$|QueryV2$/, ''), endpoint])); const thirdPartySupportedAPI = ['UserByScreenName', 'UserByRestId', 'UserTweets', 'UserTweetsAndReplies', 'ListLatestTweetsTimeline', 'SearchTimeline', 'UserMedia']; @@ -109,4 +114,4 @@ const timelineParams = { const bearerToken = 'Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA'; -export { baseUrl, bearerToken, gqlFeatures, gqlMap, initGqlMap, thirdPartySupportedAPI, timelineParams }; +export { baseUrl, bearerToken, gqlFeatures, gqlMap, thirdPartySupportedAPI, timelineParams }; diff --git a/lib/routes/twitter/api/web-api/gql-id-resolver.ts b/lib/routes/twitter/api/web-api/gql-id-resolver.ts deleted file mode 100644 index 9c2067aceba7..000000000000 --- a/lib/routes/twitter/api/web-api/gql-id-resolver.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { config } from '@/config'; -import cache from '@/utils/cache'; -import logger from '@/utils/logger'; -import ofetch from '@/utils/ofetch'; - -const CACHE_KEY = 'twitter:gql-query-ids'; - -// Hardcoded fallback IDs (last known working values) -export const fallbackIds: Record = { - UserTweets: 'E3opETHurmVJflFsUBVuUQ', - UserByScreenName: 'Yka-W8dz7RaEuQNkroPkYw', - HomeTimeline: 'xhYBF94fPSp8ey64FfYXiA', - HomeLatestTimeline: '0vp2Au9doTKsbn2vIk48Dg', - UserTweetsAndReplies: 'bt4TKuFz4T7Ckk-VvQVSow', - UserMedia: 'dexO_2tohK86JDudXXG3Yw', - UserByRestId: 'Qw77dDjp9xCpUY-AXwt-yQ', - SearchTimeline: 'UN1i3zUiCWa-6r-Uaho4fw', - ListLatestTweetsTimeline: 'Pa45JvqZuKcW1plybfgBlQ', - TweetDetail: 'QuBlQ6SxNAQCt6-kBiCXCQ', -}; - -const operationNames = Object.keys(fallbackIds); - -async function fetchTwitterPage(): Promise { - const response = await ofetch('https://x.com', { - parseResponse: (txt) => txt, - }); - return response as unknown as string; -} - -function extractQueryIds(scriptContent: string): Record { - const ids: Record = {}; - const matches = scriptContent.matchAll(/queryId:"([^"]+?)".+?operationName:"([^"]+?)"/g); - for (const match of matches) { - const [, queryId, operationName] = match; - if (operationNames.includes(operationName)) { - ids[operationName] = queryId; - } - } - return ids; -} - -async function fetchAndExtractIds(): Promise> { - const html = await fetchTwitterPage(); - - // Extract main.hash.js URL — it contains all the GraphQL query IDs we need - const mainMatch = html.match(/\/client-web\/main\.([a-z0-9]+)\./); - if (!mainMatch) { - logger.warn('twitter gql-id-resolver: main.js URL not found in Twitter page'); - return {}; - } - - const mainUrl = `https://abs.twimg.com/responsive-web/client-web/main.${mainMatch[1]}.js`; - logger.debug(`twitter gql-id-resolver: fetching ${mainUrl}`); - - const content = await ofetch(mainUrl, { - parseResponse: (txt) => txt, - }); - return extractQueryIds(content as unknown as string); -} - -let resolvePromise: Promise> | null = null; - -export async function resolveQueryIds(): Promise> { - // Check cache first - const cached = await cache.get(CACHE_KEY); - if (cached) { - try { - const parsed = typeof cached === 'string' ? JSON.parse(cached) : cached; - if (parsed && typeof parsed === 'object' && Object.keys(parsed).length > 0) { - logger.debug(`twitter gql-id-resolver: using cached query IDs`); - return { ...fallbackIds, ...parsed }; - } - } catch { - // ignore parse error - } - } - - // Deduplicate concurrent requests - if (!resolvePromise) { - resolvePromise = (async () => { - try { - logger.info('twitter gql-id-resolver: fetching fresh query IDs from Twitter JS bundles'); - const ids = await fetchAndExtractIds(); - - if (Object.keys(ids).length > 0) { - await cache.set(CACHE_KEY, JSON.stringify(ids), config.cache.contentExpire); - const found = operationNames.filter((name) => ids[name]); - const missing = operationNames.filter((name) => !ids[name]); - logger.debug(`twitter gql-id-resolver: resolved ${found.length}/${operationNames.length} query IDs. Missing: ${missing.join(', ') || 'none'}`); - } else { - logger.warn('twitter gql-id-resolver: failed to extract any query IDs, using fallback'); - } - - return ids; - } catch (error) { - logger.warn(`twitter gql-id-resolver: error fetching query IDs: ${error}. Using fallback.`); - return {}; - } finally { - resolvePromise = null; - } - })(); - } - - const ids = await resolvePromise; - return { ...fallbackIds, ...ids }; -} - -export function buildGqlMap(queryIds: Record): Record { - const map: Record = {}; - for (const name of operationNames) { - const id = queryIds[name] || fallbackIds[name]; - map[name] = `/graphql/${id}/${name}`; - } - return map; -} diff --git a/lib/routes/twitter/api/web-api/utils.ts b/lib/routes/twitter/api/web-api/utils.ts index 560211aabce4..becf3f74aaac 100644 --- a/lib/routes/twitter/api/web-api/utils.ts +++ b/lib/routes/twitter/api/web-api/utils.ts @@ -1,7 +1,7 @@ import { cookie as HttpCookieAgentCookie, CookieAgent } from 'http-cookie-agent/undici'; import queryString from 'query-string'; import { Cookie, CookieJar } from 'tough-cookie'; -import undici, { Client, ProxyAgent } from 'undici'; +import { Client, ProxyAgent } from 'undici'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; @@ -136,21 +136,8 @@ export const twitterGot = async ( ) : {}; - // Use undici.fetch directly instead of ofetch.raw to preserve the CookieAgent - // dispatcher. Two layers drop it in the normal path: - // 1. ofetch does not forward `dispatcher` to its internal fetch() call - // 2. wrappedFetch (request-rewriter) does `new Request(input, init)` which - // discards non-standard options like `dispatcher` - // Additionally, setting `cookie` header manually doesn't work either because - // the Fetch spec treats `cookie` as a forbidden header name, so - // `new Request()` silently strips it. - // The only way to send cookies via CookieAgent is to call undici.fetch with - // the dispatcher option directly. - // - // Because undici.fetch is the standard Fetch API and does not support ofetch's - // `onResponse` callback, the rate-limit and auth error handling that was - // previously in `onResponse` is now inlined below. - const response = await undici.fetch(requestUrl, { + const response = await ofetch.raw(requestUrl, { + retry: 0, headers: { authority: 'x.com', accept: '*/*', @@ -173,77 +160,67 @@ export const twitterGot = async ( }), }, dispatcher: dispatchers?.agent, - }); - - let responseData: any; - try { - responseData = await response.json(); - } catch { - responseData = null; - } - - // Handle rate limiting and auth errors - const remaining = response.headers.get('x-rate-limit-remaining'); - const remainingInt = Number.parseInt(remaining || '0'); - const reset = response.headers.get('x-rate-limit-reset'); - logger.debug( - `twitter debug: twitter rate limit remaining for token ${auth?.token} is ${remaining} and reset at ${reset}, auth: ${JSON.stringify(auth)}, status: ${response.status}, data: ${JSON.stringify(responseData?.data)}, cookie: ${JSON.stringify(dispatchers?.jar.serializeSync())}` - ); - if (auth) { - if (remaining && remainingInt < 2 && reset) { - const resetTime = new Date(Number.parseInt(reset) * 1000); - const delay = (resetTime.getTime() - Date.now()) / 1000; - logger.debug(`twitter debug: twitter rate limit exceeded for token ${auth.token} with status ${response.status}, will unlock after ${delay}s`); - await cache.set(`${lockPrefix}${auth.token}`, '1', Math.ceil(delay) * 2); - } else if (response.status === 429 || JSON.stringify(responseData?.data) === '{"user":{}}') { - logger.debug(`twitter debug: twitter rate limit exceeded for token ${auth.token} with status ${response.status}`); - await cache.set(`${lockPrefix}${auth.token}`, '1', 2000); - } else if (response.status === 403 || response.status === 401) { - const newCookie = await login({ - username: auth.username, - password: auth.password, - authenticationSecret: auth.authenticationSecret, - }); - if (newCookie) { - logger.debug(`twitter debug: reset twitter cookie for token ${auth.token}, ${newCookie}`); - await cache.set(`twitter:cookie:${auth.token}`, newCookie, config.cache.contentExpire); - await cache.set(`${lockPrefix}${auth.token}`, '', 1); - } else { - const tokenIndex = config.twitter.authToken?.indexOf(auth.token); - if (tokenIndex !== undefined && tokenIndex !== -1) { - config.twitter.authToken?.splice(tokenIndex, 1); - } - if (auth.username) { - const usernameIndex = config.twitter.username?.indexOf(auth.username); - if (usernameIndex !== undefined && usernameIndex !== -1) { - config.twitter.username?.splice(usernameIndex, 1); - } - } - if (auth.password) { - const passwordIndex = config.twitter.password?.indexOf(auth.password); - if (passwordIndex !== undefined && passwordIndex !== -1) { - config.twitter.password?.splice(passwordIndex, 1); + onResponse: async ({ response }) => { + const remaining = response.headers.get('x-rate-limit-remaining'); + const remainingInt = Number.parseInt(remaining || '0'); + const reset = response.headers.get('x-rate-limit-reset'); + logger.debug( + `twitter debug: twitter rate limit remaining for token ${auth?.token} is ${remaining} and reset at ${reset}, auth: ${JSON.stringify(auth)}, status: ${response.status}, data: ${JSON.stringify(response._data?.data)}, cookie: ${JSON.stringify(dispatchers?.jar.serializeSync())}` + ); + if (auth) { + if (remaining && remainingInt < 2 && reset) { + const resetTime = new Date(Number.parseInt(reset) * 1000); + const delay = (resetTime.getTime() - Date.now()) / 1000; + logger.debug(`twitter debug: twitter rate limit exceeded for token ${auth.token} with status ${response.status}, will unlock after ${delay}s`); + await cache.set(`${lockPrefix}${auth.token}`, '1', Math.ceil(delay) * 2); + } else if (response.status === 429 || JSON.stringify(response._data?.data) === '{"user":{}}') { + logger.debug(`twitter debug: twitter rate limit exceeded for token ${auth.token} with status ${response.status}`); + await cache.set(`${lockPrefix}${auth.token}`, '1', 2000); + } else if (response.status === 403 || response.status === 401) { + const newCookie = await login({ + username: auth.username, + password: auth.password, + authenticationSecret: auth.authenticationSecret, + }); + if (newCookie) { + logger.debug(`twitter debug: reset twitter cookie for token ${auth.token}, ${newCookie}`); + await cache.set(`twitter:cookie:${auth.token}`, newCookie, config.cache.contentExpire); + logger.debug(`twitter debug: unlock twitter cookie for token ${auth.token} with error1`); + await cache.set(`${lockPrefix}${auth.token}`, '', 1); + } else { + const tokenIndex = config.twitter.authToken?.indexOf(auth.token); + if (tokenIndex !== undefined && tokenIndex !== -1) { + config.twitter.authToken?.splice(tokenIndex, 1); + } + if (auth.username) { + const usernameIndex = config.twitter.username?.indexOf(auth.username); + if (usernameIndex !== undefined && usernameIndex !== -1) { + config.twitter.username?.splice(usernameIndex, 1); + } + } + if (auth.password) { + const passwordIndex = config.twitter.password?.indexOf(auth.password); + if (passwordIndex !== undefined && passwordIndex !== -1) { + config.twitter.password?.splice(passwordIndex, 1); + } + } + logger.debug(`twitter debug: delete twitter cookie for token ${auth.token} with status ${response.status}, remaining tokens: ${config.twitter.authToken?.length}`); + await cache.set(`${lockPrefix}${auth.token}`, '1', 3600); } + } else { + logger.debug(`twitter debug: unlock twitter cookie with success for token ${auth.token}`); + await cache.set(`${lockPrefix}${auth.token}`, '', 1); } - logger.debug(`twitter debug: delete twitter cookie for token ${auth.token} with status ${response.status}, remaining tokens: ${config.twitter.authToken?.length}`); - await cache.set(`${lockPrefix}${auth.token}`, '1', 3600); } - } else { - logger.debug(`twitter debug: unlock twitter cookie with success for token ${auth.token}`); - await cache.set(`${lockPrefix}${auth.token}`, '', 1); - } - } - - if (response.status >= 400) { - throw new Error(`Twitter API error: ${response.status}`); - } + }, + }); if (auth?.token) { logger.debug(`twitter debug: update twitter cookie for token ${auth.token}`); await cache.set(`twitter:cookie:${auth.token}`, JSON.stringify(dispatchers?.jar.serializeSync()), config.cache.contentExpire); } - return responseData; + return response._data; }; export const paginationTweets = async (endpoint: string, userId: number | undefined, variables: Record, path?: string[]) => { diff --git a/lib/routes/typst/universe.ts b/lib/routes/typst/universe.ts index 7d34a8d0c30e..bf432f71dcfd 100644 --- a/lib/routes/typst/universe.ts +++ b/lib/routes/typst/universe.ts @@ -1,42 +1,50 @@ +import vm from 'node:vm'; + import { load } from 'cheerio'; +import markdownit from 'markdown-it'; import type { Route } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; -function deserializeAstroProps(val: unknown): unknown { - if (Array.isArray(val)) { - const tag = val[0]; - if (tag === 0) { - return val.length > 1 ? deserializeAstroProps(val[1]) : undefined; - } - if (tag === 1) { - return val[1].map((item) => deserializeAstroProps(item)); - } - return val.map((item) => deserializeAstroProps(item)); - } - if (val && typeof val === 'object') { - const result = {}; - for (const [key, v] of Object.entries(val)) { - result[key] = deserializeAstroProps(v); - } - return result; - } - return val; -} - interface Package { name: string; version: string; + entrypoint: string; authors: string[]; license: string; description: string; + repository: string; keywords: string[]; + compiler: string; + exclude: string[]; + size: number; + readme: string; updatedAt: number; releasedAt: number; - hasRepo: boolean; - categories: string[]; - template: string | undefined; +} + +interface Context { + an: { exports: Package[] }; +} + +const GITHUBRAW_BASE = 'https://raw.githubusercontent.com'; +const PKG_GITHUB_BASE = `${GITHUBRAW_BASE}/typst/packages/main/packages/preview`; + +function fixImageSrc(src: string, env: Package) { + if (src.includes('://')) { + if (src.startsWith('https://typst.app/universe/package')) { + src = src.replaceAll('https://typst.app/universe/package', `${PKG_GITHUB_BASE}/${env.name}/${env.version}`); + } else if (src.startsWith('https://github.com/') && src.match(/\.(jpeg|jpg|gif|png|bmp|webp)$/gi)?.length) { + src = src.replace('https://github.com/', `${GITHUBRAW_BASE}/`); + } + } else { + const suffix = src.startsWith('/') ? '' : '/'; + const package_base = `${PKG_GITHUB_BASE}/${env.name}/${env.version}${suffix}`; + const url = new URL(src, package_base); + src = url.toString(); + } + return src; } export const route: Route = { @@ -52,24 +60,51 @@ export const route: Route = { name: 'Universe', maintainers: ['HPDell'], handler: async () => { - const targetUrl = 'https://typst.app/universe/search'; + const targetUrl = 'https://typst.app/universe/search?kind=packages%2Ctemplates&packages=last-updated'; const page = await ofetch(targetUrl); const $ = load(page); - const props = $('astro-island[component-export="SearchResults"]').attr('props'); - const searchResults = deserializeAstroProps(JSON.parse(props!)) as { packages: Package[] }; - const pkgs = searchResults.packages.map((item) => ({ - title: `${item.name} (${item.version}) | ${item.description}`, - link: `https://typst.app/universe/package/${item.name}`, - description: item.description, - pubDate: parseDate(item.updatedAt, 'X'), - category: item.keywords, - author: item.authors.join(', '), - })); - - return { - title: 'Typst Universe', - link: targetUrl, - item: pkgs, - }; + const script = $('script') + .toArray() + .map((item) => item.attribs.src) + .find((item) => item && item.startsWith('/scripts/universe-search')); + const data: string = await ofetch(`https://typst.app${script}`, { + parseResponse: (txt) => txt, + }); + let packages = data.match(/(an.exports=[\S\s]+);var ([$A-Z_a-z][\w$]*)=new Intl.Collator/)?.[1]; + if (packages) { + packages = packages.slice(0, -2); + const context: Context = { an: { exports: [] } }; + vm.createContext(context); + vm.runInContext(packages, context, { + displayErrors: true, + }); + const md = markdownit('commonmark'); + const items = context.an.exports.toSorted((a, b) => a.updatedAt - b.updatedAt); + const groups = new Map(items.map((it) => [it.name, it])); + const pkgs = [...groups.values()].map((item) => { + const $ = load(md.render(item.readme)); + $('img').each((i, el) => { + const src = el.attribs.src; + el.attribs.src = fixImageSrc(src, item); + }); + return { + title: `${item.name} (${item.version}) | ${item.description}`, + link: `https://typst.app/universe/package/${item.name}`, + description: $.html(), + pubDate: parseDate(item.updatedAt, 'X'), + }; + }); + return { + title: 'Typst universe', + link: targetUrl, + item: pkgs, + }; + } else { + return { + title: 'Typst universe', + link: targetUrl, + item: [], + }; + } }, }; diff --git a/lib/routes/udn/breaking-news.tsx b/lib/routes/udn/breaking-news.tsx index 4fa9fe943a1e..871602aafced 100644 --- a/lib/routes/udn/breaking-news.tsx +++ b/lib/routes/udn/breaking-news.tsx @@ -26,7 +26,7 @@ export const route: Route = { }, ], name: '即時新聞', - maintainers: ['miles170', 'pseudoyu'], + maintainers: ['miles170'], handler, description: `| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 99 | | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ------ | diff --git a/lib/routes/udn/global/index.ts b/lib/routes/udn/global/index.ts index 8c346aee96da..0c4a4a8845ca 100644 --- a/lib/routes/udn/global/index.ts +++ b/lib/routes/udn/global/index.ts @@ -25,7 +25,7 @@ export const route: Route = { }, ], name: '轉角國際 - 首頁', - maintainers: ['nczitzk', 'pseudoyu'], + maintainers: ['nczitzk'], handler, description: `| 首頁 | 編輯精選 | 熱門文章 | | ---- | -------- | -------- | diff --git a/lib/routes/udn/global/tag.ts b/lib/routes/udn/global/tag.ts index a15b2f8fd601..d5288f982975 100644 --- a/lib/routes/udn/global/tag.ts +++ b/lib/routes/udn/global/tag.ts @@ -25,7 +25,7 @@ export const route: Route = { }, ], name: '轉角國際 - 標籤', - maintainers: ['emdoe', 'nczitzk', 'pseudoyu'], + maintainers: ['emdoe', 'nczitzk'], handler, description: `| 過去 24 小時 | 鏡頭背後 | 深度專欄 | 重磅廣播 | | ------------ | -------- | -------- | -------- |`, diff --git a/lib/routes/vimeo/channel.ts b/lib/routes/vimeo/channel.ts index eb34fd65bbd1..8d6d169f52ff 100644 --- a/lib/routes/vimeo/channel.ts +++ b/lib/routes/vimeo/channel.ts @@ -3,7 +3,6 @@ import { load } from 'cheerio'; import type { Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; -import { PRESETS } from '@/utils/header-generator'; import { parseDate } from '@/utils/parse-date'; import { renderDescription } from './templates/description'; @@ -65,8 +64,8 @@ async function handler(ctx) { url: `https://vimeo.com${link}/description?breeze=1`, headers: { 'X-Requested-With': 'XMLHttpRequest', + 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) ', }, - headerGeneratorOptions: PRESETS.MODERN_IOS, }); const articledata = response2.data; const $2 = load(articledata); diff --git a/lib/routes/wechat/wechat2rss.ts b/lib/routes/wechat/wechat2rss.ts index a91b195fcfba..f518268c934e 100644 --- a/lib/routes/wechat/wechat2rss.ts +++ b/lib/routes/wechat/wechat2rss.ts @@ -1,6 +1,7 @@ import type { Route } from '@/types'; import { parseDate } from '@/utils/parse-date'; import parser from '@/utils/rss-parser'; +import { finishArticleItem } from '@/utils/wechat-mp'; export const route: Route = { path: '/wechat2rss/:id', @@ -28,13 +29,14 @@ async function handler(ctx) { const { title, link, description, image, items: item } = await parser.parseURL(feedUrl); - const items = item.map((i) => ({ + let items = item.map((i) => ({ title: i.title, - pubDate: parseDate(i.isoDate), + pubDate: parseDate(i.pubDate), link: i.link, - description: i['content:encoded'] || i.content, })); + items = await Promise.all(items.map((item) => finishArticleItem(item))); + return { title, link, diff --git a/lib/routes/weibo/utils.ts b/lib/routes/weibo/utils.ts index f33e283157bb..9750dd47bd07 100644 --- a/lib/routes/weibo/utils.ts +++ b/lib/routes/weibo/utils.ts @@ -80,7 +80,7 @@ const weiboUtils = { logger.info(`Fetching visitor Cookies from ${url}`); } let times = 0; - const { page, destroy } = await getPuppeteerPage(url, { + const { page, destory } = await getPuppeteerPage(url, { onBeforeLoad: async (page) => { const expectResourceTypes = new Set(['document', 'script', 'xhr', 'fetch']); await page.setUserAgent(weiboUtils.apiHeaders['User-Agent']); @@ -101,7 +101,7 @@ const weiboUtils = { gotoConfig: { waitUntil: 'networkidle0' }, }); const cookies: string = await getCookies(page, 'weibo.cn'); - await destroy(); + await destory(); if (times < 2 || !cookies) { throw new Error(`Unable to fetch visitor cookies. Please set WEIBO_COOKIES. Redirection: ${times}, last URL: ${page.url()}`); } diff --git a/lib/routes/wkjyqh/namespace.ts b/lib/routes/wkjyqh/namespace.ts deleted file mode 100644 index 9f25ff9f147c..000000000000 --- a/lib/routes/wkjyqh/namespace.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: '五矿期货', - url: 'www.wkjyqh.com', - categories: ['finance'], - lang: 'zh-CN', -}; diff --git a/lib/routes/wkjyqh/research.ts b/lib/routes/wkjyqh/research.ts deleted file mode 100644 index 31b6111a10d9..000000000000 --- a/lib/routes/wkjyqh/research.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { load } from 'cheerio'; - -import type { DataItem, Route } from '@/types'; -import cache from '@/utils/cache'; -import ofetch from '@/utils/ofetch'; -import { parseDate } from '@/utils/parse-date'; -import timezone from '@/utils/timezone'; - -export const route: Route = { - path: '/research', - categories: ['finance'], - example: '/wkjyqh/research', - radar: [ - { - source: ['www.wkjyqh.com/main/research_center/yjbg/index.shtml', 'www.wkjyqh.com/main/research_center/'], - }, - ], - name: '研究报告', - maintainers: ['TonyRL'], - handler, - url: 'www.wkjyqh.com/main/research_center/yjbg/index.shtml', -}; - -async function handler() { - const baseUrl = 'https://www.wkjyqh.com'; - const link = `${baseUrl}/main/research_center/yjbg/index.shtml`; - - const apiResponse = await ofetch(`${baseUrl}/servlet/json`, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: new URLSearchParams({ - funcNo: '2000153', - catalogId: '232', - pageNow: '1', - pageSize: '15', - isFilter: '1', - titleLength: '35', - briefLength: '70', - _catalogId: '', - rightId: '', - }), - responseType: 'json', - }); - - const list: DataItem[] = apiResponse.results[0].data.map((item) => ({ - title: item.title, - link: new URL(item.url, baseUrl).href, - pubDate: timezone(parseDate(item.publish_date), +8), - })); - - const items = await Promise.all( - list.map((item) => - cache.tryGet(item.link!, async () => { - const response = await ofetch(item.link!); - const $ = load(response); - - const content = $('.article_detail'); - item.pubDate = timezone(parseDate(content.find('b#time').text()), +8); - content.find('h2, .tips').remove(); - item.description = content.html()?.trim(); - - return item; - }) - ) - ); - - return { - title: '五矿期货 - 研究报告', - link, - language: 'zh-CN' as const, - image: `${baseUrl}/favicon.ico`, - item: items, - }; -} diff --git a/lib/routes/xhamster/index.ts b/lib/routes/xhamster/index.ts deleted file mode 100644 index c92562d5a00c..000000000000 --- a/lib/routes/xhamster/index.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { load } from 'cheerio'; - -import type { Route } from '@/types'; -import got from '@/utils/got'; -import { parseDate } from '@/utils/parse-date'; - -export const route: Route = { - path: '/:creators', - categories: ['multimedia'], - example: '/xhamster/faustina-pierre', - parameters: { - creators: 'Creator slug from the URL (e.g. `faustina-pierre`)', - }, - features: { - requireConfig: false, - requirePuppeteer: false, - antiCrawler: false, - supportBT: false, - supportPodcast: false, - supportScihub: false, - nsfw: true, - }, - radar: [ - { - source: ['xhamster.com/creators/:creators', 'xhamster.com/creators/:creators/newest'], - target: '/:creators', - }, - ], - name: 'Newest Videos by Creator', - maintainers: ['eve2ptp'], - handler, - url: 'xhamster.com/faustina-pierre/newest', -}; - -interface VideoThumb { - id: number; - title: string; - pageURL: string; - thumbURL: string; - imageURL?: string; - trailerURL?: string; - trailerFallbackUrl?: string; - created?: number; - duration?: number; - views?: number; - isUHD?: boolean; -} - -interface Initials { - infoComponent?: { - pornstarTop?: { - name?: string; - }; - }; - trendingVideoSectionComponent?: { - videoListProps?: { - videoThumbProps?: VideoThumb[]; - }; - }; -} - -function extractInitials(scriptContent: string): Initials { - const match = scriptContent.match(/window\.initials\s*=\s*([\s\S]*?);?$/); - if (!match) { - throw new Error('initials not found'); - } - return JSON.parse(match[1]); -} - -function formatDuration(seconds: number): string { - const h = Math.floor(seconds / 3600); - const m = Math.floor((seconds % 3600) / 60); - const s = seconds % 60; - return h > 0 ? `${h}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}` : `${m}:${String(s).padStart(2, '0')}`; -} - -function renderDescription(video: VideoThumb): string { - const thumb = video.imageURL ?? video.thumbURL; - const duration = video.duration ? formatDuration(video.duration) : ''; - const views = video.views === undefined ? '' : video.views.toLocaleString(); - const quality = video.isUHD ? '4K' : ''; - - let meta = ''; - - if (quality) { - meta += quality; - } - if (duration) { - meta += `${meta ? ' · ' : ''}Duration: ${duration}`; - } - if (views) { - meta += `${meta ? ' · ' : ''}Views: ${views}`; - } - - return ` - ${video.title} -

    ${meta}

    - `.trim(); -} - -async function handler(ctx) { - const { creators } = ctx.req.param(); - const pageUrl = `https://xhamster.com/creators/${encodeURIComponent(creators)}/newest`; - - const response = await got(pageUrl); - - const $ = load(response.data); - const initialsRaw = $('#initials-script').text(); - if (!initialsRaw) { - throw new Error('Could not locate initials script on page'); - } - - let initials: Initials; - try { - initials = extractInitials(initialsRaw); - } catch { - throw new Error('Failed to parse page data'); - } - - const creatorName = initials.infoComponent?.pornstarTop?.name ?? creators; - const videos = initials.trendingVideoSectionComponent?.videoListProps?.videoThumbProps ?? []; - - const items = videos.map((video) => ({ - title: `${video.title}${video.isUHD ? ' [4K]' : ''}`, - link: video.pageURL, - pubDate: video.created ? parseDate(video.created * 1000) : undefined, - author: creatorName, - description: renderDescription(video), - media: { - content: { - url: video.trailerURL ?? video.pageURL, - type: 'video/mp4', - ...(video.duration && { duration: video.duration }), - }, - thumbnail: { - url: video.imageURL ?? video.thumbURL, - }, - }, - })); - - return { - title: `${creatorName} - newest videos on xHamster`, - link: pageUrl, - description: `Latest videos from ${creatorName} on xHamster`, - item: items, - }; -} diff --git a/lib/routes/xhamster/namespace.ts b/lib/routes/xhamster/namespace.ts deleted file mode 100644 index 48e5450af3b5..000000000000 --- a/lib/routes/xhamster/namespace.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { Namespace } from '@/types'; - -export const namespace: Namespace = { - name: 'xHamster', - url: 'xhamster.com', - lang: 'en', -}; diff --git a/lib/routes/xiaohongshu/user.ts b/lib/routes/xiaohongshu/user.ts index 5cc0d88f6009..138959c65cb5 100644 --- a/lib/routes/xiaohongshu/user.ts +++ b/lib/routes/xiaohongshu/user.ts @@ -103,7 +103,7 @@ async function getUserFeeds(url: string, category: string) { title: noteCard.displayTitle, link: new URL(noteCard.noteId || id, url).toString(), guid: noteCard.displayTitle, - description: `
    ${noteCard.displayTitle}`, + description: `
    ${noteCard.displayTitle}`, author: noteCard.user.nickname, upvotes: noteCard.interactInfo.likedCount, })) diff --git a/lib/routes/xiaohongshu/util.ts b/lib/routes/xiaohongshu/util.ts index dcd23dd56e40..b4247bea06ab 100644 --- a/lib/routes/xiaohongshu/util.ts +++ b/lib/routes/xiaohongshu/util.ts @@ -63,7 +63,7 @@ const getUser = (url, cache) => } // Use puppeteer - const { page, destroy } = await getPuppeteerPage(url, { + const { page, destory } = await getPuppeteerPage(url, { onBeforeLoad: async (page) => { await page.setRequestInterception(true); page.on('request', (request) => { @@ -107,7 +107,7 @@ const getUser = (url, cache) => return { userPageData, notes, collect }; } finally { - await destroy(); + await destory(); } }, config.cache.routeExpire, diff --git a/lib/routes/youmemark/index.ts b/lib/routes/youmemark/index.ts index 1d272abbd004..90236327da80 100644 --- a/lib/routes/youmemark/index.ts +++ b/lib/routes/youmemark/index.ts @@ -36,7 +36,11 @@ async function handler(ctx): Promise { const userid = ctx.req.param('userid'); const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 10; - const response = await ofetch(`https://youmemark.com/user/${userid}`); + const response = await ofetch(`https://youmemark.com/user/${userid}`, { + headers: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + }, + }); const $ = load(response); diff --git a/lib/shims/honeybadger.ts b/lib/shims/honeybadger.ts deleted file mode 100644 index 2c3699c0735d..000000000000 --- a/lib/shims/honeybadger.ts +++ /dev/null @@ -1,6 +0,0 @@ -// No-op shim for @honeybadger-io/js in Cloudflare Workers -export default { - configure: () => {}, - notify: () => {}, - setContext: () => {}, -}; diff --git a/lib/shims/node-module.ts b/lib/shims/node-module.ts index f41cd800f181..fdaedae8a121 100644 --- a/lib/shims/node-module.ts +++ b/lib/shims/node-module.ts @@ -1,5 +1,3 @@ -// oxlint-disable n/no-deprecated-api -// oxlint-disable unicorn-js/import-style -- need full util module for CJS compatibility // Shim for node:module in Cloudflare Workers // Provides a createRequire that returns pre-imported modules @@ -36,6 +34,7 @@ import * as timers_promises from 'node:timers/promises'; import * as tls from 'node:tls'; import * as tty from 'node:tty'; import * as url from 'node:url'; +// eslint-disable-next-line unicorn/import-style -- need full util module for CJS compatibility import * as util from 'node:util'; import * as util_types from 'node:util/types'; import * as worker_threads from 'node:worker_threads'; diff --git a/lib/utils/got.ts b/lib/utils/got.ts index 1c04dfb97072..deb9d7cbbf97 100644 --- a/lib/utils/got.ts +++ b/lib/utils/got.ts @@ -5,7 +5,7 @@ import ofetch from '@/utils/ofetch'; import { getSearchParamsString } from './helpers'; const getFakeGot = (defaultOptions?: any) => { - const fakeGot = async (request, options?: any) => { + const fakeGot = (request, options?: any) => { if (!(typeof request === 'string' || request instanceof Request) && request.url) { options = { ...request, @@ -67,11 +67,10 @@ const getFakeGot = (defaultOptions?: any) => { const response = ofetch(request, options); if (options?.responseType === 'arrayBuffer') { - const responseData = await response; - return { + return response.then((responseData) => ({ data: Buffer.from(responseData), body: Buffer.from(responseData), - }; + })); } return response; }; diff --git a/lib/utils/puppeteer.mock.test.ts b/lib/utils/puppeteer.mock.test.ts index a4c8e46de892..713347ff3af0 100644 --- a/lib/utils/puppeteer.mock.test.ts +++ b/lib/utils/puppeteer.mock.test.ts @@ -69,7 +69,7 @@ describe('getPuppeteerPage (mocked)', () => { expect(endpoint).toContain('stealth=true'); expect(onBeforeLoad).toHaveBeenCalled(); - await result.destroy(); + await result.destory(); expect(browser.close).toHaveBeenCalled(); delete process.env.PUPPETEER_WS_ENDPOINT; diff --git a/lib/utils/puppeteer.ts b/lib/utils/puppeteer.ts index 2888aaf65f81..1abfbfc77351 100644 --- a/lib/utils/puppeteer.ts +++ b/lib/utils/puppeteer.ts @@ -187,7 +187,7 @@ export const getPuppeteerPage = async ( return { page, - destroy: async () => { + destory: async () => { await browser.close(); }, browser, diff --git a/lib/utils/puppeteer.worker.ts b/lib/utils/puppeteer.worker.ts index 74f94425aad7..8fcc6efc090b 100644 --- a/lib/utils/puppeteer.worker.ts +++ b/lib/utils/puppeteer.worker.ts @@ -91,7 +91,7 @@ export const getPuppeteerPage = async ( return { page, - destroy: async () => { + destory: async () => { await browser.close(); }, browser, diff --git a/lib/utils/request-rewriter.test.ts b/lib/utils/request-rewriter.test.ts index 794868e9697e..0407fbfef8e9 100644 --- a/lib/utils/request-rewriter.test.ts +++ b/lib/utils/request-rewriter.test.ts @@ -91,7 +91,7 @@ describe('request-rewriter', () => { // headers const headers: Headers = fetchSpy.mock.lastCall?.[0].headers; - expect(headers.get('user-agent')).toMatch(/Chrome/); + expect(headers.get('user-agent')).toBe(config.ua); expect(headers.get('accept')).toBeDefined(); expect(headers.get('referer')).toBe('http://rsshub.test'); expect(headers.get('sec-ch-ua')).toBeDefined(); @@ -138,7 +138,7 @@ describe('request-rewriter', () => { // headers const headers: Headers = fetchSpy.mock.lastCall?.[0].headers; - expect(headers.get('user-agent')).toMatch(/Chrome/); + expect(headers.get('user-agent')).toBe(config.ua); expect(headers.get('accept')).toBeDefined(); expect(headers.get('referer')).toBe('http://rsshub.test'); expect(headers.get('sec-ch-ua')).toBeDefined(); @@ -237,7 +237,7 @@ describe('request-rewriter', () => { // headers const options = httpSpy.mock.lastCall?.[1]; const headers = options?.headers; - expect(headers?.['user-agent']).toMatch(/Chrome/); + expect(headers?.['user-agent']).toBe(config.ua); expect(headers?.accept).toBeDefined(); expect(headers?.referer).toBe('http://rsshub.test'); diff --git a/lib/utils/request-rewriter/fetch.ts b/lib/utils/request-rewriter/fetch.ts index 5d36e56f5700..8acfe06e58fe 100644 --- a/lib/utils/request-rewriter/fetch.ts +++ b/lib/utils/request-rewriter/fetch.ts @@ -35,21 +35,17 @@ const wrappedFetch: typeof undici.fetch = async (input: RequestInfo, init?: Requ logger.debug(`Outgoing request: ${request.method} ${request.url}`); - // ua - if (config.isDefaultUA || init?.headerGeneratorOptions) { - const generatedHeaders = generateHeaders(init?.headerGeneratorOptions); + const generatedHeaders = generateHeaders(init?.headerGeneratorOptions); - if (!request.headers.get('user-agent')) { - request.headers.set('user-agent', generatedHeaders['user-agent']); - } + // ua + if (!request.headers.has('user-agent')) { + request.headers.set('user-agent', config.ua); + } - for (const header of HEADER_LIST) { - if (!request.headers.has(header) && generatedHeaders[header]) { - request.headers.set(header, generatedHeaders[header]); - } + for (const header of HEADER_LIST) { + if (!request.headers.has(header) && generatedHeaders[header]) { + request.headers.set(header, generatedHeaders[header]); } - } else if (!request.headers.get('user-agent')) { - request.headers.set('user-agent', config.ua); } // referer diff --git a/lib/utils/request-rewriter/fetch.worker.ts b/lib/utils/request-rewriter/fetch.worker.ts index 62c3846d2ba4..022e507e73ea 100644 --- a/lib/utils/request-rewriter/fetch.worker.ts +++ b/lib/utils/request-rewriter/fetch.worker.ts @@ -4,13 +4,12 @@ import { config } from '@/config'; import logger from '@/utils/logger'; // Static browser headers (Chrome-like fingerprint) -const STATIC_BROWSER_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 15_6_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'; const STATIC_BROWSER_HEADERS: Record = { accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8', 'accept-language': 'en-US,en;q=0.9', - 'sec-ch-ua': '"Google Chrome";v="139", "Chromium";v="139", "Not_A Brand";v="24"', + 'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"', 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"macOS"', + 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'document', 'sec-fetch-mode': 'navigate', 'sec-fetch-site': 'none', @@ -26,19 +25,15 @@ const wrappedFetch = (input: RequestInfo | URL, init?: RequestInit): Promise(origin: T) => T = (origin) => options.headers = options.headers || {}; const headersLowerCaseKeys = new Set(Object.keys(options.headers).map((key) => key.toLowerCase())); - // ua - if (config.isDefaultUA || options.headerGeneratorOptions) { - const generatedHeaders = generateHeaders(options.headerGeneratorOptions); + const generatedHeaders = generateHeaders(options.headerGeneratorOptions); - if (!headersLowerCaseKeys.has('user-agent')) { - options.headers['user-agent'] = generatedHeaders['user-agent']; - } + // ua + if (!headersLowerCaseKeys.has('user-agent')) { + options.headers['user-agent'] = config.ua; + } - for (const header of HEADER_LIST) { - if (!headersLowerCaseKeys.has(header) && generatedHeaders[header]) { - options.headers[header] = generatedHeaders[header]; - } + for (const header of HEADER_LIST) { + if (!headersLowerCaseKeys.has(header) && generatedHeaders[header]) { + options.headers[header] = generatedHeaders[header]; } - } else if (!headersLowerCaseKeys.has('user-agent')) { - options.headers['user-agent'] = config.ua; } // referer diff --git a/lib/utils/rss-parser.test.ts b/lib/utils/rss-parser.test.ts index 1c5edad9893a..880b454d1b4a 100644 --- a/lib/utils/rss-parser.test.ts +++ b/lib/utils/rss-parser.test.ts @@ -1,89 +1,10 @@ -import zlib from 'node:zlib'; - -import { http, HttpResponse } from 'msw'; import { describe, expect, it } from 'vitest'; import parser from '@/utils/rss-parser'; -const rssXml = 'TestItem'; - describe('rss-parser', () => { it('rss', async () => { const result = await parser.parseURL('http://rsshub.test/rss'); expect(result).toBeTruthy(); }); - - it('gzip', async () => { - const { default: server } = await import('@/setup.test'); - const compressed = zlib.gzipSync(Buffer.from(rssXml)); - server.use( - http.get('http://rsshub.test/rss-gzip', () => - HttpResponse.arrayBuffer(compressed.buffer as ArrayBuffer, { - headers: { - 'content-type': 'application/xml', - 'content-encoding': 'gzip', - }, - }) - ) - ); - const result = await parser.parseURL('http://rsshub.test/rss-gzip'); - expect(result.title).toBe('Test'); - expect(result.items).toHaveLength(1); - }); - - it('deflate', async () => { - const { default: server } = await import('@/setup.test'); - const compressed = zlib.deflateSync(Buffer.from(rssXml)); - server.use( - http.get('http://rsshub.test/rss-deflate', () => - HttpResponse.arrayBuffer(compressed.buffer as ArrayBuffer, { - headers: { - 'content-type': 'application/xml', - 'content-encoding': 'deflate', - }, - }) - ) - ); - const result = await parser.parseURL('http://rsshub.test/rss-deflate'); - expect(result.title).toBe('Test'); - expect(result.items).toHaveLength(1); - }); - - it('brotli', async () => { - const { default: server } = await import('@/setup.test'); - const compressed = zlib.brotliCompressSync(Buffer.from(rssXml)); - server.use( - http.get('http://rsshub.test/rss-br', () => - HttpResponse.arrayBuffer(compressed.buffer as ArrayBuffer, { - headers: { - 'content-type': 'application/xml', - 'content-encoding': 'br', - }, - }) - ) - ); - const result = await parser.parseURL('http://rsshub.test/rss-br'); - expect(result.title).toBe('Test'); - expect(result.items).toHaveLength(1); - }); - - if (zlib.zstdCompressSync) { - it('zstd', async () => { - const { default: server } = await import('@/setup.test'); - const compressed = zlib.zstdCompressSync(Buffer.from(rssXml)); - server.use( - http.get('http://rsshub.test/rss-zstd', () => - HttpResponse.arrayBuffer(compressed.buffer as ArrayBuffer, { - headers: { - 'content-type': 'application/xml', - 'content-encoding': 'zstd', - }, - }) - ) - ); - const result = await parser.parseURL('http://rsshub.test/rss-zstd'); - expect(result.title).toBe('Test'); - expect(result.items).toHaveLength(1); - }); - } }); diff --git a/lib/utils/wechat-mp.test.ts b/lib/utils/wechat-mp.test.ts index 4e59d2b051f3..4ff1d9b2a12f 100644 --- a/lib/utils/wechat-mp.test.ts +++ b/lib/utils/wechat-mp.test.ts @@ -135,29 +135,6 @@ describe('wechat-mp', () => { realShowType: '112233445566778899', createTime: '1713009660', }); - - // item_show_type in a separate script tag from real_item_show_type - expect( - ExtractMetadata.common( - load(` - - - - - `) - ) - ).toMatchObject({ - showType: showTypeMapReverse['0'], - realShowType: showTypeMapReverse['0'], - createTime: '1713009660', - sourceUrl: 'https://mp.weixin.qq.com/rsshub_test/fake', - }); }); it('ExtractMetadata.common rethrows unexpected errors', () => { diff --git a/lib/utils/wechat-mp.ts b/lib/utils/wechat-mp.ts index 292d4f04ec7a..56e0cab27a7a 100644 --- a/lib/utils/wechat-mp.ts +++ b/lib/utils/wechat-mp.ts @@ -173,67 +173,41 @@ class ExtractMetadata { }; private static commonMetadataToBeExtracted = { - showType: this.genExtractFunc('item_show_type', { valuePattern: String.raw`\d+`, allowNotFound: true }), + showType: this.genExtractFunc('item_show_type', { valuePattern: String.raw`\d+` }), realShowType: this.genExtractFunc('real_item_show_type', { valuePattern: String.raw`\d+` }), createTime: this.genExtractFunc('ct', { valuePattern: String.raw`\d+`, allowNotFound: true }), sourceUrl: this.genExtractFunc('msg_source_url', { valuePattern: `https?://[^'"]*`, allowNotFound: true }), }; - private static showTypeMetadataToBeExtracted = { - showType: this.genExtractFunc('item_show_type', { valuePattern: String.raw`\d+` }), - }; - - static common = ($: CheerioAPI) => { - const metadataExtracted = forEachScript( + static common = ($: CheerioAPI) => + forEachScript( $, (script) => { const scriptText = $(script).text(); const metadataExtracted = this.doExtract(this.commonMetadataToBeExtracted, scriptText) as Record; + const showType = showTypeMapReverse[metadataExtracted.showType]; + const realShowType = showTypeMapReverse[metadataExtracted.realShowType]; + metadataExtracted.sourceUrl = metadataExtracted.sourceUrl && fixUrl(metadataExtracted.sourceUrl); + if (showType) { + metadataExtracted.showType = showType; + } else { + warn('showType not found', `item_show_type=${metadataExtracted.showType}`); + } + if (realShowType) { + metadataExtracted.realShowType = realShowType; + } else { + warn('realShowType not found', `real_item_show_type=${metadataExtracted.realShowType}`); + } + if (metadataExtracted.showType !== metadataExtracted.realShowType) { + // never seen this happen, waiting for examples + warn('showType mismatch', `item_show_type=${metadataExtracted.showType}, real_item_show_type=${metadataExtracted.realShowType}`); + } throw new LoopReturn(metadataExtracted); }, {}, 'script[nonce][type="text/javascript"]:contains("real_item_show_type")' ); - // APP_MSG_PAGE has its item_show_type in a separate script - if (!metadataExtracted.showType) { - const showTypeExtracted = forEachScript( - $, - (script) => { - const scriptText = $(script).text(); - const metadataExtracted = this.doExtract(this.showTypeMetadataToBeExtracted, scriptText) as Record; - throw new LoopReturn(metadataExtracted); - }, - {}, - 'script[nonce][type="text/javascript"]:contains("item_show_type")' - ); - if (showTypeExtracted.showType) { - metadataExtracted.showType = showTypeExtracted.showType; - } - } - - const showType = showTypeMapReverse[metadataExtracted.showType]; - const realShowType = showTypeMapReverse[metadataExtracted.realShowType]; - if (metadataExtracted.sourceUrl) { - metadataExtracted.sourceUrl = fixUrl(metadataExtracted.sourceUrl); - } - if (showType) { - metadataExtracted.showType = showType; - } else { - warn('showType not found', `item_show_type=${metadataExtracted.showType}`); - } - if (realShowType) { - metadataExtracted.realShowType = realShowType; - } else { - warn('realShowType not found', `real_item_show_type=${metadataExtracted.realShowType}`); - } - if (metadataExtracted.showType !== metadataExtracted.realShowType) { - // never seen this happen, waiting for examples - warn('showType mismatch', `item_show_type=${metadataExtracted.showType}, real_item_show_type=${metadataExtracted.realShowType}`); - } - return metadataExtracted; - }; - private static audioMetadataToBeExtracted = { voiceId: this.genExtractFunc('voiceid', { assignPattern: ':' }), duration: this.genExtractFunc('duration', { valuePattern: String.raw`\d*`, assignPattern: ':', allowNotFound: true }), @@ -655,19 +629,21 @@ const fetchArticle = (url: string, bypassHostCheck: boolean = false) => { * @return {Promise} - The incoming `item` object, with the article and its metadata filled in. */ const finishArticleItem = async (item, setMpNameAsAuthor = false, skipLink = false) => { - const fetchedItem = await fetchArticle(item.link); - for (const key in fetchedItem) { - switch (key) { - case 'author': - item.author = setMpNameAsAuthor - ? fetchedItem.mpName || item.author // the Official Account itself. if your route return articles from different accounts, you may want to use this - : fetchedItem.author || item.author; // the real author of the article. if your route return articles from a certain account, use this - break; - case 'link': - item.link = skipLink ? item.link : fetchedItem.link || item.link; - break; - default: - item[key] = item[key] || fetchedItem[key]; + if (item.link) { + const fetchedItem = await fetchArticle(item.link); + for (const key in fetchedItem) { + switch (key) { + case 'author': + item.author = setMpNameAsAuthor + ? fetchedItem.mpName || item.author // the Official Account itself. if your route return articles from different accounts, you may want to use this + : fetchedItem.author || item.author; // the real author of the article. if your route return articles from a certain account, use this + break; + case 'link': + item.link = skipLink ? item.link : fetchedItem.link || item.link; + break; + default: + item[key] = item[key] || fetchedItem[key]; + } } } return item; diff --git a/package.json b/package.json index 01eaed2b938e..d09907cfcaeb 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,10 @@ "@bbob/html": "4.3.1", "@bbob/plugin-helper": "4.3.1", "@bbob/preset-html5": "4.3.1", - "@honeybadger-io/js": "6.12.3", - "@hono/node-server": "1.19.13", - "@hono/zod-openapi": "1.2.4", + "@hono/node-server": "1.19.11", + "@hono/zod-openapi": "1.2.3", "@jocmp/mercury-parser": "3.0.7", - "@notionhq/client": "5.17.0", + "@notionhq/client": "5.15.0", "@opentelemetry/api": "1.9.1", "@opentelemetry/exporter-prometheus": "0.214.0", "@opentelemetry/exporter-trace-otlp-http": "0.214.0", @@ -72,8 +71,8 @@ "@opentelemetry/sdk-trace-base": "2.6.1", "@opentelemetry/semantic-conventions": "1.40.0", "@rss3/sdk": "0.0.25", - "@scalar/hono-api-reference": "0.10.7", - "@sentry/node": "10.48.0", + "@scalar/hono-api-reference": "0.10.5", + "@sentry/node": "10.46.0", "aes-js": "3.1.2", "cheerio": "1.2.0", "city-timezones": "1.3.3", @@ -82,29 +81,30 @@ "currency-symbol-map": "5.1.0", "dayjs": "1.11.20", "destr": "2.0.5", - "dotenv": "17.4.1", + "dotenv": "17.3.1", "entities": "8.0.0", "etag": "1.8.1", "fanfou-sdk": "6.0.0", + "form-data": "4.0.5", "google-play-scraper": "10.1.2", "googleapis": "171.4.0", - "header-generator": "2.1.82", - "hono": "4.12.12", + "header-generator": "2.1.81", + "hono": "4.12.8", "html-to-text": "9.0.5", "http-cookie-agent": "7.0.3", - "https-proxy-agent": "9.0.0", + "https-proxy-agent": "8.0.0", "iconv-lite": "0.7.2", - "imapflow": "1.3.1", + "imapflow": "1.2.18", "instagram-private-api": "1.46.1", "ioredis": "5.10.1", "ip-regex": "5.0.0", - "jsdom": "29.0.2", + "jsdom": "29.0.1", "json-bigint": "1.0.0", "jsonpath-plus": "10.4.0", "jsrsasign": "11.1.1", - "lru-cache": "11.3.3", + "lru-cache": "11.2.7", "lz-string": "1.5.0", - "mailparser": "3.9.8", + "mailparser": "3.9.6", "markdown-it": "14.1.1", "mixi2": "0.2.2", "narou": "2.0.1", @@ -113,28 +113,28 @@ "ofetch": "1.5.1", "otplib": "13.4.0", "p-map": "7.0.4", - "pac-proxy-agent": "9.0.1", + "pac-proxy-agent": "8.0.0", "proxy-chain": "2.7.1", "puppeteer-real-browser": "1.4.4", "query-string": "9.3.1", - "rate-limiter-flexible": "11.0.0", - "re2js": "2.0.1", + "rate-limiter-flexible": "10.0.1", + "re2js": "1.2.3", "rebrowser-puppeteer": "24.8.1", "rfc4648": "1.5.4", "rss-parser": "3.13.0", "sanitize-html": "2.17.2", "simplecc-wasm": "1.1.1", - "socks-proxy-agent": "10.0.0", + "socks-proxy-agent": "9.0.0", "source-map": "0.7.6", "telegram": "2.26.22", "title": "4.0.1", - "tldts": "7.0.28", + "tldts": "7.0.27", "tosource": "2.0.0-alpha.3", "tough-cookie": "6.0.1", "tsx": "4.21.0", "twitter-api-v2": "1.29.0", "ufo": "1.6.3", - "undici": "7.24.7", + "undici": "7.24.6", "uuid": "13.0.0", "winston": "3.19.0", "xxhash-wasm": "1.1.0", @@ -144,14 +144,14 @@ }, "devDependencies": { "@actions/core": "3.0.0", - "@actions/github": "9.1.0", + "@actions/github": "9.0.0", "@bbob/types": "4.3.1", - "@cloudflare/containers": "0.3.0", - "@cloudflare/puppeteer": "1.0.7", - "@cloudflare/workers-types": "4.20260410.1", + "@cloudflare/containers": "0.2.0", + "@cloudflare/puppeteer": "1.0.6", + "@cloudflare/workers-types": "4.20260317.1", "@eslint/eslintrc": "3.3.5", "@eslint/js": "10.0.1", - "@oxlint/plugins": "1.59.0", + "@oxlint/plugins": "1.57.0", "@stylistic/eslint-plugin": "5.10.0", "@types/aes-js": "3.1.4", "@types/babel__preset-env": "7.10.0", @@ -167,42 +167,41 @@ "@types/mailparser": "3.4.6", "@types/markdown-it": "14.1.2", "@types/module-alias": "2.0.4", - "@types/node": "25.6.0", + "@types/node": "25.5.0", "@types/sanitize-html": "2.16.1", - "@typescript-eslint/eslint-plugin": "8.58.1", - "@typescript-eslint/parser": "8.58.1", + "@typescript-eslint/eslint-plugin": "8.57.2", + "@typescript-eslint/parser": "8.57.2", "@vercel/nft": "1.5.0", "@vitest/coverage-v8": "4.0.9", - "discord-api-types": "0.38.45", + "discord-api-types": "0.38.42", "domhandler": "6.0.1", - "eslint": "10.2.0", + "eslint": "10.1.0", "eslint-nibble": "9.1.1", "eslint-plugin-import-x": "4.16.2", "eslint-plugin-n": "17.24.0", - "eslint-plugin-simple-import-sort": "13.0.0", - "eslint-plugin-unicorn": "64.0.0", + "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-unicorn": "63.0.0", "eslint-plugin-yml": "3.3.1", "fs-extra": "11.3.4", "globals": "17.4.0", - "got": "15.0.1", + "got": "14.6.6", "husky": "9.1.7", "js-beautify": "1.15.4", "lint-staged": "16.4.0", "magic-string": "0.30.21", "mockdate": "3.0.5", - "msw": "2.13.2", + "msw": "2.12.14", "node-network-devtools": "1.0.29", - "oxfmt": "0.44.0", - "oxlint": "1.59.0", - "oxlint-plugin-eslint": "1.59.0", - "oxlint-tsgolint": "0.20.0", + "oxfmt": "0.42.0", + "oxlint": "1.57.0", + "oxlint-tsgolint": "0.17.4", "remark-parse": "11.0.0", - "tsdown": "0.21.7", + "tsdown": "0.21.5", "typescript": "5.9.3", "unified": "11.0.5", "vite-tsconfig-paths": "6.1.1", "vitest": "4.0.9", - "wrangler": "4.81.1", + "wrangler": "4.77.0", "yaml-eslint-parser": "2.0.0" }, "lint-staged": { diff --git a/patches/rss-parser@3.13.0.patch b/patches/rss-parser@3.13.0.patch index 88d97ebf2e01..c5ff3d6d4d44 100644 --- a/patches/rss-parser@3.13.0.patch +++ b/patches/rss-parser@3.13.0.patch @@ -1,5 +1,5 @@ diff --git a/lib/parser.js b/lib/parser.js -index 2852b5f9249a59adf8f51f3451181ac2c994bc54..e56d2c932b92424a0f43a77b57e575d90a634cc2 100644 +index 2852b5f9249a59adf8f51f3451181ac2c994bc54..50e16ca0a97c98d7048122d5427fe467058485fb 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -3,6 +3,7 @@ const http = require('http'); @@ -10,7 +10,7 @@ index 2852b5f9249a59adf8f51f3451181ac2c994bc54..e56d2c932b92424a0f43a77b57e575d9 const fields = require('./fields'); const utils = require('./utils'); -@@ -88,14 +89,43 @@ class Parser { +@@ -88,14 +89,27 @@ class Parser { return reject(new Error("Status code " + res.statusCode)) } let encoding = utils.getEncodingFromContentType(res.headers['content-type']); @@ -23,32 +23,16 @@ index 2852b5f9249a59adf8f51f3451181ac2c994bc54..e56d2c932b92424a0f43a77b57e575d9 - }); - }) + const contentEncoding = (res.headers['content-encoding'] || '').toLowerCase(); -+ let decompressStream; -+ switch (contentEncoding) { -+ case 'gzip': -+ decompressStream = zlib.createGunzip(); -+ break; -+ case 'deflate': -+ decompressStream = zlib.createInflate(); -+ break; -+ case 'br': -+ decompressStream = zlib.createBrotliDecompress(); -+ break; -+ case 'zstd': -+ if (zlib.createZstdDecompress) { -+ decompressStream = zlib.createZstdDecompress(); -+ } -+ break; -+ } -+ if (decompressStream) { ++ if (contentEncoding === 'gzip') { ++ const gunzip = zlib.createGunzip(); + const chunks = []; -+ decompressStream.on('data', (chunk) => chunks.push(chunk)); -+ decompressStream.on('end', () => { ++ gunzip.on('data', (chunk) => chunks.push(chunk)); ++ gunzip.on('end', () => { + const decompressed = Buffer.concat(chunks).toString(encoding); + return this.parseString(decompressed).then(resolve, reject); + }); -+ decompressStream.on('error', reject); -+ res.pipe(decompressStream); ++ gunzip.on('error', reject); ++ res.pipe(gunzip); + } else { + res.setEncoding(encoding); + res.on('data', (chunk) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8c41f84624a..42c7f6e470b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,7 +24,7 @@ patchedDependencies: hash: 5027fcc424409c41c41147fc6c90b36166061522e0b03e73b45f9a973fcd2a28 path: patches/@mswjs__interceptors@0.41.3.patch rss-parser@3.13.0: - hash: afac79a31a3db94c953d49680bc5528468f051957d461e913d2e2dbf5cd22a8d + hash: e1697dd9dde771024b5d0669a3eff6237e75fbac78381a6127012b67593bb2b7 path: patches/rss-parser@3.13.0.patch importers: @@ -40,21 +40,18 @@ importers: '@bbob/preset-html5': specifier: 4.3.1 version: 4.3.1 - '@honeybadger-io/js': - specifier: 6.12.3 - version: 6.12.3 '@hono/node-server': - specifier: 1.19.13 - version: 1.19.13(hono@4.12.12) + specifier: 1.19.11 + version: 1.19.11(hono@4.12.8) '@hono/zod-openapi': - specifier: 1.2.4 - version: 1.2.4(hono@4.12.12)(zod@4.3.6) + specifier: 1.2.3 + version: 1.2.3(hono@4.12.8)(zod@4.3.6) '@jocmp/mercury-parser': specifier: 3.0.7 version: 3.0.7 '@notionhq/client': - specifier: 5.17.0 - version: 5.17.0 + specifier: 5.15.0 + version: 5.15.0 '@opentelemetry/api': specifier: 1.9.1 version: 1.9.1 @@ -80,11 +77,11 @@ importers: specifier: 0.0.25 version: 0.0.25 '@scalar/hono-api-reference': - specifier: 0.10.7 - version: 0.10.7(hono@4.12.12) + specifier: 0.10.5 + version: 0.10.5(hono@4.12.8) '@sentry/node': - specifier: 10.48.0 - version: 10.48.0(@opentelemetry/exporter-trace-otlp-http@0.214.0(@opentelemetry/api@1.9.1)) + specifier: 10.46.0 + version: 10.46.0 aes-js: specifier: 3.1.2 version: 3.1.2 @@ -110,8 +107,8 @@ importers: specifier: 2.0.5 version: 2.0.5 dotenv: - specifier: 17.4.1 - version: 17.4.1 + specifier: 17.3.1 + version: 17.3.1 entities: specifier: 8.0.0 version: 8.0.0 @@ -121,6 +118,9 @@ importers: fanfou-sdk: specifier: 6.0.0 version: 6.0.0 + form-data: + specifier: 4.0.5 + version: 4.0.5 google-play-scraper: specifier: 10.1.2 version: 10.1.2 @@ -128,26 +128,26 @@ importers: specifier: 171.4.0 version: 171.4.0 header-generator: - specifier: 2.1.82 - version: 2.1.82 + specifier: 2.1.81 + version: 2.1.81 hono: - specifier: 4.12.12 - version: 4.12.12 + specifier: 4.12.8 + version: 4.12.8 html-to-text: specifier: 9.0.5 version: 9.0.5 http-cookie-agent: specifier: 7.0.3 - version: 7.0.3(tough-cookie@6.0.1)(undici@7.24.7) + version: 7.0.3(tough-cookie@6.0.1)(undici@7.24.6) https-proxy-agent: - specifier: 9.0.0 - version: 9.0.0 + specifier: 8.0.0 + version: 8.0.0 iconv-lite: specifier: 0.7.2 version: 0.7.2 imapflow: - specifier: 1.3.1 - version: 1.3.1 + specifier: 1.2.18 + version: 1.2.18 instagram-private-api: specifier: 1.46.1 version: 1.46.1 @@ -158,8 +158,8 @@ importers: specifier: 5.0.0 version: 5.0.0 jsdom: - specifier: 29.0.2 - version: 29.0.2(@noble/hashes@2.0.1) + specifier: 29.0.1 + version: 29.0.1(@noble/hashes@2.0.1) json-bigint: specifier: 1.0.0 version: 1.0.0 @@ -170,14 +170,14 @@ importers: specifier: 11.1.1 version: 11.1.1 lru-cache: - specifier: 11.3.3 - version: 11.3.3 + specifier: 11.2.7 + version: 11.2.7 lz-string: specifier: 1.5.0 version: 1.5.0 mailparser: - specifier: 3.9.8 - version: 3.9.8 + specifier: 3.9.6 + version: 3.9.6 markdown-it: specifier: 14.1.1 version: 14.1.1 @@ -203,8 +203,8 @@ importers: specifier: 7.0.4 version: 7.0.4 pac-proxy-agent: - specifier: 9.0.1 - version: 9.0.1 + specifier: 8.0.0 + version: 8.0.0 proxy-chain: specifier: 2.7.1 version: 2.7.1 @@ -215,11 +215,11 @@ importers: specifier: 9.3.1 version: 9.3.1 rate-limiter-flexible: - specifier: 11.0.0 - version: 11.0.0 + specifier: 10.0.1 + version: 10.0.1 re2js: - specifier: 2.0.1 - version: 2.0.1 + specifier: 1.2.3 + version: 1.2.3 rebrowser-puppeteer: specifier: 24.8.1 version: 24.8.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@5.0.10) @@ -228,7 +228,7 @@ importers: version: 1.5.4 rss-parser: specifier: 3.13.0 - version: 3.13.0(patch_hash=afac79a31a3db94c953d49680bc5528468f051957d461e913d2e2dbf5cd22a8d) + version: 3.13.0(patch_hash=e1697dd9dde771024b5d0669a3eff6237e75fbac78381a6127012b67593bb2b7) sanitize-html: specifier: 2.17.2 version: 2.17.2 @@ -236,8 +236,8 @@ importers: specifier: 1.1.1 version: 1.1.1 socks-proxy-agent: - specifier: 10.0.0 - version: 10.0.0 + specifier: 9.0.0 + version: 9.0.0 source-map: specifier: 0.7.6 version: 0.7.6 @@ -248,8 +248,8 @@ importers: specifier: 4.0.1 version: 4.0.1 tldts: - specifier: 7.0.28 - version: 7.0.28 + specifier: 7.0.27 + version: 7.0.27 tosource: specifier: 2.0.0-alpha.3 version: 2.0.0-alpha.3 @@ -266,8 +266,8 @@ importers: specifier: 1.6.3 version: 1.6.3 undici: - specifier: 7.24.7 - version: 7.24.7 + specifier: 7.24.6 + version: 7.24.6 uuid: specifier: 13.0.0 version: 13.0.0 @@ -291,32 +291,32 @@ importers: specifier: 3.0.0 version: 3.0.0 '@actions/github': - specifier: 9.1.0 - version: 9.1.0 + specifier: 9.0.0 + version: 9.0.0 '@bbob/types': specifier: 4.3.1 version: 4.3.1 '@cloudflare/containers': - specifier: 0.3.0 - version: 0.3.0 + specifier: 0.2.0 + version: 0.2.0 '@cloudflare/puppeteer': - specifier: 1.0.7 - version: 1.0.7(bufferutil@4.1.0)(utf-8-validate@5.0.10) + specifier: 1.0.6 + version: 1.0.6(bufferutil@4.1.0)(utf-8-validate@5.0.10) '@cloudflare/workers-types': - specifier: 4.20260410.1 - version: 4.20260410.1 + specifier: 4.20260317.1 + version: 4.20260317.1 '@eslint/eslintrc': specifier: 3.3.5 version: 3.3.5 '@eslint/js': specifier: 10.0.1 - version: 10.0.1(eslint@10.2.0(jiti@2.6.1)) + version: 10.0.1(eslint@10.1.0(jiti@2.6.1)) '@oxlint/plugins': - specifier: 1.59.0 - version: 1.59.0 + specifier: 1.57.0 + version: 1.57.0 '@stylistic/eslint-plugin': specifier: 5.10.0 - version: 5.10.0(eslint@10.2.0(jiti@2.6.1)) + version: 5.10.0(eslint@10.1.0(jiti@2.6.1)) '@types/aes-js': specifier: 3.1.4 version: 3.1.4 @@ -360,50 +360,50 @@ importers: specifier: 2.0.4 version: 2.0.4 '@types/node': - specifier: 25.6.0 - version: 25.6.0 + specifier: 25.5.0 + version: 25.5.0 '@types/sanitize-html': specifier: 2.16.1 version: 2.16.1 '@typescript-eslint/eslint-plugin': - specifier: 8.58.1 - version: 8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.57.2 + version: 8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': - specifier: 8.58.1 - version: 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + specifier: 8.57.2 + version: 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) '@vercel/nft': specifier: 1.5.0 - version: 1.5.0(rollup@4.60.1) + version: 1.5.0(rollup@4.60.0) '@vitest/coverage-v8': specifier: 4.0.9 - version: 4.0.9(vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.6.0)(jiti@2.6.1)(jsdom@29.0.2(@noble/hashes@2.0.1))(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3)) + version: 4.0.9(vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.5.0)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3)) discord-api-types: - specifier: 0.38.45 - version: 0.38.45 + specifier: 0.38.42 + version: 0.38.42 domhandler: specifier: 6.0.1 version: 6.0.1 eslint: - specifier: 10.2.0 - version: 10.2.0(jiti@2.6.1) + specifier: 10.1.0 + version: 10.1.0(jiti@2.6.1) eslint-nibble: specifier: 9.1.1 - version: 9.1.1(@types/node@25.6.0)(eslint@10.2.0(jiti@2.6.1)) + version: 9.1.1(@types/node@25.5.0)(eslint@10.1.0(jiti@2.6.1)) eslint-plugin-import-x: specifier: 4.16.2 - version: 4.16.2(@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.2.0(jiti@2.6.1)) + version: 4.16.2(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.1.0(jiti@2.6.1)) eslint-plugin-n: specifier: 17.24.0 - version: 17.24.0(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + version: 17.24.0(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) eslint-plugin-simple-import-sort: - specifier: 13.0.0 - version: 13.0.0(eslint@10.2.0(jiti@2.6.1)) + specifier: 12.1.1 + version: 12.1.1(eslint@10.1.0(jiti@2.6.1)) eslint-plugin-unicorn: - specifier: 64.0.0 - version: 64.0.0(eslint@10.2.0(jiti@2.6.1)) + specifier: 63.0.0 + version: 63.0.0(eslint@10.1.0(jiti@2.6.1)) eslint-plugin-yml: specifier: 3.3.1 - version: 3.3.1(eslint@10.2.0(jiti@2.6.1)) + version: 3.3.1(eslint@10.1.0(jiti@2.6.1)) fs-extra: specifier: 11.3.4 version: 11.3.4 @@ -411,8 +411,8 @@ importers: specifier: 17.4.0 version: 17.4.0 got: - specifier: 15.0.1 - version: 15.0.1 + specifier: 14.6.6 + version: 14.6.6 husky: specifier: 9.1.7 version: 9.1.7 @@ -429,29 +429,26 @@ importers: specifier: 3.0.5 version: 3.0.5 msw: - specifier: 2.13.2 - version: 2.13.2(@types/node@25.6.0)(typescript@5.9.3) + specifier: 2.12.14 + version: 2.12.14(@types/node@25.5.0)(typescript@5.9.3) node-network-devtools: specifier: 1.0.29 - version: 1.0.29(undici@7.24.7)(utf-8-validate@5.0.10) + version: 1.0.29(undici@7.24.6)(utf-8-validate@5.0.10) oxfmt: - specifier: 0.44.0 - version: 0.44.0 + specifier: 0.42.0 + version: 0.42.0 oxlint: - specifier: 1.59.0 - version: 1.59.0(oxlint-tsgolint@0.20.0) - oxlint-plugin-eslint: - specifier: 1.59.0 - version: 1.59.0 + specifier: 1.57.0 + version: 1.57.0(oxlint-tsgolint@0.17.4) oxlint-tsgolint: - specifier: 0.20.0 - version: 0.20.0 + specifier: 0.17.4 + version: 0.17.4 remark-parse: specifier: 11.0.0 version: 11.0.0 tsdown: - specifier: 0.21.7 - version: 0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)(synckit@0.11.12)(typescript@5.9.3) + specifier: 0.21.5 + version: 0.21.5(synckit@0.11.12)(typescript@5.9.3) typescript: specifier: 5.9.3 version: 5.9.3 @@ -460,13 +457,13 @@ importers: version: 11.0.5 vite-tsconfig-paths: specifier: 6.1.1 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) vitest: specifier: 4.0.9 - version: 4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.6.0)(jiti@2.6.1)(jsdom@29.0.2(@noble/hashes@2.0.1))(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3) + version: 4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.5.0)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3) wrangler: - specifier: 4.81.1 - version: 4.81.1(@cloudflare/workers-types@4.20260410.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10) + specifier: 4.77.0 + version: 4.77.0(@cloudflare/workers-types@4.20260317.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10) yaml-eslint-parser: specifier: 2.0.0 version: 2.0.0 @@ -479,8 +476,8 @@ packages: '@actions/exec@3.0.0': resolution: {integrity: sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==} - '@actions/github@9.1.0': - resolution: {integrity: sha512-u0hDGQeCS+7VNoLA8hYG65RLdPLMaPGfka0sZ0up7P0AiShqfX6xcuXNteGkQ7X7Tod7AMNwHd4p7DS63i8zzA==} + '@actions/github@9.0.0': + resolution: {integrity: sha512-yJ0RoswsAaKcvkmpCE4XxBRiy/whH2SdTBHWzs0gi4wkqTDhXMChjSdqBz/F4AeiDlP28rQqL33iHb+kjAMX6w==} '@actions/http-client@3.0.2': resolution: {integrity: sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==} @@ -491,12 +488,12 @@ packages: '@actions/io@3.0.2': resolution: {integrity: sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==} - '@asamuzakjp/css-color@5.1.6': - resolution: {integrity: sha512-BXWCh8dHs9GOfpo/fWGDJtDmleta2VePN9rn6WQt3GjEbxzutVF4t0x2pmH+7dbMCLtuv3MlwqRsAuxlzFXqFg==} + '@asamuzakjp/css-color@5.0.1': + resolution: {integrity: sha512-2SZFvqMyvboVV1d15lMf7XiI3m7SDqXUuKaTymJYLN6dSGadqp+fVojqJlVoMlbZnlTmu3S0TLwLTJpvBMO1Aw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@asamuzakjp/dom-selector@7.0.7': - resolution: {integrity: sha512-d2BgqDUOS1Hfp4IzKUZqCNz+Kg3Y88AkaBvJK/ZVSQPU1f7OpPNi7nQTH6/oI47Dkdg+Z3e8Yp6ynOu4UMINAQ==} + '@asamuzakjp/dom-selector@7.0.4': + resolution: {integrity: sha512-jXR6x4AcT3eIrS2fSNAwJpwirOkGcd+E7F7CP3zjdTqz9B/2huHOL8YJZBgekKwLML+u7qB/6P1LXQuMScsx0w==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} '@asamuzakjp/nwsapi@2.3.9': @@ -511,8 +508,8 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} - '@babel/generator@8.0.0-rc.3': - resolution: {integrity: sha512-em37/13/nR320G4jab/nIIHZgc2Wz2y/D39lxnTyxB4/D/omPQncl/lSdlnJY1OhQcRGugTSIF2l/69o31C9dA==} + '@babel/generator@8.0.0-rc.2': + resolution: {integrity: sha512-oCQ1IKPwkzCeJzAPb7Fv8rQ9k5+1sG8mf2uoHiMInPYvkRfrDJxbTIbH51U+jstlkghus0vAi3EBvkfvEsYNLQ==} engines: {node: ^20.19.0 || >=22.12.0} '@babel/helper-string-parser@7.27.1': @@ -527,8 +524,8 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@8.0.0-rc.3': - resolution: {integrity: sha512-8AWCJ2VJJyDFlGBep5GpaaQ9AAaE/FjAcrqI7jyssYhtL7WGV0DOKpJsQqM037xDbpRLHXsY8TwU7zDma7coOw==} + '@babel/helper-validator-identifier@8.0.0-rc.2': + resolution: {integrity: sha512-xExUBkuXWJjVuIbO7z6q7/BA9bgfJDEhVL0ggrggLMbg0IzCUWGT1hZGE8qUH7Il7/RD/a6cZ3AAFrrlp1LF/A==} engines: {node: ^20.19.0 || >=22.12.0} '@babel/parser@7.29.2': @@ -536,8 +533,8 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@8.0.0-rc.3': - resolution: {integrity: sha512-B20dvP3MfNc/XS5KKCHy/oyWl5IA6Cn9YjXRdDlCjNmUFrjvLXMNUfQq/QUy9fnG2gYkKKcrto2YaF9B32ToOQ==} + '@babel/parser@8.0.0-rc.2': + resolution: {integrity: sha512-29AhEtcq4x8Dp3T72qvUMZHx0OMXCj4Jy/TEReQa+KWLln524Cj1fWb3QFi0l/xSpptQBR6y9RNEXuxpFvwiUQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -549,8 +546,8 @@ packages: resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@babel/types@8.0.0-rc.3': - resolution: {integrity: sha512-mOm5ZrYmphGfqVWoH5YYMTITb3cDXsFgmvFlvkvWDMsR9X8RFnt7a0Wb6yNIdoFsiMO9WjYLq+U/FMtqIYAF8Q==} + '@babel/types@8.0.0-rc.2': + resolution: {integrity: sha512-91gAaWRznDwSX4E2tZ1YjBuIfnQVOFDCQ2r0Toby0gu4XEbyF623kXLMA8d4ZbCu+fINcrudkmEcwSUHgDDkNw==} engines: {node: ^20.19.0 || >=22.12.0} '@bbob/core@4.3.1': @@ -585,15 +582,15 @@ packages: '@bufbuild/protobuf@2.11.0': resolution: {integrity: sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==} - '@cloudflare/containers@0.3.0': - resolution: {integrity: sha512-8HM1NgXThWCTk7SH28QFxqMNLJwl6RrMkj3qd0KvDA59BALsn3mZXNDT94i1JaGZnP4Bc8sPGs1u9UAl/mVUVg==} + '@cloudflare/containers@0.2.0': + resolution: {integrity: sha512-npxGQCHKx5grXnzAHHVAlg6FbyrH07v3COHxXniq7qWfqqIxD64Vrp7Jy9iCPkZamTRfXr0E4Pi0tRIY10Dq9w==} '@cloudflare/kv-asset-handler@0.4.2': resolution: {integrity: sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==} engines: {node: '>=18.0.0'} - '@cloudflare/puppeteer@1.0.7': - resolution: {integrity: sha512-8kjmXjNoS2C1iOMcSmL+If4AOOH2ADbGhyI2V94DJSmuBrUKHZSVcCp6UJjojcCG9dLNNE27SabpRrqIGETF0w==} + '@cloudflare/puppeteer@1.0.6': + resolution: {integrity: sha512-e/0s9Ac2IhyBrgnyTDrYEippqrXqKtllP8qezyunOb6icOJ2FzbfQwhWRIVwV3AgZtutQTF5Kb/gFAGXCuGRqQ==} engines: {node: '>=18'} '@cloudflare/unenv-preset@2.16.0': @@ -605,38 +602,38 @@ packages: workerd: optional: true - '@cloudflare/workerd-darwin-64@1.20260409.1': - resolution: {integrity: sha512-h/bkaC0HJL63aqAGnV0oagqpBiTSstabODThkeMSbG8kctl0Jb4jlq1pNHJPmYGazFNtfyagrUZFb6HN22GX7w==} + '@cloudflare/workerd-darwin-64@1.20260317.1': + resolution: {integrity: sha512-8hjh3sPMwY8M/zedq3/sXoA2Q4BedlGufn3KOOleIG+5a4ReQKLlUah140D7J6zlKmYZAFMJ4tWC7hCuI/s79g==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20260409.1': - resolution: {integrity: sha512-HTAC+B9uSYcm+GjN3UYJjuun19GqYtK1bAFJ0KECXyfsgIDwH1MTzxbTxzJpZUbWLw8s0jcwCU06MWZj6cgnxQ==} + '@cloudflare/workerd-darwin-arm64@1.20260317.1': + resolution: {integrity: sha512-M/MnNyvO5HMgoIdr3QHjdCj2T1ki9gt0vIUnxYxBu9ISXS/jgtMl6chUVPJ7zHYBn9MyYr8ByeN6frjYxj0MGg==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@cloudflare/workerd-linux-64@1.20260409.1': - resolution: {integrity: sha512-QIoNq5cgmn1ko8qlngmgZLXQr2KglrjvIwVFOyJI3rbIpt8631n/YMzHPiOWgt38Cb6tcni8fXOzkcvIX2lBDg==} + '@cloudflare/workerd-linux-64@1.20260317.1': + resolution: {integrity: sha512-1ltuEjkRcS3fsVF7CxsKlWiRmzq2ZqMfqDN0qUOgbUwkpXsLVJsXmoblaLf5OP00ELlcgF0QsN0p2xPEua4Uug==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20260409.1': - resolution: {integrity: sha512-HJGBMTfPDb0GCjwdxWFx63wS20TYDVmtOuA5KVri/CiFnit71y++kmseVmemjsgLFFIzoEAuFG/xUh1FJLo6tg==} + '@cloudflare/workerd-linux-arm64@1.20260317.1': + resolution: {integrity: sha512-3QrNnPF1xlaNwkHpasvRvAMidOvQs2NhXQmALJrEfpIJ/IDL2la8g499yXp3eqhG3hVMCB07XVY149GTs42Xtw==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@cloudflare/workerd-windows-64@1.20260409.1': - resolution: {integrity: sha512-GttFO0+TvE0rJNQbDlxC6kq2Q7uFxoZRo74Z9d/trUrLgA14HEVTTXobYyiWrDZ9Qp2W5KN1CrXQXiko0zE38Q==} + '@cloudflare/workerd-windows-64@1.20260317.1': + resolution: {integrity: sha512-MfZTz+7LfuIpMGTa3RLXHX8Z/pnycZLItn94WRdHr8LPVet+C5/1Nzei399w/jr3+kzT4pDKk26JF/tlI5elpQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] - '@cloudflare/workers-types@4.20260410.1': - resolution: {integrity: sha512-dPZT4aXxwhGHFhWA9iZhWVfFoO8g9exiLzeaS8y43Dw0Sard6Gb3o5LJjReav3ejHbQLHUfGEiZsRPGW8qmgMg==} + '@cloudflare/workers-types@4.20260317.1': + resolution: {integrity: sha512-+G4eVwyCpm8Au1ex8vQBCuA9wnwqetz4tPNRoB/53qvktERWBRMQnrtvC1k584yRE3emMThtuY0gWshvSJ++PQ==} '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} @@ -702,9 +699,6 @@ packages: '@emnapi/runtime@1.9.1': resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} - '@emnapi/runtime@1.9.2': - resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} - '@emnapi/wasi-threads@1.2.0': resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} @@ -723,12 +717,6 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.7': - resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/android-arm64@0.27.3': resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} engines: {node: '>=18'} @@ -741,12 +729,6 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.7': - resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm@0.27.3': resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} engines: {node: '>=18'} @@ -759,12 +741,6 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.7': - resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-x64@0.27.3': resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} engines: {node: '>=18'} @@ -777,12 +753,6 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.7': - resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/darwin-arm64@0.27.3': resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} engines: {node: '>=18'} @@ -795,12 +765,6 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.7': - resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-x64@0.27.3': resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} engines: {node: '>=18'} @@ -813,12 +777,6 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.7': - resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/freebsd-arm64@0.27.3': resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} engines: {node: '>=18'} @@ -831,12 +789,6 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.7': - resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-x64@0.27.3': resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} engines: {node: '>=18'} @@ -849,12 +801,6 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.7': - resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/linux-arm64@0.27.3': resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} engines: {node: '>=18'} @@ -867,12 +813,6 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.7': - resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm@0.27.3': resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} engines: {node: '>=18'} @@ -885,12 +825,6 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.7': - resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-ia32@0.27.3': resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} engines: {node: '>=18'} @@ -903,12 +837,6 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.7': - resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-loong64@0.27.3': resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} engines: {node: '>=18'} @@ -921,12 +849,6 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.7': - resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-mips64el@0.27.3': resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} engines: {node: '>=18'} @@ -939,12 +861,6 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.7': - resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-ppc64@0.27.3': resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} engines: {node: '>=18'} @@ -957,12 +873,6 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.7': - resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-riscv64@0.27.3': resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} engines: {node: '>=18'} @@ -975,12 +885,6 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.7': - resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-s390x@0.27.3': resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} engines: {node: '>=18'} @@ -993,12 +897,6 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.7': - resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} @@ -1011,12 +909,6 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.7': - resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/netbsd-arm64@0.27.3': resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} engines: {node: '>=18'} @@ -1029,12 +921,6 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.7': - resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-x64@0.27.3': resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} engines: {node: '>=18'} @@ -1047,12 +933,6 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.7': - resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/openbsd-arm64@0.27.3': resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} engines: {node: '>=18'} @@ -1065,12 +945,6 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.7': - resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-x64@0.27.3': resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} engines: {node: '>=18'} @@ -1083,12 +957,6 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.7': - resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openharmony-arm64@0.27.3': resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} engines: {node: '>=18'} @@ -1101,12 +969,6 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.7': - resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/sunos-x64@0.27.3': resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} engines: {node: '>=18'} @@ -1119,12 +981,6 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.7': - resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/win32-arm64@0.27.3': resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} engines: {node: '>=18'} @@ -1137,12 +993,6 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.7': - resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-ia32@0.27.3': resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} engines: {node: '>=18'} @@ -1155,12 +1005,6 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.7': - resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-x64@0.27.3': resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} engines: {node: '>=18'} @@ -1173,12 +1017,6 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.7': - resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@eslint-community/eslint-utils@4.9.1': resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1189,22 +1027,18 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.23.4': - resolution: {integrity: sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow==} + '@eslint/config-array@0.23.3': + resolution: {integrity: sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/config-helpers@0.5.4': - resolution: {integrity: sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg==} + '@eslint/config-helpers@0.5.3': + resolution: {integrity: sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/core@1.1.1': resolution: {integrity: sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/core@1.2.0': - resolution: {integrity: sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/eslintrc@3.3.5': resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1218,18 +1052,14 @@ packages: eslint: optional: true - '@eslint/object-schema@3.0.4': - resolution: {integrity: sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw==} + '@eslint/object-schema@3.0.3': + resolution: {integrity: sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} '@eslint/plugin-kit@0.6.1': resolution: {integrity: sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@eslint/plugin-kit@0.7.0': - resolution: {integrity: sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg==} - engines: {node: ^20.19.0 || ^22.13.0 || >=24} - '@exodus/bytes@1.15.0': resolution: {integrity: sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} @@ -1239,28 +1069,19 @@ packages: '@noble/hashes': optional: true - '@fastify/otel@0.18.0': - resolution: {integrity: sha512-3TASCATfw+ctICSb4ymrv7iCm0qJ0N9CarB+CZ7zIJ7KqNbwI5JjyDL1/sxoC0ccTO1Zyd1iQ+oqncPg5FJXaA==} + '@fastify/otel@0.17.1': + resolution: {integrity: sha512-K4wyxfUZx2ux5o+b6BtTqouYFVILohLZmSbA2tKUueJstNcBnoGPVhllCaOvbQ3ZrXdUxUC/fyrSWSCqHhdOPg==} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@honeybadger-io/core@6.7.2': - resolution: {integrity: sha512-4+hyrFI0S/Eni2cBgO40Lqyft5hyNXjgnuh1EbeH457kty8g4YatJYuHBffmrjwLiZHgFbWXRGv7SlG+NehC5Q==} - engines: {node: '>=14'} - - '@honeybadger-io/js@6.12.3': - resolution: {integrity: sha512-CL+9A8tGpjawsJEKE74P94hmimHRsq+B90i5N/pXNgnJbgZG40bs9yZpfn2z3w0+3z9wtH12D2RqBjxsGm9DBg==} - engines: {node: '>=14'} - hasBin: true - - '@hono/node-server@1.19.13': - resolution: {integrity: sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==} + '@hono/node-server@1.19.11': + resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==} engines: {node: '>=18.14.1'} peerDependencies: hono: ^4 - '@hono/zod-openapi@1.2.4': - resolution: {integrity: sha512-cZu71bpODTbtIDoUsIIYPrs58wJ565Tbg6FE+JshU0irBAd6KxrP+k62Amm/mjA7tTOQ3+ingODHKGFOnv+Ibw==} + '@hono/zod-openapi@1.2.3': + resolution: {integrity: sha512-zAviC3ApRAYGUiGWZiW/mrK/UBqkTi9BKQxn1IvwYyp2kS+k1tlnwut59DfEInpcsq1347zAYOqYI+obMy4vzQ==} engines: {node: '>=16.0.0'} peerDependencies: hono: '>=4.3.6' @@ -1561,11 +1382,8 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@napi-rs/wasm-runtime@1.1.2': - resolution: {integrity: sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==} - peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} '@noble/hashes@2.0.1': resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} @@ -1595,8 +1413,8 @@ packages: resolution: {integrity: sha512-y3SvzjuY1ygnzWA4Krwx/WaJAsTMP11DN+e21A8Fa8PW1oDtVB5NSRW7LWurAiS2oKRkuCgcjTYMkBuBkcPCRg==} engines: {node: '>=12.4.0'} - '@notionhq/client@5.17.0': - resolution: {integrity: sha512-hSNm3VUW5+Qs9vPOmegS6r1RT8O1jtTE/22wmSmiJc9kkb2YyddWr8SBQruvp06rALn2r2RAh9mLPirUUonsvw==} + '@notionhq/client@5.15.0': + resolution: {integrity: sha512-boQ+zMmTu/HRfPajynYjlXkytkmn0rUgD0FJrbMaz6n1WC6HPxe2Lgn/Ay/VEA2j2dMzB1Hpnhtrtkz4Q1I/rw==} engines: {node: '>=18'} '@octokit/auth-token@6.0.0': @@ -1661,6 +1479,10 @@ packages: resolution: {integrity: sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==} engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.213.0': + resolution: {integrity: sha512-zRM5/Qj6G84Ej3F1yt33xBVY/3tnMxtL1fiDIxYbDWYaZ/eudVw3/PBiZ8G7JwUxXxjW8gU4g6LnOyfGKYHYgw==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.214.0': resolution: {integrity: sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA==} engines: {node: '>=8.0.0'} @@ -1675,6 +1497,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.6.0': + resolution: {integrity: sha512-HLM1v2cbZ4TgYN6KEOj+Bbj8rAKriOdkF9Ed3tG25FoprSiQl7kYc+RRT6fUZGOvx0oMi5U67GoFdT+XUn8zEg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.6.1': resolution: {integrity: sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==} engines: {node: ^18.19.0 || >=20.6.0} @@ -1693,128 +1521,134 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-amqplib@0.61.0': - resolution: {integrity: sha512-mCKoyTGfRNisge4br0NpOFSy2Z1NnEW8hbCJdUDdJFHrPqVzc4IIBPA/vX0U+LUcQqrQvJX+HMIU0dbDRe0i0Q==} + '@opentelemetry/instrumentation-amqplib@0.60.0': + resolution: {integrity: sha512-q/B2IvoVXRm1M00MvhnzpMN6rKYOszPXVsALi6u0ss4AYHe+TidZEtLW9N1ZhrobI1dSriHnBqqtAOZVAv07sg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-connect@0.57.0': - resolution: {integrity: sha512-FMEBChnI4FLN5TE9DHwfH7QpNir1JzXno1uz/TAucVdLCyrG0jTrKIcNHt/i30A0M2AunNBCkcd8Ei26dIPKdg==} + '@opentelemetry/instrumentation-connect@0.56.0': + resolution: {integrity: sha512-PKp+sSZ7AfzMvGgO3VCyo1inwNu+q7A1k9X88WK4PQ+S6Hp7eFk8pie+sWHDTaARovmqq5V2osav3lQej2B0nw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-dataloader@0.31.0': - resolution: {integrity: sha512-f654tZFQXS5YeLDNb9KySrwtg7SnqZN119FauD7acBoTzuLduaiGTNz88ixcVSOOMGZ+EjJu/RFtx5klObC95g==} + '@opentelemetry/instrumentation-dataloader@0.30.0': + resolution: {integrity: sha512-MXHP2Q38cd2OhzEBKAIXUi9uBlPEYzF6BNJbyjUXBQ6kLaf93kRC41vNMIz0Nl5mnuwK7fDvKT+/lpx7BXRwdg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-fs@0.33.0': - resolution: {integrity: sha512-sCZWXGalQ01wr3tAhSR9ucqFJ0phidpAle6/17HVjD6gN8FLmZMK/8sKxdXYHy3PbnlV1P4zeiSVFNKpbFMNLA==} + '@opentelemetry/instrumentation-express@0.61.0': + resolution: {integrity: sha512-Xdmqo9RZuZlL29Flg8QdwrrX7eW1CZ7wFQPKHyXljNymgKhN1MCsYuqQ/7uxavhSKwAl7WxkTzKhnqpUApLMvQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-generic-pool@0.57.0': - resolution: {integrity: sha512-orhmlaK+ZIW9hKU+nHTbXrCSXZcH83AescTqmpamHRobRmYSQwRbD0a1odc0yAzuzOtxYiHiXAnpnIpaSSY7Ow==} + '@opentelemetry/instrumentation-fs@0.32.0': + resolution: {integrity: sha512-koR6apx0g0wX6RRiPpjA4AFQUQUbXrK16kq4/SZjVp7u5cffJhNkY4TnITxcGA4acGSPYAfx3NHRIv4Khn1axQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-graphql@0.62.0': - resolution: {integrity: sha512-3YNuLVPUxafXkH1jBAbGsKNsP3XVzcFDhCDCE3OqBwCwShlqQbLMRMFh1T/d5jaVZiGVmSsfof+ICKD2iOV8xg==} + '@opentelemetry/instrumentation-generic-pool@0.56.0': + resolution: {integrity: sha512-fg+Jffs6fqrf0uQS0hom7qBFKsbtpBiBl8+Vkc63Gx8xh6pVh+FhagmiO6oM0m3vyb683t1lP7yGYq22SiDnqg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-hapi@0.60.0': - resolution: {integrity: sha512-aNljZKYrEa7obLAxd1bCEDxF7kzCLGXTuTJZ8lMR9rIVEjmuKBXN1gfqpm/OB//Zc2zP4iIve1jBp7sr3mQV6w==} + '@opentelemetry/instrumentation-graphql@0.61.0': + resolution: {integrity: sha512-pUiVASv6nh2XrerTvlbVHh7vKFzscpgwiQ/xvnZuAIzQ5lRjWVdRPUuXbvZJ/Yq79QsE81TZdJ7z9YsXiss1ew==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-http@0.214.0': - resolution: {integrity: sha512-FlkDhZDRjDJDcO2LcSCtjRpkal1NJ8y0fBqBhTvfAR3JSYY2jAIj1kSS5IjmEBt4c3aWv+u/lqLuoCDrrKCSKg==} + '@opentelemetry/instrumentation-hapi@0.59.0': + resolution: {integrity: sha512-33wa4mEr+9+ztwdgLor1SeBu4Opz4IsmpcLETXAd3VmBrOjez8uQtrsOhPCa5Vhbm5gzDlMYTgFRLQzf8/YHFA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-ioredis@0.62.0': - resolution: {integrity: sha512-ZYt//zcPve8qklaZX+5Z4MkU7UpEkFRrxsf2cnaKYBitqDnsCN69CPAuuMOX6NYdW2rG9sFy7V/QWtBlP5XiNQ==} + '@opentelemetry/instrumentation-http@0.213.0': + resolution: {integrity: sha512-B978Xsm5XEPGhm1P07grDoaOFLHapJPkOG9h016cJsyWWxmiLnPu2M/4Nrm7UCkHSiLnkXgC+zVGUAIahy8EEA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-kafkajs@0.23.0': - resolution: {integrity: sha512-4K+nVo+zI+aDz0Z85SObwbdixIbzS9moIuKJaYsdlzcHYnKOPtB7ya8r8Ezivy/GVIBHiKJVq4tv+BEkgOMLaQ==} + '@opentelemetry/instrumentation-ioredis@0.61.0': + resolution: {integrity: sha512-hsHDadUtAFbws1YSDc1XW0svGFKiUbqv2td1Cby+UAiwvojm1NyBo/taifH0t8CuFZ0x/2SDm0iuTwrM5pnVOg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-knex@0.58.0': - resolution: {integrity: sha512-Hc/o8fSsaWxZ8r1Yw4rNDLwTpUopTf4X32y4W6UhlHmW8Wizz8wfhgOKIelSeqFVTKBBPIDUOsQWuIMxBmu8Bw==} + '@opentelemetry/instrumentation-kafkajs@0.22.0': + resolution: {integrity: sha512-wJU4IBQMUikdJAcTChLFqK5lo+flo7pahqd8DSLv7uMxsdOdAHj6RzKYAm8pPfUS6ItKYutYyuicwKaFwQKsoA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-koa@0.62.0': - resolution: {integrity: sha512-uVip0VuGUQXZ+vFxkKxAUNq8qNl+VFlyHDh/U6IQ8COOEDfbEchdaHnpFrMYF3psZRUuoSIgb7xOeXj00RdwDA==} + '@opentelemetry/instrumentation-knex@0.57.0': + resolution: {integrity: sha512-vMCSh8kolEm5rRsc+FZeTZymWmIJwc40hjIKnXH4O0Dv/gAkJJIRXCsPX5cPbe0c0j/34+PsENd0HqKruwhVYw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-koa@0.61.0': + resolution: {integrity: sha512-lvrfWe9ShK/D2X4brmx8ZqqeWPfRl8xekU0FCn7C1dHm5k6+rTOOi36+4fnaHAP8lig9Ux6XQ1D4RNIpPCt1WQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.9.0 - '@opentelemetry/instrumentation-lru-memoizer@0.58.0': - resolution: {integrity: sha512-6grM3TdMyHzlGY1cUA+mwoPueB1F3dYKgKtZIH6jOFXqfHAByyLTc+6PFjGM9tKh52CFBJaDwodNlL/Td39z7Q==} + '@opentelemetry/instrumentation-lru-memoizer@0.57.0': + resolution: {integrity: sha512-cEqpUocSKJfwDtLYTTJehRLWzkZ2eoePCxfVIgGkGkb83fMB71O+y4MvRHJPbeV2bdoWdOVrl8uO0+EynWhTEA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongodb@0.67.0': - resolution: {integrity: sha512-1WJp5N1lYfHq2IhECOTewFs5Tf2NfUOwQRqs/rZdXKTezArMlucxgzAaqcgp3A3YREXopXTpXHsxZTGHjNhMdQ==} + '@opentelemetry/instrumentation-mongodb@0.66.0': + resolution: {integrity: sha512-d7m9QnAY+4TCWI4q1QRkfrc6fo/92VwssaB1DzQfXNRvu51b78P+HJlWP7Qg6N6nkwdb9faMZNBCZJfftmszkw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongoose@0.60.0': - resolution: {integrity: sha512-8BahAZpKsOoc+lrZGb7Ofn4g3z8qtp5IxDfvAVpKXsEheQN7ONMH5djT5ihy6yf8yyeQJGS0gXFfpEAEeEHqQg==} + '@opentelemetry/instrumentation-mongoose@0.59.0': + resolution: {integrity: sha512-6/jWU+c1NgznkVLDU/2y0bXV2nJo3o9FWZ9mZ9nN6T/JBNRoMnVXZl2FdBmgH+a5MwaWLs5kmRJTP5oUVGIkPw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql2@0.60.0': - resolution: {integrity: sha512-m/5d3bxQALllCzezYDk/6vajh0tj5OijMMvOZGr+qN1NMXm1dzMNwyJ0gNZW7Fo3YFRyj/jJMxIw+W7d525dlw==} + '@opentelemetry/instrumentation-mysql2@0.59.0': + resolution: {integrity: sha512-n9/xrVCRBfG9egVbffnlU1uhr+HX0vF4GgtAB/Bvm48wpFgRidqD8msBMiym1kRYzmpWvJqTxNT47u1MkgBEdw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql@0.60.0': - resolution: {integrity: sha512-08pO8GFPEIz2zquKDGteBZDNmwketdgH8hTe9rVYgW9kCJXq1Psj3wPQGx+VaX4ZJKCfPeoLMYup9+cxHvZyVQ==} + '@opentelemetry/instrumentation-mysql@0.59.0': + resolution: {integrity: sha512-r+V/Fh0sm7Ga8/zk/TI5H5FQRAjwr0RrpfPf8kNIehlsKf12XnvIaZi8ViZkpX0gyPEpLXqzqWD6QHlgObgzZw==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-pg@0.66.0': - resolution: {integrity: sha512-KxfLGXBb7k2ueaPJfq2GXBDXBly8P+SpR/4Mj410hhNgmQF3sCqwXvUBQxZQkDAmsdBAoenM+yV1LhtsMRamcA==} + '@opentelemetry/instrumentation-pg@0.65.0': + resolution: {integrity: sha512-W0zpHEIEuyZ8zvb3njaX9AAbHgPYOsSWVOoWmv1sjVRSF6ZpBqtlxBWbU+6hhq1TFWBeWJOXZ8nZS/PUFpLJYQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-redis@0.62.0': - resolution: {integrity: sha512-y3pPpot7WzR/8JtHcYlTYsyY8g+pbFhAqbwAuG5bLPnR6v6pt1rQc0DpH0OlGP/9CZbWBP+Zhwp9yFoygf/ZXQ==} + '@opentelemetry/instrumentation-redis@0.61.0': + resolution: {integrity: sha512-JnPexA034/0UJRsvH96B0erQoNOqKJZjE2ZRSw9hiTSC23LzE0nJE/u6D+xqOhgUhRnhhcPHq4MdYtmUdYTF+Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-tedious@0.33.0': - resolution: {integrity: sha512-Q6WQwAD01MMTub31GlejoiFACYNw26J426wyjvU7by7fDIr2nZXNW4vhTGs7i7F0TnXBO3xN688g1tdUgYwJ5w==} + '@opentelemetry/instrumentation-tedious@0.32.0': + resolution: {integrity: sha512-BQS6gG8RJ1foEqfEZ+wxoqlwfCAzb1ZVG0ad8Gfe4x8T658HJCLGLd4E4NaoQd8EvPfLqOXgzGaE/2U4ytDSWA==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-undici@0.24.0': - resolution: {integrity: sha512-oKzZ3uvqP17sV0EsoQcJgjEfIp0kiZRbYu/eD8p13Cbahumf8lb/xpYeNr/hfAJ4owzEtIDcGIjprfLcYbIKBQ==} + '@opentelemetry/instrumentation-undici@0.23.0': + resolution: {integrity: sha512-LL0VySzKVR2cJSFVZaTYpZl1XTpBGnfzoQPe2W7McS2267ldsaEIqtQY6VXs2KCXN0poFjze5110PIpxHDaDGg==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.7.0 @@ -1831,8 +1665,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation@0.214.0': - resolution: {integrity: sha512-MHqEX5Dk59cqVah5LiARMACku7jXSVk9iVDWOea4x3cr7VfdByeDCURK6o1lntT1JS/Tsovw01UJrBhN3/uC5w==} + '@opentelemetry/instrumentation@0.213.0': + resolution: {integrity: sha512-3i9NdkET/KvQomeh7UaR/F4r9P25Rx6ooALlWXPIjypcEOUxksCmVu0zA70NBJWlrMW1rPr/LRidFAflLI+s/w==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -1912,282 +1746,282 @@ packages: '@oxc-project/types@0.122.0': resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==} - '@oxfmt/binding-android-arm-eabi@0.44.0': - resolution: {integrity: sha512-5UvghMd9SA/yvKTWCAxMAPXS1d2i054UeOf4iFjZjfayTwCINcC3oaSXjtbZfCaEpxgJod7XiOjTtby5yEv/BQ==} + '@oxfmt/binding-android-arm-eabi@0.42.0': + resolution: {integrity: sha512-dsqPTYsozeokRjlrt/b4E7Pj0z3eS3Eg74TWQuuKbjY4VttBmA88rB7d50Xrd+TZ986qdXCNeZRPEzZHAe+jow==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxfmt/binding-android-arm64@0.44.0': - resolution: {integrity: sha512-IVudM1BWfvrYO++Khtzr8q9n5Rxu7msUvoFMqzGJVdX7HfUXUDHwaH2zHZNB58svx2J56pmCUzophyaPFkcG/A==} + '@oxfmt/binding-android-arm64@0.42.0': + resolution: {integrity: sha512-t+aAjHxcr5eOBphFHdg1ouQU9qmZZoRxnX7UOJSaTwSoKsb6TYezNKO0YbWytGXCECObRqNcUxPoPr0KaraAIg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxfmt/binding-darwin-arm64@0.44.0': - resolution: {integrity: sha512-eWCLAIKAHfx88EqEP1Ga2yz7qVcqDU5lemn4xck+07bH182hDdprOHjbogyk0In1Djys3T0/pO2JepFnRJ41Mg==} + '@oxfmt/binding-darwin-arm64@0.42.0': + resolution: {integrity: sha512-ulpSEYMKg61C5bRMZinFHrKJYRoKGVbvMEXA5zM1puX3O9T6Q4XXDbft20yrDijpYWeuG59z3Nabt+npeTsM1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxfmt/binding-darwin-x64@0.44.0': - resolution: {integrity: sha512-eHTBznHLM49++dwz07MblQ2cOXyIgeedmE3Wgy4ptUESj38/qYZyRi1MPwC9olQJWssMeY6WI3UZ7YmU5ggvyQ==} + '@oxfmt/binding-darwin-x64@0.42.0': + resolution: {integrity: sha512-ttxLKhQYPdFiM8I/Ri37cvqChE4Xa562nNOsZFcv1CKTVLeEozXjKuYClNvxkXmNlcF55nzM80P+CQkdFBu+uQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxfmt/binding-freebsd-x64@0.44.0': - resolution: {integrity: sha512-jLMmbj0u0Ft43QpkUVr/0v1ZfQCGWAvU+WznEHcN3wZC/q6ox7XeSJtk9P36CCpiDSUf3sGnzbIuG1KdEMEDJQ==} + '@oxfmt/binding-freebsd-x64@0.42.0': + resolution: {integrity: sha512-Og7QS3yI3tdIKYZ58SXik0rADxIk2jmd+/YvuHRyKULWpG4V2fR5V4hvKm624Mc0cQET35waPXiCQWvjQEjwYQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxfmt/binding-linux-arm-gnueabihf@0.44.0': - resolution: {integrity: sha512-n+A/u/ByK1qV8FVGOwyaSpw5NPNl0qlZfgTBqHeGIqr8Qzq1tyWZ4lAaxPoe5mZqE3w88vn3+jZtMxriHPE7tg==} + '@oxfmt/binding-linux-arm-gnueabihf@0.42.0': + resolution: {integrity: sha512-jwLOw/3CW4H6Vxcry4/buQHk7zm9Ne2YsidzTL1kpiMe4qqrRCwev3dkyWe2YkFmP+iZCQ7zku4KwjcLRoh8ew==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm-musleabihf@0.44.0': - resolution: {integrity: sha512-5eax+FkxyCqAi3Rw0mrZFr7+KTt/XweFsbALR+B5ljWBLBl8nHe4ADrUnb1gLEfQCJLl+Ca5FIVD4xEt95AwIw==} + '@oxfmt/binding-linux-arm-musleabihf@0.42.0': + resolution: {integrity: sha512-XwXu2vkMtiq2h7tfvN+WA/9/5/1IoGAVCFPiiQUvcAuG3efR97KNcRGM8BetmbYouFotQ2bDal3yyjUx6IPsTg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxfmt/binding-linux-arm64-gnu@0.44.0': - resolution: {integrity: sha512-58l8JaHxSGOmOMOG2CIrNsnkRJAj0YcHQCmvNACniOa/vd1iRHhlPajczegzS5jwMENlqgreyiTR9iNlke8qCw==} + '@oxfmt/binding-linux-arm64-gnu@0.42.0': + resolution: {integrity: sha512-ea7s/XUJoT7ENAtUQDudFe3nkSM3e3Qpz4nJFRdzO2wbgXEcjnchKLEsV3+t4ev3r8nWxIYr9NRjPWtnyIFJVA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-arm64-musl@0.44.0': - resolution: {integrity: sha512-AlObQIXyVRZ96LbtVljtFq0JqH5B92NU+BQeDFrXWBUWlCKAM0wF5GLfIhCLT5kQ3Sl+U0YjRJ7Alqj5hGQaCg==} + '@oxfmt/binding-linux-arm64-musl@0.42.0': + resolution: {integrity: sha512-+JA0YMlSdDqmacygGi2REp57c3fN+tzARD8nwsukx9pkCHK+6DkbAA9ojS4lNKsiBjIW8WWa0pBrBWhdZEqfuw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-ppc64-gnu@0.44.0': - resolution: {integrity: sha512-YcFE8/q/BbrCiIiM5piwbkA6GwJc5QqhMQp2yDrqQ2fuVkZ7CInb1aIijZ/k8EXc72qXMSwKpVlBv1w/MsGO/A==} + '@oxfmt/binding-linux-ppc64-gnu@0.42.0': + resolution: {integrity: sha512-VfnET0j4Y5mdfCzh5gBt0NK28lgn5DKx+8WgSMLYYeSooHhohdbzwAStLki9pNuGy51y4I7IoW8bqwAaCMiJQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-gnu@0.44.0': - resolution: {integrity: sha512-eOdzs6RqkRzuqNHUX5C8ISN5xfGh4xDww8OEd9YAmc3OWN8oAe5bmlIqQ+rrHLpv58/0BuU48bxkhnIGjA/ATQ==} + '@oxfmt/binding-linux-riscv64-gnu@0.42.0': + resolution: {integrity: sha512-gVlCbmBkB0fxBWbhBj9rcxezPydsQHf4MFKeHoTSPicOQ+8oGeTQgQ8EeesSybWeiFPVRx3bgdt4IJnH6nOjAA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-riscv64-musl@0.44.0': - resolution: {integrity: sha512-YBgNTxntD/QvlFUfgvh8bEdwOhXiquX8gaofZJAwYa/Xp1S1DQrFVZEeck7GFktr24DztsSp8N8WtWCBwxs0Hw==} + '@oxfmt/binding-linux-riscv64-musl@0.42.0': + resolution: {integrity: sha512-zN5OfstL0avgt/IgvRu0zjQzVh/EPkcLzs33E9LMAzpqlLWiPWeMDZyMGFlSRGOdDjuNmlZBCgj0pFnK5u32TQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxfmt/binding-linux-s390x-gnu@0.44.0': - resolution: {integrity: sha512-GLIh1R6WHWshl/i4QQDNgj0WtT25aRO4HNUWEoitxiywyRdhTFmFEYT2rXlcl9U6/26vhmOqG5cRlMLG3ocaIA==} + '@oxfmt/binding-linux-s390x-gnu@0.42.0': + resolution: {integrity: sha512-9X6+H2L0qMc2sCAgO9HS03bkGLMKvOFjmEdchaFlany3vNZOjnVui//D8k/xZAtQv2vaCs1reD5KAgPoIU4msA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-gnu@0.44.0': - resolution: {integrity: sha512-gZOpgTlOsLcLfAF9qgpTr7FIIFSKnQN3hDf/0JvQ4CIwMY7h+eilNjxq/CorqvYcEOu+LRt1W4ZS7KccEHLOdA==} + '@oxfmt/binding-linux-x64-gnu@0.42.0': + resolution: {integrity: sha512-BajxJ6KQvMMdpXGPWhBGyjb2Jvx4uec0w+wi6TJZ6Tv7+MzPwe0pO8g5h1U0jyFgoaF7mDl6yKPW3ykWcbUJRw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxfmt/binding-linux-x64-musl@0.44.0': - resolution: {integrity: sha512-1CyS9JTB+pCUFYFI6pkQGGZaT/AY5gnhHVrQQLhFba6idP9AzVYm1xbdWfywoldTYvjxQJV6x4SuduCIfP3W+A==} + '@oxfmt/binding-linux-x64-musl@0.42.0': + resolution: {integrity: sha512-0wV284I6vc5f0AqAhgAbHU2935B4bVpncPoe5n/WzVZY/KnHgqxC8iSFGeSyLWEgstFboIcWkOPck7tqbdHkzA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxfmt/binding-openharmony-arm64@0.44.0': - resolution: {integrity: sha512-bmEv70Ak6jLr1xotCbF5TxIKjsmQaiX+jFRtnGtfA03tJPf6VG3cKh96S21boAt3JZc+Vjx8PYcDuLj39vM2Pw==} + '@oxfmt/binding-openharmony-arm64@0.42.0': + resolution: {integrity: sha512-p4BG6HpGnhfgHk1rzZfyR6zcWkE7iLrWxyehHfXUy4Qa5j3e0roglFOdP/Nj5cJJ58MA3isQ5dlfkW2nNEpolw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxfmt/binding-win32-arm64-msvc@0.44.0': - resolution: {integrity: sha512-yWzB+oCpSnP/dmw85eFLAT5o35Ve5pkGS2uF/UCISpIwDqf1xa7OpmtomiqY/Vzg8VyvMbuf6vroF2khF/+1Vg==} + '@oxfmt/binding-win32-arm64-msvc@0.42.0': + resolution: {integrity: sha512-mn//WV60A+IetORDxYieYGAoQso4KnVRRjORDewMcod4irlRe0OSC7YPhhwaexYNPQz/GCFk+v9iUcZ2W22yxQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxfmt/binding-win32-ia32-msvc@0.44.0': - resolution: {integrity: sha512-TcWpo18xEIE3AmIG2kpr3kz5IEhQgnx0lazl2+8L+3eTopOAUevQcmlr4nhguImNWz0OMeOZrYZOhJNCf16nlQ==} + '@oxfmt/binding-win32-ia32-msvc@0.42.0': + resolution: {integrity: sha512-3gWltUrvuz4LPJXWivoAxZ28Of2O4N7OGuM5/X3ubPXCEV8hmgECLZzjz7UYvSDUS3grfdccQwmjynm+51EFpw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxfmt/binding-win32-x64-msvc@0.44.0': - resolution: {integrity: sha512-oj8aLkPJZppIM4CMQNsyir9ybM1Xw/CfGPTSsTnzpVGyljgfbdP0EVUlURiGM0BDrmw5psQ6ArmGCcUY/yABaQ==} + '@oxfmt/binding-win32-x64-msvc@0.42.0': + resolution: {integrity: sha512-Wg4TMAfQRL9J9AZevJ/ZNy3uyyDztDYQtGr4P8UyyzIhLhFrdSmz1J/9JT+rv0fiCDLaFOBQnj3f3K3+a5PzDQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxlint-tsgolint/darwin-arm64@0.20.0': - resolution: {integrity: sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA==} + '@oxlint-tsgolint/darwin-arm64@0.17.4': + resolution: {integrity: sha512-XEA7vl/T1+wiVnMq2MR6u5OYr2pwKHiAPgklxpK8tPrjQ1ci/amNmwI8ECn6TPXSCsC8SJsSN5xvzXm5H3dTfw==} cpu: [arm64] os: [darwin] - '@oxlint-tsgolint/darwin-x64@0.20.0': - resolution: {integrity: sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g==} + '@oxlint-tsgolint/darwin-x64@0.17.4': + resolution: {integrity: sha512-EY2wmHWqkz72B0/ddMiAM564ZXpEuN1i7JqJJhLmDUQfiHX0/X0EqK3xlSScMCFcVicitOxbKO9oqbde3658yg==} cpu: [x64] os: [darwin] - '@oxlint-tsgolint/linux-arm64@0.20.0': - resolution: {integrity: sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag==} + '@oxlint-tsgolint/linux-arm64@0.17.4': + resolution: {integrity: sha512-XL2X8hgp3/TZWeHFLUnWrveTCBPxy1kNtpzfvVkLtBgyoaRyopPYL0Mnm+ypXKgGvUdcjDaiJhnRjFHWmqZkew==} cpu: [arm64] os: [linux] - '@oxlint-tsgolint/linux-x64@0.20.0': - resolution: {integrity: sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg==} + '@oxlint-tsgolint/linux-x64@0.17.4': + resolution: {integrity: sha512-jT+aWtQuU8jefwfBLAZu16p4t8xUDjxL6KKlOeuwX3cS6NO60ITJ4Glm8eQYq5cGsOmYIKXNIe4ckPpL5LC+5g==} cpu: [x64] os: [linux] - '@oxlint-tsgolint/win32-arm64@0.20.0': - resolution: {integrity: sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA==} + '@oxlint-tsgolint/win32-arm64@0.17.4': + resolution: {integrity: sha512-pnnkBaI5tHBFhx+EhmpUHccBT3VOAXTgWK2eQBVLE4a/ywhpHN+8D6/QQN+ZTaA4LTkKowvlGD6vDOVP5KRPvw==} cpu: [arm64] os: [win32] - '@oxlint-tsgolint/win32-x64@0.20.0': - resolution: {integrity: sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw==} + '@oxlint-tsgolint/win32-x64@0.17.4': + resolution: {integrity: sha512-JxT81aEUBNA/s01Ql2OQ2DLAsuM0M+mK9iLHunukOdPMhjA6NvFE/GtTablBYJKScK21d/xTvnoSLgQU3l22Cw==} cpu: [x64] os: [win32] - '@oxlint/binding-android-arm-eabi@1.59.0': - resolution: {integrity: sha512-etYDw/UaEv936AQUd/CRMBVd+e+XuuU6wC+VzOv1STvsTyZenLChepLWqLtnyTTp4YMlM22ypzogDDwqYxv5cg==} + '@oxlint/binding-android-arm-eabi@1.57.0': + resolution: {integrity: sha512-C7EiyfAJG4B70496eV543nKiq5cH0o/xIh/ufbjQz3SIvHhlDDsyn+mRFh+aW8KskTyUpyH2LGWL8p2oN6bl1A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [android] - '@oxlint/binding-android-arm64@1.59.0': - resolution: {integrity: sha512-TgLc7XVLKH2a4h8j3vn1MDjfK33i9MY60f/bKhRGWyVzbk5LCZ4X01VZG7iHrMmi5vYbAp8//Ponigx03CLsdw==} + '@oxlint/binding-android-arm64@1.57.0': + resolution: {integrity: sha512-9i80AresjZ/FZf5xK8tKFbhQnijD4s1eOZw6/FHUwD59HEZbVLRc2C88ADYJfLZrF5XofWDiRX/Ja9KefCLy7w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@oxlint/binding-darwin-arm64@1.59.0': - resolution: {integrity: sha512-DXyFPf5ZKldMLloRHx/B9fsxsiTQomaw7cmEW3YIJko2HgCh+GUhp9gGYwHrqlLJPsEe3dYj9JebjX92D3j3AA==} + '@oxlint/binding-darwin-arm64@1.57.0': + resolution: {integrity: sha512-0eUfhRz5L2yKa9I8k3qpyl37XK3oBS5BvrgdVIx599WZK63P8sMbg+0s4IuxmIiZuBK68Ek+Z+gcKgeYf0otsg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@oxlint/binding-darwin-x64@1.59.0': - resolution: {integrity: sha512-LgvrsdgVLX1qWqIEmNsSmMXJhpAWdtUQ0M+oR0CySwi+9IHWyOGuIL8w8+u/kbZNMyZr4WUyYB5i0+D+AKgkLg==} + '@oxlint/binding-darwin-x64@1.57.0': + resolution: {integrity: sha512-UvrSuzBaYOue+QMAcuDITe0k/Vhj6KZGjfnI6x+NkxBTke/VoM7ZisaxgNY0LWuBkTnd1OmeQfEQdQ48fRjkQg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@oxlint/binding-freebsd-x64@1.59.0': - resolution: {integrity: sha512-bOJhqX/ny4hrFuTPlyk8foSRx/vLRpxJh0jOOKN2NWW6FScXHPAA5rQbrwdQPcgGB5V8Ua51RS03fke8ssBcug==} + '@oxlint/binding-freebsd-x64@1.57.0': + resolution: {integrity: sha512-wtQq0dCoiw4bUwlsNVDJJ3pxJA218fOezpgtLKrbQqUtQJcM9yP8z+I9fu14aHg0uyAxIY+99toL6uBa2r7nxA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@oxlint/binding-linux-arm-gnueabihf@1.59.0': - resolution: {integrity: sha512-vVUXxYMF9trXCsz4m9H6U0IjehosVHxBzVgJUxly1uz4W1PdDyicaBnpC0KRXsHYretLVe+uS9pJy8iM57Kujw==} + '@oxlint/binding-linux-arm-gnueabihf@1.57.0': + resolution: {integrity: sha512-qxFWl2BBBFcT4djKa+OtMdnLgoHEJXpqjyGwz8OhW35ImoCwR5qtAGqApNYce5260FQqoAHW8S8eZTjiX67Tsg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm-musleabihf@1.59.0': - resolution: {integrity: sha512-TULQW8YBPGRWg5yZpFPL54HLOnJ3/HiX6VenDPi6YfxB/jlItwSMFh3/hCeSNbh+DAMaE1Py0j5MOaivHkI/9Q==} + '@oxlint/binding-linux-arm-musleabihf@1.57.0': + resolution: {integrity: sha512-SQoIsBU7J0bDW15/f0/RvxHfY3Y0+eB/caKBQtNFbuerTiA6JCYx9P1MrrFTwY2dTm/lMgTSgskvCEYk2AtG/Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@oxlint/binding-linux-arm64-gnu@1.59.0': - resolution: {integrity: sha512-Gt54Y4eqSgYJ90xipm24xeyaPV854706o/kiT8oZvUt3VDY7qqxdqyGqchMaujd87ib+/MXvnl9WkK8Cc1BExg==} + '@oxlint/binding-linux-arm64-gnu@1.57.0': + resolution: {integrity: sha512-jqxYd1W6WMeozsCmqe9Rzbu3SRrGTyGDAipRlRggetyYbUksJqJKvUNTQtZR/KFoJPb+grnSm5SHhdWrywv3RQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-arm64-musl@1.59.0': - resolution: {integrity: sha512-3CtsKp7NFB3OfqQzbuAecrY7GIZeiv7AD+xutU4tefVQzlfmTI7/ygWLrvkzsDEjTlMq41rYHxgsn6Yh8tybmA==} + '@oxlint/binding-linux-arm64-musl@1.57.0': + resolution: {integrity: sha512-i66WyEPVEvq9bxRUCJ/MP5EBfnTDN3nhwEdFZFTO5MmLLvzngfWEG3NSdXQzTT3vk5B9i6C2XSIYBh+aG6uqyg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@oxlint/binding-linux-ppc64-gnu@1.59.0': - resolution: {integrity: sha512-K0diOpT3ncDmOfl9I1HuvpEsAuTxkts0VYwIv/w6Xiy9CdwyPBVX88Ga9l8VlGgMrwBMnSY4xIvVlVY/fkQk7Q==} + '@oxlint/binding-linux-ppc64-gnu@1.57.0': + resolution: {integrity: sha512-oMZDCwz4NobclZU3pH+V1/upVlJZiZvne4jQP+zhJwt+lmio4XXr4qG47CehvrW1Lx2YZiIHuxM2D4YpkG3KVA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-gnu@1.59.0': - resolution: {integrity: sha512-xAU7+QDU6kTJJ7mJLOGgo7oOjtAtkKyFZ0Yjdb5cEo3DiCCPFLvyr08rWiQh6evZ7RiUTf+o65NY/bqttzJiQQ==} + '@oxlint/binding-linux-riscv64-gnu@1.57.0': + resolution: {integrity: sha512-uoBnjJ3MMEBbfnWC1jSFr7/nSCkcQYa72NYoNtLl1imshDnWSolYCjzb8LVCwYCCfLJXD+0gBLD7fyC14c0+0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-riscv64-musl@1.59.0': - resolution: {integrity: sha512-KUmZmKlTTyauOnvUNVxK7G40sSSx0+w5l1UhaGsC6KPpOYHenx2oqJTnabmpLJicok7IC+3Y6fXAUOMyexaeJQ==} + '@oxlint/binding-linux-riscv64-musl@1.57.0': + resolution: {integrity: sha512-BdrwD7haPZ8a9KrZhKJRSj6jwCor+Z8tHFZ3PT89Y3Jq5v3LfMfEePeAmD0LOTWpiTmzSzdmyw9ijneapiVHKQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] libc: [musl] - '@oxlint/binding-linux-s390x-gnu@1.59.0': - resolution: {integrity: sha512-4usRxC8gS0PGdkHnRmwJt/4zrQNZyk6vL0trCxwZSsAKM+OxhB8nKiR+mhjdBbl8lbMh2gc3bZpNN/ik8c4c2A==} + '@oxlint/binding-linux-s390x-gnu@1.57.0': + resolution: {integrity: sha512-BNs+7ZNsRstVg2tpNxAXfMX/Iv5oZh204dVyb8Z37+/gCh+yZqNTlg6YwCLIMPSk5wLWIGOaQjT0GUOahKYImw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-gnu@1.59.0': - resolution: {integrity: sha512-s/rNE2gDmbwAOOP493xk2X7M8LZfI1LJFSSW1+yanz3vuQCFPiHkx4GY+O1HuLUDtkzGlhtMrIcxxzyYLv308w==} + '@oxlint/binding-linux-x64-gnu@1.57.0': + resolution: {integrity: sha512-AghS18w+XcENcAX0+BQGLiqjpqpaxKJa4cWWP0OWNLacs27vHBxu7TYkv9LUSGe5w8lOJHeMxcYfZNOAPqw2bg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@oxlint/binding-linux-x64-musl@1.59.0': - resolution: {integrity: sha512-+yYj1udJa2UvvIUmEm0IcKgc0UlPMgz0nsSTvkPL2y6n0uU5LgIHSwVu4AHhrve6j9BpVSoRksnz8c9QcvITJA==} + '@oxlint/binding-linux-x64-musl@1.57.0': + resolution: {integrity: sha512-E/FV3GB8phu/Rpkhz5T96hAiJlGzn91qX5yj5gU754P5cmVGXY1Jw/VSjDSlZBCY3VHjsVLdzgdkJaomEmcNOg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@oxlint/binding-openharmony-arm64@1.59.0': - resolution: {integrity: sha512-bUplUb48LYsB3hHlQXP2ZMOenpieWoOyppLAnnAhuPag3MGPnt+7caxE3w/Vl9wpQsTA3gzLntQi9rxWrs7Xqg==} + '@oxlint/binding-openharmony-arm64@1.57.0': + resolution: {integrity: sha512-xvZ2yZt0nUVfU14iuGv3V25jpr9pov5N0Wr28RXnHFxHCRxNDMtYPHV61gGLhN9IlXM96gI4pyYpLSJC5ClLCQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@oxlint/binding-win32-arm64-msvc@1.59.0': - resolution: {integrity: sha512-/HLsLuz42rWl7h7ePdmMTpHm2HIDmPtcEMYgm5BBEHiEiuNOrzMaUpd2z7UnNni5LGN9obJy2YoAYBLXQwazrA==} + '@oxlint/binding-win32-arm64-msvc@1.57.0': + resolution: {integrity: sha512-Z4D8Pd0AyHBKeazhdIXeUUy5sIS3Mo0veOlzlDECg6PhRRKgEsBJCCV1n+keUZtQ04OP+i7+itS3kOykUyNhDg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@oxlint/binding-win32-ia32-msvc@1.59.0': - resolution: {integrity: sha512-rUPy+JnanpPwV/aJCPnxAD1fW50+XPI0VkWr7f0vEbqcdsS8NpB24Rw6RsS7SdpFv8Dw+8ugCwao5nCFbqOUSg==} + '@oxlint/binding-win32-ia32-msvc@1.57.0': + resolution: {integrity: sha512-StOZ9nFMVKvevicbQfql6Pouu9pgbeQnu60Fvhz2S6yfMaii+wnueLnqQ5I1JPgNF0Syew4voBlAaHD13wH6tw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ia32] os: [win32] - '@oxlint/binding-win32-x64-msvc@1.59.0': - resolution: {integrity: sha512-xkE7puteDS/vUyRngLXW0t8WgdWoS/tfxXjhP/P7SMqPDx+hs44SpssO3h3qmTqECYEuXBUPzcAw5257Ka+ofA==} + '@oxlint/binding-win32-x64-msvc@1.57.0': + resolution: {integrity: sha512-6PuxhYgth8TuW0+ABPOIkGdBYw+qYGxgIdXPHSVpiCDm+hqTTWCmC739St1Xni0DJBt8HnSHTG67i1y6gr8qrA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@oxlint/plugins@1.59.0': - resolution: {integrity: sha512-KIEedExMc60HKrkZi79403NbSgnJUyC9w6dCsqrY45ygIPzEyFdpxboiTyI8ZjeEw6Os03bspgZBfm6/fZbkOg==} + '@oxlint/plugins@1.57.0': + resolution: {integrity: sha512-4mAGdfUZNQSZwUbHs0xoUcKjByrdBSJ9iaCI3STn/d1ZVRKhW/82oCA6rdfSzO4vxrWH3/l+qYWh/tyrwPSpag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} '@package-json/types@0.0.12': @@ -2224,8 +2058,8 @@ packages: '@postman/tunnel-agent@0.6.8': resolution: {integrity: sha512-2U42SmZW5G+suEcS++zB94sBWNO4qD4bvETGFRFDTqSpYl5ksfjcPqzYpgQgXgUmb6dfz+fAGbkcRamounGm0w==} - '@prisma/instrumentation@7.6.0': - resolution: {integrity: sha512-ZPW2gRiwpPzEfgeZgaekhqXrbW+Y2RJKHVqUmlhZhKzRNCcvR6DykzylDrynpArKKRQtLxoZy36fK7U0p3pdgQ==} + '@prisma/instrumentation@7.4.2': + resolution: {integrity: sha512-r9JfchJF1Ae6yAxcaLu/V1TGqBhAuSDe3mRNOssBfx1rMzfZ4fdNvrgUBwyb/TNTGXFxlH9AZix5P257x07nrg==} peerDependencies: '@opentelemetry/api': ^1.8 @@ -2277,36 +2111,73 @@ packages: '@quansync/fs@1.0.0': resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + '@rolldown/binding-android-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-SJ+/g+xNnOh6NqYxD0V3uVN4W3VfnrGsC9/hoglicgTNfABFG9JjISvkkU0dNY84MNHLWyOgxP9v9Y9pX4S7+A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-android-arm64@1.0.0-rc.12': resolution: {integrity: sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-7WQgR8SfOPwmDZGFkThUvsmd/nwAWv91oCO4I5LS7RKrssPZmOt7jONN0cW17ydGC1n/+puol1IpoieKqQidmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': resolution: {integrity: sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + resolution: {integrity: sha512-39Ks6UvIHq4rEogIfQBoBRusj0Q0nPVWIvqmwBLaT6aqQGIakHdESBVOPRRLacy4WwUPIx4ZKzfZ9PMW+IeyUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.0-rc.12': resolution: {integrity: sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + resolution: {integrity: sha512-jfsm0ZHfhiqrvWjJAmzsqiIFPz5e7mAoCOPBNTcNgkiid/LaFKiq92+0ojH+nmJmKYkre4t71BWXUZDNp7vsag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': resolution: {integrity: sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + resolution: {integrity: sha512-zjQaUtSyq1nVe3nxmlSCuR96T1LPlpvmJ0SZy0WJFEsV4kFbXcq2u68L4E6O0XeFj4aex9bEauqjW8UQBeAvfQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': resolution: {integrity: sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-WMW1yE6IOnehTcFE9eipFkm3XN63zypWlrJQ2iF7NrQ9b2LDRjumFoOGJE8RJJTJCTBAdmLMnJ8uVitACUUo1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2314,6 +2185,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': + resolution: {integrity: sha512-jfndI9tsfm4APzjNt6QdBkYwre5lRPUgHeDHoI7ydKUuJvz3lZeCfMsI56BZj+7BYqiKsJm7cfd/6KYV7ubrBg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2321,6 +2199,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-ZlFgw46NOAGMgcdvdYwAGu2Q+SLFA9LzbJLW+iyMOJyhj5wk6P3KEE9Gct4xWwSzFoPI7JCdYmYMzVtlgQ+zfw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2328,6 +2213,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-hIOYmuT6ofM4K04XAZd3OzMySEO4K0/nc9+jmNcxNAxRi6c5UWpqfw3KMFV4MVFWL+jQsSh+bGw2VqmaPMTLyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2335,6 +2227,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': + resolution: {integrity: sha512-qXBQQO9OvkjjQPLdUVr7Nr2t3QTZI7s4KZtfw7HzBgjbmAPSFwSv4rmET9lLSgq3rH/ndA3ngv3Qb8l2njoPNA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2342,6 +2241,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': + resolution: {integrity: sha512-/tpFfoSTzUkH9LPY+cYbqZBDyyX62w5fICq9qzsHLL8uTI6BHip3Q9Uzft0wylk/i8OOwKik8OxW+QAhDmzwmg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} engines: {node: ^20.19.0 || >=22.12.0} @@ -2349,29 +2255,55 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': + resolution: {integrity: sha512-mcp3Rio2w72IvdZG0oQ4bM2c2oumtwHfUfKncUM6zGgz0KgPz4YmDPQfnXEiY5t3+KD/i8HG2rOB/LxdmieK2g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11': + resolution: {integrity: sha512-LXk5Hii1Ph9asuGRjBuz8TUxdc1lWzB7nyfdoRgI0WGPZKmCxvlKk8KfYysqtr4MfGElu/f/pEQRh8fcEgkrWw==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': resolution: {integrity: sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==} engines: {node: '>=14.0.0'} cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-dDwf5otnx0XgRY1yqxOC4ITizcdzS/8cQ3goOWv3jFAo4F+xQYni+hnMuO6+LssHHdJW7+OCVL3CoU4ycnh35Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': resolution: {integrity: sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + resolution: {integrity: sha512-LN4/skhSggybX71ews7dAj6r2geaMJfm3kMbK2KhFMg9B10AZXnKoLCVVgzhMHL0S+aKtr4p8QbAW8k+w95bAA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': resolution: {integrity: sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@rolldown/pluginutils@1.0.0-rc.11': + resolution: {integrity: sha512-xQO9vbwBecJRv9EUcQ/y0dzSTJgA7Q6UVN7xp6B81+tBGSLVAK03yJ9NkJaUA7JFD91kbjxRSC/mDnmvXzbHoQ==} + '@rolldown/pluginutils@1.0.0-rc.12': resolution: {integrity: sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==} @@ -2384,141 +2316,141 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.60.1': - resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==} + '@rollup/rollup-android-arm-eabi@4.60.0': + resolution: {integrity: sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.60.1': - resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==} + '@rollup/rollup-android-arm64@4.60.0': + resolution: {integrity: sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.60.1': - resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==} + '@rollup/rollup-darwin-arm64@4.60.0': + resolution: {integrity: sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.60.1': - resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==} + '@rollup/rollup-darwin-x64@4.60.0': + resolution: {integrity: sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.60.1': - resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==} + '@rollup/rollup-freebsd-arm64@4.60.0': + resolution: {integrity: sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.60.1': - resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==} + '@rollup/rollup-freebsd-x64@4.60.0': + resolution: {integrity: sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': - resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==} + '@rollup/rollup-linux-arm-gnueabihf@4.60.0': + resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.60.1': - resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==} + '@rollup/rollup-linux-arm-musleabihf@4.60.0': + resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.60.1': - resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==} + '@rollup/rollup-linux-arm64-gnu@4.60.0': + resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.60.1': - resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==} + '@rollup/rollup-linux-arm64-musl@4.60.0': + resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.60.1': - resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==} + '@rollup/rollup-linux-loong64-gnu@4.60.0': + resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-loong64-musl@4.60.1': - resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==} + '@rollup/rollup-linux-loong64-musl@4.60.0': + resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==} cpu: [loong64] os: [linux] libc: [musl] - '@rollup/rollup-linux-ppc64-gnu@4.60.1': - resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==} + '@rollup/rollup-linux-ppc64-gnu@4.60.0': + resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.60.1': - resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==} + '@rollup/rollup-linux-ppc64-musl@4.60.0': + resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==} cpu: [ppc64] os: [linux] libc: [musl] - '@rollup/rollup-linux-riscv64-gnu@4.60.1': - resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==} + '@rollup/rollup-linux-riscv64-gnu@4.60.0': + resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.60.1': - resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==} + '@rollup/rollup-linux-riscv64-musl@4.60.0': + resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.60.1': - resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==} + '@rollup/rollup-linux-s390x-gnu@4.60.0': + resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.60.1': - resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==} + '@rollup/rollup-linux-x64-gnu@4.60.0': + resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.60.1': - resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==} + '@rollup/rollup-linux-x64-musl@4.60.0': + resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.60.1': - resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==} + '@rollup/rollup-openbsd-x64@4.60.0': + resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==} cpu: [x64] os: [openbsd] - '@rollup/rollup-openharmony-arm64@4.60.1': - resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==} + '@rollup/rollup-openharmony-arm64@4.60.0': + resolution: {integrity: sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.60.1': - resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==} + '@rollup/rollup-win32-arm64-msvc@4.60.0': + resolution: {integrity: sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.60.1': - resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==} + '@rollup/rollup-win32-ia32-msvc@4.60.0': + resolution: {integrity: sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.60.1': - resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==} + '@rollup/rollup-win32-x64-gnu@4.60.0': + resolution: {integrity: sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.60.1': - resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==} + '@rollup/rollup-win32-x64-msvc@4.60.0': + resolution: {integrity: sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==} cpu: [x64] os: [win32] @@ -2531,26 +2463,22 @@ packages: '@rss3/sdk@0.0.25': resolution: {integrity: sha512-jyXT4YTwefxxRZ0tt5xjbnw8e7zPg2OGdo/0xb+h/7qWnMNhLtWpc95DsYs/1C/I0rIyiDpZBhLI2DieQ9y+tw==} - '@scalar/client-side-rendering@0.1.0': - resolution: {integrity: sha512-SUuLgDmY1mUYOrGB2vpKj2HnYmPibKOewIV0gugv6k/qajE9R88uIj6u0DxAJVOLgihvKdMGyeXsnUs4fTLZYg==} - engines: {node: '>=22'} - - '@scalar/core@0.5.0': - resolution: {integrity: sha512-quPUndgBB1fwUkdIgJiCVA3vR6hyCgMYgca9YPI+RwbAB7/H/1otNEKfLBzLVbNllXlGnY4BxmGSft4fUg49jg==} + '@scalar/core@0.4.5': + resolution: {integrity: sha512-W+GN4oInzUWJzS2uwTQpRWl4uCOcnyXyu2zS05jApWUO5Pn7VSh9JSlqDz0nKVMaizWyjblJqocirlGo71pDPA==} engines: {node: '>=22'} - '@scalar/helpers@0.4.3': - resolution: {integrity: sha512-Gv2V7SFreLx3DltzF2lKXdaJSH5cP1LOyt9PxON1cSWGxkrs3sg93c1taEJsW24E9ckfYXkL5hjCAVLfAN3wQw==} + '@scalar/helpers@0.4.2': + resolution: {integrity: sha512-IrgrGVSahCfYDNWITazz4Q1BOndp5eEzlimRkfxiYn++KqeWyLfALyym1omqcdKGYtiSx1KIbKaUJL9vkjaN7w==} engines: {node: '>=22'} - '@scalar/hono-api-reference@0.10.7': - resolution: {integrity: sha512-OkOtpMYUchkgMwqJ8M0cgOg5SzMIR4uajhggCWqIZa6b2masLHmS15y2ervEDUZRp0UhEXQWbIJv+6eQJ7KG3g==} + '@scalar/hono-api-reference@0.10.5': + resolution: {integrity: sha512-1C8hww4d2DjEtIUNof9zY2jtQNJl1x22ynk6T4yQK3/hnv1EHBtf5c1VMQuTBerAukt1Q22fU2wjSQKhnUcI1Q==} engines: {node: '>=22'} peerDependencies: hono: ^4.12.5 - '@scalar/types@0.8.0': - resolution: {integrity: sha512-3GP0eqe+4XR8MyKOSCTly/VRobT3sKoFBX1ZSuuZAlcBROqzRkBSzQ+kloGWqTR60vP9GAwW7SnHo72MdCP0DQ==} + '@scalar/types@0.7.5': + resolution: {integrity: sha512-LUR/+nNpHfMbGCqTnrzyRlgRTC4FMyyqwCYCFYVs57gkEWzmXnrx+r3+igrWtuZoK/Hsr+ffFMzbBvmxnTFH7g==} engines: {node: '>=22'} '@scure/base@2.0.0': @@ -2562,18 +2490,17 @@ packages: '@selderee/plugin-htmlparser2@0.11.0': resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==} - '@sentry/core@10.48.0': - resolution: {integrity: sha512-h8F+fXVwYC9ro5ZaO8V+v3vqc0awlXHGblEAuVxSGgh4IV/oFX+QVzXeDTTrFOFS6v/Vn5vAyu240eJrJAS6/g==} + '@sentry/core@10.46.0': + resolution: {integrity: sha512-N3fj4zqBQOhXliS1Ne9euqIKuciHCGOJfPGQLwBoW9DNz03jF+NB8+dUKtrJ79YLoftjVgf8nbgwtADK7NR+2Q==} engines: {node: '>=18'} - '@sentry/node-core@10.48.0': - resolution: {integrity: sha512-D1TnPhN6vhrRqJ+bN+rdXDM+INibI6lNBm0eGx45zz7DBx9ouq2e9gm/DPx+y/hAkYYq0qTd6x84cGxtVZbKLw==} + '@sentry/node-core@10.46.0': + resolution: {integrity: sha512-gwLGXfkzmiCmUI1VWttyoZBaVp1ItpDKc8AV2mQblWPQGdLSD0c6uKV/FkU291yZA3rXsrLXVwcWoibwnjE2vw==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 '@opentelemetry/context-async-hooks': ^1.30.1 || ^2.1.0 '@opentelemetry/core': ^1.30.1 || ^2.1.0 - '@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1' '@opentelemetry/instrumentation': '>=0.57.1 <1' '@opentelemetry/resources': ^1.30.1 || ^2.1.0 '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 @@ -2585,8 +2512,6 @@ packages: optional: true '@opentelemetry/core': optional: true - '@opentelemetry/exporter-trace-otlp-http': - optional: true '@opentelemetry/instrumentation': optional: true '@opentelemetry/resources': @@ -2596,12 +2521,12 @@ packages: '@opentelemetry/semantic-conventions': optional: true - '@sentry/node@10.48.0': - resolution: {integrity: sha512-MzyLJyYmr0Qg60K6NJ2EdwJUX1OuAYXs9tyYxnqVO3nJ8MyYwIcuN4FCYEnXkG6Jiy/4q7OuZgXWnfdQJVcaqw==} + '@sentry/node@10.46.0': + resolution: {integrity: sha512-vF+7FrUXEtmYWuVcnvBjlWKeyLw/kwHpwnGj9oUmO/a2uKjDmUr53ZVcapggNxCjivavGYr9uHOY64AGdeUyzA==} engines: {node: '>=18'} - '@sentry/opentelemetry@10.48.0': - resolution: {integrity: sha512-Tn6Y0PZjRJ7OW8loK1ntK7wnJnIINnCfSpnwuqow0FMblaDmu5jDVOYq0U1SJBoBcMD5j9aSqrwyj6zqKwjc0A==} + '@sentry/opentelemetry@10.46.0': + resolution: {integrity: sha512-dzzV2ovruGsx9jzusGGr6cNPvMgYRu2BIrF8aMZ3rkQ1OpPJjPStqtA1l1fw0aoxHOxIjFU7ml4emF+xdmMl3g==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 @@ -2642,9 +2567,6 @@ packages: '@types/aes-js@3.1.4': resolution: {integrity: sha512-v3D66IptpUqh+pHKVNRxY8yvp2ESSZXe0rTzsGdzUhEwag7ljVfgCllkWv2YgiYXDhWFBrEywll4A5JToyTNFA==} - '@types/aws-lambda@8.10.161': - resolution: {integrity: sha512-rUYdp+MQwSFocxIOcSsYSF3YYYC/uUpMbCY/mbO21vGqfrEYvNSoPyKYDj6RhXXpPfS0KstW9RwG3qXh9sL7FQ==} - '@types/babel__preset-env@7.10.0': resolution: {integrity: sha512-LS8hRb/8TQir2f8W9/s5enDtrRS2F/6fsdkVw5ePHp6Q8SrSJHOGtWnP93ryaYMmg2du03vOsiGrl5mllz4uDA==} @@ -2654,9 +2576,6 @@ packages: '@types/bluebird@3.5.42': resolution: {integrity: sha512-Jhy+MWRlro6UjVi578V/4ZGNfeCOcNCp0YaFNIUGFKlImowqwb1O/22wDVk3FDGMLqxdpOV3qQHD5fPEH4hK6A==} - '@types/body-parser@1.19.6': - resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} - '@types/caseless@0.12.5': resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} @@ -2690,12 +2609,6 @@ packages: '@types/etag@1.8.4': resolution: {integrity: sha512-f1z/UMth8gQ6636NBqhFmJ3zES7EuDcUnV6K1gl1osHp+85KPKX+VixYWUpqLkw1fftCagyHJjJOZjZkEi2rHw==} - '@types/express-serve-static-core@5.1.1': - resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} - - '@types/express@5.0.6': - resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} - '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} @@ -2705,9 +2618,6 @@ packages: '@types/http-cache-semantics@4.2.0': resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} - '@types/http-errors@2.0.5': - resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - '@types/js-beautify@1.14.3': resolution: {integrity: sha512-FMbQHz+qd9DoGvgLHxeqqVPaNRffpIu5ZjozwV8hf9JAGpIOzuAf4wGbRSo8LNITHqGjmmVjaMggTT5P4v4IHg==} @@ -2753,8 +2663,8 @@ packages: '@types/mysql@2.15.27': resolution: {integrity: sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==} - '@types/node@25.6.0': - resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} '@types/pg-pool@2.0.7': resolution: {integrity: sha512-U4CwmGVQcbEuqpyju8/ptOKg6gEC+Tqsvj2xS9o1g71bUh8twxnC6ZL5rZKCsGN0iyH0CwgUyc9VR5owNQF9Ng==} @@ -2762,12 +2672,6 @@ packages: '@types/pg@8.15.6': resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} - '@types/qs@6.15.0': - resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} - - '@types/range-parser@1.2.7': - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/request-promise@4.1.51': resolution: {integrity: sha512-qVcP9Fuzh9oaAh8oPxiSoWMFGnWKkJDknnij66vi09Yiy62bsSDqtd+fG5kIM9wLLgZsRP3Y6acqj9O/v2ZtRw==} @@ -2777,12 +2681,6 @@ packages: '@types/sanitize-html@2.16.1': resolution: {integrity: sha512-n9wjs8bCOTyN/ynwD8s/nTcTreIHB1vf31vhLMGqUPNHaweKC4/fAl4Dj+hUlCTKYgm4P3k83fmiFfzkZ6sgMA==} - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - - '@types/serve-static@2.2.0': - resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} - '@types/statuses@2.0.6': resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} @@ -2801,67 +2699,63 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.58.1': - resolution: {integrity: sha512-eSkwoemjo76bdXl2MYqtxg51HNwUSkWfODUOQ3PaTLZGh9uIWWFZIjyjaJnex7wXDu+TRx+ATsnSxdN9YWfRTQ==} + '@typescript-eslint/eslint-plugin@8.57.2': + resolution: {integrity: sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.58.1 + '@typescript-eslint/parser': ^8.57.2 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.58.1': - resolution: {integrity: sha512-gGkiNMPqerb2cJSVcruigx9eHBlLG14fSdPdqMoOcBfh+vvn4iCq2C8MzUB89PrxOXk0y3GZ1yIWb9aOzL93bw==} + '@typescript-eslint/parser@8.57.2': + resolution: {integrity: sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.58.1': - resolution: {integrity: sha512-gfQ8fk6cxhtptek+/8ZIqw8YrRW5048Gug8Ts5IYcMLCw18iUgrZAEY/D7s4hkI0FxEfGakKuPK/XUMPzPxi5g==} + '@typescript-eslint/project-service@8.57.2': + resolution: {integrity: sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.58.1': - resolution: {integrity: sha512-TPYUEqJK6avLcEjumWsIuTpuYODTTDAtoMdt8ZZa93uWMTX13Nb8L5leSje1NluammvU+oI3QRr5lLXPgihX3w==} + '@typescript-eslint/scope-manager@8.57.2': + resolution: {integrity: sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.58.1': - resolution: {integrity: sha512-JAr2hOIct2Q+qk3G+8YFfqkqi7sC86uNryT+2i5HzMa2MPjw4qNFvtjnw1IiA1rP7QhNKVe21mSSLaSjwA1Olw==} + '@typescript-eslint/tsconfig-utils@8.57.2': + resolution: {integrity: sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.58.1': - resolution: {integrity: sha512-HUFxvTJVroT+0rXVJC7eD5zol6ID+Sn5npVPWoFuHGg9Ncq5Q4EYstqR+UOqaNRFXi5TYkpXXkLhoCHe3G0+7w==} + '@typescript-eslint/type-utils@8.57.2': + resolution: {integrity: sha512-Co6ZCShm6kIbAM/s+oYVpKFfW7LBc6FXoPXjTRQ449PPNBY8U0KZXuevz5IFuuUj2H9ss40atTaf9dlGLzbWZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.58.0': - resolution: {integrity: sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==} + '@typescript-eslint/types@8.57.2': + resolution: {integrity: sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.58.1': - resolution: {integrity: sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.58.1': - resolution: {integrity: sha512-w4w7WR7GHOjqqPnvAYbazq+Y5oS68b9CzasGtnd6jIeOIeKUzYzupGTB2T4LTPSv4d+WPeccbxuneTFHYgAAWg==} + '@typescript-eslint/typescript-estree@8.57.2': + resolution: {integrity: sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.58.1': - resolution: {integrity: sha512-Ln8R0tmWC7pTtLOzgJzYTXSCjJ9rDNHAqTaVONF4FEi2qwce8mD9iSOxOpLFFvWp/wBFlew0mjM1L1ihYWfBdQ==} + '@typescript-eslint/utils@8.57.2': + resolution: {integrity: sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.58.1': - resolution: {integrity: sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==} + '@typescript-eslint/visitor-keys@8.57.2': + resolution: {integrity: sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -3047,9 +2941,9 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - agent-base@9.0.0: - resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==} - engines: {node: '>= 20'} + agent-base@8.0.0: + resolution: {integrity: sha512-QT8i0hCz6C/KQ+KTAbSNwCHDGdmUJl2tp2ZpNlGSWCfhUNVbYG2WLE3MdZGBAgXPV4GAvjGMxo+C1hroyxmZEg==} + engines: {node: '>= 14'} ajv@6.14.0: resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} @@ -3154,8 +3048,8 @@ packages: bare-abort-controller: optional: true - bare-fs@4.7.0: - resolution: {integrity: sha512-xzqKsCFxAek9aezYhjJuJRXBIaYlg/0OGDTZp+T8eYmYMlm66cs6cYko02drIyjN2CBbi+I6L7YfXyqpqtKRXA==} + bare-fs@4.5.6: + resolution: {integrity: sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==} engines: {bare: '>=1.16.0'} peerDependencies: bare-buffer: '*' @@ -3163,15 +3057,15 @@ packages: bare-buffer: optional: true - bare-os@3.8.7: - resolution: {integrity: sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w==} + bare-os@3.8.0: + resolution: {integrity: sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==} engines: {bare: '>=1.14.0'} bare-path@3.0.0: resolution: {integrity: sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==} - bare-stream@2.12.0: - resolution: {integrity: sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g==} + bare-stream@2.11.0: + resolution: {integrity: sha512-Y/+iQ49fL3rIn6w/AVxI/2+BRrpmzJvdWt5Jv8Za6Ngqc6V227c+pYjYYgLdpR3MwQ9ObVXD0ZrqoBztakM0rw==} peerDependencies: bare-abort-controller: '*' bare-buffer: '*' @@ -3190,19 +3084,14 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.10.13: - resolution: {integrity: sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==} + baseline-browser-mapping@2.10.11: + resolution: {integrity: sha512-DAKrHphkJyiGuau/cFieRYhcTFeK/lBuD++C7cZ6KZHbMhBrisoi+EvhQ5RZrIfV5qwsW8kgQ07JIC+MDJRAhg==} engines: {node: '>=6.0.0'} hasBin: true basic-ftp@5.2.0: resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} engines: {node: '>=10.0.0'} - deprecated: Security vulnerability fixed in 5.2.1, please upgrade - - basic-ftp@5.2.2: - resolution: {integrity: sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==} - engines: {node: '>=10.0.0'} bcrypt-pbkdf@1.0.2: resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} @@ -3254,8 +3143,8 @@ packages: resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} engines: {node: 18 || 20 || >=22} - browserslist@4.28.2: - resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -3310,8 +3199,8 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001784: - resolution: {integrity: sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==} + caniuse-lite@1.0.30001781: + resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==} caseless@0.12.0: resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} @@ -3359,10 +3248,6 @@ packages: peerDependencies: devtools-protocol: '*' - chunk-data@0.1.0: - resolution: {integrity: sha512-zFyPtyC0SZ6Zu79b9sOYtXZcgrsXe0RpePrzRyj52hYVFG1+Rk6rBqjjOEk+GNQwc3PIX+86teQMok970pod1g==} - engines: {node: '>=20'} - ci-info@4.4.0: resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} @@ -3442,8 +3327,8 @@ packages: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - comment-parser@1.4.6: - resolution: {integrity: sha512-ObxuY6vnbWTN6Od72xfwN9DbzC7Y2vv8u1Soi9ahRKL37gb6y1qk6/dgjs+3JWuXJHWvsg3BXIwzd/rkmAwavg==} + comment-parser@1.4.5: + resolution: {integrity: sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==} engines: {node: '>= 12.0.0'} concat-map@0.0.1: @@ -3521,9 +3406,9 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} - data-uri-to-buffer@8.0.0: - resolution: {integrity: sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==} - engines: {node: '>= 20'} + data-uri-to-buffer@7.0.0: + resolution: {integrity: sha512-CuRUx0TXGSbbWdEci3VK/XOZGP3n0P4pIKpsqpVtBqaIIuj3GKK8H45oAqA4Rg8FHipc+CzRdUzmD4YQXxv66Q==} + engines: {node: '>= 14'} data-urls@7.0.0: resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} @@ -3597,11 +3482,11 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} - degenerator@7.0.1: - resolution: {integrity: sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==} - engines: {node: '>= 20'} + degenerator@6.0.0: + resolution: {integrity: sha512-j5MdXdefrecJeSqTpUrgZd4fBsD2IxZx0JlJD+n1Q7+aTf7/HcyXSfHsicPW6ekPurX159v1ZYla6OJgSPh2Dw==} + engines: {node: '>= 14'} peerDependencies: - quickjs-wasi: ^2.2.0 + quickjs-wasi: ^0.0.1 delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} @@ -3642,8 +3527,8 @@ packages: resolution: {tarball: https://codeload.github.com/postlight/difflib.js/tar.gz/32e8e38c7fcd935241b9baab71bb432fd9b166ed} version: 0.2.6 - discord-api-types@0.38.45: - resolution: {integrity: sha512-DiI01i00FPv6n+hXcFkFxK8Y/rFRpKs6U6aP32N4T73nTbj37Eua3H/95TBpLktLWB6xnLXhYDGvyLq6zzYY2w==} + discord-api-types@0.38.42: + resolution: {integrity: sha512-qs1kya7S84r5RR8m9kgttywGrmmoHaRifU1askAoi+wkoSefLpZP6aGXusjNw5b0jD3zOg3LTwUa3Tf2iHIceQ==} dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} @@ -3680,8 +3565,8 @@ packages: resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} engines: {node: '>=10'} - dotenv@17.4.1: - resolution: {integrity: sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==} + dotenv@17.3.1: + resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} dts-resolver@2.1.3: @@ -3707,8 +3592,8 @@ packages: engines: {node: '>=14'} hasBin: true - electron-to-chromium@1.5.330: - resolution: {integrity: sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA==} + electron-to-chromium@1.5.328: + resolution: {integrity: sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==} ellipsize@0.6.0: resolution: {integrity: sha512-oest45O39yGzIKJj3gJv/Gt6jtYN6PHw/IbCXHPEd2KwC0dgxKqXOhTU0EGwRXWhGKoBJk7eJQkb3sp8W0px2g==} @@ -3806,11 +3691,6 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.7: - resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} - engines: {node: '>=18'} - hasBin: true - escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -3888,13 +3768,13 @@ packages: peerDependencies: eslint: '>=8.23.0' - eslint-plugin-simple-import-sort@13.0.0: - resolution: {integrity: sha512-McAc+/Nlvcg4byY/CABGH8kqnefWBj8s3JA2okEtz8ixbECQgU46p0HkTUKa4YS7wvgGceimlc34p1nXqbWqtA==} + eslint-plugin-simple-import-sort@12.1.1: + resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} peerDependencies: eslint: '>=5.0.0' - eslint-plugin-unicorn@64.0.0: - resolution: {integrity: sha512-rNZwalHh8i0UfPlhNwg5BTUO1CMdKNmjqe+TgzOTZnpKoi8VBgsW7u9qCHIdpxEzZ1uwrJrPF0uRb7l//K38gA==} + eslint-plugin-unicorn@63.0.0: + resolution: {integrity: sha512-Iqecl9118uQEXYh7adylgEmGfkn5es3/mlQTLLkd4pXkIk9CTGrAbeUux+YljSa2ohXCBmQQ0+Ej1kZaFgcfkA==} engines: {node: ^20.10.0 || >=21.0.0} peerDependencies: eslint: '>=9.38.0' @@ -3921,8 +3801,8 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} - eslint@10.2.0: - resolution: {integrity: sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==} + eslint@10.1.0: + resolution: {integrity: sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} hasBin: true peerDependencies: @@ -4116,8 +3996,8 @@ packages: resolution: {integrity: sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==} engines: {node: '>=18'} - generative-bayesian-network@2.1.82: - resolution: {integrity: sha512-DH4NrmQheoMaJErdVv2IzaqkbOYSDQZmiZTV6UPDJYRDK2EyPpIQ88XRcYdPeFrUjS1N0Jj25H3HUywoJ1dbow==} + generative-bayesian-network@2.1.81: + resolution: {integrity: sha512-LrYK+CY5n21p437oahz8jRqTgw0i+S08H+ypag1sgZilfCj33k8Tp8kcFtPiWKsEEJ6niN9gRFP12+r06xB4rQ==} get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} @@ -4146,9 +4026,9 @@ packages: resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} engines: {node: '>= 14'} - get-uri@8.0.0: - resolution: {integrity: sha512-CqtZlMKvfJeY0Zxv8wazDwXmSKmnMnsmNy8j8+wudi8EyG/pMUB1NqHc+Tv1QaNtpYsK9nOYjb7r7Ufu32RPSw==} - engines: {node: '>= 20'} + get-uri@7.0.0: + resolution: {integrity: sha512-ZsC7KQxm1Hra8yO0RvMZ4lGJT7vnBtSNpEHKq39MPN7vjuvCiu1aQ8rkXUaIXG1y/TSDez97Gmv04ibnYqCp/A==} + engines: {node: '>= 14'} getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} @@ -4177,6 +4057,10 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + globals@17.4.0: resolution: {integrity: sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==} engines: {node: '>=18'} @@ -4207,10 +4091,6 @@ packages: resolution: {integrity: sha512-QLV1qeYSo5l13mQzWgP/y0LbMr5Plr5fJilgAIwgnwseproEbtNym8xpLsDzeZ6MWXgNE6kdWGBjdh3zT/Qerg==} engines: {node: '>=20'} - got@15.0.1: - resolution: {integrity: sha512-InYCBboAj9YmFiMcxbIRQ/WPoLsKSc9t9EGaUjGENtxunnx8USWtRY/SO/V3VsHLfDvUxAO2Qmx+6fQyG1jjaw==} - engines: {node: '>=22'} - graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -4235,8 +4115,8 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - header-generator@2.1.82: - resolution: {integrity: sha512-4NjPB0+bAKjPoponSmTOkK58IEF2W22sOJA5O48k/MxbCZgOm+jrU4WVR53Z2I6xFgIPkVrQmKtt1LAbWtfqXw==} + header-generator@2.1.81: + resolution: {integrity: sha512-6+27UuqCHFx4xrTWIgcSF/x2WJ+PuVLxziXfPaVLRXi1lXIbTkXO+ffHJefVrdRT5/XEeWfJHrSIE2m1hAdWxw==} engines: {node: '>=16.0.0'} headers-polyfill@4.0.3: @@ -4248,8 +4128,8 @@ packages: hmacsha1@1.0.0: resolution: {integrity: sha512-4FP6J0oI8jqb6gLLl9tSwVdosWJ/AKSGJ+HwYf6Ixe4MUcEkst4uWzpVQrNOCin0fzTRQbXV8ePheU8WiiDYBw==} - hono@4.12.12: - resolution: {integrity: sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==} + hono@4.12.8: + resolution: {integrity: sha512-VJCEvtrezO1IAR+kqEYnxUOoStaQPGrCmX3j4wDTNOcD1uRPFpGlwQUIW8niPuvHXaTUxeOUl5MMDGrl+tmO9A==} engines: {node: '>=16.9.0'} hookable@6.1.0: @@ -4292,9 +4172,9 @@ packages: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} - http-proxy-agent@9.0.0: - resolution: {integrity: sha512-FcF8VhXYLQcxWCnt/cCpT2apKsRDUGeVEeMqGu4HSTu29U8Yw0TLOjdYIlDsYk3IkUh+taX4IDWpPcCqKDhCjA==} - engines: {node: '>= 20'} + http-proxy-agent@8.0.0: + resolution: {integrity: sha512-7pose0uGgrCJeH2Qh4JcNhWZp3u/oNrWjNYDK4ydOLxOpTw8V8ogHFAmkz0VWq96JBFj4umVJpvmQi287rSYLg==} + engines: {node: '>= 14'} http-signature@1.2.0: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} @@ -4312,9 +4192,9 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} - https-proxy-agent@9.0.0: - resolution: {integrity: sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==} - engines: {node: '>= 20'} + https-proxy-agent@8.0.0: + resolution: {integrity: sha512-YYeW+iCnAS3xhvj2dvVoWgsbca3RfQy/IlaNHHOtDmU0jMqPI9euIq3Y9BJETdxk16h9NHHCKqp/KB9nIMStCQ==} + engines: {node: '>= 14'} human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} @@ -4349,8 +4229,8 @@ packages: engines: {node: '>=6.9.0'} hasBin: true - imapflow@1.3.1: - resolution: {integrity: sha512-DKwpMDR1EWXpV5T7adqQAccN7n684AX3poEZ5F3YoPlm2MyGeKavpRgNr3qptdEQaK+x5SlZ9jigT+cMs4geBA==} + imapflow@1.2.18: + resolution: {integrity: sha512-zxYvcG9ckj/UcTRs+ZDT+wJzW8DqkjgWZwc1z4Q28R/4C/1YvJieVETOuR/9ztCXcycURC50PJShMimITvz5wQ==} import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} @@ -4359,8 +4239,8 @@ packages: import-in-the-middle@2.0.6: resolution: {integrity: sha512-3vZV3jX0XRFW3EJDTwzWoZa+RH1b8eTTx6YOCjglrLyPuepwoBti1k3L2dKwdCUrnVEfc5CuRuGstaC/uQJJaw==} - import-in-the-middle@3.0.1: - resolution: {integrity: sha512-pYkiyXVL2Mf3pozdlDGV6NAObxQx13Ae8knZk1UJRJ6uRW/ZRmTGHlQYtrsSl7ubuE5F8CD1z+s1n4RHNuTtuA==} + import-in-the-middle@3.0.0: + resolution: {integrity: sha512-OnGy+eYT7wVejH2XWgLRgbmzujhhVIATQH0ztIeRilwHBjTeG3pD+XnH3PKX0r9gJ0BuJmJ68q/oh9qgXnNDQg==} engines: {node: '>=18'} import-without-cache@0.2.5: @@ -4546,8 +4426,8 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsdom@29.0.2: - resolution: {integrity: sha512-9VnGEBosc/ZpwyOsJBCQ/3I5p7Q5ngOY14a9bf5btenAORmZfDse1ZEheMiWcJ3h81+Fv7HmJFdS0szo/waF2w==} + jsdom@29.0.1: + resolution: {integrity: sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg==} engines: {node: ^20.19.0 || ^22.13.0 || >=24.0.0} peerDependencies: canvas: ^3.0.0 @@ -4570,9 +4450,6 @@ packages: json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-nd@1.0.0: - resolution: {integrity: sha512-8TIp0HZAY0VVrwRQJJPb4+nOTSPoOWZeEKBTLizUfQO4oym5Fc/MKqN8vEbLCxcyxDf2vwNxOQ1q84O49GWPyQ==} - json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} @@ -4642,9 +4519,6 @@ packages: libmime@5.3.7: resolution: {integrity: sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw==} - libmime@5.3.8: - resolution: {integrity: sha512-ZrCY+Q66mPvasAfjsQ/IgahzoBvfE1VdtGRpo1hwRB1oK3wJKxhKA3GOcd2a6j7AH5eMFccxK9fBoCpRZTf8ng==} - libqp@2.1.1: resolution: {integrity: sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow==} @@ -4698,15 +4572,11 @@ packages: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lowercase-keys@4.0.1: - resolution: {integrity: sha512-wI9Nui/L8VfADa/cr/7NQruaASk1k23/Uh1khQ02BCVYiiy8F4AhOGnQzJy3Fl/c44GnYSbZHv8g7EcG3kJ1Qg==} - engines: {node: '>=20'} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.3.3: - resolution: {integrity: sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ==} + lru-cache@11.2.7: + resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} engines: {node: 20 || >=22} lru-cache@7.18.3: @@ -4729,8 +4599,8 @@ packages: magicast@0.5.2: resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} - mailparser@3.9.8: - resolution: {integrity: sha512-7jSlFGXiianVnhnb6wdutJFloD34488nrHY7r6FNqwXAhZ7YiJDYrKKTxZJ0oSrXcAPHm8YoYnh97xyGtrBQ3w==} + mailparser@3.9.6: + resolution: {integrity: sha512-EJYTDWMrOS1kddK1mTsRkrx2Ngh2nYsg54SRMWVVWGVEGbHH4tod8tqqU9hIRPgGQVboSjFubDn9cboSitbM3Q==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -4865,13 +4735,13 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - miniflare@4.20260409.0: - resolution: {integrity: sha512-ayl6To4av0YuXsSivGgWLj+Ug8xZ0Qz3sGV8+Ok2LhNVl6m8m5ktEBM3LX9iT9MtLZRJwBlJrKcraNs/DlZQfA==} + miniflare@4.20260317.2: + resolution: {integrity: sha512-qNL+yWAFMX6fr0pWU6Lx1vNpPobpnDSF1V8eunIckWvoIQl8y1oBjL2RJFEGY3un+l3f9gwW9dirDPP26usYJQ==} engines: {node: '>=18.0.0'} hasBin: true - minimatch@10.2.5: - resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} minimatch@3.1.5: @@ -4907,8 +4777,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msw@2.13.2: - resolution: {integrity: sha512-go2H1TIERKkC48pXiwec5l6sbNqYuvqOk3/vHGo1Zd+pq/H63oFawDQerH+WQdUw/flJFHDG7F+QdWMwhntA/A==} + msw@2.12.14: + resolution: {integrity: sha512-4KXa4nVBIBjbDbd7vfQNuQ25eFxug0aropCQFoI0JdOBuJWamkT1yLVIWReFI8SiTRc+H1hKzaNk+cLk2N9rtQ==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -4953,10 +4823,6 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - netmask@2.1.1: - resolution: {integrity: sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==} - engines: {node: '>= 0.4.0'} - next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} @@ -4997,8 +4863,8 @@ packages: node-releases@2.0.36: resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} - nodemailer@8.0.5: - resolution: {integrity: sha512-0PF8Yb1yZuQfQbq+5/pZJrtF6WQcjTd5/S4JOHs9PGFxuTqoB/icwuB44pOdURHJbRKX1PPoJZtY7R4VUoCC8w==} + nodemailer@8.0.4: + resolution: {integrity: sha512-k+jf6N8PfQJ0Fe8ZhJlgqU5qJU44Lpvp2yvidH3vp1lPnVQMgi4yEEMPXg5eJS1gFIJTVq1NHBk7Ia9ARdSBdQ==} engines: {node: '>=6.0.0'} nopt@7.2.1: @@ -5087,25 +4953,21 @@ packages: resolution: {integrity: sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==} engines: {node: '>=12'} - oxfmt@0.44.0: - resolution: {integrity: sha512-lnncqvHewyRvaqdrnntVIrZV2tEddz8lbvPsQzG/zlkfvgZkwy0HP1p/2u1aCDToeg1jb9zBpbJdfkV73Itw+w==} + oxfmt@0.42.0: + resolution: {integrity: sha512-QhejGErLSMReNuZ6vxgFHDyGoPbjTRNi6uGHjy0cvIjOQFqD6xmr/T+3L41ixR3NIgzcNiJ6ylQKpvShTgDfqg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - oxlint-plugin-eslint@1.59.0: - resolution: {integrity: sha512-8es8JMwVyo8d8/f/xqOW1Xosvr25w8+6lZA8yB9d/Ipn6zogu2XBtQ+lBic6m8UNj7F8ak9BzjbOrB/JVSM3Sg==} - engines: {node: ^20.19.0 || >=22.12.0} - - oxlint-tsgolint@0.20.0: - resolution: {integrity: sha512-/Uc9TQyN1l8w9QNvXtVHYtz+SzDJHKpb5X0UnHodl0BVzijUPk0LPlDOHAvogd1UI+iy9ZSF6gQxEqfzUxCULQ==} + oxlint-tsgolint@0.17.4: + resolution: {integrity: sha512-4F/NXJiK2KnK4LQiULUPXRzVq0LOfextGvwCVRW1VKQbF5epI3MDMEGVAl5XjAGL6IFc7xBc/eVA95wczPeEQg==} hasBin: true - oxlint@1.59.0: - resolution: {integrity: sha512-0xBLeGGjP4vD9pygRo8iuOkOzEU1MqOnfiOl7KYezL/QvWL8NUg6n03zXc7ZVqltiOpUxBk2zgHI3PnRIEdAvw==} + oxlint@1.57.0: + resolution: {integrity: sha512-DGFsuBX5MFZX9yiDdtKjTrYPq45CZ8Fft6qCltJITYZxfwYjVdGf/6wycGYTACloauwIPxUnYhBVeZbHvleGhw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - oxlint-tsgolint: '>=0.18.0' + oxlint-tsgolint: '>=0.15.0' peerDependenciesMeta: oxlint-tsgolint: optional: true @@ -5130,19 +4992,19 @@ packages: resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} engines: {node: '>= 14'} - pac-proxy-agent@9.0.1: - resolution: {integrity: sha512-3ZOSpLboOlpW4yp8Cuv21KlTULRqyJ5Uuad3wXpSKFrxdNgcHEyoa22GRaZ2UlgCVuR6z+5BiavtYVvbajL/Yw==} - engines: {node: '>= 20'} + pac-proxy-agent@8.0.0: + resolution: {integrity: sha512-HyCoVbyQ/nbVlQ/R6wBu0YXhbG2oAnEK5BQ3xMyj1OffQmU5NoOnpLzgPlKHaobUzz5NK0+AZHby4TdydAEBUA==} + engines: {node: '>= 14'} pac-resolver@7.0.1: resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} engines: {node: '>= 14'} - pac-resolver@9.0.1: - resolution: {integrity: sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==} - engines: {node: '>= 20'} + pac-resolver@8.0.0: + resolution: {integrity: sha512-SVNzOxVq2zuTew3WAt7U8UghwzJzuWYuJryd3y8FxyLTZdjVoCzY8kLP39PpEqQCDvlMWdQXwViu0sYT3eiU2w==} + engines: {node: '>= 14'} peerDependencies: - quickjs-wasi: ^2.2.0 + quickjs-wasi: ^0.0.1 package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -5367,17 +5229,17 @@ packages: resolution: {integrity: sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==} engines: {node: '>=12'} - quickjs-wasi@2.2.0: - resolution: {integrity: sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==} + quickjs-wasi@0.0.1: + resolution: {integrity: sha512-fBWNLTBkxkLAhe1AzF1hyXEvuA+N+vV1WMP2D6iiMUblvmOt8Pp5t8zUcgvz7aYA1ldUdxDlgUse15dmcKjkNg==} ramda@0.32.0: resolution: {integrity: sha512-GQWAHhxhxWBWA8oIBr1XahFVjQ9Fic6MK9ikijfd4TZHfE2+urfk+irVlR5VOn48uwMgM+loRRBJd6Yjsbc0zQ==} - rate-limiter-flexible@11.0.0: - resolution: {integrity: sha512-UhN3xVeU6Az3y6hAuxMUwFsKcKD1HffhMGK0MknbSxH9vkwslS/p19ovCvJqIVT97pE778nKu2sUgYAcxj4dmQ==} + rate-limiter-flexible@10.0.1: + resolution: {integrity: sha512-3G6GMFz5Oz5nVnDv9gQ1LLMdExR4B1lOjogPIjehtgyxPMIkY09BGyk2eCYt36/OkV/0t12GEt6J6HpTl6RzZg==} - re2js@2.0.1: - resolution: {integrity: sha512-X59sWAF3UaMKfsVZT5/kJk1kBK10artA4jxScW4dPYtIuyDAWITcTDgkgEf9GPaqCKMVPgL2oEJGib9jN4WnkQ==} + re2js@1.2.3: + resolution: {integrity: sha512-M2/7k8LkP+LmB/muGZXvAHiwhgwqq0Ign2UHCZkea39nHOakeixyMSfb7rql7N/6u5PTS+IpP2MKfRLJ4fed0g==} readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} @@ -5498,14 +5360,14 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rolldown-plugin-dts@0.23.2: - resolution: {integrity: sha512-PbSqLawLgZBGcOGT3yqWBGn4cX+wh2nt5FuBGdcMHyOhoukmjbhYAl8NT9sE4U38Cm9tqLOIQeOrvzeayM0DLQ==} + rolldown-plugin-dts@0.22.5: + resolution: {integrity: sha512-M/HXfM4cboo+jONx9Z0X+CUf3B5tCi7ni+kR5fUW50Fp9AlZk0oVLesibGWgCXDKFp5lpgQ9yhKoImUFjl3VZw==} engines: {node: '>=20.19.0'} peerDependencies: '@ts-macro/tsc': ^0.3.6 - '@typescript/native-preview': '>=7.0.0-dev.20260325.1' - rolldown: ^1.0.0-rc.12 - typescript: ^5.0.0 || ^6.0.0 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-rc.3 + typescript: ^5.0.0 || ^6.0.0-beta vue-tsc: ~3.2.0 peerDependenciesMeta: '@ts-macro/tsc': @@ -5517,13 +5379,18 @@ packages: vue-tsc: optional: true + rolldown@1.0.0-rc.11: + resolution: {integrity: sha512-NRjoKMusSjfRbSYiH3VSumlkgFe7kYAa3pzVOsVYVFY3zb5d7nS+a3KGQ7hJKXuYWbzJKPVQ9Wxq2UvyK+ENpw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rolldown@1.0.0-rc.12: resolution: {integrity: sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - rollup@4.60.1: - resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==} + rollup@4.60.0: + resolution: {integrity: sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -5602,14 +5469,14 @@ packages: resolution: {integrity: sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==} engines: {node: '>=8'} - socks-proxy-agent@10.0.0: - resolution: {integrity: sha512-pyp2YR3mNxAMu0mGLtzs4g7O3uT4/9sQOLAKcViAkaS9fJWkud7nmaf6ZREFqQEi24IPkBcjfHjXhPTUWjo3uA==} - engines: {node: '>= 20'} - socks-proxy-agent@8.0.5: resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} engines: {node: '>= 14'} + socks-proxy-agent@9.0.0: + resolution: {integrity: sha512-fFlbMlfsXhK02ZB8aZY7Hwxh/IHBV9b1Oq9bvBk6tkFWXvdAxUgA0wbw/NYR5liU3Y5+KI6U4FH3kYJt9QYv0w==} + engines: {node: '>= 14'} + socks@2.8.7: resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} @@ -5652,10 +5519,6 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - stacktrace-parser@0.1.11: - resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} - engines: {node: '>=6'} - standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} @@ -5812,10 +5675,6 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinyglobby@0.2.16: - resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} - engines: {node: '>=12.0.0'} - tinypool@2.1.0: resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} engines: {node: ^20.0.0 || >=22.0.0} @@ -5832,11 +5691,11 @@ packages: resolution: {integrity: sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA==} hasBin: true - tldts-core@7.0.28: - resolution: {integrity: sha512-7W5Efjhsc3chVdFhqtaU0KtK32J37Zcr9RKtID54nG+tIpcY79CQK/veYPODxtD/LJ4Lue66jvrQzIX2Z2/pUQ==} + tldts-core@7.0.27: + resolution: {integrity: sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==} - tldts@7.0.28: - resolution: {integrity: sha512-+Zg3vWhRUv8B1maGSTFdev9mjoo8Etn2Ayfs4cnjlD3CsGkxXX4QyW3j2WJ0wdjYcYmy7Lx2RDsZMhgCWafKIw==} + tldts@7.0.27: + resolution: {integrity: sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==} hasBin: true to-no-case@1.0.2: @@ -5914,14 +5773,14 @@ packages: typescript: optional: true - tsdown@0.21.7: - resolution: {integrity: sha512-ukKIxKQzngkWvOYJAyptudclkm4VQqbjq+9HF5K5qDO8GJsYtMh8gIRwicbnZEnvFPr6mquFwYAVZ8JKt3rY2g==} + tsdown@0.21.5: + resolution: {integrity: sha512-TlgNhfPioAD6ECCUnZsxcUsXXuPPR4Rrxz3az741kL/M3oGIET4a9GajSNRNRx+jIva73TYUKQybrEPkDYN+fQ==} engines: {node: '>=20.19.0'} hasBin: true peerDependencies: '@arethetypeswrong/core': ^0.18.1 - '@tsdown/css': 0.21.7 - '@tsdown/exe': 0.21.7 + '@tsdown/css': 0.21.5 + '@tsdown/exe': 0.21.5 '@vitejs/devtools': '*' publint: ^0.3.0 typescript: ^5.0.0 || ^6.0.0 @@ -5973,10 +5832,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - type-fest@3.13.1: resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} engines: {node: '>=14.16'} @@ -6009,10 +5864,6 @@ packages: ufo@1.6.3: resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} - uint8array-extras@1.5.0: - resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} - engines: {node: '>=18'} - ultron@1.0.2: resolution: {integrity: sha512-QMpnpVtYaWEeY+MwKDN/UdKlE/LsFZXM5lO1u7GaZzNgmIbGixHEmVMIKT+vqYOALu3m5GYQy9kz4Xu4IVn7Ow==} @@ -6022,8 +5873,8 @@ packages: unconfig-core@7.5.0: resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} - undici-types@7.19.2: - resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} @@ -6036,8 +5887,8 @@ packages: resolution: {integrity: sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==} engines: {node: '>=20.18.1'} - undici@7.24.7: - resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} + undici@7.24.6: + resolution: {integrity: sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==} engines: {node: '>=20.18.1'} unenv@2.0.0-rc.24: @@ -6284,17 +6135,17 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - workerd@1.20260409.1: - resolution: {integrity: sha512-kuWP20fAaqaLBqLbvUfY9nCF6c3C78L60G9lS6eVwBf+v8trVFIsAdLB/FtrnKm7vgVvpDzvFAfB80VIiVj95w==} + workerd@1.20260317.1: + resolution: {integrity: sha512-ZuEq1OdrJBS+NV+L5HMYPCzVn49a2O60slQiiLpG44jqtlOo+S167fWC76kEXteXLLLydeuRrluRel7WdOUa4g==} engines: {node: '>=16'} hasBin: true - wrangler@4.81.1: - resolution: {integrity: sha512-fppPXi+W2KJ5bx1zxdUYe1e7CHj5cWPFVBPXy8hSMZhrHeIojMe3ozAktAOw1voVuQjXzbZJf/GVKyVeSjbF8w==} + wrangler@4.77.0: + resolution: {integrity: sha512-E2Gm69+K++BFd3QvoWjC290RPQj1vDOUotA++sNHmtKPb7EP6C8Qv+1D5Ii73tfZtyNgakpqHlh8lBBbVWTKAQ==} engines: {node: '>=20.3.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20260409.1 + '@cloudflare/workers-types': ^4.20260317.1 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -6458,7 +6309,7 @@ snapshots: dependencies: '@actions/io': 3.0.2 - '@actions/github@9.1.0': + '@actions/github@9.0.0': dependencies: '@actions/http-client': 3.0.2 '@octokit/core': 7.0.6 @@ -6480,19 +6331,21 @@ snapshots: '@actions/io@3.0.2': {} - '@asamuzakjp/css-color@5.1.6': + '@asamuzakjp/css-color@5.0.1': dependencies: '@csstools/css-calc': 3.1.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-color-parser': 4.0.2(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.2.7 - '@asamuzakjp/dom-selector@7.0.7': + '@asamuzakjp/dom-selector@7.0.4': dependencies: '@asamuzakjp/nwsapi': 2.3.9 bidi-js: 1.0.3 css-tree: 3.2.1 is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.7 '@asamuzakjp/nwsapi@2.3.9': {} @@ -6507,10 +6360,10 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/generator@8.0.0-rc.3': + '@babel/generator@8.0.0-rc.2': dependencies: - '@babel/parser': 8.0.0-rc.3 - '@babel/types': 8.0.0-rc.3 + '@babel/parser': 8.0.0-rc.2 + '@babel/types': 8.0.0-rc.2 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 '@types/jsesc': 2.5.1 @@ -6522,15 +6375,15 @@ snapshots: '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@8.0.0-rc.3': {} + '@babel/helper-validator-identifier@8.0.0-rc.2': {} '@babel/parser@7.29.2': dependencies: '@babel/types': 7.29.0 - '@babel/parser@8.0.0-rc.3': + '@babel/parser@8.0.0-rc.2': dependencies: - '@babel/types': 8.0.0-rc.3 + '@babel/types': 8.0.0-rc.2 '@babel/runtime-corejs2@7.29.2': dependencies: @@ -6541,10 +6394,10 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@8.0.0-rc.3': + '@babel/types@8.0.0-rc.2': dependencies: '@babel/helper-string-parser': 8.0.0-rc.3 - '@babel/helper-validator-identifier': 8.0.0-rc.3 + '@babel/helper-validator-identifier': 8.0.0-rc.2 '@bbob/core@4.3.1': dependencies: @@ -6588,11 +6441,11 @@ snapshots: '@bufbuild/protobuf@2.11.0': {} - '@cloudflare/containers@0.3.0': {} + '@cloudflare/containers@0.2.0': {} '@cloudflare/kv-asset-handler@0.4.2': {} - '@cloudflare/puppeteer@1.0.7(bufferutil@4.1.0)(utf-8-validate@5.0.10)': + '@cloudflare/puppeteer@1.0.6(bufferutil@4.1.0)(utf-8-validate@5.0.10)': dependencies: '@puppeteer/browsers': 2.2.4 debug: 4.4.3 @@ -6606,28 +6459,28 @@ snapshots: - supports-color - utf-8-validate - '@cloudflare/unenv-preset@2.16.0(unenv@2.0.0-rc.24)(workerd@1.20260409.1)': + '@cloudflare/unenv-preset@2.16.0(unenv@2.0.0-rc.24)(workerd@1.20260317.1)': dependencies: unenv: 2.0.0-rc.24 optionalDependencies: - workerd: 1.20260409.1 + workerd: 1.20260317.1 - '@cloudflare/workerd-darwin-64@1.20260409.1': + '@cloudflare/workerd-darwin-64@1.20260317.1': optional: true - '@cloudflare/workerd-darwin-arm64@1.20260409.1': + '@cloudflare/workerd-darwin-arm64@1.20260317.1': optional: true - '@cloudflare/workerd-linux-64@1.20260409.1': + '@cloudflare/workerd-linux-64@1.20260317.1': optional: true - '@cloudflare/workerd-linux-arm64@1.20260409.1': + '@cloudflare/workerd-linux-arm64@1.20260317.1': optional: true - '@cloudflare/workerd-windows-64@1.20260409.1': + '@cloudflare/workerd-windows-64@1.20260317.1': optional: true - '@cloudflare/workers-types@4.20260410.1': {} + '@cloudflare/workers-types@4.20260317.1': {} '@colors/colors@1.6.0': {} @@ -6686,11 +6539,6 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.9.2': - dependencies: - tslib: 2.8.1 - optional: true - '@emnapi/wasi-threads@1.2.0': dependencies: tslib: 2.8.1 @@ -6704,261 +6552,179 @@ snapshots: '@esbuild/aix-ppc64@0.27.4': optional: true - '@esbuild/aix-ppc64@0.27.7': - optional: true - '@esbuild/android-arm64@0.27.3': optional: true '@esbuild/android-arm64@0.27.4': optional: true - '@esbuild/android-arm64@0.27.7': - optional: true - '@esbuild/android-arm@0.27.3': optional: true '@esbuild/android-arm@0.27.4': optional: true - '@esbuild/android-arm@0.27.7': - optional: true - '@esbuild/android-x64@0.27.3': optional: true '@esbuild/android-x64@0.27.4': optional: true - '@esbuild/android-x64@0.27.7': - optional: true - '@esbuild/darwin-arm64@0.27.3': optional: true '@esbuild/darwin-arm64@0.27.4': optional: true - '@esbuild/darwin-arm64@0.27.7': - optional: true - '@esbuild/darwin-x64@0.27.3': optional: true '@esbuild/darwin-x64@0.27.4': optional: true - '@esbuild/darwin-x64@0.27.7': - optional: true - '@esbuild/freebsd-arm64@0.27.3': optional: true '@esbuild/freebsd-arm64@0.27.4': optional: true - '@esbuild/freebsd-arm64@0.27.7': - optional: true - '@esbuild/freebsd-x64@0.27.3': optional: true '@esbuild/freebsd-x64@0.27.4': optional: true - '@esbuild/freebsd-x64@0.27.7': - optional: true - '@esbuild/linux-arm64@0.27.3': optional: true '@esbuild/linux-arm64@0.27.4': optional: true - '@esbuild/linux-arm64@0.27.7': - optional: true - '@esbuild/linux-arm@0.27.3': optional: true '@esbuild/linux-arm@0.27.4': optional: true - '@esbuild/linux-arm@0.27.7': - optional: true - '@esbuild/linux-ia32@0.27.3': optional: true '@esbuild/linux-ia32@0.27.4': optional: true - '@esbuild/linux-ia32@0.27.7': - optional: true - '@esbuild/linux-loong64@0.27.3': optional: true '@esbuild/linux-loong64@0.27.4': optional: true - '@esbuild/linux-loong64@0.27.7': - optional: true - '@esbuild/linux-mips64el@0.27.3': optional: true '@esbuild/linux-mips64el@0.27.4': optional: true - '@esbuild/linux-mips64el@0.27.7': - optional: true - '@esbuild/linux-ppc64@0.27.3': optional: true '@esbuild/linux-ppc64@0.27.4': optional: true - '@esbuild/linux-ppc64@0.27.7': - optional: true - '@esbuild/linux-riscv64@0.27.3': optional: true '@esbuild/linux-riscv64@0.27.4': optional: true - '@esbuild/linux-riscv64@0.27.7': - optional: true - '@esbuild/linux-s390x@0.27.3': optional: true '@esbuild/linux-s390x@0.27.4': optional: true - '@esbuild/linux-s390x@0.27.7': - optional: true - '@esbuild/linux-x64@0.27.3': optional: true '@esbuild/linux-x64@0.27.4': optional: true - '@esbuild/linux-x64@0.27.7': - optional: true - '@esbuild/netbsd-arm64@0.27.3': optional: true '@esbuild/netbsd-arm64@0.27.4': optional: true - '@esbuild/netbsd-arm64@0.27.7': - optional: true - '@esbuild/netbsd-x64@0.27.3': optional: true '@esbuild/netbsd-x64@0.27.4': optional: true - '@esbuild/netbsd-x64@0.27.7': - optional: true - '@esbuild/openbsd-arm64@0.27.3': optional: true '@esbuild/openbsd-arm64@0.27.4': optional: true - '@esbuild/openbsd-arm64@0.27.7': - optional: true - '@esbuild/openbsd-x64@0.27.3': optional: true '@esbuild/openbsd-x64@0.27.4': optional: true - '@esbuild/openbsd-x64@0.27.7': - optional: true - '@esbuild/openharmony-arm64@0.27.3': optional: true '@esbuild/openharmony-arm64@0.27.4': optional: true - '@esbuild/openharmony-arm64@0.27.7': - optional: true - '@esbuild/sunos-x64@0.27.3': optional: true '@esbuild/sunos-x64@0.27.4': optional: true - '@esbuild/sunos-x64@0.27.7': - optional: true - '@esbuild/win32-arm64@0.27.3': optional: true '@esbuild/win32-arm64@0.27.4': optional: true - '@esbuild/win32-arm64@0.27.7': - optional: true - '@esbuild/win32-ia32@0.27.3': optional: true '@esbuild/win32-ia32@0.27.4': optional: true - '@esbuild/win32-ia32@0.27.7': - optional: true - '@esbuild/win32-x64@0.27.3': optional: true '@esbuild/win32-x64@0.27.4': optional: true - '@esbuild/win32-x64@0.27.7': - optional: true - - '@eslint-community/eslint-utils@4.9.1(eslint@10.2.0(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.1(eslint@10.1.0(jiti@2.6.1))': dependencies: - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint/config-array@0.23.4': + '@eslint/config-array@0.23.3': dependencies: - '@eslint/object-schema': 3.0.4 + '@eslint/object-schema': 3.0.3 debug: 4.4.3 - minimatch: 10.2.5 + minimatch: 10.2.4 transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.5.4': + '@eslint/config-helpers@0.5.3': dependencies: - '@eslint/core': 1.2.0 + '@eslint/core': 1.1.1 '@eslint/core@1.1.1': dependencies: '@types/json-schema': 7.0.15 - '@eslint/core@1.2.0': - dependencies: - '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.5': dependencies: ajv: 6.14.0 @@ -6973,62 +6739,46 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@10.0.1(eslint@10.2.0(jiti@2.6.1))': + '@eslint/js@10.0.1(eslint@10.1.0(jiti@2.6.1))': optionalDependencies: - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) - '@eslint/object-schema@3.0.4': {} + '@eslint/object-schema@3.0.3': {} '@eslint/plugin-kit@0.6.1': dependencies: '@eslint/core': 1.1.1 levn: 0.4.1 - '@eslint/plugin-kit@0.7.0': - dependencies: - '@eslint/core': 1.2.0 - levn: 0.4.1 - '@exodus/bytes@1.15.0(@noble/hashes@2.0.1)': optionalDependencies: '@noble/hashes': 2.0.1 - '@fastify/otel@0.18.0(@opentelemetry/api@1.9.1)': + '@fastify/otel@0.17.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/instrumentation': 0.212.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 - minimatch: 10.2.5 + minimatch: 10.2.4 transitivePeerDependencies: - supports-color - '@honeybadger-io/core@6.7.2': - dependencies: - json-nd: 1.0.0 - stacktrace-parser: 0.1.11 - - '@honeybadger-io/js@6.12.3': - dependencies: - '@honeybadger-io/core': 6.7.2 - '@types/aws-lambda': 8.10.161 - '@types/express': 5.0.6 - - '@hono/node-server@1.19.13(hono@4.12.12)': + '@hono/node-server@1.19.11(hono@4.12.8)': dependencies: - hono: 4.12.12 + hono: 4.12.8 - '@hono/zod-openapi@1.2.4(hono@4.12.12)(zod@4.3.6)': + '@hono/zod-openapi@1.2.3(hono@4.12.8)(zod@4.3.6)': dependencies: '@asteasolutions/zod-to-openapi': 8.5.0(zod@4.3.6) - '@hono/zod-validator': 0.7.6(hono@4.12.12)(zod@4.3.6) - hono: 4.12.12 + '@hono/zod-validator': 0.7.6(hono@4.12.8)(zod@4.3.6) + hono: 4.12.8 openapi3-ts: 4.5.0 zod: 4.3.6 - '@hono/zod-validator@0.7.6(hono@4.12.12)(zod@4.3.6)': + '@hono/zod-validator@0.7.6(hono@4.12.8)(zod@4.3.6)': dependencies: - hono: 4.12.12 + hono: 4.12.8 zod: 4.3.6 '@humanfs/core@0.19.1': {} @@ -7126,7 +6876,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.9.2 + '@emnapi/runtime': 1.9.1 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -7140,51 +6890,51 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@25.6.0)': + '@inquirer/checkbox@4.3.2(@types/node@25.5.0)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.6.0) + '@inquirer/core': 10.3.2(@types/node@25.5.0) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.6.0) + '@inquirer/type': 3.0.10(@types/node@25.5.0) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 - '@inquirer/confirm@5.1.21(@types/node@25.6.0)': + '@inquirer/confirm@5.1.21(@types/node@25.5.0)': dependencies: - '@inquirer/core': 10.3.2(@types/node@25.6.0) - '@inquirer/type': 3.0.10(@types/node@25.6.0) + '@inquirer/core': 10.3.2(@types/node@25.5.0) + '@inquirer/type': 3.0.10(@types/node@25.5.0) optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 - '@inquirer/core@10.3.2(@types/node@25.6.0)': + '@inquirer/core@10.3.2(@types/node@25.5.0)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.6.0) + '@inquirer/type': 3.0.10(@types/node@25.5.0) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@inquirer/figures@1.0.15': {} - '@inquirer/select@4.4.2(@types/node@25.6.0)': + '@inquirer/select@4.4.2(@types/node@25.5.0)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@25.6.0) + '@inquirer/core': 10.3.2(@types/node@25.5.0) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@25.6.0) + '@inquirer/type': 3.0.10(@types/node@25.5.0) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 - '@inquirer/type@3.0.10(@types/node@25.6.0)': + '@inquirer/type@3.0.10(@types/node@25.5.0)': optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@ioredis/commands@1.5.1': {} @@ -7279,10 +7029,10 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@napi-rs/wasm-runtime@1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)': + '@napi-rs/wasm-runtime@1.1.1': dependencies: '@emnapi/core': 1.9.1 - '@emnapi/runtime': 1.9.2 + '@emnapi/runtime': 1.9.1 '@tybys/wasm-util': 0.10.1 optional: true @@ -7301,7 +7051,7 @@ snapshots: '@nolyfill/side-channel@1.0.44': {} - '@notionhq/client@5.17.0': {} + '@notionhq/client@5.15.0': {} '@octokit/auth-token@6.0.0': {} @@ -7374,6 +7124,10 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs@0.213.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs@0.214.0': dependencies: '@opentelemetry/api': 1.9.1 @@ -7384,6 +7138,11 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.1 + '@opentelemetry/core@2.6.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -7406,154 +7165,163 @@ snapshots: '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-amqplib@0.61.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-amqplib@0.60.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-connect@0.57.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-connect@0.56.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 '@types/connect': 3.4.38 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-dataloader@0.31.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-dataloader@0.30.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-fs@0.33.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-express@0.61.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-generic-pool@0.57.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-fs@0.32.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-graphql@0.62.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-generic-pool@0.56.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-hapi@0.60.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-graphql@0.61.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-hapi@0.59.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-http@0.214.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-http@0.213.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 forwarded-parse: 2.1.2 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-ioredis@0.62.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-ioredis@0.61.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/redis-common': 0.38.2 '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-kafkajs@0.23.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-kafkajs@0.22.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-knex@0.58.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-knex@0.57.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-koa@0.62.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-koa@0.61.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-lru-memoizer@0.58.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-lru-memoizer@0.57.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongodb@0.67.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-mongodb@0.66.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongoose@0.60.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-mongoose@0.59.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql2@0.60.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-mysql2@0.59.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql@0.60.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-mysql@0.59.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 '@types/mysql': 2.15.27 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pg@0.66.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-pg@0.65.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 '@opentelemetry/sql-common': 0.41.2(@opentelemetry/api@1.9.1) '@types/pg': 8.15.6 @@ -7561,29 +7329,29 @@ snapshots: transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-redis@0.62.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-redis@0.61.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/redis-common': 0.38.2 '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-tedious@0.33.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-tedious@0.32.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 '@types/tedious': 4.0.14 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-undici@0.24.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation-undici@0.23.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 transitivePeerDependencies: - supports-color @@ -7606,11 +7374,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1)': + '@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 - '@opentelemetry/api-logs': 0.214.0 - import-in-the-middle: 3.0.1 + '@opentelemetry/api-logs': 0.213.0 + import-in-the-middle: 3.0.0 require-in-the-middle: 8.0.1 transitivePeerDependencies: - supports-color @@ -7699,139 +7467,139 @@ snapshots: '@oxc-project/types@0.122.0': {} - '@oxfmt/binding-android-arm-eabi@0.44.0': + '@oxfmt/binding-android-arm-eabi@0.42.0': optional: true - '@oxfmt/binding-android-arm64@0.44.0': + '@oxfmt/binding-android-arm64@0.42.0': optional: true - '@oxfmt/binding-darwin-arm64@0.44.0': + '@oxfmt/binding-darwin-arm64@0.42.0': optional: true - '@oxfmt/binding-darwin-x64@0.44.0': + '@oxfmt/binding-darwin-x64@0.42.0': optional: true - '@oxfmt/binding-freebsd-x64@0.44.0': + '@oxfmt/binding-freebsd-x64@0.42.0': optional: true - '@oxfmt/binding-linux-arm-gnueabihf@0.44.0': + '@oxfmt/binding-linux-arm-gnueabihf@0.42.0': optional: true - '@oxfmt/binding-linux-arm-musleabihf@0.44.0': + '@oxfmt/binding-linux-arm-musleabihf@0.42.0': optional: true - '@oxfmt/binding-linux-arm64-gnu@0.44.0': + '@oxfmt/binding-linux-arm64-gnu@0.42.0': optional: true - '@oxfmt/binding-linux-arm64-musl@0.44.0': + '@oxfmt/binding-linux-arm64-musl@0.42.0': optional: true - '@oxfmt/binding-linux-ppc64-gnu@0.44.0': + '@oxfmt/binding-linux-ppc64-gnu@0.42.0': optional: true - '@oxfmt/binding-linux-riscv64-gnu@0.44.0': + '@oxfmt/binding-linux-riscv64-gnu@0.42.0': optional: true - '@oxfmt/binding-linux-riscv64-musl@0.44.0': + '@oxfmt/binding-linux-riscv64-musl@0.42.0': optional: true - '@oxfmt/binding-linux-s390x-gnu@0.44.0': + '@oxfmt/binding-linux-s390x-gnu@0.42.0': optional: true - '@oxfmt/binding-linux-x64-gnu@0.44.0': + '@oxfmt/binding-linux-x64-gnu@0.42.0': optional: true - '@oxfmt/binding-linux-x64-musl@0.44.0': + '@oxfmt/binding-linux-x64-musl@0.42.0': optional: true - '@oxfmt/binding-openharmony-arm64@0.44.0': + '@oxfmt/binding-openharmony-arm64@0.42.0': optional: true - '@oxfmt/binding-win32-arm64-msvc@0.44.0': + '@oxfmt/binding-win32-arm64-msvc@0.42.0': optional: true - '@oxfmt/binding-win32-ia32-msvc@0.44.0': + '@oxfmt/binding-win32-ia32-msvc@0.42.0': optional: true - '@oxfmt/binding-win32-x64-msvc@0.44.0': + '@oxfmt/binding-win32-x64-msvc@0.42.0': optional: true - '@oxlint-tsgolint/darwin-arm64@0.20.0': + '@oxlint-tsgolint/darwin-arm64@0.17.4': optional: true - '@oxlint-tsgolint/darwin-x64@0.20.0': + '@oxlint-tsgolint/darwin-x64@0.17.4': optional: true - '@oxlint-tsgolint/linux-arm64@0.20.0': + '@oxlint-tsgolint/linux-arm64@0.17.4': optional: true - '@oxlint-tsgolint/linux-x64@0.20.0': + '@oxlint-tsgolint/linux-x64@0.17.4': optional: true - '@oxlint-tsgolint/win32-arm64@0.20.0': + '@oxlint-tsgolint/win32-arm64@0.17.4': optional: true - '@oxlint-tsgolint/win32-x64@0.20.0': + '@oxlint-tsgolint/win32-x64@0.17.4': optional: true - '@oxlint/binding-android-arm-eabi@1.59.0': + '@oxlint/binding-android-arm-eabi@1.57.0': optional: true - '@oxlint/binding-android-arm64@1.59.0': + '@oxlint/binding-android-arm64@1.57.0': optional: true - '@oxlint/binding-darwin-arm64@1.59.0': + '@oxlint/binding-darwin-arm64@1.57.0': optional: true - '@oxlint/binding-darwin-x64@1.59.0': + '@oxlint/binding-darwin-x64@1.57.0': optional: true - '@oxlint/binding-freebsd-x64@1.59.0': + '@oxlint/binding-freebsd-x64@1.57.0': optional: true - '@oxlint/binding-linux-arm-gnueabihf@1.59.0': + '@oxlint/binding-linux-arm-gnueabihf@1.57.0': optional: true - '@oxlint/binding-linux-arm-musleabihf@1.59.0': + '@oxlint/binding-linux-arm-musleabihf@1.57.0': optional: true - '@oxlint/binding-linux-arm64-gnu@1.59.0': + '@oxlint/binding-linux-arm64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-arm64-musl@1.59.0': + '@oxlint/binding-linux-arm64-musl@1.57.0': optional: true - '@oxlint/binding-linux-ppc64-gnu@1.59.0': + '@oxlint/binding-linux-ppc64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-riscv64-gnu@1.59.0': + '@oxlint/binding-linux-riscv64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-riscv64-musl@1.59.0': + '@oxlint/binding-linux-riscv64-musl@1.57.0': optional: true - '@oxlint/binding-linux-s390x-gnu@1.59.0': + '@oxlint/binding-linux-s390x-gnu@1.57.0': optional: true - '@oxlint/binding-linux-x64-gnu@1.59.0': + '@oxlint/binding-linux-x64-gnu@1.57.0': optional: true - '@oxlint/binding-linux-x64-musl@1.59.0': + '@oxlint/binding-linux-x64-musl@1.57.0': optional: true - '@oxlint/binding-openharmony-arm64@1.59.0': + '@oxlint/binding-openharmony-arm64@1.57.0': optional: true - '@oxlint/binding-win32-arm64-msvc@1.59.0': + '@oxlint/binding-win32-arm64-msvc@1.57.0': optional: true - '@oxlint/binding-win32-ia32-msvc@1.59.0': + '@oxlint/binding-win32-ia32-msvc@1.57.0': optional: true - '@oxlint/binding-win32-x64-msvc@1.59.0': + '@oxlint/binding-win32-x64-msvc@1.57.0': optional: true - '@oxlint/plugins@1.59.0': {} + '@oxlint/plugins@1.57.0': {} '@package-json/types@0.0.12': {} @@ -7872,7 +7640,7 @@ snapshots: dependencies: safe-buffer: '@nolyfill/safe-buffer@1.0.44' - '@prisma/instrumentation@7.6.0(@opentelemetry/api@1.9.1)': + '@prisma/instrumentation@7.4.2(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/instrumentation': 0.207.0(@opentelemetry/api@1.9.1) @@ -7953,139 +7721,185 @@ snapshots: dependencies: quansync: 1.0.0 + '@rolldown/binding-android-arm64@1.0.0-rc.11': + optional: true + '@rolldown/binding-android-arm64@1.0.0-rc.12': optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.11': + optional: true + '@rolldown/binding-darwin-arm64@1.0.0-rc.12': optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.11': + optional: true + '@rolldown/binding-darwin-x64@1.0.0-rc.12': optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.11': + optional: true + '@rolldown/binding-freebsd-x64@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.11': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.11': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.11': dependencies: - '@napi-rs/wasm-runtime': 1.1.2(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2) - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.12': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11': optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.11': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.12': optional: true + '@rolldown/pluginutils@1.0.0-rc.11': {} + '@rolldown/pluginutils@1.0.0-rc.12': {} - '@rollup/pluginutils@5.3.0(rollup@4.60.1)': + '@rollup/pluginutils@5.3.0(rollup@4.60.0)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.4 optionalDependencies: - rollup: 4.60.1 + rollup: 4.60.0 - '@rollup/rollup-android-arm-eabi@4.60.1': + '@rollup/rollup-android-arm-eabi@4.60.0': optional: true - '@rollup/rollup-android-arm64@4.60.1': + '@rollup/rollup-android-arm64@4.60.0': optional: true - '@rollup/rollup-darwin-arm64@4.60.1': + '@rollup/rollup-darwin-arm64@4.60.0': optional: true - '@rollup/rollup-darwin-x64@4.60.1': + '@rollup/rollup-darwin-x64@4.60.0': optional: true - '@rollup/rollup-freebsd-arm64@4.60.1': + '@rollup/rollup-freebsd-arm64@4.60.0': optional: true - '@rollup/rollup-freebsd-x64@4.60.1': + '@rollup/rollup-freebsd-x64@4.60.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': + '@rollup/rollup-linux-arm-gnueabihf@4.60.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.60.1': + '@rollup/rollup-linux-arm-musleabihf@4.60.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.60.1': + '@rollup/rollup-linux-arm64-gnu@4.60.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.60.1': + '@rollup/rollup-linux-arm64-musl@4.60.0': optional: true - '@rollup/rollup-linux-loong64-gnu@4.60.1': + '@rollup/rollup-linux-loong64-gnu@4.60.0': optional: true - '@rollup/rollup-linux-loong64-musl@4.60.1': + '@rollup/rollup-linux-loong64-musl@4.60.0': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.60.1': + '@rollup/rollup-linux-ppc64-gnu@4.60.0': optional: true - '@rollup/rollup-linux-ppc64-musl@4.60.1': + '@rollup/rollup-linux-ppc64-musl@4.60.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.60.1': + '@rollup/rollup-linux-riscv64-gnu@4.60.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.60.1': + '@rollup/rollup-linux-riscv64-musl@4.60.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.60.1': + '@rollup/rollup-linux-s390x-gnu@4.60.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.60.1': + '@rollup/rollup-linux-x64-gnu@4.60.0': optional: true - '@rollup/rollup-linux-x64-musl@4.60.1': + '@rollup/rollup-linux-x64-musl@4.60.0': optional: true - '@rollup/rollup-openbsd-x64@4.60.1': + '@rollup/rollup-openbsd-x64@4.60.0': optional: true - '@rollup/rollup-openharmony-arm64@4.60.1': + '@rollup/rollup-openharmony-arm64@4.60.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.60.1': + '@rollup/rollup-win32-arm64-msvc@4.60.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.60.1': + '@rollup/rollup-win32-ia32-msvc@4.60.0': optional: true - '@rollup/rollup-win32-x64-gnu@4.60.1': + '@rollup/rollup-win32-x64-gnu@4.60.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.60.1': + '@rollup/rollup-win32-x64-msvc@4.60.0': optional: true '@rss3/api-core@0.0.25': @@ -8103,25 +7917,20 @@ snapshots: '@rss3/api-core': 0.0.25 '@rss3/api-utils': 0.0.25 - '@scalar/client-side-rendering@0.1.0': - dependencies: - '@scalar/types': 0.8.0 - - '@scalar/core@0.5.0': + '@scalar/core@0.4.5': dependencies: - '@scalar/client-side-rendering': 0.1.0 - '@scalar/types': 0.8.0 + '@scalar/types': 0.7.5 - '@scalar/helpers@0.4.3': {} + '@scalar/helpers@0.4.2': {} - '@scalar/hono-api-reference@0.10.7(hono@4.12.12)': + '@scalar/hono-api-reference@0.10.5(hono@4.12.8)': dependencies: - '@scalar/core': 0.5.0 - hono: 4.12.12 + '@scalar/core': 0.4.5 + hono: 4.12.8 - '@scalar/types@0.8.0': + '@scalar/types@0.7.5': dependencies: - '@scalar/helpers': 0.4.3 + '@scalar/helpers': 0.4.2 nanoid: 5.1.7 type-fest: 5.5.0 zod: 4.3.6 @@ -8135,71 +7944,70 @@ snapshots: domhandler: 5.0.3 selderee: 0.11.0 - '@sentry/core@10.48.0': {} + '@sentry/core@10.46.0': {} - '@sentry/node-core@10.48.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/node-core@10.46.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.1))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: - '@sentry/core': 10.48.0 - '@sentry/opentelemetry': 10.48.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) - import-in-the-middle: 3.0.1 + '@sentry/core': 10.46.0 + '@sentry/opentelemetry': 10.46.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) + import-in-the-middle: 3.0.0 optionalDependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/exporter-trace-otlp-http': 0.214.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 - '@sentry/node@10.48.0(@opentelemetry/exporter-trace-otlp-http@0.214.0(@opentelemetry/api@1.9.1))': + '@sentry/node@10.46.0': dependencies: - '@fastify/otel': 0.18.0(@opentelemetry/api@1.9.1) + '@fastify/otel': 0.17.1(@opentelemetry/api@1.9.1) '@opentelemetry/api': 1.9.1 '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-amqplib': 0.61.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-connect': 0.57.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-dataloader': 0.31.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-fs': 0.33.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-generic-pool': 0.57.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-graphql': 0.62.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-hapi': 0.60.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-http': 0.214.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-ioredis': 0.62.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-kafkajs': 0.23.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-knex': 0.58.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-koa': 0.62.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-lru-memoizer': 0.58.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-mongodb': 0.67.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-mongoose': 0.60.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-mysql': 0.60.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-mysql2': 0.60.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-pg': 0.66.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-redis': 0.62.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-tedious': 0.33.0(@opentelemetry/api@1.9.1) - '@opentelemetry/instrumentation-undici': 0.24.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation': 0.213.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-amqplib': 0.60.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-connect': 0.56.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-dataloader': 0.30.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-express': 0.61.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-fs': 0.32.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-generic-pool': 0.56.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-graphql': 0.61.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-hapi': 0.59.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-http': 0.213.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-ioredis': 0.61.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-kafkajs': 0.22.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-knex': 0.57.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-koa': 0.61.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-lru-memoizer': 0.57.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongodb': 0.66.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mongoose': 0.59.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql': 0.59.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-mysql2': 0.59.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-pg': 0.65.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-redis': 0.61.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-tedious': 0.32.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-undici': 0.23.0(@opentelemetry/api@1.9.1) '@opentelemetry/resources': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 - '@prisma/instrumentation': 7.6.0(@opentelemetry/api@1.9.1) - '@sentry/core': 10.48.0 - '@sentry/node-core': 10.48.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/exporter-trace-otlp-http@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) - '@sentry/opentelemetry': 10.48.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) - import-in-the-middle: 3.0.1 + '@prisma/instrumentation': 7.4.2(@opentelemetry/api@1.9.1) + '@sentry/core': 10.46.0 + '@sentry/node-core': 10.46.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.213.0(@opentelemetry/api@1.9.1))(@opentelemetry/resources@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) + '@sentry/opentelemetry': 10.46.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) + import-in-the-middle: 3.0.0 transitivePeerDependencies: - - '@opentelemetry/exporter-trace-otlp-http' - supports-color - '@sentry/opentelemetry@10.48.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)': + '@sentry/opentelemetry@10.46.0(@opentelemetry/api@1.9.1)(@opentelemetry/context-async-hooks@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.6.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/context-async-hooks': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/core': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/sdk-trace-base': 2.6.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 - '@sentry/core': 10.48.0 + '@sentry/core': 10.46.0 '@sindresorhus/is@4.6.0': {} @@ -8214,11 +8022,11 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@stylistic/eslint-plugin@5.10.0(eslint@10.2.0(jiti@2.6.1))': + '@stylistic/eslint-plugin@5.10.0(eslint@10.1.0(jiti@2.6.1))': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) - '@typescript-eslint/types': 8.58.0 - eslint: 10.2.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) + '@typescript-eslint/types': 8.57.2 + eslint: 10.1.0(jiti@2.6.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -8233,19 +8041,12 @@ snapshots: '@types/aes-js@3.1.4': {} - '@types/aws-lambda@8.10.161': {} - '@types/babel__preset-env@7.10.0': {} '@types/bezier-js@4.1.3': {} '@types/bluebird@3.5.42': {} - '@types/body-parser@1.19.6': - dependencies: - '@types/connect': 3.4.38 - '@types/node': 25.6.0 - '@types/caseless@0.12.5': {} '@types/chai@5.2.3': @@ -8257,7 +8058,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/crypto-js@4.2.2': {} @@ -8278,37 +8079,22 @@ snapshots: '@types/etag@1.8.4': dependencies: - '@types/node': 25.6.0 - - '@types/express-serve-static-core@5.1.1': - dependencies: - '@types/node': 25.6.0 - '@types/qs': 6.15.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - - '@types/express@5.0.6': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 5.1.1 - '@types/serve-static': 2.2.0 + '@types/node': 25.5.0 '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/html-to-text@9.0.4': {} '@types/http-cache-semantics@4.2.0': {} - '@types/http-errors@2.0.5': {} - '@types/js-beautify@1.14.3': {} '@types/jsdom@28.0.1': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/tough-cookie': 4.0.5 parse5: 7.3.0 undici-types: 7.24.6 @@ -8321,7 +8107,7 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/jsrsasign@10.5.15': {} @@ -8329,7 +8115,7 @@ snapshots: '@types/mailparser@3.4.6': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 iconv-lite: 0.6.3 '@types/markdown-it@14.1.2': @@ -8349,11 +8135,11 @@ snapshots: '@types/mysql@2.15.27': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 - '@types/node@25.6.0': + '@types/node@25.5.0': dependencies: - undici-types: 7.19.2 + undici-types: 7.18.2 '@types/pg-pool@2.0.7': dependencies: @@ -8361,14 +8147,10 @@ snapshots: '@types/pg@8.15.6': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 pg-protocol: 1.13.0 pg-types: 2.2.0 - '@types/qs@6.15.0': {} - - '@types/range-parser@1.2.7': {} - '@types/request-promise@4.1.51': dependencies: '@types/bluebird': 3.5.42 @@ -8377,7 +8159,7 @@ snapshots: '@types/request@2.48.13': dependencies: '@types/caseless': 0.12.5 - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/tough-cookie': 4.0.5 form-data: 2.5.5 @@ -8385,20 +8167,11 @@ snapshots: dependencies: htmlparser2: 10.1.0 - '@types/send@1.2.1': - dependencies: - '@types/node': 25.6.0 - - '@types/serve-static@2.2.0': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 25.6.0 - '@types/statuses@2.0.6': {} '@types/tedious@4.0.14': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 '@types/tough-cookie@4.0.5': {} @@ -8408,18 +8181,18 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 optional: true - '@typescript-eslint/eslint-plugin@8.58.1(@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.57.2(@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3))(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.58.1 - '@typescript-eslint/type-utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.58.1 - eslint: 10.2.0(jiti@2.6.1) + '@typescript-eslint/parser': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.57.2 + '@typescript-eslint/type-utils': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.2 + eslint: 10.1.0(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -8427,81 +8200,79 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.58.1 - '@typescript-eslint/types': 8.58.1 - '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.58.1 + '@typescript-eslint/scope-manager': 8.57.2 + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.2 debug: 4.4.3 - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.58.1(typescript@5.9.3)': + '@typescript-eslint/project-service@8.57.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.9.3) - '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.58.1': + '@typescript-eslint/scope-manager@8.57.2': dependencies: - '@typescript-eslint/types': 8.58.1 - '@typescript-eslint/visitor-keys': 8.58.1 + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/visitor-keys': 8.57.2 - '@typescript-eslint/tsconfig-utils@8.58.1(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.57.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.58.1 - '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.58.0': {} + '@typescript-eslint/types@8.57.2': {} - '@typescript-eslint/types@8.58.1': {} - - '@typescript-eslint/typescript-estree@8.58.1(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.57.2(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.58.1(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.58.1(typescript@5.9.3) - '@typescript-eslint/types': 8.58.1 - '@typescript-eslint/visitor-keys': 8.58.1 + '@typescript-eslint/project-service': 8.57.2(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.57.2(typescript@5.9.3) + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/visitor-keys': 8.57.2 debug: 4.4.3 - minimatch: 10.2.5 + minimatch: 10.2.4 semver: 7.7.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.15 ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.58.1 - '@typescript-eslint/types': 8.58.1 - '@typescript-eslint/typescript-estree': 8.58.1(typescript@5.9.3) - eslint: 10.2.0(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.57.2 + '@typescript-eslint/types': 8.57.2 + '@typescript-eslint/typescript-estree': 8.57.2(typescript@5.9.3) + eslint: 10.1.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.58.1': + '@typescript-eslint/visitor-keys@8.57.2': dependencies: - '@typescript-eslint/types': 8.58.1 + '@typescript-eslint/types': 8.57.2 eslint-visitor-keys: 5.0.1 '@unrs/resolver-binding-android-arm-eabi@1.11.1': @@ -8563,10 +8334,10 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.11.1': optional: true - '@vercel/nft@1.5.0(rollup@4.60.1)': + '@vercel/nft@1.5.0(rollup@4.60.0)': dependencies: '@mapbox/node-pre-gyp': 2.0.3 - '@rollup/pluginutils': 5.3.0(rollup@4.60.1) + '@rollup/pluginutils': 5.3.0(rollup@4.60.0) acorn: 8.16.0 acorn-import-attributes: 1.9.5(acorn@8.16.0) async-sema: 3.1.1 @@ -8582,7 +8353,7 @@ snapshots: - rollup - supports-color - '@vitest/coverage-v8@4.0.9(vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.6.0)(jiti@2.6.1)(jsdom@29.0.2(@noble/hashes@2.0.1))(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/coverage-v8@4.0.9(vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.5.0)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.9 @@ -8595,7 +8366,7 @@ snapshots: magicast: 0.5.2 std-env: 3.10.0 tinyrainbow: 3.1.0 - vitest: 4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.6.0)(jiti@2.6.1)(jsdom@29.0.2(@noble/hashes@2.0.1))(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3) + vitest: 4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.5.0)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -8608,14 +8379,14 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.0.9(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.0.9(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.0.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - msw: 2.13.2(@types/node@25.6.0)(typescript@5.9.3) - vite: 7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + msw: 2.12.14(@types/node@25.5.0)(typescript@5.9.3) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) '@vitest/pretty-format@4.0.9': dependencies: @@ -8665,7 +8436,7 @@ snapshots: agent-base@7.1.4: {} - agent-base@9.0.0: {} + agent-base@8.0.0: {} ajv@6.14.0: dependencies: @@ -8704,7 +8475,7 @@ snapshots: ast-kit@3.0.0-beta.1: dependencies: - '@babel/parser': 8.0.0-rc.3 + '@babel/parser': 8.0.0-rc.2 estree-walker: 3.0.3 pathe: 2.0.3 @@ -8744,24 +8515,24 @@ snapshots: bare-events@2.8.2: {} - bare-fs@4.7.0: + bare-fs@4.5.6: dependencies: bare-events: 2.8.2 bare-path: 3.0.0 - bare-stream: 2.12.0(bare-events@2.8.2) + bare-stream: 2.11.0(bare-events@2.8.2) bare-url: 2.4.0 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller - react-native-b4a - bare-os@3.8.7: {} + bare-os@3.8.0: {} bare-path@3.0.0: dependencies: - bare-os: 3.8.7 + bare-os: 3.8.0 - bare-stream@2.12.0(bare-events@2.8.2): + bare-stream@2.11.0(bare-events@2.8.2): dependencies: streamx: 2.25.0 teex: 1.0.1 @@ -8776,12 +8547,10 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.10.13: {} + baseline-browser-mapping@2.10.11: {} basic-ftp@5.2.0: {} - basic-ftp@5.2.2: {} - bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 @@ -8828,13 +8597,13 @@ snapshots: dependencies: balanced-match: 4.0.4 - browserslist@4.28.2: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.10.13 - caniuse-lite: 1.0.30001784 - electron-to-chromium: 1.5.330 + baseline-browser-mapping: 2.10.11 + caniuse-lite: 1.0.30001781 + electron-to-chromium: 1.5.328 node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.2) + update-browserslist-db: 1.2.3(browserslist@4.28.1) buffer-crc32@0.2.13: {} @@ -8889,7 +8658,7 @@ snapshots: camelcase@8.0.0: {} - caniuse-lite@1.0.30001784: {} + caniuse-lite@1.0.30001781: {} caseless@0.12.0: {} @@ -8923,14 +8692,14 @@ snapshots: parse5: 7.3.0 parse5-htmlparser2-tree-adapter: 7.1.0 parse5-parser-stream: 7.1.2 - undici: 7.24.7 + undici: 7.24.6 whatwg-mimetype: 4.0.0 chownr@3.0.0: {} chrome-launcher@1.2.1: dependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 2.0.2 @@ -8950,8 +8719,6 @@ snapshots: mitt: 3.0.1 zod: 3.25.76 - chunk-data@0.1.0: {} - ci-info@4.4.0: {} city-timezones@1.3.3: {} @@ -9020,7 +8787,7 @@ snapshots: commander@14.0.3: {} - comment-parser@1.4.6: {} + comment-parser@1.4.5: {} concat-map@0.0.1: {} @@ -9035,7 +8802,7 @@ snapshots: core-js-compat@3.49.0: dependencies: - browserslist: 4.28.2 + browserslist: 4.28.1 core-js@2.6.12: {} @@ -9093,7 +8860,7 @@ snapshots: data-uri-to-buffer@6.0.2: {} - data-uri-to-buffer@8.0.0: {} + data-uri-to-buffer@7.0.0: {} data-urls@7.0.0(@noble/hashes@2.0.1): dependencies: @@ -9151,12 +8918,12 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 - degenerator@7.0.1(quickjs-wasi@2.2.0): + degenerator@6.0.0(quickjs-wasi@0.0.1): dependencies: ast-types: 0.13.4 escodegen: 2.1.0 esprima: 4.0.1 - quickjs-wasi: 2.2.0 + quickjs-wasi: 0.0.1 delayed-stream@1.0.0: {} @@ -9184,7 +8951,7 @@ snapshots: dependencies: heap: 0.2.7 - discord-api-types@0.38.45: {} + discord-api-types@0.38.42: {} dom-serializer@1.4.1: dependencies: @@ -9230,7 +8997,7 @@ snapshots: dependencies: is-obj: 2.0.0 - dotenv@17.4.1: {} + dotenv@17.3.1: {} dts-resolver@2.1.3: {} @@ -9252,7 +9019,7 @@ snapshots: minimatch: 9.0.9 semver: 7.7.4 - electron-to-chromium@1.5.330: {} + electron-to-chromium@1.5.328: {} ellipsize@0.6.0: {} @@ -9391,35 +9158,6 @@ snapshots: '@esbuild/win32-ia32': 0.27.4 '@esbuild/win32-x64': 0.27.4 - esbuild@0.27.7: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.7 - '@esbuild/android-arm': 0.27.7 - '@esbuild/android-arm64': 0.27.7 - '@esbuild/android-x64': 0.27.7 - '@esbuild/darwin-arm64': 0.27.7 - '@esbuild/darwin-x64': 0.27.7 - '@esbuild/freebsd-arm64': 0.27.7 - '@esbuild/freebsd-x64': 0.27.7 - '@esbuild/linux-arm': 0.27.7 - '@esbuild/linux-arm64': 0.27.7 - '@esbuild/linux-ia32': 0.27.7 - '@esbuild/linux-loong64': 0.27.7 - '@esbuild/linux-mips64el': 0.27.7 - '@esbuild/linux-ppc64': 0.27.7 - '@esbuild/linux-riscv64': 0.27.7 - '@esbuild/linux-s390x': 0.27.7 - '@esbuild/linux-x64': 0.27.7 - '@esbuild/netbsd-arm64': 0.27.7 - '@esbuild/netbsd-x64': 0.27.7 - '@esbuild/openbsd-arm64': 0.27.7 - '@esbuild/openbsd-x64': 0.27.7 - '@esbuild/openharmony-arm64': 0.27.7 - '@esbuild/sunos-x64': 0.27.7 - '@esbuild/win32-arm64': 0.27.7 - '@esbuild/win32-ia32': 0.27.7 - '@esbuild/win32-x64': 0.27.7 - escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -9436,14 +9174,14 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-compat-utils@0.5.1(eslint@10.2.0(jiti@2.6.1)): + eslint-compat-utils@0.5.1(eslint@10.1.0(jiti@2.6.1)): dependencies: - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) semver: 7.7.4 - eslint-filtered-fix@0.3.0(eslint@10.2.0(jiti@2.6.1)): + eslint-filtered-fix@0.3.0(eslint@10.1.0(jiti@2.6.1)): dependencies: - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) optionator: 0.9.4 eslint-import-context@0.1.9(unrs-resolver@1.11.1): @@ -9462,52 +9200,52 @@ snapshots: - supports-color optional: true - eslint-nibble@9.1.1(@types/node@25.6.0)(eslint@10.2.0(jiti@2.6.1)): + eslint-nibble@9.1.1(@types/node@25.5.0)(eslint@10.1.0(jiti@2.6.1)): dependencies: '@babel/code-frame': 7.29.0 - '@inquirer/checkbox': 4.3.2(@types/node@25.6.0) - '@inquirer/confirm': 5.1.21(@types/node@25.6.0) - '@inquirer/select': 4.4.2(@types/node@25.6.0) - eslint: 10.2.0(jiti@2.6.1) - eslint-filtered-fix: 0.3.0(eslint@10.2.0(jiti@2.6.1)) + '@inquirer/checkbox': 4.3.2(@types/node@25.5.0) + '@inquirer/confirm': 5.1.21(@types/node@25.5.0) + '@inquirer/select': 4.4.2(@types/node@25.5.0) + eslint: 10.1.0(jiti@2.6.1) + eslint-filtered-fix: 0.3.0(eslint@10.1.0(jiti@2.6.1)) optionator: 0.9.4 text-table: 0.2.0 yoctocolors: 2.1.2 transitivePeerDependencies: - '@types/node' - eslint-plugin-es-x@7.8.0(eslint@10.2.0(jiti@2.6.1)): + eslint-plugin-es-x@7.8.0(eslint@10.1.0(jiti@2.6.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - eslint: 10.2.0(jiti@2.6.1) - eslint-compat-utils: 0.5.1(eslint@10.2.0(jiti@2.6.1)) + eslint: 10.1.0(jiti@2.6.1) + eslint-compat-utils: 0.5.1(eslint@10.1.0(jiti@2.6.1)) - eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.2.0(jiti@2.6.1)): + eslint-plugin-import-x@4.16.2(@typescript-eslint/utils@8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint@10.1.0(jiti@2.6.1)): dependencies: '@package-json/types': 0.0.12 - '@typescript-eslint/types': 8.58.0 - comment-parser: 1.4.6 + '@typescript-eslint/types': 8.57.2 + comment-parser: 1.4.5 debug: 4.4.3 - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 - minimatch: 10.2.5 + minimatch: 10.2.4 semver: 7.7.4 stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.58.1(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.2(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-n@17.24.0(eslint@10.2.0(jiti@2.6.1))(typescript@5.9.3): + eslint-plugin-n@17.24.0(eslint@10.1.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) enhanced-resolve: 5.20.1 - eslint: 10.2.0(jiti@2.6.1) - eslint-plugin-es-x: 7.8.0(eslint@10.2.0(jiti@2.6.1)) + eslint: 10.1.0(jiti@2.6.1) + eslint-plugin-es-x: 7.8.0(eslint@10.1.0(jiti@2.6.1)) get-tsconfig: 4.13.7 globals: 15.15.0 globrex: 0.1.2 @@ -9517,21 +9255,21 @@ snapshots: transitivePeerDependencies: - typescript - eslint-plugin-simple-import-sort@13.0.0(eslint@10.2.0(jiti@2.6.1)): + eslint-plugin-simple-import-sort@12.1.1(eslint@10.1.0(jiti@2.6.1)): dependencies: - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) - eslint-plugin-unicorn@64.0.0(eslint@10.2.0(jiti@2.6.1)): + eslint-plugin-unicorn@63.0.0(eslint@10.1.0(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) change-case: 5.4.4 ci-info: 4.4.0 clean-regexp: 1.0.0 core-js-compat: 3.49.0 - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) find-up-simple: 1.0.1 - globals: 17.4.0 + globals: 16.5.0 indent-string: 5.0.0 is-builtin-module: 5.0.0 jsesc: 3.1.0 @@ -9541,7 +9279,7 @@ snapshots: semver: 7.7.4 strip-indent: 4.1.1 - eslint-plugin-yml@3.3.1(eslint@10.2.0(jiti@2.6.1)): + eslint-plugin-yml@3.3.1(eslint@10.1.0(jiti@2.6.1)): dependencies: '@eslint/core': 1.1.1 '@eslint/plugin-kit': 0.6.1 @@ -9549,7 +9287,7 @@ snapshots: debug: 4.4.3 diff-sequences: 29.6.3 escape-string-regexp: 5.0.0 - eslint: 10.2.0(jiti@2.6.1) + eslint: 10.1.0(jiti@2.6.1) natural-compare: 1.4.0 yaml-eslint-parser: 2.0.0 transitivePeerDependencies: @@ -9568,14 +9306,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@10.2.0(jiti@2.6.1): + eslint@10.1.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.2.0(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.1(eslint@10.1.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.23.4 - '@eslint/config-helpers': 0.5.4 - '@eslint/core': 1.2.0 - '@eslint/plugin-kit': 0.7.0 + '@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.7 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 @@ -9597,7 +9335,7 @@ snapshots: imurmurhash: 0.1.4 is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 - minimatch: 10.2.5 + minimatch: 10.2.4 natural-compare: 1.4.0 optionator: 0.9.4 optionalDependencies: @@ -9808,7 +9546,7 @@ snapshots: transitivePeerDependencies: - supports-color - generative-bayesian-network@2.1.82: + generative-bayesian-network@2.1.81: dependencies: adm-zip: 0.5.16 tslib: 2.8.1 @@ -9834,16 +9572,16 @@ snapshots: get-uri@6.0.5: dependencies: - basic-ftp: 5.2.2 + basic-ftp: 5.2.0 data-uri-to-buffer: 6.0.2 debug: 4.4.3 transitivePeerDependencies: - supports-color - get-uri@8.0.0: + get-uri@7.0.0: dependencies: basic-ftp: 5.2.0 - data-uri-to-buffer: 8.0.0 + data-uri-to-buffer: 7.0.0 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -9875,7 +9613,7 @@ snapshots: glob@13.0.6: dependencies: - minimatch: 10.2.5 + minimatch: 10.2.4 minipass: 7.1.3 path-scurry: 2.0.2 @@ -9883,6 +9621,8 @@ snapshots: globals@15.15.0: {} + globals@16.5.0: {} + globals@17.4.0: {} globrex@0.1.2: {} @@ -9943,21 +9683,6 @@ snapshots: responselike: 4.0.2 type-fest: 4.41.0 - got@15.0.1: - dependencies: - '@sindresorhus/is': 7.2.0 - byte-counter: 0.1.0 - cacheable-lookup: 7.0.0 - cacheable-request: 13.0.18 - chunk-data: 0.1.0 - decompress-response: 10.0.0 - http2-wrapper: 2.2.1 - keyv: 5.6.0 - lowercase-keys: 4.0.1 - responselike: 4.0.2 - type-fest: 5.5.0 - uint8array-extras: 1.5.0 - graceful-fs@4.2.11: {} graphql@16.13.2: {} @@ -9973,10 +9698,10 @@ snapshots: he@1.2.0: {} - header-generator@2.1.82: + header-generator@2.1.81: dependencies: - browserslist: 4.28.2 - generative-bayesian-network: 2.1.82 + browserslist: 4.28.1 + generative-bayesian-network: 2.1.81 ow: 0.28.2 tslib: 2.8.1 @@ -9986,7 +9711,7 @@ snapshots: hmacsha1@1.0.0: {} - hono@4.12.12: {} + hono@4.12.8: {} hookable@6.1.0: {} @@ -10029,12 +9754,12 @@ snapshots: http-cache-semantics@4.2.0: {} - http-cookie-agent@7.0.3(tough-cookie@6.0.1)(undici@7.24.7): + http-cookie-agent@7.0.3(tough-cookie@6.0.1)(undici@7.24.6): dependencies: agent-base: 7.1.4 tough-cookie: 6.0.1 optionalDependencies: - undici: 7.24.7 + undici: 7.24.6 http-proxy-agent@7.0.2: dependencies: @@ -10043,9 +9768,9 @@ snapshots: transitivePeerDependencies: - supports-color - http-proxy-agent@9.0.0: + http-proxy-agent@8.0.0: dependencies: - agent-base: 9.0.0 + agent-base: 8.0.0 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -10074,9 +9799,9 @@ snapshots: transitivePeerDependencies: - supports-color - https-proxy-agent@9.0.0: + https-proxy-agent@8.0.0: dependencies: - agent-base: 9.0.0 + agent-base: 8.0.0 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -10101,15 +9826,15 @@ snapshots: image-size@0.7.5: {} - imapflow@1.3.1: + imapflow@1.2.18: dependencies: '@zone-eu/mailsplit': 5.4.8 encoding-japanese: 2.2.0 iconv-lite: 0.7.2 libbase64: 1.3.0 - libmime: 5.3.8 + libmime: 5.3.7 libqp: 2.1.1 - nodemailer: 8.0.5 + nodemailer: 8.0.4 pino: 10.3.1 socks: 2.8.7 @@ -10125,7 +9850,7 @@ snapshots: cjs-module-lexer: 2.2.0 module-details-from-path: 1.0.4 - import-in-the-middle@3.0.1: + import-in-the-middle@3.0.0: dependencies: acorn: 8.16.0 acorn-import-attributes: 1.9.5(acorn@8.16.0) @@ -10305,10 +10030,10 @@ snapshots: jsbn@0.1.1: {} - jsdom@29.0.2(@noble/hashes@2.0.1): + jsdom@29.0.1(@noble/hashes@2.0.1): dependencies: - '@asamuzakjp/css-color': 5.1.6 - '@asamuzakjp/dom-selector': 7.0.7 + '@asamuzakjp/css-color': 5.0.1 + '@asamuzakjp/dom-selector': 7.0.4 '@bramus/specificity': 2.4.2 '@csstools/css-syntax-patches-for-csstree': 1.1.2(css-tree@3.2.1) '@exodus/bytes': 1.15.0(@noble/hashes@2.0.1) @@ -10317,12 +10042,12 @@ snapshots: decimal.js: 10.6.0 html-encoding-sniffer: 6.0.0(@noble/hashes@2.0.1) is-potential-custom-element-name: 1.0.1 - lru-cache: 11.3.3 + lru-cache: 11.2.7 parse5: 8.0.0 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 6.0.1 - undici: 7.24.7 + undici: 7.24.6 w3c-xmlserializer: 5.0.0 webidl-conversions: 8.0.1 whatwg-mimetype: 5.0.0 @@ -10341,8 +10066,6 @@ snapshots: json-buffer@3.0.1: {} - json-nd@1.0.0: {} - json-parse-even-better-errors@2.3.1: {} json-schema-traverse@0.4.1: {} @@ -10422,13 +10145,6 @@ snapshots: libbase64: 1.3.0 libqp: 2.1.1 - libmime@5.3.8: - dependencies: - encoding-japanese: 2.2.0 - iconv-lite: 0.7.2 - libbase64: 1.3.0 - libqp: 2.1.1 - libqp@2.1.1: {} lighthouse-logger@2.0.2: @@ -10495,11 +10211,9 @@ snapshots: lowercase-keys@3.0.0: {} - lowercase-keys@4.0.1: {} - lru-cache@10.4.3: {} - lru-cache@11.3.3: {} + lru-cache@11.2.7: {} lru-cache@7.18.3: {} @@ -10521,16 +10235,16 @@ snapshots: '@babel/types': 7.29.0 source-map-js: 1.2.1 - mailparser@3.9.8: + mailparser@3.9.6: dependencies: '@zone-eu/mailsplit': 5.4.8 encoding-japanese: 2.2.0 he: 1.2.0 html-to-text: 9.0.5 iconv-lite: 0.7.2 - libmime: 5.3.8 + libmime: 5.3.7 linkify-it: 5.0.0 - nodemailer: 8.0.5 + nodemailer: 8.0.4 punycode.js: 2.3.1 tlds: 1.261.0 @@ -10744,19 +10458,19 @@ snapshots: mimic-response@4.0.0: {} - miniflare@4.20260409.0(bufferutil@4.1.0)(utf-8-validate@5.0.10): + miniflare@4.20260317.2(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: '@cspotcode/source-map-support': 0.8.1 sharp: 0.34.5 undici: 7.24.4 - workerd: 1.20260409.1 + workerd: 1.20260317.1 ws: 8.18.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) youch: 4.1.0-beta.10 transitivePeerDependencies: - bufferutil - utf-8-validate - minimatch@10.2.5: + minimatch@10.2.4: dependencies: brace-expansion: 5.0.5 @@ -10788,9 +10502,9 @@ snapshots: ms@2.1.3: {} - msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3): + msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3): dependencies: - '@inquirer/confirm': 5.1.21(@types/node@25.6.0) + '@inquirer/confirm': 5.1.21(@types/node@25.5.0) '@mswjs/interceptors': 0.41.3(patch_hash=5027fcc424409c41c41147fc6c90b36166061522e0b03e73b45f9a973fcd2a28) '@open-draft/deferred-promise': 2.2.0 '@types/statuses': 2.0.6 @@ -10833,8 +10547,6 @@ snapshots: netmask@2.0.2: {} - netmask@2.1.1: {} - next-tick@1.1.0: {} node-domexception@1.0.0: {} @@ -10857,20 +10569,20 @@ snapshots: dependencies: write-file-atomic: 1.3.4 - node-network-devtools@1.0.29(undici@7.24.7)(utf-8-validate@5.0.10): + node-network-devtools@1.0.29(undici@7.24.6)(utf-8-validate@5.0.10): dependencies: bufferutil: 4.1.0 iconv-lite: 0.6.3 inspector: 0.5.0 open: 8.4.2 - undici: 7.24.7 + undici: 7.24.6 ws: 8.20.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) transitivePeerDependencies: - utf-8-validate node-releases@2.0.36: {} - nodemailer@8.0.5: {} + nodemailer@8.0.4: {} nopt@7.2.1: dependencies: @@ -10973,63 +10685,61 @@ snapshots: lodash.isequal: 4.5.0 vali-date: 1.0.0 - oxfmt@0.44.0: + oxfmt@0.42.0: dependencies: tinypool: 2.1.0 optionalDependencies: - '@oxfmt/binding-android-arm-eabi': 0.44.0 - '@oxfmt/binding-android-arm64': 0.44.0 - '@oxfmt/binding-darwin-arm64': 0.44.0 - '@oxfmt/binding-darwin-x64': 0.44.0 - '@oxfmt/binding-freebsd-x64': 0.44.0 - '@oxfmt/binding-linux-arm-gnueabihf': 0.44.0 - '@oxfmt/binding-linux-arm-musleabihf': 0.44.0 - '@oxfmt/binding-linux-arm64-gnu': 0.44.0 - '@oxfmt/binding-linux-arm64-musl': 0.44.0 - '@oxfmt/binding-linux-ppc64-gnu': 0.44.0 - '@oxfmt/binding-linux-riscv64-gnu': 0.44.0 - '@oxfmt/binding-linux-riscv64-musl': 0.44.0 - '@oxfmt/binding-linux-s390x-gnu': 0.44.0 - '@oxfmt/binding-linux-x64-gnu': 0.44.0 - '@oxfmt/binding-linux-x64-musl': 0.44.0 - '@oxfmt/binding-openharmony-arm64': 0.44.0 - '@oxfmt/binding-win32-arm64-msvc': 0.44.0 - '@oxfmt/binding-win32-ia32-msvc': 0.44.0 - '@oxfmt/binding-win32-x64-msvc': 0.44.0 - - oxlint-plugin-eslint@1.59.0: {} - - oxlint-tsgolint@0.20.0: + '@oxfmt/binding-android-arm-eabi': 0.42.0 + '@oxfmt/binding-android-arm64': 0.42.0 + '@oxfmt/binding-darwin-arm64': 0.42.0 + '@oxfmt/binding-darwin-x64': 0.42.0 + '@oxfmt/binding-freebsd-x64': 0.42.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.42.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.42.0 + '@oxfmt/binding-linux-arm64-gnu': 0.42.0 + '@oxfmt/binding-linux-arm64-musl': 0.42.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.42.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.42.0 + '@oxfmt/binding-linux-riscv64-musl': 0.42.0 + '@oxfmt/binding-linux-s390x-gnu': 0.42.0 + '@oxfmt/binding-linux-x64-gnu': 0.42.0 + '@oxfmt/binding-linux-x64-musl': 0.42.0 + '@oxfmt/binding-openharmony-arm64': 0.42.0 + '@oxfmt/binding-win32-arm64-msvc': 0.42.0 + '@oxfmt/binding-win32-ia32-msvc': 0.42.0 + '@oxfmt/binding-win32-x64-msvc': 0.42.0 + + oxlint-tsgolint@0.17.4: optionalDependencies: - '@oxlint-tsgolint/darwin-arm64': 0.20.0 - '@oxlint-tsgolint/darwin-x64': 0.20.0 - '@oxlint-tsgolint/linux-arm64': 0.20.0 - '@oxlint-tsgolint/linux-x64': 0.20.0 - '@oxlint-tsgolint/win32-arm64': 0.20.0 - '@oxlint-tsgolint/win32-x64': 0.20.0 - - oxlint@1.59.0(oxlint-tsgolint@0.20.0): + '@oxlint-tsgolint/darwin-arm64': 0.17.4 + '@oxlint-tsgolint/darwin-x64': 0.17.4 + '@oxlint-tsgolint/linux-arm64': 0.17.4 + '@oxlint-tsgolint/linux-x64': 0.17.4 + '@oxlint-tsgolint/win32-arm64': 0.17.4 + '@oxlint-tsgolint/win32-x64': 0.17.4 + + oxlint@1.57.0(oxlint-tsgolint@0.17.4): optionalDependencies: - '@oxlint/binding-android-arm-eabi': 1.59.0 - '@oxlint/binding-android-arm64': 1.59.0 - '@oxlint/binding-darwin-arm64': 1.59.0 - '@oxlint/binding-darwin-x64': 1.59.0 - '@oxlint/binding-freebsd-x64': 1.59.0 - '@oxlint/binding-linux-arm-gnueabihf': 1.59.0 - '@oxlint/binding-linux-arm-musleabihf': 1.59.0 - '@oxlint/binding-linux-arm64-gnu': 1.59.0 - '@oxlint/binding-linux-arm64-musl': 1.59.0 - '@oxlint/binding-linux-ppc64-gnu': 1.59.0 - '@oxlint/binding-linux-riscv64-gnu': 1.59.0 - '@oxlint/binding-linux-riscv64-musl': 1.59.0 - '@oxlint/binding-linux-s390x-gnu': 1.59.0 - '@oxlint/binding-linux-x64-gnu': 1.59.0 - '@oxlint/binding-linux-x64-musl': 1.59.0 - '@oxlint/binding-openharmony-arm64': 1.59.0 - '@oxlint/binding-win32-arm64-msvc': 1.59.0 - '@oxlint/binding-win32-ia32-msvc': 1.59.0 - '@oxlint/binding-win32-x64-msvc': 1.59.0 - oxlint-tsgolint: 0.20.0 + '@oxlint/binding-android-arm-eabi': 1.57.0 + '@oxlint/binding-android-arm64': 1.57.0 + '@oxlint/binding-darwin-arm64': 1.57.0 + '@oxlint/binding-darwin-x64': 1.57.0 + '@oxlint/binding-freebsd-x64': 1.57.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.57.0 + '@oxlint/binding-linux-arm-musleabihf': 1.57.0 + '@oxlint/binding-linux-arm64-gnu': 1.57.0 + '@oxlint/binding-linux-arm64-musl': 1.57.0 + '@oxlint/binding-linux-ppc64-gnu': 1.57.0 + '@oxlint/binding-linux-riscv64-gnu': 1.57.0 + '@oxlint/binding-linux-riscv64-musl': 1.57.0 + '@oxlint/binding-linux-s390x-gnu': 1.57.0 + '@oxlint/binding-linux-x64-gnu': 1.57.0 + '@oxlint/binding-linux-x64-musl': 1.57.0 + '@oxlint/binding-openharmony-arm64': 1.57.0 + '@oxlint/binding-win32-arm64-msvc': 1.57.0 + '@oxlint/binding-win32-ia32-msvc': 1.57.0 + '@oxlint/binding-win32-x64-msvc': 1.57.0 + oxlint-tsgolint: 0.17.4 p-cancelable@4.0.1: {} @@ -11056,29 +10766,29 @@ snapshots: transitivePeerDependencies: - supports-color - pac-proxy-agent@9.0.1: + pac-proxy-agent@8.0.0: dependencies: - agent-base: 9.0.0 + agent-base: 8.0.0 debug: 4.4.3 - get-uri: 8.0.0 - http-proxy-agent: 9.0.0 - https-proxy-agent: 9.0.0 - pac-resolver: 9.0.1(quickjs-wasi@2.2.0) - quickjs-wasi: 2.2.0 - socks-proxy-agent: 10.0.0 + get-uri: 7.0.0 + http-proxy-agent: 8.0.0 + https-proxy-agent: 8.0.0 + pac-resolver: 8.0.0(quickjs-wasi@0.0.1) + quickjs-wasi: 0.0.1 + socks-proxy-agent: 9.0.0 transitivePeerDependencies: - supports-color pac-resolver@7.0.1: dependencies: degenerator: 5.0.1 - netmask: 2.1.1 + netmask: 2.0.2 - pac-resolver@9.0.1(quickjs-wasi@2.2.0): + pac-resolver@8.0.0(quickjs-wasi@0.0.1): dependencies: - degenerator: 7.0.1(quickjs-wasi@2.2.0) + degenerator: 6.0.0(quickjs-wasi@0.0.1) netmask: 2.0.2 - quickjs-wasi: 2.2.0 + quickjs-wasi: 0.0.1 package-json-from-dist@1.0.1: {} @@ -11137,7 +10847,7 @@ snapshots: path-scurry@2.0.2: dependencies: - lru-cache: 11.3.3 + lru-cache: 11.2.7 minipass: 7.1.3 path-to-regexp@6.3.0: {} @@ -11249,7 +10959,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 25.6.0 + '@types/node': 25.5.0 long: 5.3.2 proxy-agent@6.5.0: @@ -11341,13 +11051,13 @@ snapshots: quick-lru@6.1.2: {} - quickjs-wasi@2.2.0: {} + quickjs-wasi@0.0.1: {} ramda@0.32.0: {} - rate-limiter-flexible@11.0.0: {} + rate-limiter-flexible@10.0.1: {} - re2js@2.0.1: {} + re2js@1.2.3: {} readable-stream@3.6.2: dependencies: @@ -11512,25 +11222,45 @@ snapshots: rfdc@1.4.1: {} - rolldown-plugin-dts@0.23.2(rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2))(typescript@5.9.3): + rolldown-plugin-dts@0.22.5(rolldown@1.0.0-rc.11)(typescript@5.9.3): dependencies: - '@babel/generator': 8.0.0-rc.3 - '@babel/helper-validator-identifier': 8.0.0-rc.3 - '@babel/parser': 8.0.0-rc.3 - '@babel/types': 8.0.0-rc.3 + '@babel/generator': 8.0.0-rc.2 + '@babel/helper-validator-identifier': 8.0.0-rc.2 + '@babel/parser': 8.0.0-rc.2 + '@babel/types': 8.0.0-rc.2 ast-kit: 3.0.0-beta.1 birpc: 4.0.0 dts-resolver: 2.1.3 get-tsconfig: 4.13.7 obug: 2.1.1 - picomatch: 4.0.4 - rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2) + rolldown: 1.0.0-rc.11 optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - oxc-resolver - rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2): + rolldown@1.0.0-rc.11: + dependencies: + '@oxc-project/types': 0.122.0 + '@rolldown/pluginutils': 1.0.0-rc.11 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.11 + '@rolldown/binding-darwin-x64': 1.0.0-rc.11 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.11 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.11 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.11 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.11 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.11 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.11 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.11 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.11 + + rolldown@1.0.0-rc.12: dependencies: '@oxc-project/types': 0.122.0 '@rolldown/pluginutils': 1.0.0-rc.12 @@ -11547,45 +11277,42 @@ snapshots: '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.12 '@rolldown/binding-linux-x64-musl': 1.0.0-rc.12 '@rolldown/binding-openharmony-arm64': 1.0.0-rc.12 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2) + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.12 '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.12 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.12 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - rollup@4.60.1: + rollup@4.60.0: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.60.1 - '@rollup/rollup-android-arm64': 4.60.1 - '@rollup/rollup-darwin-arm64': 4.60.1 - '@rollup/rollup-darwin-x64': 4.60.1 - '@rollup/rollup-freebsd-arm64': 4.60.1 - '@rollup/rollup-freebsd-x64': 4.60.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.60.1 - '@rollup/rollup-linux-arm-musleabihf': 4.60.1 - '@rollup/rollup-linux-arm64-gnu': 4.60.1 - '@rollup/rollup-linux-arm64-musl': 4.60.1 - '@rollup/rollup-linux-loong64-gnu': 4.60.1 - '@rollup/rollup-linux-loong64-musl': 4.60.1 - '@rollup/rollup-linux-ppc64-gnu': 4.60.1 - '@rollup/rollup-linux-ppc64-musl': 4.60.1 - '@rollup/rollup-linux-riscv64-gnu': 4.60.1 - '@rollup/rollup-linux-riscv64-musl': 4.60.1 - '@rollup/rollup-linux-s390x-gnu': 4.60.1 - '@rollup/rollup-linux-x64-gnu': 4.60.1 - '@rollup/rollup-linux-x64-musl': 4.60.1 - '@rollup/rollup-openbsd-x64': 4.60.1 - '@rollup/rollup-openharmony-arm64': 4.60.1 - '@rollup/rollup-win32-arm64-msvc': 4.60.1 - '@rollup/rollup-win32-ia32-msvc': 4.60.1 - '@rollup/rollup-win32-x64-gnu': 4.60.1 - '@rollup/rollup-win32-x64-msvc': 4.60.1 + '@rollup/rollup-android-arm-eabi': 4.60.0 + '@rollup/rollup-android-arm64': 4.60.0 + '@rollup/rollup-darwin-arm64': 4.60.0 + '@rollup/rollup-darwin-x64': 4.60.0 + '@rollup/rollup-freebsd-arm64': 4.60.0 + '@rollup/rollup-freebsd-x64': 4.60.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.0 + '@rollup/rollup-linux-arm-musleabihf': 4.60.0 + '@rollup/rollup-linux-arm64-gnu': 4.60.0 + '@rollup/rollup-linux-arm64-musl': 4.60.0 + '@rollup/rollup-linux-loong64-gnu': 4.60.0 + '@rollup/rollup-linux-loong64-musl': 4.60.0 + '@rollup/rollup-linux-ppc64-gnu': 4.60.0 + '@rollup/rollup-linux-ppc64-musl': 4.60.0 + '@rollup/rollup-linux-riscv64-gnu': 4.60.0 + '@rollup/rollup-linux-riscv64-musl': 4.60.0 + '@rollup/rollup-linux-s390x-gnu': 4.60.0 + '@rollup/rollup-linux-x64-gnu': 4.60.0 + '@rollup/rollup-linux-x64-musl': 4.60.0 + '@rollup/rollup-openbsd-x64': 4.60.0 + '@rollup/rollup-openharmony-arm64': 4.60.0 + '@rollup/rollup-win32-arm64-msvc': 4.60.0 + '@rollup/rollup-win32-ia32-msvc': 4.60.0 + '@rollup/rollup-win32-x64-gnu': 4.60.0 + '@rollup/rollup-win32-x64-msvc': 4.60.0 fsevents: 2.3.3 - rss-parser@3.13.0(patch_hash=afac79a31a3db94c953d49680bc5528468f051957d461e913d2e2dbf5cd22a8d): + rss-parser@3.13.0(patch_hash=e1697dd9dde771024b5d0669a3eff6237e75fbac78381a6127012b67593bb2b7): dependencies: entities: 7.0.1 xml2js: 0.6.2 @@ -11684,17 +11411,17 @@ snapshots: map-obj: 4.3.0 to-snake-case: 1.0.0 - socks-proxy-agent@10.0.0: + socks-proxy-agent@8.0.5: dependencies: - agent-base: 9.0.0 + agent-base: 7.1.4 debug: 4.4.3 socks: 2.8.7 transitivePeerDependencies: - supports-color - socks-proxy-agent@8.0.5: + socks-proxy-agent@9.0.0: dependencies: - agent-base: 7.1.4 + agent-base: 8.0.0 debug: 4.4.3 socks: 2.8.7 transitivePeerDependencies: @@ -11738,10 +11465,6 @@ snapshots: stackback@0.0.2: {} - stacktrace-parser@0.1.11: - dependencies: - type-fest: 0.7.1 - standard-as-callback@2.1.0: {} statuses@2.0.2: {} @@ -11841,7 +11564,7 @@ snapshots: pump: 3.0.4 tar-stream: 3.1.8 optionalDependencies: - bare-fs: 4.7.0 + bare-fs: 4.5.6 bare-path: 3.0.0 transitivePeerDependencies: - bare-abort-controller @@ -11851,7 +11574,7 @@ snapshots: tar-stream@3.1.8: dependencies: b4a: 1.8.0 - bare-fs: 4.7.0 + bare-fs: 4.5.6 fast-fifo: 1.3.2 streamx: 2.25.0 transitivePeerDependencies: @@ -11928,11 +11651,6 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinyglobby@0.2.16: - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - tinypool@2.1.0: {} tinyrainbow@3.1.0: {} @@ -11945,11 +11663,11 @@ snapshots: tlds@1.261.0: {} - tldts-core@7.0.28: {} + tldts-core@7.0.27: {} - tldts@7.0.28: + tldts@7.0.27: dependencies: - tldts-core: 7.0.28 + tldts-core: 7.0.27 to-no-case@1.0.2: {} @@ -11970,7 +11688,7 @@ snapshots: tough-cookie@6.0.1: dependencies: - tldts: 7.0.28 + tldts: 7.0.27 tr46@0.0.3: {} @@ -12005,7 +11723,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 - tsdown@0.21.7(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)(synckit@0.11.12)(typescript@5.9.3): + tsdown@0.21.5(synckit@0.11.12)(typescript@5.9.3): dependencies: ansis: 4.2.0 cac: 7.0.0 @@ -12015,19 +11733,17 @@ snapshots: import-without-cache: 0.2.5 obug: 2.1.1 picomatch: 4.0.4 - rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2) - rolldown-plugin-dts: 0.23.2(rolldown@1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2))(typescript@5.9.3) + rolldown: 1.0.0-rc.11 + rolldown-plugin-dts: 0.22.5(rolldown@1.0.0-rc.11)(typescript@5.9.3) semver: 7.7.4 tinyexec: 1.0.4 tinyglobby: 0.2.15 tree-kill: 1.2.2 unconfig-core: 7.5.0 - unrun: 0.2.34(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)(synckit@0.11.12) + unrun: 0.2.34(synckit@0.11.12) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' - '@ts-macro/tsc' - '@typescript/native-preview' - oxc-resolver @@ -12063,8 +11779,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-fest@0.7.1: {} - type-fest@3.13.1: {} type-fest@4.41.0: {} @@ -12087,8 +11801,6 @@ snapshots: ufo@1.6.3: {} - uint8array-extras@1.5.0: {} - ultron@1.0.2: {} unbzip2-stream@1.4.3: @@ -12101,7 +11813,7 @@ snapshots: '@quansync/fs': 1.0.0 quansync: 1.0.0 - undici-types@7.19.2: {} + undici-types@7.18.2: {} undici-types@7.24.6: {} @@ -12109,7 +11821,7 @@ snapshots: undici@7.24.4: {} - undici@7.24.7: {} + undici@7.24.6: {} unenv@2.0.0-rc.24: dependencies: @@ -12159,20 +11871,17 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - unrun@0.2.34(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2)(synckit@0.11.12): + unrun@0.2.34(synckit@0.11.12): dependencies: - rolldown: 1.0.0-rc.12(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.2) + rolldown: 1.0.0-rc.12 optionalDependencies: synckit: 0.11.12 - transitivePeerDependencies: - - '@emnapi/core' - - '@emnapi/runtime' until-async@3.0.2: {} - update-browserslist-db@1.2.3(browserslist@4.28.2): + update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: - browserslist: 4.28.2 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -12232,35 +11941,35 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)): + vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) - vite: 7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color - typescript - vite@7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): + vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3): dependencies: - esbuild: 0.27.7 + esbuild: 0.27.4 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 postcss: 8.5.8 - rollup: 4.60.1 + rollup: 4.60.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.6.0 + '@types/node': 25.5.0 fsevents: 2.3.3 jiti: 2.6.1 tsx: 4.21.0 yaml: 2.8.3 - vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.6.0)(jiti@2.6.1)(jsdom@29.0.2(@noble/hashes@2.0.1))(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3): + vitest@4.0.9(@edge-runtime/vm@3.2.0)(@types/debug@4.1.13)(@types/node@25.5.0)(jiti@2.6.1)(jsdom@29.0.1(@noble/hashes@2.0.1))(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(tsx@4.21.0)(yaml@2.8.3): dependencies: '@vitest/expect': 4.0.9 - '@vitest/mocker': 4.0.9(msw@2.13.2(@types/node@25.6.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.0.9(msw@2.12.14(@types/node@25.5.0)(typescript@5.9.3))(vite@7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 4.0.9 '@vitest/runner': 4.0.9 '@vitest/snapshot': 4.0.9 @@ -12277,13 +11986,13 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vite: 7.3.1(@types/node@25.6.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) + vite: 7.3.1(@types/node@25.5.0)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@edge-runtime/vm': 3.2.0 '@types/debug': 4.1.13 - '@types/node': 25.6.0 - jsdom: 29.0.2(@noble/hashes@2.0.1) + '@types/node': 25.5.0 + jsdom: 29.0.1(@noble/hashes@2.0.1) transitivePeerDependencies: - jiti - less @@ -12371,26 +12080,26 @@ snapshots: word-wrap@1.2.5: {} - workerd@1.20260409.1: + workerd@1.20260317.1: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20260409.1 - '@cloudflare/workerd-darwin-arm64': 1.20260409.1 - '@cloudflare/workerd-linux-64': 1.20260409.1 - '@cloudflare/workerd-linux-arm64': 1.20260409.1 - '@cloudflare/workerd-windows-64': 1.20260409.1 + '@cloudflare/workerd-darwin-64': 1.20260317.1 + '@cloudflare/workerd-darwin-arm64': 1.20260317.1 + '@cloudflare/workerd-linux-64': 1.20260317.1 + '@cloudflare/workerd-linux-arm64': 1.20260317.1 + '@cloudflare/workerd-windows-64': 1.20260317.1 - wrangler@4.81.1(@cloudflare/workers-types@4.20260410.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10): + wrangler@4.77.0(@cloudflare/workers-types@4.20260317.1)(bufferutil@4.1.0)(utf-8-validate@5.0.10): dependencies: '@cloudflare/kv-asset-handler': 0.4.2 - '@cloudflare/unenv-preset': 2.16.0(unenv@2.0.0-rc.24)(workerd@1.20260409.1) + '@cloudflare/unenv-preset': 2.16.0(unenv@2.0.0-rc.24)(workerd@1.20260317.1) blake3-wasm: 2.1.5 esbuild: 0.27.3 - miniflare: 4.20260409.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + miniflare: 4.20260317.2(bufferutil@4.1.0)(utf-8-validate@5.0.10) path-to-regexp: 6.3.0 unenv: 2.0.0-rc.24 - workerd: 1.20260409.1 + workerd: 1.20260317.1 optionalDependencies: - '@cloudflare/workers-types': 4.20260410.1 + '@cloudflare/workers-types': 4.20260317.1 fsevents: 2.3.3 transitivePeerDependencies: - bufferutil diff --git a/tsdown-worker.config.ts b/tsdown-worker.config.ts index 979a5850b2dc..5b7626951411 100644 --- a/tsdown-worker.config.ts +++ b/tsdown-worker.config.ts @@ -89,7 +89,6 @@ export default defineConfig({ 'node:child_process': path.resolve('./lib/shims/node-child-process.ts'), 'dotenv/config': path.resolve('./lib/shims/dotenv-config.ts'), '@sentry/node': path.resolve('./lib/shims/sentry-node.ts'), - '@honeybadger-io/js': path.resolve('./lib/shims/honeybadger.ts'), 'xxhash-wasm': path.resolve('./lib/shims/xxhash-wasm.ts'), // Routes file with Worker-specific build (match relative import from lib/) '../assets/build/routes.js': path.resolve('./assets/build/routes-worker.js'),