mirror of
https://github.com/yt-dlp/ejs.git
synced 2026-06-13 08:42:29 +00:00
Compare commits
24 Commits
0.3.0
...
d60b8244e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d60b8244e7 | ||
|
|
64067b031b | ||
|
|
7c5c5e0dd1 | ||
|
|
2231f1fd6e | ||
|
|
aef78f70e7 | ||
|
|
4fb477f4af | ||
|
|
68448fa0ab | ||
|
|
cd4e87f52e | ||
|
|
41ff68e6f8 | ||
|
|
5bc9811c7a | ||
|
|
1b648c34c1 | ||
|
|
d13ca53401 | ||
|
|
a3095891a9 | ||
|
|
c51d14fa61 | ||
|
|
96c417f90a | ||
|
|
e91d03f58a | ||
|
|
32e63d577f | ||
|
|
83777e845d | ||
|
|
f4189efdc7 | ||
|
|
a0faf4144a | ||
|
|
06d71457ef | ||
|
|
3e76dde153 | ||
|
|
4f1d91dbb1 | ||
|
|
4b4ac2b896 |
466
.github/workflows/ci.yml
vendored
466
.github/workflows/ci.yml
vendored
@@ -1,76 +1,151 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'LICENSE'
|
||||
branches: ['main']
|
||||
# This workflow contains required checks and needs to run for EVERY pull_request
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'README.md'
|
||||
- 'LICENSE'
|
||||
branches: ['**']
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
ACTIONLINT_VERSION: "1.7.12"
|
||||
ACTIONLINT_SHA256SUM: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
|
||||
ACTIONLINT_REPO: rhysd/actionlint
|
||||
GH_TELEMETRY: "false"
|
||||
|
||||
jobs:
|
||||
ruff-format:
|
||||
name: Ruff format check
|
||||
actionlint:
|
||||
name: Lint workflows
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: astral-sh/ruff-action@v3
|
||||
with:
|
||||
args: "check --output-format github"
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
ruff-lint:
|
||||
name: Ruff linting check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: astral-sh/ruff-action@v3
|
||||
with:
|
||||
args: "format --check --diff"
|
||||
- name: Install requirements
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ACTIONLINT_TARBALL: ${{ format('actionlint_{0}_linux_amd64.tar.gz', env.ACTIONLINT_VERSION) }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt -y install shellcheck
|
||||
gh release download \
|
||||
--repo "${ACTIONLINT_REPO}" \
|
||||
--pattern "${ACTIONLINT_TARBALL}" \
|
||||
"v${ACTIONLINT_VERSION}"
|
||||
gh attestation verify \
|
||||
--repo "${ACTIONLINT_REPO}" \
|
||||
"${ACTIONLINT_TARBALL}"
|
||||
printf '%s %s' "${ACTIONLINT_SHA256SUM}" "${ACTIONLINT_TARBALL}" | sha256sum -c -
|
||||
tar xvzf "${ACTIONLINT_TARBALL}" actionlint
|
||||
sudo install -D --mode=755 actionlint /usr/bin/
|
||||
|
||||
prettier:
|
||||
name: Prettier check
|
||||
- name: Run actionlint
|
||||
run: |
|
||||
actionlint -color
|
||||
|
||||
zizmor:
|
||||
name: Audit workflows
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read # Needed by zizmorcore/zizmor-action if repository is private
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
|
||||
with:
|
||||
advanced-security: false
|
||||
persona: pedantic
|
||||
|
||||
py_format:
|
||||
name: Python format check
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
|
||||
with:
|
||||
args: "check --output-format github"
|
||||
|
||||
py_lint:
|
||||
name: Python lint check
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
|
||||
with:
|
||||
args: "format --check --diff"
|
||||
|
||||
js_format:
|
||||
name: JavaScript format check
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno v2.x (latest)
|
||||
uses: denoland/setup-deno@v2
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- name: Install Deno requirements
|
||||
run: |
|
||||
deno install
|
||||
- name: Run Prettier check
|
||||
deno install --frozen
|
||||
|
||||
- name: Run format check
|
||||
run: |
|
||||
deno task fmt:check
|
||||
|
||||
eslint:
|
||||
name: ESLint check
|
||||
js_lint:
|
||||
name: JavaScript lint check
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno v2.x (latest)
|
||||
uses: denoland/setup-deno@v2
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- name: Install Deno requirements
|
||||
run: |
|
||||
deno install
|
||||
- name: Run ESLint check
|
||||
deno install --frozen
|
||||
|
||||
- name: Run lint check
|
||||
run: |
|
||||
deno task lint
|
||||
|
||||
python_tests:
|
||||
name: Python tests
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -78,72 +153,98 @@ jobs:
|
||||
runner: [ubuntu-latest, windows-latest]
|
||||
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', pypy-3.11]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# required for hatch-vcs versioning
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno v2.x (latest)
|
||||
uses: denoland/setup-deno@v2
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Build project
|
||||
shell: bash
|
||||
run: |
|
||||
# `pip install -e` omits the force-included JS, so use `build` instead
|
||||
python -m pip install -U build
|
||||
python -m build
|
||||
|
||||
- name: Unpack wheel (Linux)
|
||||
if: matrix.runner == 'ubuntu-latest'
|
||||
shell: bash
|
||||
run: |
|
||||
unzip -u dist/yt_dlp_ejs-*.whl "yt_dlp_ejs/*"
|
||||
|
||||
- name: Unpack wheel (Windows)
|
||||
if: matrix.runner == 'windows-latest'
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
$PSNativeCommandUseErrorActionPreference = $true
|
||||
Expand-Archive -Path dist/yt_dlp_ejs-*.whl -DestinationPath ./ -Force
|
||||
|
||||
- name: Run Python tests
|
||||
timeout-minutes: 5
|
||||
shell: bash
|
||||
run: |
|
||||
python -Werror -m unittest
|
||||
|
||||
prepare:
|
||||
name: Prepare JS runtime tests
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno v2.x (latest)
|
||||
uses: denoland/setup-deno@v2
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
deno-version: v2.x
|
||||
|
||||
- name: Install Deno requirements
|
||||
run: |
|
||||
deno install
|
||||
deno install --frozen
|
||||
|
||||
- name: Build control bundle
|
||||
run: |
|
||||
deno task bundle
|
||||
|
||||
- name: Generate bundle hashes
|
||||
shell: bash
|
||||
run: |
|
||||
pushd dist
|
||||
sha256sum -- yt.solver.*.js | tee SHA2-256SUMS
|
||||
popd
|
||||
|
||||
- name: Upload bundle hashes
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: bundle-hashes
|
||||
path: |
|
||||
dist/SHA2-256SUMS
|
||||
compression-level: 0
|
||||
|
||||
- name: Cache player JS files
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MINS: 1
|
||||
with:
|
||||
path: |
|
||||
src/yt/solver/test/players
|
||||
key: test-player-js-${{ hashFiles('src/yt/solver/test/tests.ts') }}
|
||||
|
||||
- name: Download player JS files
|
||||
timeout-minutes: 15
|
||||
run: |
|
||||
deno run \
|
||||
--no-prompt \
|
||||
@@ -152,52 +253,147 @@ jobs:
|
||||
--allow-net=www.youtube.com \
|
||||
--allow-sys=uid \
|
||||
src/yt/solver/test/download.ts
|
||||
|
||||
- name: Upload player JS artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: player-js
|
||||
path: |
|
||||
src/yt/solver/test/players/*
|
||||
compression-level: 0
|
||||
|
||||
deno_build:
|
||||
name: Test Deno build
|
||||
pnpm_build:
|
||||
name: Test pnpm build
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# required for hatch-vcs versioning
|
||||
fetch-depth: 0
|
||||
- name: Install Deno
|
||||
uses: denoland/setup-deno@v2
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||
with:
|
||||
deno-version: "2.0.0" # minimum supported version
|
||||
- uses: actions/setup-python@v6
|
||||
# minimum supported version
|
||||
version: "10.16.0"
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.10" # minimum supported version
|
||||
# minimum supported version
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python requirements
|
||||
run: |
|
||||
python -m pip install -U build
|
||||
- name: Test Deno build
|
||||
|
||||
- name: Test pnpm build
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Verify artifact contents
|
||||
shell: bash
|
||||
run: |
|
||||
tar -tvzf dist/yt_dlp_ejs-*.tar.gz
|
||||
unzip -l dist/yt_dlp_ejs-*.whl | tee .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/core\.min\.js' .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/lib\.min\.js' .wheel_contents
|
||||
- name: Install Deno requirements
|
||||
|
||||
- name: Install pnpm requirements
|
||||
run: |
|
||||
deno install
|
||||
- name: Bundle with Deno
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
- name: Bundle with pnpm
|
||||
run: |
|
||||
deno task bundle
|
||||
pnpm run bundle
|
||||
|
||||
- name: Download bundle hashes
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: bundle-hashes
|
||||
|
||||
- name: Verify bundle hashes
|
||||
run: |
|
||||
cd dist
|
||||
sha256sum -c SHA2-256SUMS
|
||||
|
||||
deno_lock_check:
|
||||
name: Test Deno lockfile
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
# minimum supported version
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Verify lockfile
|
||||
run: |
|
||||
python ./check.py
|
||||
|
||||
deno_build:
|
||||
name: Test Deno build
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# required for hatch-vcs versioning
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
# minimum supported version
|
||||
deno-version: "2.3.0"
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
# minimum supported version
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python requirements
|
||||
run: |
|
||||
python -m pip install -U build
|
||||
|
||||
- name: Test Deno build
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Verify artifact contents
|
||||
shell: bash
|
||||
run: |
|
||||
tar -tvzf dist/yt_dlp_ejs-*.tar.gz
|
||||
unzip -l dist/yt_dlp_ejs-*.whl | tee .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/core\.min\.js' .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/lib\.min\.js' .wheel_contents
|
||||
|
||||
- name: Install Deno requirements
|
||||
run: |
|
||||
deno install --frozen
|
||||
|
||||
- name: Bundle with Deno
|
||||
run: |
|
||||
deno task bundle
|
||||
|
||||
- name: Download bundle hashes
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: bundle-hashes
|
||||
|
||||
- name: Verify bundle hashes
|
||||
run: |
|
||||
cd dist
|
||||
@@ -206,65 +402,93 @@ jobs:
|
||||
deno_tests:
|
||||
name: Run Deno tests
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Deno
|
||||
uses: denoland/setup-deno@v2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
deno-version: "2.0.0" # minimum supported version
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Deno
|
||||
uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
# minimum supported version
|
||||
deno-version: "2.3.0"
|
||||
|
||||
- name: Install Deno requirements
|
||||
run: |
|
||||
deno install
|
||||
deno install --frozen
|
||||
|
||||
- name: Download player JS artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: src/yt/solver/test/players
|
||||
name: player-js
|
||||
|
||||
- name: Run Deno tests
|
||||
run: |
|
||||
deno test \
|
||||
xargs -n 1 -P 10 deno test \
|
||||
--no-prompt \
|
||||
--allow-read=src/yt/solver/test/players/
|
||||
--no-check \
|
||||
--allow-read=src/yt/solver/test/players/ \
|
||||
--filter <<<"$(printf -- '-%s-\n' main tcc tce es5 es6 tv tv_es6 phone es6_tcc es6_tce)"
|
||||
|
||||
bun_build:
|
||||
name: Test Bun build
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# required for hatch-vcs versioning
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
with:
|
||||
bun-version: "1.0.31" # minimum supported version
|
||||
- uses: actions/setup-python@v6
|
||||
# minimum supported version
|
||||
bun-version: "1.2.11"
|
||||
no-cache: true
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.10" # minimum supported version
|
||||
# minimum supported version
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python requirements
|
||||
run: |
|
||||
python -m pip install -U build
|
||||
|
||||
- name: Test Bun build
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Verify artifact contents
|
||||
shell: bash
|
||||
run: |
|
||||
tar -tvzf dist/yt_dlp_ejs-*.tar.gz
|
||||
unzip -l dist/yt_dlp_ejs-*.whl | tee .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/core\.min\.js' .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/lib\.min\.js' .wheel_contents
|
||||
|
||||
- name: Install Bun requirements
|
||||
run: |
|
||||
bun install
|
||||
bun install --frozen-lockfile
|
||||
|
||||
- name: Bundle with Bun
|
||||
run: |
|
||||
bun --bun run bundle
|
||||
|
||||
- name: Download bundle hashes
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: bundle-hashes
|
||||
|
||||
- name: Verify bundle hashes
|
||||
run: |
|
||||
cd dist
|
||||
@@ -273,21 +497,31 @@ jobs:
|
||||
bun_tests:
|
||||
name: Run Bun tests
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
bun-version: "1.2.11" # XXX: We support 1.0.31, but test suite requires 1.2.11+
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Bun
|
||||
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
|
||||
with:
|
||||
# minimum supported version
|
||||
bun-version: "1.2.11"
|
||||
no-cache: true
|
||||
|
||||
- name: Install Bun requirements
|
||||
run: |
|
||||
bun install
|
||||
bun install --frozen-lockfile
|
||||
|
||||
- name: Download player JS artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: src/yt/solver/test/players
|
||||
name: player-js
|
||||
|
||||
- name: Run Bun tests
|
||||
run: |
|
||||
bun test
|
||||
@@ -295,41 +529,57 @@ jobs:
|
||||
node_build:
|
||||
name: Test Node build
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
# required for hatch-vcs versioning
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: "20.0" # minimum supported version
|
||||
- uses: actions/setup-python@v6
|
||||
# minimum supported version
|
||||
node-version: "22.0.0"
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.10" # minimum supported version
|
||||
# minimum supported version
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python requirements
|
||||
run: |
|
||||
python -m pip install -U build
|
||||
|
||||
- name: Test Node build
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Verify artifact contents
|
||||
shell: bash
|
||||
run: |
|
||||
tar -tvzf dist/yt_dlp_ejs-*.tar.gz
|
||||
unzip -l dist/yt_dlp_ejs-*.whl | tee .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/core\.min\.js' .wheel_contents
|
||||
grep -q 'yt_dlp_ejs/yt/solver/lib\.min\.js' .wheel_contents
|
||||
|
||||
- name: Install Node requirements
|
||||
run: |
|
||||
npm install
|
||||
npm ci
|
||||
|
||||
- name: Bundle with Node
|
||||
run: |
|
||||
npm run bundle
|
||||
|
||||
- name: Download bundle hashes
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: bundle-hashes
|
||||
|
||||
- name: Verify bundle hashes
|
||||
run: |
|
||||
cd dist
|
||||
@@ -338,40 +588,54 @@ jobs:
|
||||
node_tests:
|
||||
name: Run Node tests
|
||||
needs: [prepare]
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
node-version: "22.18" # XXX: We support 20.0, but test suite requires 22.18+
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
# minimum supported version
|
||||
node-version: "22.0.0"
|
||||
|
||||
- name: Install Node requirements
|
||||
run: |
|
||||
npm install
|
||||
npm ci
|
||||
|
||||
- name: Download player JS artifact
|
||||
uses: actions/download-artifact@v5
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: src/yt/solver/test/players
|
||||
name: player-js
|
||||
|
||||
- name: Run Node tests
|
||||
run: |
|
||||
node --test
|
||||
|
||||
all_passed:
|
||||
# Required check; do not change name
|
||||
name: all_passed
|
||||
needs:
|
||||
- ruff-format
|
||||
- ruff-lint
|
||||
- prettier
|
||||
- eslint
|
||||
- actionlint
|
||||
- zizmor
|
||||
- py_format
|
||||
- py_lint
|
||||
- js_format
|
||||
- js_lint
|
||||
- python_tests
|
||||
- pnpm_build
|
||||
- deno_lock_check
|
||||
- deno_build
|
||||
- deno_tests
|
||||
- bun_build
|
||||
- bun_tests
|
||||
- node_build
|
||||
- node_tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- name: All checks passed
|
||||
run: |
|
||||
echo "All checks passed!"
|
||||
- run: |
|
||||
true
|
||||
|
||||
55
.github/workflows/release.yml
vendored
55
.github/workflows/release.yml
vendored
@@ -4,43 +4,56 @@ on:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
GH_TELEMETRY: "false"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build artifacts
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: denoland/setup-deno@v2
|
||||
fetch-depth: 0 # Needed for hatch-vcs versioning
|
||||
persist-credentials: false
|
||||
|
||||
- uses: denoland/setup-deno@e95548e56dfa95d4e1a28d6f422fafe75c4c26fb # v2.0.3
|
||||
with:
|
||||
deno-version: v2.x
|
||||
- uses: actions/setup-python@v6
|
||||
deno-version: 3fbb1daddbc9333cddf0d8c0735811717dd70f7a # v2.6.3
|
||||
cache: false
|
||||
|
||||
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: "3.14"
|
||||
|
||||
- name: Install Python requirements
|
||||
run: |
|
||||
python -m pip install -U build
|
||||
|
||||
- name: Build Python artifacts
|
||||
run: |
|
||||
python -m build
|
||||
|
||||
- name: Upload Python artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: artifacts-py
|
||||
path: |
|
||||
dist/yt_dlp_ejs-*.whl
|
||||
dist/yt_dlp_ejs-*.tar.gz
|
||||
compression-level: 0
|
||||
|
||||
- name: Build JavaScript artifacts
|
||||
run: |
|
||||
deno install --frozen
|
||||
deno task bundle
|
||||
|
||||
- name: Upload JavaScript artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
with:
|
||||
name: artifacts-js
|
||||
path: |
|
||||
@@ -51,17 +64,17 @@ jobs:
|
||||
name: Publish to PyPI
|
||||
needs: [build]
|
||||
if: github.repository == 'yt-dlp/ejs'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write # required for PyPI trusted publishing
|
||||
id-token: write # Needed for PyPI trusted publishing
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
name: artifacts-py
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
|
||||
with:
|
||||
verbose: true
|
||||
|
||||
@@ -69,18 +82,20 @@ jobs:
|
||||
name: Create GitHub release
|
||||
needs: [build, publish_pypi]
|
||||
if: always() && !failure() && !cancelled()
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
contents: write # Needed by gh to publish release to Github
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/download-artifact@v5
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
pattern: artifacts-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
TAG: ${{ github.ref_name }}
|
||||
|
||||
8
.github/zizmor.yml
vendored
Normal file
8
.github/zizmor.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
rules:
|
||||
concurrency-limits:
|
||||
ignore:
|
||||
- release.yml # Can only be triggered by a tag pushed by a maintainer
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
"*": hash-pin
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,7 +2,5 @@
|
||||
*.py[cd]
|
||||
/yt_dlp_ejs/_version.py
|
||||
/node_modules
|
||||
/bun.lock
|
||||
/package-lock.json
|
||||
/.idea
|
||||
/.venv
|
||||
|
||||
6
.oxfmtrc.json
Normal file
6
.oxfmtrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "./node_modules/oxfmt/configuration_schema.json",
|
||||
"printWidth": 80,
|
||||
"sortImports": true,
|
||||
"ignorePatterns": ["**/*.toml", ".github/**"]
|
||||
}
|
||||
106
README.md
106
README.md
@@ -10,13 +10,44 @@ Install ejs into the same environment as yt-dlp:
|
||||
pip install -U yt-dlp-ejs
|
||||
```
|
||||
|
||||
## Runtime requirements
|
||||
|
||||
This project supports the following runtimes/engines:
|
||||
|
||||
| Runtime / engine | Required version |
|
||||
| ------------------ | -------------------- |
|
||||
| deno | `>=2.3` |
|
||||
| node | `>=22` |
|
||||
| quickjs | `>=2023-12-9` |
|
||||
| quickjs-ng | any |
|
||||
| bun _(deprecated)_ | `>=1.2.11, <=1.3.14` |
|
||||
|
||||
## Development
|
||||
|
||||
While this project does pin its dependencies,
|
||||
it only provides a lockfile for building with `deno`.
|
||||
You may install dependencies using any compatible package manager.
|
||||
The project provides lockfiles for every supported package manager.
|
||||
|
||||
If you only have Python and a JS runtime, then you may instead run `./hatch_build.py`.
|
||||
This will transparently invoke one of the supported JS runtimes for the build.
|
||||
|
||||
If you notice differences between different runtimes' builds
|
||||
please open an issue [here](<https://github.com/yt-dlp/ejs/issues/new>).
|
||||
please open an issue [here](https://github.com/yt-dlp/ejs/issues/new).
|
||||
|
||||
### Development requirements
|
||||
|
||||
Developers should have the following tools installed:
|
||||
|
||||
| Runtime / package manager | Required version |
|
||||
| ------------------------- | --------------------------------- |
|
||||
| deno | `>=2.6` |
|
||||
| node | `^24.14.1 \|\| ^25.7.0 \|\| >=26` |
|
||||
| npm | `>=11.10` |
|
||||
| bun | `>=1.2.11, <=1.3.14` |
|
||||
| pnpm | `>=10.16.0` |
|
||||
| quickjs _(optional)_ | `>=2025-4-26` |
|
||||
| quickjs-ng _(optional)_ | `>=0.12.0` |
|
||||
|
||||
quickjs/quickjs-ng is only needed for yt-dlp integration tests,
|
||||
which can usually be handled by CI.
|
||||
|
||||
### Build
|
||||
|
||||
@@ -26,19 +57,23 @@ The build hook will automatically invoke `deno`, `bun` or `node` as required.
|
||||
Alternatively, to only build the JavaScript files you can run the `bundle` script manually:
|
||||
|
||||
```bash
|
||||
# Deno:
|
||||
deno install --frozen
|
||||
deno task bundle
|
||||
|
||||
# Bun:
|
||||
bun install
|
||||
bun --bun run bundle
|
||||
|
||||
# Node:
|
||||
npm install
|
||||
npm run bundle
|
||||
python hatch_build.py
|
||||
```
|
||||
|
||||
This will automatically select an available runtime and build using it.
|
||||
|
||||
For more fine-grained control over how to build the package, you can set these environment variables:
|
||||
|
||||
- `EJS_BUILD_SKIP_INSTALL`: If this environment variable is set, the install step will be skipped.
|
||||
It is expected that the required packages are available for the selected bundler.
|
||||
No network access should be required if this variable is set.
|
||||
- `EJS_BUILD_INSTALLER`: Order of installers to try, separated by `:` on POSIX or `;` on Windows.
|
||||
These will be used to install the required dependencies for bundling the JavaScript package.
|
||||
Can be any of `pnpm`, `deno`, `bun` or `npm` (this is also the default order).
|
||||
- `EJS_BUILD_BUNDLER`: Order of bundlers to try, separated by `:` on POSIX or `;` on Windows.
|
||||
These will be used to perform the bundling of the JavaScript package (calling rollup under the hood).
|
||||
Can be any of `esbuild`, `pnpm`, `deno`, `bun`, `node` (this is also the default order).
|
||||
|
||||
### Tests
|
||||
|
||||
First, make sure the project's dependencies are installed and download the player JS files:
|
||||
@@ -49,11 +84,11 @@ deno install --frozen
|
||||
deno run src/yt/solver/test/download.ts
|
||||
|
||||
# Bun:
|
||||
bun install
|
||||
bun install --frozen-lockfile
|
||||
bun --bun run src/yt/solver/test/download.ts
|
||||
|
||||
# Node 22.6+:
|
||||
npm install
|
||||
npm ci
|
||||
node --experimental-strip-types src/yt/solver/test/download.ts
|
||||
```
|
||||
|
||||
@@ -70,10 +105,39 @@ bun test
|
||||
node --test
|
||||
```
|
||||
|
||||
## Upgrading packages
|
||||
|
||||
When upgrading packages in package.json, all lockfiles must be updated simultaneously.
|
||||
To do this, run the following commands:
|
||||
|
||||
```bash
|
||||
# 1. Upgrade all packages automatically
|
||||
pnpm upgrade --latest
|
||||
# or upgrade only development dependencies
|
||||
pnpm upgrade --latest --dev
|
||||
# or upgrade a specific package, e.g. meriyah
|
||||
pnpm upgrade --latest meriyah
|
||||
|
||||
# 2. Generate base `package-lock.json` with npm (using a 7-day cooldown)
|
||||
npm config set min-release-age=7
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install
|
||||
|
||||
# 3. Migrate to other package managers
|
||||
pnpm import
|
||||
bun pm migrate --force
|
||||
|
||||
# 4. Generate a separate `deno.lock` (using a 7-day cooldown)
|
||||
deno install --lockfile-only --minimum-dependency-age=P7D
|
||||
|
||||
# 5. Ensure that `deno.lock` is equivalent to `package-lock.json`
|
||||
python check.py
|
||||
```
|
||||
|
||||
## Licensing
|
||||
|
||||
This code is licensed under [Unlicense](<https://unlicense.org/>).
|
||||
This code is licensed under [Unlicense](https://unlicense.org/).
|
||||
|
||||
An exception to this are the prebuilt wheels, which contain both
|
||||
[`meriyah`](<https://github.com/meriyah/meriyah>) and [`astring`](<https://github.com/davidbonnet/astring>),
|
||||
licensed under [`ISC`](<https://github.com/meriyah/meriyah?tab=ISC-1-ov-file>) and [`MIT`](<https://github.com/davidbonnet/astring?tab=MIT-1-ov-file>), respectively.
|
||||
An exception to this is the prebuilt wheels, which contain both
|
||||
[`meriyah`](https://github.com/meriyah/meriyah) and [`astring`](https://github.com/davidbonnet/astring),
|
||||
licensed under [`ISC`](https://github.com/meriyah/meriyah?tab=ISC-1-ov-file) and [`MIT`](https://github.com/davidbonnet/astring?tab=MIT-1-ov-file), respectively.
|
||||
|
||||
32
build.mjs
Normal file
32
build.mjs
Normal file
@@ -0,0 +1,32 @@
|
||||
import * as esbuild from "esbuild";
|
||||
|
||||
const buildConfig = await stdinJSON();
|
||||
const result = await esbuild.build(buildConfig);
|
||||
console.log(JSON.stringify(result.metafile ?? null));
|
||||
await esbuild.stop();
|
||||
|
||||
async function stdinJSON() {
|
||||
const chunks = [];
|
||||
if (globalThis.Deno) {
|
||||
for await (const chunk of globalThis.Deno.stdin.readable) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
const length = chunks.reduce(
|
||||
(previous, chunk) => previous + chunk.length,
|
||||
0,
|
||||
);
|
||||
const buffer = new Uint8Array(length);
|
||||
let offset = 0;
|
||||
for (const chunk of chunks) {
|
||||
buffer.set(chunk, offset);
|
||||
offset += chunk.length;
|
||||
}
|
||||
return JSON.parse(new TextDecoder().decode(buffer));
|
||||
}
|
||||
|
||||
for await (const chunk of process.stdin) {
|
||||
chunks.push(chunk);
|
||||
}
|
||||
const text = Buffer.concat(chunks).toString("utf-8");
|
||||
return JSON.parse(text);
|
||||
}
|
||||
179
bun.lock
Normal file
179
bun.lock
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"configVersion": 1,
|
||||
"workspaces": {
|
||||
"": {
|
||||
"name": "ejs",
|
||||
"dependencies": {
|
||||
"astring": "1.9.0",
|
||||
"meriyah": "6.1.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "1.3.0",
|
||||
"@types/deno": "2.5.0",
|
||||
"@types/node": "24.8.1",
|
||||
"esbuild": "0.28.0",
|
||||
"globals": "16.4.0",
|
||||
"oxfmt": "^0.48.0",
|
||||
"oxlint": "^1.63.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.0", "", { "os": "aix", "cpu": "ppc64" }, "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA=="],
|
||||
|
||||
"@esbuild/android-arm": ["@esbuild/android-arm@0.28.0", "", { "os": "android", "cpu": "arm" }, "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ=="],
|
||||
|
||||
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.0", "", { "os": "android", "cpu": "arm64" }, "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw=="],
|
||||
|
||||
"@esbuild/android-x64": ["@esbuild/android-x64@0.28.0", "", { "os": "android", "cpu": "x64" }, "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA=="],
|
||||
|
||||
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q=="],
|
||||
|
||||
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ=="],
|
||||
|
||||
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q=="],
|
||||
|
||||
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw=="],
|
||||
|
||||
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.0", "", { "os": "linux", "cpu": "arm" }, "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw=="],
|
||||
|
||||
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A=="],
|
||||
|
||||
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.0", "", { "os": "linux", "cpu": "ia32" }, "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ=="],
|
||||
|
||||
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg=="],
|
||||
|
||||
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w=="],
|
||||
|
||||
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg=="],
|
||||
|
||||
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.0", "", { "os": "linux", "cpu": "none" }, "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ=="],
|
||||
|
||||
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q=="],
|
||||
|
||||
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.0", "", { "os": "linux", "cpu": "x64" }, "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ=="],
|
||||
|
||||
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw=="],
|
||||
|
||||
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.0", "", { "os": "none", "cpu": "x64" }, "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw=="],
|
||||
|
||||
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.0", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g=="],
|
||||
|
||||
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA=="],
|
||||
|
||||
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.0", "", { "os": "none", "cpu": "arm64" }, "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w=="],
|
||||
|
||||
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.0", "", { "os": "sunos", "cpu": "x64" }, "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw=="],
|
||||
|
||||
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA=="],
|
||||
|
||||
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA=="],
|
||||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.0", "", { "os": "win32", "cpu": "x64" }, "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw=="],
|
||||
|
||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.48.0", "", { "os": "android", "cpu": "arm" }, "sha512-uwqk+/KhQvBIpULD8SMM/zAafMRC/+DV/xsEQjkkIsJ/kLmEI/2bxonVowcYTiXqqZ/a0FEW8DPkZY3VvwELDA=="],
|
||||
|
||||
"@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.48.0", "", { "os": "android", "cpu": "arm64" }, "sha512-VUCiKuXK5+McVssgHEJdrcGK7hRJzrRb36zm9/jwzMholyYt4BgXhw5Nm1V1DX6Ce717Zi/1jk432b/tgmQgtQ=="],
|
||||
|
||||
"@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.48.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-IkKp8rnIyQLW6Jt+6jragCbUVYSayk55lapiprLjIVvt4NczLyO/nwX2GgefLQ5iaBdfS8UEAFgCs/pLO6Cl0w=="],
|
||||
|
||||
"@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.48.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-+aFuhsGIuvnoOjXyKVHMhPKJZR1kQkAl8QyrKoMlA7yJsSTC3N0Asl53La8TChSHhW8epToQ/Q0nvLmEmfNmLg=="],
|
||||
|
||||
"@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.48.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fbqzQL8FjI9gGnktI7RIo0dksDziTAYBy7xlI7jU7eID5fxLF/25fS4Xj6GydD8Y5oWHL83U4NK160QaOAxtyg=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.48.0", "", { "os": "linux", "cpu": "arm" }, "sha512-hn4i0zhAyTiB3ZHjQfYUZkDvrbVkohw1S7pySWxWUoZ87HnkDoTFThj7QTxk40hNPOTUP0vHbPRNamFIv1HBJQ=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.48.0", "", { "os": "linux", "cpu": "arm" }, "sha512-R4WBD9qF3QM9hqgdAa+fBGXmquTvDUujrPQ36t2Sjk8RPOSKGHDeN7l/khr10hqbQaOq9KCgPHG9ubNET/X/RQ=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.48.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-5bVdwSwlm1M8wbYCorLOxWxUBw/8tBvHYyQNIfwWVPwOJaj5vg1APSGJQVpwJfV5VNE9PSrR91UKEpoNwHhqUA=="],
|
||||
|
||||
"@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.48.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-vCS3Fk7gFslTqE1lUE2IlroyVV7u/9SmMA/uBqDoshuck2psGWcjW0ePyPZI3rM3+qtf2pDaMVIKMHozraifuw=="],
|
||||
|
||||
"@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.48.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-gKtfFfueUClXDumyoHUbymqRf7prHejOOyzJK0eIJn93GF9JBdFHdo60TM1ZBHxkEwZvjuOgHmKtneKbEOc/Eg=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.48.0", "", { "os": "linux", "cpu": "none" }, "sha512-SYt0UhOvZD/UwZz9sXq6J2uAw8o24f5VZpLB2DH01f6MevshmlgakQlZe2lwek2sZJkd07eLu7mZa0g7yeiw7Q=="],
|
||||
|
||||
"@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.48.0", "", { "os": "linux", "cpu": "none" }, "sha512-JLbrwck2AopG4ud/XklZO5N+qxGC7cS7ROvXZVNfx0MCLDDL2kGOLvzuWORkVjnjAM0CMAfIMU2zNBtQbM+4dw=="],
|
||||
|
||||
"@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.48.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-mdxt5L8OQLxkQH+JVpdC/lknZNe0lX4hlO3d8+xvw2wToo+iDrid9tiGOd5bmHfUVd5wVhrUry0qlu5vq66NkQ=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.48.0", "", { "os": "linux", "cpu": "x64" }, "sha512-oEz1BQwMrV7OMEFx/3VPDU3n9TM0AnxpktDYXjEg5i6nTX87wo18wSfBvkl4tzAICdKtoAQAdBIl7Y7hsPlx5w=="],
|
||||
|
||||
"@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.48.0", "", { "os": "linux", "cpu": "x64" }, "sha512-g2SKTTurP5mWjd8Ecait0erYqmltL4IqW1EwttM25BxM6NiTt4ubobJYMR1uox1V2QgG4UfHH10CGRvWlUixjw=="],
|
||||
|
||||
"@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.48.0", "", { "os": "none", "cpu": "arm64" }, "sha512-CIg24VgheEpvolHL2gQuax5qcQ602bRMHrJ9g8XsQr3iVj9aSPgopigBKuMqrXsupwkrU+RQCn5cG8PgFntR6w=="],
|
||||
|
||||
"@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.48.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-zeaWkcxcEULwkGF3I/HgEvcDPN8buYDrxibBUa/IFh5Vmwyge+KpLO+hEwSovW349H0O/C0Z2kaFmEzEDm00/Q=="],
|
||||
|
||||
"@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.48.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-yiEKnIAGvx5CyZQOlMaNlZkAbwT7/Quk0j3WLt+PR5hK+qYjPTRRJYDfD77wCBPLvEYAG41v4KG3iL0H+uxoxg=="],
|
||||
|
||||
"@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.48.0", "", { "os": "win32", "cpu": "x64" }, "sha512-GSD2+7t2UoVMV2NgxXypa4bKewflPMAjYnF0Xw9/ht82ZfafAHhb8STwrEd7wlH2PFogt5zw3WVCxYJaHUdbeQ=="],
|
||||
|
||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.63.0", "", { "os": "android", "cpu": "arm" }, "sha512-A9xLtQt7i0OA1PoB/meog6kikXI9CdwEp7ZwQqmgnpKn3G3b1orvTDy8CQ6T7w1HvDrgWGB78PkFKcWgibcTCg=="],
|
||||
|
||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.63.0", "", { "os": "android", "cpu": "arm64" }, "sha512-SQo+ZMvdR9l3CxZp5W5gFNxSiDxclY6lOzzNpKYLF8asESpm3Pwumx0gER5T7aHLF1/2BAAtLD3DiDkdgy4V1A=="],
|
||||
|
||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.63.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-6W82XjJDTmMnjg30427l0dufpnyLoq7wEukKdM6/g2VIybRVuQiBVh43EA4b+UxZ3+tLcKm+Or/pXGNgLCEU8g=="],
|
||||
|
||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.63.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-CnWd/YCuVG5W1BYkjJEVbJG11o526O9qAwBEQM+nh8K19CRFUkFdROXCyYkGmroHEYQe4vgQ6+lh3550Lp35Xw=="],
|
||||
|
||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.63.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-a4eZAqrmtajqcxfdAzC+l7g3PaE3V8hpAYqqeD3fTxLXOMFdK3eNTZrU80n4dDEVm0JXy1aL5PqvqWldBl6zYA=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.63.0", "", { "os": "linux", "cpu": "arm" }, "sha512-tYUtU9TdbU3uXF5D62g5zXJ13iniFGhXQx5vp9cyEjGdbSAY3VdFBSaldYvyoDmgMZ0ZYuwQP1Y4t2Fhejwa0w=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.63.0", "", { "os": "linux", "cpu": "arm" }, "sha512-I5r3twFf776UZg9dmRo2xbrKt00tTkORXEVe0ctg4vdTkQvJAjiCHxnbAU2HL1AiJ9cqADA76MAliuilsAWnvg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.63.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-t7ltUkg6FFh4b564QyGir8xIj/QZbXu8FlcRkcyW9+ztr/mfRHlvUOFd95pJCXi9s/L5DrUeWWgpXRS+V+6igQ=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.63.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Q5mmZy/XWjuYFUuQyYjOvZ5U/JkKEwnpir6hGxhh6HcdP0V/BKxLo8dqkfF/t7r7AguB17dfS/8+go5AQDRR6g=="],
|
||||
|
||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.63.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-uBGtuZ0TzLB4x5wVa82HGNvYqY8buwDhyCnCP0R0gkk9szqVsP0MeTtD5HX7EsEuFIt+aYmYxuxeVxs3nTSwtQ=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.63.0", "", { "os": "linux", "cpu": "none" }, "sha512-h4s6FwxE+9MeA181o0dnDwHP32Y/bG8EiB/vrD6Ib+AMt6haigDc/0bUtI/sLmQDBMJnUfaCmtSSrEAqjtEVrA=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.63.0", "", { "os": "linux", "cpu": "none" }, "sha512-2EaNcCBR8Mcjl5ARtuN3BdEpVkX7KpjSjMGZ/mJMIeaXgTtdz5ytg2VwygMSStA/k0ixfvZFoZOfjDEcouV5vQ=="],
|
||||
|
||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.63.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-p4hlf/fd7TrYYl3QrWWD0GocqJefwMu3cHQhmi2FvEB/YOvFb5DZN3SMBaPi7B1TM5DeypkEtrVib674q1KKPg=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.63.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Vgq9rkRVcPcjbcH+ihYTfpeR7vCXfqpd+z5ItTGc0yYUV59L5ceHYN1iV4H9bKGV7Rn5hkVc7x3mSvHegduENA=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.63.0", "", { "os": "linux", "cpu": "x64" }, "sha512-3/Lkq/ncooA61rorrC+ZQed1Bc4VpGj+WnGsp58zmxKgvZ2vhreu+dcVyr3mX8NUpq7mfZ4gDDTou/yrF1Pd7A=="],
|
||||
|
||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.63.0", "", { "os": "none", "cpu": "arm64" }, "sha512-0/EdD/6hDkx5Mfd769PTjvEM8mZ/6Dfukp1dBCL/2PjlIVGEtYdNZyok6ChqYPsT9JcFnlQnUeQzO0/1L/oC9w=="],
|
||||
|
||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.63.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-wb0CUkN8ngwPiRQBjD1Cj0LsHeNvm+Xt6YBHDMtj2DVQVD6Oj8Ri7g6BD+KICf6LaBqZlmzOvy6nF9E/8yyGOg=="],
|
||||
|
||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.63.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-BX5iq+ovdNlVYhSn5qPMUIT0uwAwt2lmEnCnzK+Gkhw4DovIvhGb96OFhV8yzQNUnQxn/xGkOR+X+BLrLDNm8w=="],
|
||||
|
||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.63.0", "", { "os": "win32", "cpu": "x64" }, "sha512-QeN/WELOfsXMeYwxvfgQrl6CbVftYUCZsGXHjXQd5Trccm8+i4gmtxaOui4xbJQaiDlviF8F3yLSBloQUeFsfA=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.0", "", { "dependencies": { "bun-types": "1.3.0" } }, "sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA=="],
|
||||
|
||||
"@types/deno": ["@types/deno@2.5.0", "", {}, "sha512-g8JS38vmc0S87jKsFzre+0ZyMOUDHPVokEJymSCRlL57h6f/FdKPWBXgdFh3Z8Ees9sz11qt9VWELU9Y9ZkiVw=="],
|
||||
|
||||
"@types/node": ["@types/node@24.8.1", "", { "dependencies": { "undici-types": "~7.14.0" } }, "sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.7", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg=="],
|
||||
|
||||
"astring": ["astring@1.9.0", "", { "bin": "bin/astring" }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.0", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"esbuild": ["esbuild@0.28.0", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.0", "@esbuild/android-arm": "0.28.0", "@esbuild/android-arm64": "0.28.0", "@esbuild/android-x64": "0.28.0", "@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-x64": "0.28.0", "@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-x64": "0.28.0", "@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-x64": "0.28.0", "@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-x64": "0.28.0", "@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-x64": "0.28.0", "@esbuild/openharmony-arm64": "0.28.0", "@esbuild/sunos-x64": "0.28.0", "@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-x64": "0.28.0" }, "bin": "bin/esbuild" }, "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw=="],
|
||||
|
||||
"globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
|
||||
|
||||
"meriyah": ["meriyah@6.1.4", "", {}, "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ=="],
|
||||
|
||||
"oxfmt": ["oxfmt@0.48.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.48.0", "@oxfmt/binding-android-arm64": "0.48.0", "@oxfmt/binding-darwin-arm64": "0.48.0", "@oxfmt/binding-darwin-x64": "0.48.0", "@oxfmt/binding-freebsd-x64": "0.48.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.48.0", "@oxfmt/binding-linux-arm-musleabihf": "0.48.0", "@oxfmt/binding-linux-arm64-gnu": "0.48.0", "@oxfmt/binding-linux-arm64-musl": "0.48.0", "@oxfmt/binding-linux-ppc64-gnu": "0.48.0", "@oxfmt/binding-linux-riscv64-gnu": "0.48.0", "@oxfmt/binding-linux-riscv64-musl": "0.48.0", "@oxfmt/binding-linux-s390x-gnu": "0.48.0", "@oxfmt/binding-linux-x64-gnu": "0.48.0", "@oxfmt/binding-linux-x64-musl": "0.48.0", "@oxfmt/binding-openharmony-arm64": "0.48.0", "@oxfmt/binding-win32-arm64-msvc": "0.48.0", "@oxfmt/binding-win32-ia32-msvc": "0.48.0", "@oxfmt/binding-win32-x64-msvc": "0.48.0" }, "bin": "bin/oxfmt" }, "sha512-AVaLh+7XeGx+R1zfFV+f6VV61nT2MWVJXVUDhbTm5LBWGyNt64xAyh3NYYyjeY2WykNt9AvqSQLPHcbWquYF9g=="],
|
||||
|
||||
"oxlint": ["oxlint@1.63.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.63.0", "@oxlint/binding-android-arm64": "1.63.0", "@oxlint/binding-darwin-arm64": "1.63.0", "@oxlint/binding-darwin-x64": "1.63.0", "@oxlint/binding-freebsd-x64": "1.63.0", "@oxlint/binding-linux-arm-gnueabihf": "1.63.0", "@oxlint/binding-linux-arm-musleabihf": "1.63.0", "@oxlint/binding-linux-arm64-gnu": "1.63.0", "@oxlint/binding-linux-arm64-musl": "1.63.0", "@oxlint/binding-linux-ppc64-gnu": "1.63.0", "@oxlint/binding-linux-riscv64-gnu": "1.63.0", "@oxlint/binding-linux-riscv64-musl": "1.63.0", "@oxlint/binding-linux-s390x-gnu": "1.63.0", "@oxlint/binding-linux-x64-gnu": "1.63.0", "@oxlint/binding-linux-x64-musl": "1.63.0", "@oxlint/binding-openharmony-arm64": "1.63.0", "@oxlint/binding-win32-arm64-msvc": "1.63.0", "@oxlint/binding-win32-ia32-msvc": "1.63.0", "@oxlint/binding-win32-x64-msvc": "1.63.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1" }, "optionalPeers": ["oxlint-tsgolint"], "bin": "bin/oxlint" }, "sha512-9TGXetdjgIHOJ9OiReomP7nnrMkV9HxC1xM2ramJSLQpzxjsAJtQwa4wqkJN2f/uCrqZuJseFuSlWDdvcruveg=="],
|
||||
|
||||
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
|
||||
|
||||
"undici-types": ["undici-types@7.14.0", "", {}, "sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA=="],
|
||||
}
|
||||
}
|
||||
104
check.py
Executable file
104
check.py
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
ADDITIONAL_PACKAGES_NODE = {}
|
||||
ADDITIONAL_PACKAGES_DENO = {
|
||||
"@types/node@22.5.4": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||
"undici-types@6.19.8": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
}
|
||||
BASE_PATH = pathlib.Path(__file__).parent
|
||||
|
||||
|
||||
def parse_deno() -> dict[str, str]:
|
||||
path = BASE_PATH / "deno.lock"
|
||||
with path.open("rb") as file:
|
||||
lockfile = json.load(file)
|
||||
|
||||
v = lockfile["version"]
|
||||
if v not in ("4", "5"):
|
||||
msg = f"Unsupported lockfile version: {v} (expected 4/5)"
|
||||
raise ValueError(msg)
|
||||
|
||||
integrities = {}
|
||||
for name, info in lockfile["npm"].items():
|
||||
integrity = info["integrity"]
|
||||
other = integrities.get(integrity)
|
||||
if other and other != name:
|
||||
msg = f"Duplicate integrity for {name} and {other}: {integrity}"
|
||||
raise ValueError(msg)
|
||||
|
||||
integrities[integrity] = name
|
||||
|
||||
return integrities
|
||||
|
||||
|
||||
def parse_node() -> dict[str, str]:
|
||||
path = BASE_PATH / "package-lock.json"
|
||||
with path.open("rb") as file:
|
||||
lockfile = json.load(file)
|
||||
|
||||
v = lockfile["lockfileVersion"]
|
||||
if v != 3:
|
||||
msg = f"Unsupported lockfile version: {v} (expected 3)"
|
||||
raise ValueError(msg)
|
||||
|
||||
integrities = {}
|
||||
for path, info in lockfile["packages"].items():
|
||||
if not path:
|
||||
continue
|
||||
|
||||
_, _, mod_name = path.rpartition("node_modules/")
|
||||
version = info["version"]
|
||||
name = f"{mod_name}@{version}"
|
||||
|
||||
integrity = info["integrity"]
|
||||
other = integrities.get(integrity)
|
||||
if other and other != name:
|
||||
msg = f"Duplicate integrity for {name} and {other}: {integrity}"
|
||||
raise ValueError(msg)
|
||||
integrities[integrity] = name
|
||||
|
||||
return integrities
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
packages_deno = parse_deno()
|
||||
except Exception as error:
|
||||
print(f"ERROR: Could not read deno lockfile: {error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
packages_node = parse_node()
|
||||
except Exception as error:
|
||||
print(f"ERROR: Could not read npm lockfile: {error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
packages_deno.update({v: k for k, v in ADDITIONAL_PACKAGES_NODE.items()})
|
||||
packages_node.update({v: k for k, v in ADDITIONAL_PACKAGES_DENO.items()})
|
||||
differences = packages_deno.keys() ^ packages_node.keys()
|
||||
|
||||
if diffs_deno := differences.intersection(packages_deno):
|
||||
print(
|
||||
"deno => npm:",
|
||||
*(f"{packages_deno[h]} ({h})" for h in diffs_deno),
|
||||
sep="\n\t",
|
||||
)
|
||||
|
||||
if diffs_node := differences.intersection(packages_node):
|
||||
print(
|
||||
" npm => deno:",
|
||||
*(f"{packages_node[h]} ({h})" for h in diffs_node),
|
||||
sep="\n\t",
|
||||
)
|
||||
|
||||
if differences:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,14 +0,0 @@
|
||||
import js from "@eslint/js";
|
||||
import globals from "globals";
|
||||
import tseslint from "typescript-eslint";
|
||||
import { defineConfig } from "eslint/config";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
files: ["**/*.{js,mjs,cjs,ts,mts,cts}"],
|
||||
plugins: { js },
|
||||
extends: ["js/recommended"],
|
||||
languageOptions: { globals: globals.node },
|
||||
},
|
||||
tseslint.configs.recommended,
|
||||
]);
|
||||
433
hatch_build.py
Normal file → Executable file
433
hatch_build.py
Normal file → Executable file
@@ -1,36 +1,142 @@
|
||||
#!/usr/bin/env python
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import os.path
|
||||
import pathlib
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import typing
|
||||
|
||||
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||
try:
|
||||
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||
except ImportError:
|
||||
BuildHookInterface = object
|
||||
|
||||
|
||||
BASE_PATH = pathlib.Path(__file__).parent.resolve()
|
||||
DEFAULT_BUNDLER = ["esbuild", "pnpm", "deno", "bun", "node"]
|
||||
DEFAULT_INSTALLER = ["pnpm", "deno", "bun", "npm"]
|
||||
|
||||
|
||||
def run():
|
||||
if not os.environ.get("EJS_BUILD_SKIP_INSTALL"):
|
||||
name, path = find_executable("EJS_BUILD_INSTALLER", DEFAULT_INSTALLER)
|
||||
args, env = build_install_args(name)
|
||||
cmd = [path, *args]
|
||||
print(f"Install command: {shlex.join(cmd)}")
|
||||
subprocess.run(cmd, env=env, check=False)
|
||||
|
||||
esbuild = ESBuild(*find_executable("EJS_BUILD_BUNDLER", DEFAULT_BUNDLER))
|
||||
print(f"Bundle command: {shlex.join(esbuild.cmd)}", file=sys.stderr)
|
||||
|
||||
externals = list(get_external_packages(esbuild))
|
||||
builds = create_builds(externals)
|
||||
print("SHA3-512 checksums:", file=sys.stderr)
|
||||
for build in builds:
|
||||
outfile = build.get("outfile")
|
||||
assert outfile
|
||||
esbuild.run(build)
|
||||
|
||||
path = BASE_PATH / outfile
|
||||
# Workaround for https://github.com/evanw/esbuild/issues/3717#issuecomment-3765731197
|
||||
data = path.read_bytes()
|
||||
if not build.get("minify"):
|
||||
data = re.sub(
|
||||
rb"^\s+// node_modules[^\n]+$",
|
||||
b"",
|
||||
data,
|
||||
flags=re.ASCII | re.MULTILINE,
|
||||
)
|
||||
path.write_bytes(data)
|
||||
digest = hashlib.sha3_512(data).hexdigest()
|
||||
print(f"{digest} {path.name}")
|
||||
|
||||
|
||||
def create_builds(externals: list[Package]) -> list[ESBuildOptions]:
|
||||
with (BASE_PATH / "package.json").open("rb") as file:
|
||||
pkg = json.load(file)
|
||||
LICENSE_PREAMBLE = (
|
||||
"SPDX-License-Identifier: Unlicense\n"
|
||||
+ f"This file was automatically generated by {pkg['homepage']}"
|
||||
)
|
||||
BANNER_WITHOUT_DEPENDENCIES = {"js": license_comment(LICENSE_PREAMBLE)}
|
||||
BANNER_WITH_DEPENDENCIES = {
|
||||
"js": license_comment(
|
||||
LICENSE_PREAMBLE
|
||||
+ "\n\nBundled dependencies:\n\n"
|
||||
+ "------\n\n".join(map(Package.license_comment, externals))
|
||||
)
|
||||
}
|
||||
EXTERNALS = [pkg.name for pkg in externals]
|
||||
ALIASES_DENO = {pkg.name: f"npm:{pkg.name}@{pkg.version}" for pkg in externals}
|
||||
ALIASES_BUN = {pkg.name: f"{pkg.name}@{pkg.version}" for pkg in externals}
|
||||
|
||||
return [
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/main.ts"],
|
||||
"outfile": "dist/yt.solver.core.js",
|
||||
"format": "iife",
|
||||
"globalName": "jsc",
|
||||
"banner": BANNER_WITHOUT_DEPENDENCIES,
|
||||
"external": EXTERNALS,
|
||||
},
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/main.ts"],
|
||||
"outfile": "dist/yt.solver.core.min.js",
|
||||
"minify": True,
|
||||
"format": "iife",
|
||||
"globalName": "jsc",
|
||||
"banner": BANNER_WITHOUT_DEPENDENCIES,
|
||||
"external": EXTERNALS,
|
||||
},
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/lib.ts"],
|
||||
"outfile": "dist/yt.solver.lib.js",
|
||||
"format": "iife",
|
||||
"globalName": "lib",
|
||||
"banner": BANNER_WITH_DEPENDENCIES,
|
||||
},
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/lib.ts"],
|
||||
"outfile": "dist/yt.solver.lib.min.js",
|
||||
"minify": True,
|
||||
"format": "iife",
|
||||
"globalName": "lib",
|
||||
"banner": BANNER_WITH_DEPENDENCIES,
|
||||
},
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/lib.ts"],
|
||||
"outfile": "dist/yt.solver.bun.lib.js",
|
||||
"minifySyntax": True,
|
||||
"format": "esm",
|
||||
"globalName": "lib",
|
||||
"banner": BANNER_WITHOUT_DEPENDENCIES,
|
||||
"alias": ALIASES_BUN,
|
||||
"external": list(ALIASES_BUN.values()),
|
||||
},
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/lib.ts"],
|
||||
"outfile": "dist/yt.solver.deno.lib.js",
|
||||
"minifySyntax": True,
|
||||
"format": "esm",
|
||||
"globalName": "lib",
|
||||
"banner": BANNER_WITHOUT_DEPENDENCIES,
|
||||
"alias": ALIASES_DENO,
|
||||
"external": list(ALIASES_DENO.values()),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class CustomBuildHook(BuildHookInterface):
|
||||
def initialize(self, version, build_data):
|
||||
if shutil.which("deno"):
|
||||
print("Building with deno...", flush=True)
|
||||
os.environ["DENO_NO_UPDATE_CHECK"] = "1"
|
||||
subprocess.run(["deno", "install", "--frozen"], check=True)
|
||||
subprocess.run(["deno", "task", "bundle"], check=True)
|
||||
|
||||
elif shutil.which("bun"):
|
||||
print("Building with bun...", flush=True)
|
||||
subprocess.run(["bun", "install"], check=True)
|
||||
subprocess.run(["bun", "--bun", "run", "bundle"], check=True)
|
||||
|
||||
elif shutil.which("npm"):
|
||||
print("Building with npm...", flush=True)
|
||||
# npm is a batch file (`npm.cmd`) on windows, which requires `shell=True`
|
||||
requires_shell = os.name == "nt"
|
||||
subprocess.run(["npm", "install"], check=True, shell=requires_shell)
|
||||
subprocess.run(["npm", "run", "bundle"], check=True, shell=requires_shell)
|
||||
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"One of 'deno', 'bun', or 'npm' could not be found. "
|
||||
"Please install one of them to proceed with the build."
|
||||
)
|
||||
|
||||
run()
|
||||
build_data["force_include"].update(
|
||||
{
|
||||
"dist/yt.solver.core.min.js": "yt_dlp_ejs/yt/solver/core.min.js",
|
||||
@@ -40,3 +146,280 @@ class CustomBuildHook(BuildHookInterface):
|
||||
|
||||
def clean(self, versions):
|
||||
shutil.rmtree("node_modules", ignore_errors=True)
|
||||
|
||||
|
||||
def find_executable(env: str, defaults: list[str]):
|
||||
values = defaults
|
||||
if value := os.getenv(env):
|
||||
values = value.split(os.path.pathsep)
|
||||
for value in values:
|
||||
if path := shutil.which(value):
|
||||
name = pathlib.Path(path).name.partition(".")[0]
|
||||
return name, path
|
||||
|
||||
return None, ""
|
||||
|
||||
|
||||
def build_install_args(name: str | None):
|
||||
if name == "pnpm":
|
||||
return ["install", "--frozen-lockfile"], None
|
||||
|
||||
if name == "deno":
|
||||
env = os.environ.copy()
|
||||
env["DENO_NO_UPDATE_CHECK"] = "1"
|
||||
return ["install", "--frozen"], env
|
||||
|
||||
if name == "bun":
|
||||
return ["install", "--frozen-lockfile"], None
|
||||
|
||||
if name == "npm":
|
||||
return ["ci"], None
|
||||
|
||||
raise RuntimeError(
|
||||
"Only 'pnpm', 'deno', 'bun', or 'npm' are supported for installing dependencies. "
|
||||
"Please install one of them or pass EJS_BUILD_SKIP_INSTALL=1 to skip install step."
|
||||
)
|
||||
|
||||
|
||||
class ESBuild:
|
||||
def __init__(self, name: str | None, path: str, /):
|
||||
self._stdin = True
|
||||
self._env = None
|
||||
|
||||
if name == "esbuild":
|
||||
self._stdin = False
|
||||
self.cmd = [path]
|
||||
|
||||
elif name == "pnpm":
|
||||
self._stdin = False
|
||||
self.cmd = [path, "run", "esbuild"]
|
||||
|
||||
elif name == "deno":
|
||||
self._env = os.environ.copy()
|
||||
self._env["DENO_NO_UPDATE_CHECK"] = "1"
|
||||
self.cmd = [
|
||||
path,
|
||||
"run",
|
||||
"--allow-read",
|
||||
"--allow-env",
|
||||
"--allow-run",
|
||||
"build.mjs",
|
||||
]
|
||||
|
||||
elif name == "bun":
|
||||
self.cmd = [path, "--bun", "run", "build.mjs"]
|
||||
|
||||
elif name == "node":
|
||||
self.cmd = [path, "build.mjs"]
|
||||
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"One of 'esbuild', 'pnpm', 'deno', 'bun', or 'node' could not be found. "
|
||||
"Please install one of them to be able to run esbuild."
|
||||
)
|
||||
|
||||
def run(self, options: ESBuildOptions, /):
|
||||
options = options.copy()
|
||||
if entrypoints := options.get("entryPoints"):
|
||||
options["entryPoints"] = [str(BASE_PATH / path) for path in entrypoints]
|
||||
if outfile := options.get("outfile"):
|
||||
options["outfile"] = str(BASE_PATH / outfile)
|
||||
|
||||
if self._stdin:
|
||||
process = self._run(self.cmd, json.dumps({"bundle": True, **options}))
|
||||
return json.loads(process.stdout)
|
||||
|
||||
cmd = [*self.cmd, "--bundle", *self._convert_args(options)]
|
||||
fd = name = None
|
||||
if options.pop("metafile", None):
|
||||
fd, name = tempfile.mkstemp(prefix="ejs-build-metadata-", suffix=".json")
|
||||
cmd.append(f"--metafile={name}")
|
||||
|
||||
try:
|
||||
self._run(cmd)
|
||||
if fd and name:
|
||||
with open(fd, "rb", closefd=True) as file:
|
||||
return json.load(file)
|
||||
return None
|
||||
finally:
|
||||
if name:
|
||||
os.unlink(name)
|
||||
|
||||
def _run(self, cmd: list[str], stdin: str | None = None, /):
|
||||
process = subprocess.run(
|
||||
cmd,
|
||||
env=self._env,
|
||||
input=stdin,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if process.returncode:
|
||||
raise RuntimeError(
|
||||
f"failed to run esbuild:\n{process.stdout}{process.stderr}"
|
||||
)
|
||||
return process
|
||||
|
||||
@staticmethod
|
||||
def _convert_args(options: ESBuildOptions):
|
||||
for entrypoint in options.pop("entryPoints", ()):
|
||||
yield entrypoint
|
||||
if not options.pop("write", True):
|
||||
options["outfile"] = "NUL" if os.name == "nt" else "/dev/null"
|
||||
|
||||
for name, value in options.items():
|
||||
parameter = "--" + re.sub(r"[A-Z]", lambda x: "-" + x[0].lower(), name)
|
||||
if isinstance(value, bool):
|
||||
yield f"{parameter}={str(value).lower()}"
|
||||
elif isinstance(value, str):
|
||||
yield f"{parameter}={value}"
|
||||
elif isinstance(value, list):
|
||||
if name == "absPaths":
|
||||
v = ",".join(value)
|
||||
yield f"{parameter}={v}"
|
||||
else:
|
||||
for v in value:
|
||||
yield f"{parameter}:{v}"
|
||||
elif isinstance(value, dict):
|
||||
for k, v in value.items():
|
||||
yield f"{parameter}:{k}={v}"
|
||||
|
||||
|
||||
class ESBuildOptions(typing.TypedDict, total=False):
|
||||
entryPoints: list[str]
|
||||
write: bool
|
||||
absPaths: list[str]
|
||||
metafile: bool
|
||||
outfile: str
|
||||
minify: bool
|
||||
minifySyntax: bool
|
||||
format: str
|
||||
globalName: str
|
||||
banner: dict[str, str]
|
||||
alias: dict[str, str]
|
||||
external: list[str]
|
||||
|
||||
|
||||
def get_external_packages(esbuild: ESBuild):
|
||||
metafile = esbuild.run(
|
||||
{
|
||||
"entryPoints": ["src/yt/solver/lib.ts"],
|
||||
"absPaths": ["metafile"],
|
||||
"metafile": True,
|
||||
"write": False,
|
||||
}
|
||||
)
|
||||
if not metafile:
|
||||
raise RuntimeError("failed to gather build metadata")
|
||||
|
||||
_externals = {}
|
||||
for input_file, meta in metafile["inputs"].items():
|
||||
try:
|
||||
pathlib.Path(input_file).relative_to(BASE_PATH)
|
||||
except ValueError:
|
||||
continue
|
||||
for import_meta in meta["imports"]:
|
||||
if "." in (import_meta.get("original") or ""):
|
||||
continue
|
||||
path = pathlib.Path(import_meta["path"])
|
||||
_externals[path] = None
|
||||
|
||||
for path in _externals:
|
||||
current = path.parent
|
||||
while current != BASE_PATH:
|
||||
package_path = current / "package.json"
|
||||
if package_path.is_file():
|
||||
break
|
||||
current = current.parent
|
||||
else:
|
||||
msg = f"Failed to find package dir for {path}"
|
||||
raise ValueError(msg)
|
||||
|
||||
yield Package.parse(current / "package.json")
|
||||
|
||||
|
||||
class Package:
|
||||
def __init__(
|
||||
self,
|
||||
/,
|
||||
name: str,
|
||||
description: str,
|
||||
version: str,
|
||||
author: str,
|
||||
repository: str,
|
||||
license: str,
|
||||
license_text: str,
|
||||
):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.version = version
|
||||
self.author = author
|
||||
self.repository = repository
|
||||
self.license = license
|
||||
self.license_text = license_text
|
||||
|
||||
@staticmethod
|
||||
def _parse_author(author):
|
||||
if isinstance(author, str):
|
||||
return author
|
||||
|
||||
result = [author["name"]]
|
||||
if email := author.get("email"):
|
||||
result.append(f"<{email}>")
|
||||
if url := author.get("url"):
|
||||
result.append(f"({url})")
|
||||
return " ".join(result)
|
||||
|
||||
@classmethod
|
||||
def parse(cls, path: pathlib.Path, /):
|
||||
with path.open("rb") as file:
|
||||
data = json.load(file)
|
||||
|
||||
licenses = list(path.parent.glob("LICENSE*"))
|
||||
if len(licenses) != 1:
|
||||
msg = "could not find appropriate license"
|
||||
raise ValueError(msg)
|
||||
|
||||
return cls(
|
||||
name=data["name"],
|
||||
version=data["version"],
|
||||
author=cls._parse_author(data["author"]),
|
||||
description=data["description"],
|
||||
repository=data["repository"]["url"],
|
||||
license=data["license"],
|
||||
license_text=licenses[0].read_text(encoding="utf-8"),
|
||||
)
|
||||
|
||||
def _license_comment(self, /):
|
||||
for name in (
|
||||
"name",
|
||||
"description",
|
||||
"version",
|
||||
"author",
|
||||
"repository",
|
||||
"license",
|
||||
"license_text",
|
||||
):
|
||||
if name == "license_text":
|
||||
yield "\n"
|
||||
else:
|
||||
yield name.capitalize()
|
||||
yield ": "
|
||||
yield getattr(self, name)
|
||||
yield "\n"
|
||||
|
||||
def license_comment(self, /):
|
||||
return "".join(self._license_comment())
|
||||
|
||||
|
||||
def license_comment(data: str):
|
||||
return "/*!\n * " + "\n * ".join(data.splitlines()) + "\n */"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
run()
|
||||
except RuntimeError as error:
|
||||
print("ERROR:", error.args[0], file=sys.stderr)
|
||||
sys.exit(128)
|
||||
|
||||
1393
package-lock.json
generated
Normal file
1393
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -1,29 +1,26 @@
|
||||
{
|
||||
"name": "ejs",
|
||||
"homepage": "https://github.com/yt-dlp/ejs",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"bundle": "rollup -c",
|
||||
"fmt": "prettier --write \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\" \"eslint.config.js\"",
|
||||
"fmt:check": "prettier --check \"src/**.ts\" \"package.json\" \"rollup.config.js\" \"run.ts\" \"eslint.config.js\"",
|
||||
"lint": "eslint src"
|
||||
"bundle": "python hatch_build.py",
|
||||
"esbuild": "esbuild",
|
||||
"fmt": "oxfmt",
|
||||
"fmt:check": "oxfmt --check",
|
||||
"lint": "oxlint --fix",
|
||||
"lint:check": "oxlint"
|
||||
},
|
||||
"dependencies": {
|
||||
"astring": "1.9.0",
|
||||
"meriyah": "6.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.38.0",
|
||||
"@rollup/plugin-node-resolve": "16.0.3",
|
||||
"@rollup/plugin-sucrase": "5.0.2",
|
||||
"@rollup/plugin-terser": "0.4.4",
|
||||
"@types/bun": "1.3.0",
|
||||
"@types/deno": "2.5.0",
|
||||
"@types/node": "24.8.1",
|
||||
"eslint": "9.38.0",
|
||||
"esbuild": "0.28.0",
|
||||
"globals": "16.4.0",
|
||||
"prettier": "3.6.2",
|
||||
"rollup": "4.52.5",
|
||||
"rollup-plugin-license": "3.6.0",
|
||||
"typescript-eslint": "8.46.2"
|
||||
"oxfmt": "^0.48.0",
|
||||
"oxlint": "^1.63.0"
|
||||
}
|
||||
}
|
||||
|
||||
801
pnpm-lock.yaml
generated
Normal file
801
pnpm-lock.yaml
generated
Normal file
@@ -0,0 +1,801 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
astring:
|
||||
specifier: 1.9.0
|
||||
version: 1.9.0
|
||||
meriyah:
|
||||
specifier: 6.1.4
|
||||
version: 6.1.4
|
||||
devDependencies:
|
||||
'@types/bun':
|
||||
specifier: 1.3.0
|
||||
version: 1.3.0(@types/react@19.2.7)
|
||||
'@types/deno':
|
||||
specifier: 2.5.0
|
||||
version: 2.5.0
|
||||
'@types/node':
|
||||
specifier: 24.8.1
|
||||
version: 24.8.1
|
||||
esbuild:
|
||||
specifier: 0.28.0
|
||||
version: 0.28.0
|
||||
globals:
|
||||
specifier: 16.4.0
|
||||
version: 16.4.0
|
||||
oxfmt:
|
||||
specifier: ^0.48.0
|
||||
version: 0.48.0
|
||||
oxlint:
|
||||
specifier: ^1.63.0
|
||||
version: 1.63.0
|
||||
|
||||
packages:
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.0':
|
||||
resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.28.0':
|
||||
resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.28.0':
|
||||
resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.28.0':
|
||||
resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.0':
|
||||
resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.28.0':
|
||||
resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.28.0':
|
||||
resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.28.0':
|
||||
resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.0':
|
||||
resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.0':
|
||||
resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.0':
|
||||
resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.28.0':
|
||||
resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.28.0':
|
||||
resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.0':
|
||||
resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.0':
|
||||
resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.28.0':
|
||||
resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.28.0':
|
||||
resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.28.0':
|
||||
resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.28.0':
|
||||
resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@oxfmt/binding-android-arm-eabi@0.48.0':
|
||||
resolution: {integrity: sha512-uwqk+/KhQvBIpULD8SMM/zAafMRC/+DV/xsEQjkkIsJ/kLmEI/2bxonVowcYTiXqqZ/a0FEW8DPkZY3VvwELDA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@oxfmt/binding-android-arm64@0.48.0':
|
||||
resolution: {integrity: sha512-VUCiKuXK5+McVssgHEJdrcGK7hRJzrRb36zm9/jwzMholyYt4BgXhw5Nm1V1DX6Ce717Zi/1jk432b/tgmQgtQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@oxfmt/binding-darwin-arm64@0.48.0':
|
||||
resolution: {integrity: sha512-IkKp8rnIyQLW6Jt+6jragCbUVYSayk55lapiprLjIVvt4NczLyO/nwX2GgefLQ5iaBdfS8UEAFgCs/pLO6Cl0w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxfmt/binding-darwin-x64@0.48.0':
|
||||
resolution: {integrity: sha512-+aFuhsGIuvnoOjXyKVHMhPKJZR1kQkAl8QyrKoMlA7yJsSTC3N0Asl53La8TChSHhW8epToQ/Q0nvLmEmfNmLg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxfmt/binding-freebsd-x64@0.48.0':
|
||||
resolution: {integrity: sha512-fbqzQL8FjI9gGnktI7RIo0dksDziTAYBy7xlI7jU7eID5fxLF/25fS4Xj6GydD8Y5oWHL83U4NK160QaOAxtyg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@oxfmt/binding-linux-arm-gnueabihf@0.48.0':
|
||||
resolution: {integrity: sha512-hn4i0zhAyTiB3ZHjQfYUZkDvrbVkohw1S7pySWxWUoZ87HnkDoTFThj7QTxk40hNPOTUP0vHbPRNamFIv1HBJQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxfmt/binding-linux-arm-musleabihf@0.48.0':
|
||||
resolution: {integrity: sha512-R4WBD9qF3QM9hqgdAa+fBGXmquTvDUujrPQ36t2Sjk8RPOSKGHDeN7l/khr10hqbQaOq9KCgPHG9ubNET/X/RQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxfmt/binding-linux-arm64-gnu@0.48.0':
|
||||
resolution: {integrity: sha512-5bVdwSwlm1M8wbYCorLOxWxUBw/8tBvHYyQNIfwWVPwOJaj5vg1APSGJQVpwJfV5VNE9PSrR91UKEpoNwHhqUA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxfmt/binding-linux-arm64-musl@0.48.0':
|
||||
resolution: {integrity: sha512-vCS3Fk7gFslTqE1lUE2IlroyVV7u/9SmMA/uBqDoshuck2psGWcjW0ePyPZI3rM3+qtf2pDaMVIKMHozraifuw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxfmt/binding-linux-ppc64-gnu@0.48.0':
|
||||
resolution: {integrity: sha512-gKtfFfueUClXDumyoHUbymqRf7prHejOOyzJK0eIJn93GF9JBdFHdo60TM1ZBHxkEwZvjuOgHmKtneKbEOc/Eg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxfmt/binding-linux-riscv64-gnu@0.48.0':
|
||||
resolution: {integrity: sha512-SYt0UhOvZD/UwZz9sXq6J2uAw8o24f5VZpLB2DH01f6MevshmlgakQlZe2lwek2sZJkd07eLu7mZa0g7yeiw7Q==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxfmt/binding-linux-riscv64-musl@0.48.0':
|
||||
resolution: {integrity: sha512-JLbrwck2AopG4ud/XklZO5N+qxGC7cS7ROvXZVNfx0MCLDDL2kGOLvzuWORkVjnjAM0CMAfIMU2zNBtQbM+4dw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxfmt/binding-linux-s390x-gnu@0.48.0':
|
||||
resolution: {integrity: sha512-mdxt5L8OQLxkQH+JVpdC/lknZNe0lX4hlO3d8+xvw2wToo+iDrid9tiGOd5bmHfUVd5wVhrUry0qlu5vq66NkQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxfmt/binding-linux-x64-gnu@0.48.0':
|
||||
resolution: {integrity: sha512-oEz1BQwMrV7OMEFx/3VPDU3n9TM0AnxpktDYXjEg5i6nTX87wo18wSfBvkl4tzAICdKtoAQAdBIl7Y7hsPlx5w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxfmt/binding-linux-x64-musl@0.48.0':
|
||||
resolution: {integrity: sha512-g2SKTTurP5mWjd8Ecait0erYqmltL4IqW1EwttM25BxM6NiTt4ubobJYMR1uox1V2QgG4UfHH10CGRvWlUixjw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxfmt/binding-openharmony-arm64@0.48.0':
|
||||
resolution: {integrity: sha512-CIg24VgheEpvolHL2gQuax5qcQ602bRMHrJ9g8XsQr3iVj9aSPgopigBKuMqrXsupwkrU+RQCn5cG8PgFntR6w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@oxfmt/binding-win32-arm64-msvc@0.48.0':
|
||||
resolution: {integrity: sha512-zeaWkcxcEULwkGF3I/HgEvcDPN8buYDrxibBUa/IFh5Vmwyge+KpLO+hEwSovW349H0O/C0Z2kaFmEzEDm00/Q==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@oxfmt/binding-win32-ia32-msvc@0.48.0':
|
||||
resolution: {integrity: sha512-yiEKnIAGvx5CyZQOlMaNlZkAbwT7/Quk0j3WLt+PR5hK+qYjPTRRJYDfD77wCBPLvEYAG41v4KG3iL0H+uxoxg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@oxfmt/binding-win32-x64-msvc@0.48.0':
|
||||
resolution: {integrity: sha512-GSD2+7t2UoVMV2NgxXypa4bKewflPMAjYnF0Xw9/ht82ZfafAHhb8STwrEd7wlH2PFogt5zw3WVCxYJaHUdbeQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-android-arm-eabi@1.63.0':
|
||||
resolution: {integrity: sha512-A9xLtQt7i0OA1PoB/meog6kikXI9CdwEp7ZwQqmgnpKn3G3b1orvTDy8CQ6T7w1HvDrgWGB78PkFKcWgibcTCg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@oxlint/binding-android-arm64@1.63.0':
|
||||
resolution: {integrity: sha512-SQo+ZMvdR9l3CxZp5W5gFNxSiDxclY6lOzzNpKYLF8asESpm3Pwumx0gER5T7aHLF1/2BAAtLD3DiDkdgy4V1A==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@oxlint/binding-darwin-arm64@1.63.0':
|
||||
resolution: {integrity: sha512-6W82XjJDTmMnjg30427l0dufpnyLoq7wEukKdM6/g2VIybRVuQiBVh43EA4b+UxZ3+tLcKm+Or/pXGNgLCEU8g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxlint/binding-darwin-x64@1.63.0':
|
||||
resolution: {integrity: sha512-CnWd/YCuVG5W1BYkjJEVbJG11o526O9qAwBEQM+nh8K19CRFUkFdROXCyYkGmroHEYQe4vgQ6+lh3550Lp35Xw==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@oxlint/binding-freebsd-x64@1.63.0':
|
||||
resolution: {integrity: sha512-a4eZAqrmtajqcxfdAzC+l7g3PaE3V8hpAYqqeD3fTxLXOMFdK3eNTZrU80n4dDEVm0JXy1aL5PqvqWldBl6zYA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.63.0':
|
||||
resolution: {integrity: sha512-tYUtU9TdbU3uXF5D62g5zXJ13iniFGhXQx5vp9cyEjGdbSAY3VdFBSaldYvyoDmgMZ0ZYuwQP1Y4t2Fhejwa0w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.63.0':
|
||||
resolution: {integrity: sha512-I5r3twFf776UZg9dmRo2xbrKt00tTkORXEVe0ctg4vdTkQvJAjiCHxnbAU2HL1AiJ9cqADA76MAliuilsAWnvg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@oxlint/binding-linux-arm64-gnu@1.63.0':
|
||||
resolution: {integrity: sha512-t7ltUkg6FFh4b564QyGir8xIj/QZbXu8FlcRkcyW9+ztr/mfRHlvUOFd95pJCXi9s/L5DrUeWWgpXRS+V+6igQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-arm64-musl@1.63.0':
|
||||
resolution: {integrity: sha512-Q5mmZy/XWjuYFUuQyYjOvZ5U/JkKEwnpir6hGxhh6HcdP0V/BKxLo8dqkfF/t7r7AguB17dfS/8+go5AQDRR6g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.63.0':
|
||||
resolution: {integrity: sha512-uBGtuZ0TzLB4x5wVa82HGNvYqY8buwDhyCnCP0R0gkk9szqVsP0MeTtD5HX7EsEuFIt+aYmYxuxeVxs3nTSwtQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.63.0':
|
||||
resolution: {integrity: sha512-h4s6FwxE+9MeA181o0dnDwHP32Y/bG8EiB/vrD6Ib+AMt6haigDc/0bUtI/sLmQDBMJnUfaCmtSSrEAqjtEVrA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-riscv64-musl@1.63.0':
|
||||
resolution: {integrity: sha512-2EaNcCBR8Mcjl5ARtuN3BdEpVkX7KpjSjMGZ/mJMIeaXgTtdz5ytg2VwygMSStA/k0ixfvZFoZOfjDEcouV5vQ==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-linux-s390x-gnu@1.63.0':
|
||||
resolution: {integrity: sha512-p4hlf/fd7TrYYl3QrWWD0GocqJefwMu3cHQhmi2FvEB/YOvFb5DZN3SMBaPi7B1TM5DeypkEtrVib674q1KKPg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-x64-gnu@1.63.0':
|
||||
resolution: {integrity: sha512-Vgq9rkRVcPcjbcH+ihYTfpeR7vCXfqpd+z5ItTGc0yYUV59L5ceHYN1iV4H9bKGV7Rn5hkVc7x3mSvHegduENA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@oxlint/binding-linux-x64-musl@1.63.0':
|
||||
resolution: {integrity: sha512-3/Lkq/ncooA61rorrC+ZQed1Bc4VpGj+WnGsp58zmxKgvZ2vhreu+dcVyr3mX8NUpq7mfZ4gDDTou/yrF1Pd7A==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@oxlint/binding-openharmony-arm64@1.63.0':
|
||||
resolution: {integrity: sha512-0/EdD/6hDkx5Mfd769PTjvEM8mZ/6Dfukp1dBCL/2PjlIVGEtYdNZyok6ChqYPsT9JcFnlQnUeQzO0/1L/oC9w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@oxlint/binding-win32-arm64-msvc@1.63.0':
|
||||
resolution: {integrity: sha512-wb0CUkN8ngwPiRQBjD1Cj0LsHeNvm+Xt6YBHDMtj2DVQVD6Oj8Ri7g6BD+KICf6LaBqZlmzOvy6nF9E/8yyGOg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-win32-ia32-msvc@1.63.0':
|
||||
resolution: {integrity: sha512-BX5iq+ovdNlVYhSn5qPMUIT0uwAwt2lmEnCnzK+Gkhw4DovIvhGb96OFhV8yzQNUnQxn/xGkOR+X+BLrLDNm8w==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@oxlint/binding-win32-x64-msvc@1.63.0':
|
||||
resolution: {integrity: sha512-QeN/WELOfsXMeYwxvfgQrl6CbVftYUCZsGXHjXQd5Trccm8+i4gmtxaOui4xbJQaiDlviF8F3yLSBloQUeFsfA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@types/bun@1.3.0':
|
||||
resolution: {integrity: sha512-+lAGCYjXjip2qY375xX/scJeVRmZ5cY0wyHYyCYxNcdEXrQ4AOe3gACgd4iQ8ksOslJtW4VNxBJ8llUwc3a6AA==}
|
||||
|
||||
'@types/deno@2.5.0':
|
||||
resolution: {integrity: sha512-g8JS38vmc0S87jKsFzre+0ZyMOUDHPVokEJymSCRlL57h6f/FdKPWBXgdFh3Z8Ees9sz11qt9VWELU9Y9ZkiVw==}
|
||||
|
||||
'@types/node@24.8.1':
|
||||
resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==}
|
||||
|
||||
'@types/react@19.2.7':
|
||||
resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
|
||||
|
||||
astring@1.9.0:
|
||||
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
|
||||
hasBin: true
|
||||
|
||||
bun-types@1.3.0:
|
||||
resolution: {integrity: sha512-u8X0thhx+yJ0KmkxuEo9HAtdfgCBaM/aI9K90VQcQioAmkVp3SG3FkwWGibUFz3WdXAdcsqOcbU40lK7tbHdkQ==}
|
||||
peerDependencies:
|
||||
'@types/react': ^19
|
||||
|
||||
csstype@3.2.3:
|
||||
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
|
||||
|
||||
esbuild@0.28.0:
|
||||
resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
globals@16.4.0:
|
||||
resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
meriyah@6.1.4:
|
||||
resolution: {integrity: sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
oxfmt@0.48.0:
|
||||
resolution: {integrity: sha512-AVaLh+7XeGx+R1zfFV+f6VV61nT2MWVJXVUDhbTm5LBWGyNt64xAyh3NYYyjeY2WykNt9AvqSQLPHcbWquYF9g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
|
||||
oxlint@1.63.0:
|
||||
resolution: {integrity: sha512-9TGXetdjgIHOJ9OiReomP7nnrMkV9HxC1xM2ramJSLQpzxjsAJtQwa4wqkJN2f/uCrqZuJseFuSlWDdvcruveg==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
oxlint-tsgolint: '>=0.22.1'
|
||||
peerDependenciesMeta:
|
||||
oxlint-tsgolint:
|
||||
optional: true
|
||||
|
||||
tinypool@2.1.0:
|
||||
resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==}
|
||||
engines: {node: ^20.0.0 || >=22.0.0}
|
||||
|
||||
undici-types@7.14.0:
|
||||
resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==}
|
||||
|
||||
snapshots:
|
||||
|
||||
'@esbuild/aix-ppc64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.28.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-android-arm-eabi@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-android-arm64@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-darwin-arm64@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-darwin-x64@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-freebsd-x64@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-arm-gnueabihf@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-arm-musleabihf@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-arm64-gnu@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-arm64-musl@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-ppc64-gnu@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-riscv64-gnu@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-riscv64-musl@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-s390x-gnu@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-x64-gnu@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-linux-x64-musl@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-openharmony-arm64@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-win32-arm64-msvc@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-win32-ia32-msvc@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxfmt/binding-win32-x64-msvc@0.48.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-android-arm-eabi@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-android-arm64@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-darwin-arm64@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-darwin-x64@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-freebsd-x64@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm-gnueabihf@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm-musleabihf@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm64-gnu@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-arm64-musl@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-ppc64-gnu@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-riscv64-gnu@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-riscv64-musl@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-s390x-gnu@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-x64-gnu@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-linux-x64-musl@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-openharmony-arm64@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-arm64-msvc@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-ia32-msvc@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@oxlint/binding-win32-x64-msvc@1.63.0':
|
||||
optional: true
|
||||
|
||||
'@types/bun@1.3.0(@types/react@19.2.7)':
|
||||
dependencies:
|
||||
bun-types: 1.3.0(@types/react@19.2.7)
|
||||
transitivePeerDependencies:
|
||||
- '@types/react'
|
||||
|
||||
'@types/deno@2.5.0': {}
|
||||
|
||||
'@types/node@24.8.1':
|
||||
dependencies:
|
||||
undici-types: 7.14.0
|
||||
|
||||
'@types/react@19.2.7':
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
astring@1.9.0: {}
|
||||
|
||||
bun-types@1.3.0(@types/react@19.2.7):
|
||||
dependencies:
|
||||
'@types/node': 24.8.1
|
||||
'@types/react': 19.2.7
|
||||
|
||||
csstype@3.2.3: {}
|
||||
|
||||
esbuild@0.28.0:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.28.0
|
||||
'@esbuild/android-arm': 0.28.0
|
||||
'@esbuild/android-arm64': 0.28.0
|
||||
'@esbuild/android-x64': 0.28.0
|
||||
'@esbuild/darwin-arm64': 0.28.0
|
||||
'@esbuild/darwin-x64': 0.28.0
|
||||
'@esbuild/freebsd-arm64': 0.28.0
|
||||
'@esbuild/freebsd-x64': 0.28.0
|
||||
'@esbuild/linux-arm': 0.28.0
|
||||
'@esbuild/linux-arm64': 0.28.0
|
||||
'@esbuild/linux-ia32': 0.28.0
|
||||
'@esbuild/linux-loong64': 0.28.0
|
||||
'@esbuild/linux-mips64el': 0.28.0
|
||||
'@esbuild/linux-ppc64': 0.28.0
|
||||
'@esbuild/linux-riscv64': 0.28.0
|
||||
'@esbuild/linux-s390x': 0.28.0
|
||||
'@esbuild/linux-x64': 0.28.0
|
||||
'@esbuild/netbsd-arm64': 0.28.0
|
||||
'@esbuild/netbsd-x64': 0.28.0
|
||||
'@esbuild/openbsd-arm64': 0.28.0
|
||||
'@esbuild/openbsd-x64': 0.28.0
|
||||
'@esbuild/openharmony-arm64': 0.28.0
|
||||
'@esbuild/sunos-x64': 0.28.0
|
||||
'@esbuild/win32-arm64': 0.28.0
|
||||
'@esbuild/win32-ia32': 0.28.0
|
||||
'@esbuild/win32-x64': 0.28.0
|
||||
|
||||
globals@16.4.0: {}
|
||||
|
||||
meriyah@6.1.4: {}
|
||||
|
||||
oxfmt@0.48.0:
|
||||
dependencies:
|
||||
tinypool: 2.1.0
|
||||
optionalDependencies:
|
||||
'@oxfmt/binding-android-arm-eabi': 0.48.0
|
||||
'@oxfmt/binding-android-arm64': 0.48.0
|
||||
'@oxfmt/binding-darwin-arm64': 0.48.0
|
||||
'@oxfmt/binding-darwin-x64': 0.48.0
|
||||
'@oxfmt/binding-freebsd-x64': 0.48.0
|
||||
'@oxfmt/binding-linux-arm-gnueabihf': 0.48.0
|
||||
'@oxfmt/binding-linux-arm-musleabihf': 0.48.0
|
||||
'@oxfmt/binding-linux-arm64-gnu': 0.48.0
|
||||
'@oxfmt/binding-linux-arm64-musl': 0.48.0
|
||||
'@oxfmt/binding-linux-ppc64-gnu': 0.48.0
|
||||
'@oxfmt/binding-linux-riscv64-gnu': 0.48.0
|
||||
'@oxfmt/binding-linux-riscv64-musl': 0.48.0
|
||||
'@oxfmt/binding-linux-s390x-gnu': 0.48.0
|
||||
'@oxfmt/binding-linux-x64-gnu': 0.48.0
|
||||
'@oxfmt/binding-linux-x64-musl': 0.48.0
|
||||
'@oxfmt/binding-openharmony-arm64': 0.48.0
|
||||
'@oxfmt/binding-win32-arm64-msvc': 0.48.0
|
||||
'@oxfmt/binding-win32-ia32-msvc': 0.48.0
|
||||
'@oxfmt/binding-win32-x64-msvc': 0.48.0
|
||||
|
||||
oxlint@1.63.0:
|
||||
optionalDependencies:
|
||||
'@oxlint/binding-android-arm-eabi': 1.63.0
|
||||
'@oxlint/binding-android-arm64': 1.63.0
|
||||
'@oxlint/binding-darwin-arm64': 1.63.0
|
||||
'@oxlint/binding-darwin-x64': 1.63.0
|
||||
'@oxlint/binding-freebsd-x64': 1.63.0
|
||||
'@oxlint/binding-linux-arm-gnueabihf': 1.63.0
|
||||
'@oxlint/binding-linux-arm-musleabihf': 1.63.0
|
||||
'@oxlint/binding-linux-arm64-gnu': 1.63.0
|
||||
'@oxlint/binding-linux-arm64-musl': 1.63.0
|
||||
'@oxlint/binding-linux-ppc64-gnu': 1.63.0
|
||||
'@oxlint/binding-linux-riscv64-gnu': 1.63.0
|
||||
'@oxlint/binding-linux-riscv64-musl': 1.63.0
|
||||
'@oxlint/binding-linux-s390x-gnu': 1.63.0
|
||||
'@oxlint/binding-linux-x64-gnu': 1.63.0
|
||||
'@oxlint/binding-linux-x64-musl': 1.63.0
|
||||
'@oxlint/binding-openharmony-arm64': 1.63.0
|
||||
'@oxlint/binding-win32-arm64-msvc': 1.63.0
|
||||
'@oxlint/binding-win32-ia32-msvc': 1.63.0
|
||||
'@oxlint/binding-win32-x64-msvc': 1.63.0
|
||||
|
||||
tinypool@2.1.0: {}
|
||||
|
||||
undici-types@7.14.0: {}
|
||||
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
|
||||
minimumReleaseAge: 10080
|
||||
@@ -47,6 +47,7 @@ source = "vcs"
|
||||
exclude = [
|
||||
"/.github/**",
|
||||
"/src/yt/solver/test/players/*",
|
||||
"!/src/yt/solver/test/players/.gitignore",
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
|
||||
250
rollup.config.js
250
rollup.config.js
@@ -1,250 +0,0 @@
|
||||
import { defineConfig } from "rollup";
|
||||
import nodeResolve from "@rollup/plugin-node-resolve";
|
||||
import sucrase from "@rollup/plugin-sucrase";
|
||||
import terser from "@rollup/plugin-terser";
|
||||
import { createHash } from "node:crypto";
|
||||
import license from "rollup-plugin-license";
|
||||
import { readFileSync } from "node:fs";
|
||||
import prettier from "prettier";
|
||||
|
||||
const pkg = JSON.parse(readFileSync("./package.json"));
|
||||
|
||||
const LICENSE_BANNER =
|
||||
"SPDX-License-Identifier: Unlicense\n" +
|
||||
"This file was automatically generated by https://github.com/yt-dlp/ejs" +
|
||||
"<% if (dependencies && dependencies.length) { %>" +
|
||||
"\n\nBundled Dependencies:" +
|
||||
"<% _.forEach(dependencies, function (dependency) { if (!dependency.private) { %>" +
|
||||
"\n\n---\nName: <%= dependency.name %>" +
|
||||
"<% if (dependency.version) { %>\nVersion: <%= dependency.version %><% } %>" +
|
||||
"\nLicense: <%= dependency.license %>" +
|
||||
"<% if (dependency.repository && dependency.repository.url) { %>\nRepository: <%= dependency.repository.url %><% } %>" +
|
||||
"<% if (dependency.homepage && dependency.homepage.url) { %>\nHomepage: <%= dependency.homepage.url %><% } %>" +
|
||||
"<% if (dependency.author) { %>\nAuthor: <%= dependency.author.text() %><% } %>" +
|
||||
"<% if (dependency.licenseText) { %>\n\n<%= dependency.licenseText %><% } %>" +
|
||||
"\n---<% } }) %>\n<% } %>";
|
||||
|
||||
function printHash() {
|
||||
return {
|
||||
name: "hash-output-plugin",
|
||||
writeBundle(_options, bundle) {
|
||||
for (const [fileName, assetInfo] of Object.entries(bundle)) {
|
||||
if (assetInfo.code) {
|
||||
try {
|
||||
const digest = createHash("sha3-512")
|
||||
.update(assetInfo.code)
|
||||
.digest("hex");
|
||||
console.log(`SHA3-512 for ${assetInfo.fileName}: ${digest}`);
|
||||
} catch (err) {
|
||||
console.error(`Error hashing ${fileName}:`, err.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function dynamicImportRewrite({ format = "deno" } = {}) {
|
||||
return {
|
||||
name: "dynamic-import-rewrite-plugin",
|
||||
resolveId(source) {
|
||||
if (pkg.dependencies[source]) {
|
||||
if (format === "deno") {
|
||||
return {
|
||||
id: `npm:${source}@${pkg.dependencies[source]}`,
|
||||
external: true,
|
||||
};
|
||||
} else if (format === "bun") {
|
||||
return {
|
||||
id: `${source}@${pkg.dependencies[source]}`,
|
||||
external: true,
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
renderDynamicImport() {
|
||||
return null;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function prettifyOutput() {
|
||||
return {
|
||||
name: "prettify-output",
|
||||
renderChunk(code) {
|
||||
return prettier.format(code, { parser: "babel", singleQuote: true });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
input: "src/yt/solver/main.ts",
|
||||
output: {
|
||||
name: "jsc",
|
||||
globals: {
|
||||
astring: "astring",
|
||||
input: "input",
|
||||
meriyah: "meriyah",
|
||||
},
|
||||
file: "dist/yt.solver.core.js",
|
||||
format: "iife",
|
||||
},
|
||||
external: ["astring", "meriyah"],
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
sucrase({
|
||||
exclude: ["node_modules/**"],
|
||||
transforms: ["typescript"],
|
||||
}),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
// Use terser to remove comments but do not minify
|
||||
terser({
|
||||
compress: false,
|
||||
mangle: false,
|
||||
}),
|
||||
prettifyOutput(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/yt/solver/main.ts",
|
||||
output: {
|
||||
name: "jsc",
|
||||
globals: {
|
||||
astring: "astring",
|
||||
input: "input",
|
||||
meriyah: "meriyah",
|
||||
},
|
||||
file: "dist/yt.solver.core.min.js",
|
||||
compact: true,
|
||||
format: "iife",
|
||||
minifyInternalExports: true,
|
||||
},
|
||||
external: ["astring", "meriyah"],
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
sucrase({
|
||||
exclude: ["node_modules/**"],
|
||||
transforms: ["typescript"],
|
||||
}),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
terser(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/yt/solver/lib.ts",
|
||||
output: {
|
||||
name: "lib",
|
||||
file: "dist/yt.solver.lib.js",
|
||||
format: "iife",
|
||||
exports: "named",
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
sucrase({
|
||||
exclude: ["node_modules/**"],
|
||||
transforms: ["typescript"],
|
||||
}),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
// Use terser to remove comments but do not minify
|
||||
terser({
|
||||
compress: false,
|
||||
mangle: false,
|
||||
}),
|
||||
prettifyOutput(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/yt/solver/lib.ts",
|
||||
output: {
|
||||
name: "lib",
|
||||
file: "dist/yt.solver.lib.min.js",
|
||||
compact: true,
|
||||
format: "iife",
|
||||
minifyInternalExports: true,
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
sucrase({
|
||||
exclude: ["node_modules/**"],
|
||||
transforms: ["typescript"],
|
||||
}),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
terser(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/yt/solver/dynamic.lib.ts",
|
||||
output: {
|
||||
name: "lib",
|
||||
file: "dist/yt.solver.deno.lib.js",
|
||||
format: "es",
|
||||
},
|
||||
plugins: [
|
||||
dynamicImportRewrite(),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
// Use terser to remove comments but do not minify
|
||||
terser({
|
||||
compress: false,
|
||||
mangle: false,
|
||||
}),
|
||||
prettifyOutput(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
{
|
||||
input: "src/yt/solver/dynamic.lib.ts",
|
||||
output: {
|
||||
name: "lib",
|
||||
file: "dist/yt.solver.bun.lib.js",
|
||||
format: "es",
|
||||
},
|
||||
plugins: [
|
||||
dynamicImportRewrite({ format: "bun" }),
|
||||
license({
|
||||
banner: {
|
||||
commentStyle: "ignored",
|
||||
content: LICENSE_BANNER,
|
||||
},
|
||||
}),
|
||||
// Use terser to remove comments but do not minify
|
||||
terser({
|
||||
compress: false,
|
||||
mangle: false,
|
||||
}),
|
||||
prettifyOutput(),
|
||||
printHash(),
|
||||
],
|
||||
},
|
||||
]);
|
||||
6
run.ts
6
run.ts
@@ -1,5 +1,5 @@
|
||||
import { argv, exit } from "node:process";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { argv, exit } from "node:process";
|
||||
|
||||
import { isOneOf } from "./src/utils.ts";
|
||||
import main from "./src/yt/solver/main.ts";
|
||||
@@ -7,9 +7,7 @@ import main from "./src/yt/solver/main.ts";
|
||||
const args = argv.slice(2);
|
||||
if (args.length < 2) {
|
||||
console.error(
|
||||
`ERROR: Missing argument\nusage: ${
|
||||
argv[1]
|
||||
} <player> [<type>:<request> ...]`,
|
||||
`ERROR: Missing argument\nusage: ${argv[1]} <player> [<type>:<request> ...]`,
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
10
src/utils.ts
10
src/utils.ts
@@ -1,4 +1,5 @@
|
||||
import { type ESTree } from "meriyah";
|
||||
import { parse, type ESTree } from "meriyah";
|
||||
|
||||
import { type DeepPartial } from "./types.ts";
|
||||
|
||||
export function matchesStructure<T extends ESTree.Node>(
|
||||
@@ -42,3 +43,10 @@ export function matchesStructure<T extends ESTree.Node>(
|
||||
export function isOneOf<T>(value: unknown, ...of: readonly T[]): value is T {
|
||||
return of.includes(value as T);
|
||||
}
|
||||
|
||||
export function generateArrowFunction(
|
||||
data: string,
|
||||
): ESTree.ArrowFunctionExpression {
|
||||
return (parse(data).body[0] as ESTree.ExpressionStatement)
|
||||
.expression as ESTree.ArrowFunctionExpression;
|
||||
}
|
||||
|
||||
26
src/yt/solver/extract.ts
Normal file
26
src/yt/solver/extract.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { argv } from "node:process";
|
||||
|
||||
import { generate } from "astring";
|
||||
import { parse } from "meriyah";
|
||||
|
||||
import { getSolutions, modifyPlayer } from "./solvers.ts";
|
||||
import { getIO } from "./test/io.ts";
|
||||
import { downloadCached } from "./test/utils.ts";
|
||||
|
||||
const data = await (
|
||||
argv.length > 3
|
||||
? () => downloadCached(argv[2], argv[3])
|
||||
: async () => {
|
||||
const io = await getIO();
|
||||
return await io.read(argv[2]);
|
||||
}
|
||||
)();
|
||||
|
||||
const program = parse(data);
|
||||
const statements = modifyPlayer(program);
|
||||
const solutionMap = getSolutions(statements);
|
||||
for (const solutions of Object.values(solutionMap)) {
|
||||
for (const solution of solutions) {
|
||||
console.log(String.raw`${generate(solution)}`);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { parse } from "meriyah";
|
||||
import { generate } from "astring";
|
||||
import { parse } from "meriyah";
|
||||
|
||||
export const meriyah = { parse };
|
||||
export const astring = { generate };
|
||||
export const lib = {
|
||||
meriyah: { parse },
|
||||
astring: { generate },
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getFromPrepared, preprocessPlayer } from "./solvers.ts";
|
||||
import { isOneOf } from "../../utils.ts";
|
||||
import { getFromPrepared, preprocessPlayer } from "./solvers.ts";
|
||||
|
||||
export default function main(input: Input): Output {
|
||||
const preprocessedPlayer =
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
import { type ESTree } from "meriyah";
|
||||
import { matchesStructure } from "../../utils.ts";
|
||||
import { type DeepPartial } from "../../types.ts";
|
||||
|
||||
const identifier: DeepPartial<ESTree.Node> = {
|
||||
or: [
|
||||
{
|
||||
type: "VariableDeclaration",
|
||||
kind: "var",
|
||||
declarations: {
|
||||
anykey: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
id: {
|
||||
type: "Identifier",
|
||||
},
|
||||
init: {
|
||||
type: "ArrayExpression",
|
||||
elements: [
|
||||
{
|
||||
type: "Identifier",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
left: {
|
||||
type: "Identifier",
|
||||
},
|
||||
operator: "=",
|
||||
right: {
|
||||
type: "ArrayExpression",
|
||||
elements: [
|
||||
{
|
||||
type: "Identifier",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
const catchBlockBody = [
|
||||
{
|
||||
type: "ReturnStatement",
|
||||
argument: {
|
||||
type: "BinaryExpression",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "Identifier",
|
||||
},
|
||||
computed: true,
|
||||
property: {
|
||||
type: "Literal",
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
right: {
|
||||
type: "Identifier",
|
||||
},
|
||||
operator: "+",
|
||||
},
|
||||
},
|
||||
] as const;
|
||||
|
||||
export function extract(
|
||||
node: ESTree.Node,
|
||||
): ESTree.ArrowFunctionExpression | null {
|
||||
if (!matchesStructure(node, identifier)) {
|
||||
// Fallback search for try { } catch { return X[12] + Y }
|
||||
let name: string | undefined | null = null;
|
||||
let block: ESTree.BlockStatement | null | undefined = null;
|
||||
switch (node.type) {
|
||||
case "ExpressionStatement": {
|
||||
if (
|
||||
node.expression.type === "AssignmentExpression" &&
|
||||
node.expression.left.type === "Identifier" &&
|
||||
node.expression.right.type === "FunctionExpression" &&
|
||||
node.expression.right.params.length === 1
|
||||
) {
|
||||
name = node.expression.left.name;
|
||||
block = node.expression.right.body;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "FunctionDeclaration": {
|
||||
if (node.params.length === 1) {
|
||||
name = node.id?.name;
|
||||
block = node.body;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!block || !name) {
|
||||
return null;
|
||||
}
|
||||
const tryNode = block.body.at(-2);
|
||||
if (
|
||||
tryNode?.type !== "TryStatement" ||
|
||||
tryNode.handler?.type !== "CatchClause"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const catchBody = tryNode.handler!.body.body;
|
||||
if (matchesStructure(catchBody, catchBlockBody)) {
|
||||
return makeSolverFuncFromName(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node.type === "VariableDeclaration") {
|
||||
for (const declaration of node.declarations) {
|
||||
if (
|
||||
declaration.type !== "VariableDeclarator" ||
|
||||
!declaration.init ||
|
||||
declaration.init.type !== "ArrayExpression" ||
|
||||
declaration.init.elements.length !== 1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const [firstElement] = declaration.init.elements;
|
||||
if (firstElement && firstElement.type === "Identifier") {
|
||||
return makeSolverFuncFromName(firstElement.name);
|
||||
}
|
||||
}
|
||||
} else if (node.type === "ExpressionStatement") {
|
||||
const expr = node.expression;
|
||||
if (
|
||||
expr.type === "AssignmentExpression" &&
|
||||
expr.left.type === "Identifier" &&
|
||||
expr.operator === "=" &&
|
||||
expr.right.type === "ArrayExpression" &&
|
||||
expr.right.elements.length === 1
|
||||
) {
|
||||
const [firstElement] = expr.right.elements;
|
||||
if (firstElement && firstElement.type === "Identifier") {
|
||||
return makeSolverFuncFromName(firstElement.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function makeSolverFuncFromName(name: string): ESTree.ArrowFunctionExpression {
|
||||
return {
|
||||
type: "ArrowFunctionExpression",
|
||||
params: [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "n",
|
||||
},
|
||||
],
|
||||
body: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: name,
|
||||
},
|
||||
arguments: [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "n",
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
async: false,
|
||||
expression: false,
|
||||
generator: false,
|
||||
};
|
||||
}
|
||||
144
src/yt/solver/nsig.ts
Normal file
144
src/yt/solver/nsig.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { generate } from "astring";
|
||||
import { type ESTree } from "meriyah";
|
||||
|
||||
import { type DeepPartial } from "../../types.ts";
|
||||
import { matchesStructure, generateArrowFunction } from "../../utils.ts";
|
||||
|
||||
const identifier: DeepPartial<ESTree.Node> = {
|
||||
or: [
|
||||
{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
or: [{ type: "Identifier" }, { type: "MemberExpression" }],
|
||||
},
|
||||
right: {
|
||||
type: "FunctionExpression",
|
||||
async: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "FunctionDeclaration",
|
||||
async: false,
|
||||
id: { type: "Identifier" },
|
||||
},
|
||||
{
|
||||
type: "VariableDeclaration",
|
||||
declarations: {
|
||||
anykey: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
init: {
|
||||
type: "FunctionExpression",
|
||||
async: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
const asdasd: DeepPartial<ESTree.ExpressionStatement> = {
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "MemberExpression",
|
||||
object: { type: "Identifier" },
|
||||
property: {},
|
||||
optional: false,
|
||||
},
|
||||
arguments: [
|
||||
{
|
||||
type: "Literal",
|
||||
value: "alr",
|
||||
},
|
||||
{
|
||||
type: "Literal",
|
||||
value: "yes",
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
};
|
||||
|
||||
export function extract(
|
||||
node: ESTree.Node,
|
||||
): ESTree.ArrowFunctionExpression | null {
|
||||
if (!matchesStructure(node, identifier)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const options: {
|
||||
name: ESTree.Expression;
|
||||
statements: ESTree.Statement[];
|
||||
}[] = [];
|
||||
|
||||
if (node.type === "FunctionDeclaration") {
|
||||
if (node.id && node.body?.body) {
|
||||
options.push({
|
||||
name: node.id,
|
||||
statements: node.body?.body,
|
||||
});
|
||||
}
|
||||
} else if (node.type === "ExpressionStatement") {
|
||||
if (node.expression.type !== "AssignmentExpression") {
|
||||
return null;
|
||||
}
|
||||
const name = node.expression.left;
|
||||
const body = (node.expression.right as ESTree.FunctionExpression)?.body
|
||||
?.body;
|
||||
if (name && body) {
|
||||
options.push({
|
||||
name: name,
|
||||
statements: body,
|
||||
});
|
||||
}
|
||||
} else if (node.type === "VariableDeclaration") {
|
||||
for (const declaration of node.declarations) {
|
||||
const name = declaration.id;
|
||||
const body = (declaration.init as ESTree.FunctionExpression)?.body?.body;
|
||||
if (name && body) {
|
||||
options.push({
|
||||
name: name,
|
||||
statements: body,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const { name, statements } of options) {
|
||||
if (matchesStructure(statements, { anykey: [asdasd] })) {
|
||||
return createSolver(name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function createSolver(
|
||||
expression: ESTree.Expression,
|
||||
): ESTree.ArrowFunctionExpression {
|
||||
return generateArrowFunction(`
|
||||
({sig, n}) => {
|
||||
const url = (${generate(expression)})("https://youtube.com/watch?v=yt-dlp-wins", "s", sig ? encodeURIComponent(sig) : undefined);
|
||||
url.set("n", n);
|
||||
const proto = Object.getPrototypeOf(url);
|
||||
const keys = Object.keys(proto).concat(Object.getOwnPropertyNames(proto));
|
||||
for (const key of keys) {
|
||||
if (!["constructor", "set", "get", "clone"].includes(key)) {
|
||||
url[key]();
|
||||
break;
|
||||
}
|
||||
}
|
||||
const s = url.get("s");
|
||||
return {
|
||||
sig: s ? decodeURIComponent(s) : null,
|
||||
n: url.get("n") ?? null,
|
||||
};
|
||||
}
|
||||
`);
|
||||
}
|
||||
@@ -4,9 +4,8 @@ export const setupNodes = parse(`
|
||||
if (typeof globalThis.XMLHttpRequest === "undefined") {
|
||||
globalThis.XMLHttpRequest = { prototype: {} };
|
||||
}
|
||||
const window = Object.create(null);
|
||||
if (typeof URL === "undefined") {
|
||||
window.location = {
|
||||
globalThis.location = {
|
||||
hash: "",
|
||||
host: "www.youtube.com",
|
||||
hostname: "www.youtube.com",
|
||||
@@ -20,7 +19,7 @@ if (typeof URL === "undefined") {
|
||||
username: "",
|
||||
};
|
||||
} else {
|
||||
window.location = new URL("https://www.youtube.com/watch?v=yt-dlp-wins");
|
||||
globalThis.location = new URL("https://www.youtube.com/watch?v=yt-dlp-wins");
|
||||
}
|
||||
if (typeof globalThis.document === "undefined") {
|
||||
globalThis.document = Object.create(null);
|
||||
@@ -31,4 +30,7 @@ if (typeof globalThis.navigator === "undefined") {
|
||||
if (typeof globalThis.self === "undefined") {
|
||||
globalThis.self = globalThis;
|
||||
}
|
||||
if (typeof globalThis.window === "undefined") {
|
||||
globalThis.window = globalThis;
|
||||
}
|
||||
`).body;
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
import { type ESTree } from "meriyah";
|
||||
import { matchesStructure } from "../../utils.ts";
|
||||
import { type DeepPartial } from "../../types.ts";
|
||||
|
||||
const logicalExpression: DeepPartial<ESTree.ExpressionStatement> = {
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "LogicalExpression",
|
||||
left: {
|
||||
type: "Identifier",
|
||||
},
|
||||
right: {
|
||||
type: "SequenceExpression",
|
||||
expressions: [
|
||||
{
|
||||
type: "AssignmentExpression",
|
||||
left: {
|
||||
type: "Identifier",
|
||||
},
|
||||
operator: "=",
|
||||
right: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
},
|
||||
arguments: {
|
||||
or: [
|
||||
[
|
||||
{ type: "Literal" },
|
||||
{
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: "decodeURIComponent",
|
||||
},
|
||||
arguments: [{ type: "Identifier" }],
|
||||
optional: false,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: "decodeURIComponent",
|
||||
},
|
||||
arguments: [{ type: "Identifier" }],
|
||||
optional: false,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "CallExpression",
|
||||
},
|
||||
],
|
||||
},
|
||||
operator: "&&",
|
||||
},
|
||||
};
|
||||
|
||||
const identifier: DeepPartial<ESTree.Node> = {
|
||||
or: [
|
||||
{
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
type: "Identifier",
|
||||
},
|
||||
right: {
|
||||
type: "FunctionExpression",
|
||||
params: [{}, {}, {}],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "FunctionDeclaration",
|
||||
params: [{}, {}, {}],
|
||||
},
|
||||
{
|
||||
type: "VariableDeclaration",
|
||||
declarations: {
|
||||
anykey: [
|
||||
{
|
||||
type: "VariableDeclarator",
|
||||
init: {
|
||||
type: "FunctionExpression",
|
||||
params: [{}, {}, {}],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
} as const;
|
||||
|
||||
export function extract(
|
||||
node: ESTree.Node,
|
||||
): ESTree.ArrowFunctionExpression | null {
|
||||
if (!matchesStructure(node, identifier)) {
|
||||
return null;
|
||||
}
|
||||
let block: ESTree.BlockStatement | undefined | null;
|
||||
if (node.type === "ExpressionStatement" &&
|
||||
node.expression.type === "AssignmentExpression" &&
|
||||
node.expression.right.type === "FunctionExpression") {
|
||||
block = node.expression.right.body;
|
||||
} else if (node.type === "VariableDeclaration") {
|
||||
for (const decl of node.declarations) {
|
||||
if (
|
||||
decl.type === "VariableDeclarator" &&
|
||||
decl.init?.type === "FunctionExpression" &&
|
||||
decl.init?.params.length === 3
|
||||
) {
|
||||
block = decl.init.body;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (node.type === "FunctionDeclaration") {
|
||||
block = node.body;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const relevantExpression = block?.body.at(-2);
|
||||
if (!matchesStructure(relevantExpression!, logicalExpression)) {
|
||||
return null;
|
||||
}
|
||||
if (
|
||||
relevantExpression?.type !== "ExpressionStatement" ||
|
||||
relevantExpression.expression.type !== "LogicalExpression" ||
|
||||
relevantExpression.expression.right.type !== "SequenceExpression" ||
|
||||
relevantExpression.expression.right.expressions[0].type !==
|
||||
"AssignmentExpression"
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const call = relevantExpression.expression.right.expressions[0].right;
|
||||
if (call.type !== "CallExpression" || call.callee.type !== "Identifier") {
|
||||
return null;
|
||||
}
|
||||
// TODO: verify identifiers here
|
||||
return {
|
||||
type: "ArrowFunctionExpression",
|
||||
params: [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "sig",
|
||||
},
|
||||
],
|
||||
body: {
|
||||
type: "CallExpression",
|
||||
callee: {
|
||||
type: "Identifier",
|
||||
name: call.callee.name,
|
||||
},
|
||||
arguments:
|
||||
call.arguments.length === 1
|
||||
? [
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "sig",
|
||||
},
|
||||
]
|
||||
: [
|
||||
call.arguments[0],
|
||||
{
|
||||
type: "Identifier",
|
||||
name: "sig",
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
async: false,
|
||||
expression: false,
|
||||
generator: false,
|
||||
};
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
import { getFromPrepared, preprocessPlayer } from "./solvers.ts";
|
||||
import { getIO } from "./test/io.ts";
|
||||
import { players, tests } from "./test/tests.ts";
|
||||
import { getCachePath } from "./test/utils.ts";
|
||||
import { getIO } from "./test/io.ts";
|
||||
|
||||
const io = await getIO();
|
||||
|
||||
for (const test of tests) {
|
||||
for (const variant of test.variants ?? players.keys()) {
|
||||
const path = getCachePath(test.player, variant);
|
||||
await io.test(`${test.player} ${variant}`, async (assert, subtest) => {
|
||||
await io.test(`-${test.player}-${variant}-`, async (assert, subtest) => {
|
||||
const content = await io.read(path);
|
||||
const solvers = getFromPrepared(preprocessPlayer(content));
|
||||
for (const mode of ["n", "sig"] as const) {
|
||||
|
||||
@@ -1,14 +1,46 @@
|
||||
import { type ESTree, parse } from "meriyah";
|
||||
import { generate } from "astring";
|
||||
import { extract as extractSig } from "./sig.ts";
|
||||
import { extract as extractN } from "./n.ts";
|
||||
import { type ESTree, parse } from "meriyah";
|
||||
|
||||
import { generateArrowFunction } from "../../utils.ts";
|
||||
import { extract } from "./nsig.ts";
|
||||
import { setupNodes } from "./setup.ts";
|
||||
|
||||
export function preprocessPlayer(data: string): string {
|
||||
const ast = parse(data);
|
||||
const body = ast.body;
|
||||
const program = parse(data);
|
||||
const plainStatements = modifyPlayer(program);
|
||||
const solutions = getSolutions(plainStatements);
|
||||
for (const [name, options] of Object.entries(solutions)) {
|
||||
plainStatements.push({
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
computed: false,
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_result",
|
||||
},
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: name,
|
||||
},
|
||||
optional: false,
|
||||
},
|
||||
right: multiTry(options),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const block = (() => {
|
||||
program.body.splice(0, 0, ...setupNodes);
|
||||
return generate(program);
|
||||
}
|
||||
|
||||
export function modifyPlayer(program: ESTree.Program) {
|
||||
const body = program.body;
|
||||
|
||||
const block: ESTree.BlockStatement = (() => {
|
||||
switch (body.length) {
|
||||
case 1: {
|
||||
const func = body[0];
|
||||
@@ -40,19 +72,7 @@ export function preprocessPlayer(data: string): string {
|
||||
throw "unexpected structure";
|
||||
})();
|
||||
|
||||
const found = {
|
||||
n: [] as ESTree.ArrowFunctionExpression[],
|
||||
sig: [] as ESTree.ArrowFunctionExpression[],
|
||||
};
|
||||
const plainExpressions = block.body.filter((node: ESTree.Node) => {
|
||||
const n = extractN(node);
|
||||
if (n) {
|
||||
found.n.push(n);
|
||||
}
|
||||
const sig = extractSig(node);
|
||||
if (sig) {
|
||||
found.sig.push(sig);
|
||||
}
|
||||
block.body = block.body.filter((node: ESTree.Statement) => {
|
||||
if (node.type === "ExpressionStatement") {
|
||||
if (node.expression.type === "AssignmentExpression") {
|
||||
return true;
|
||||
@@ -61,43 +81,75 @@ export function preprocessPlayer(data: string): string {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
block.body = plainExpressions;
|
||||
|
||||
for (const [name, options] of Object.entries(found)) {
|
||||
// TODO: this is cringe fix plz
|
||||
const unique = new Set(options.map((x) => JSON.stringify(x)));
|
||||
if (unique.size !== 1) {
|
||||
const message = `found ${unique.size} ${name} function possibilities`;
|
||||
throw (
|
||||
message +
|
||||
(unique.size ? `: ${options.map((x) => generate(x)).join(", ")}` : "")
|
||||
return block.body;
|
||||
}
|
||||
|
||||
export function getSolutions(
|
||||
statements: ESTree.Statement[],
|
||||
): Record<string, ESTree.ArrowFunctionExpression[]> {
|
||||
const found = {
|
||||
n: [] as ESTree.ArrowFunctionExpression[],
|
||||
sig: [] as ESTree.ArrowFunctionExpression[],
|
||||
};
|
||||
for (const statement of statements) {
|
||||
const result = extract(statement);
|
||||
if (result) {
|
||||
found.n.push(
|
||||
makeSolver(result, {
|
||||
type: "Identifier",
|
||||
name: "n",
|
||||
}),
|
||||
);
|
||||
found.sig.push(
|
||||
makeSolver(result, {
|
||||
type: "Identifier",
|
||||
name: "sig",
|
||||
}),
|
||||
);
|
||||
}
|
||||
plainExpressions.push({
|
||||
type: "ExpressionStatement",
|
||||
expression: {
|
||||
type: "AssignmentExpression",
|
||||
operator: "=",
|
||||
left: {
|
||||
type: "MemberExpression",
|
||||
computed: false,
|
||||
object: {
|
||||
type: "Identifier",
|
||||
name: "_result",
|
||||
},
|
||||
property: {
|
||||
type: "Identifier",
|
||||
name: name,
|
||||
},
|
||||
},
|
||||
right: options[0],
|
||||
},
|
||||
});
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
ast.body.splice(0, 0, ...setupNodes);
|
||||
|
||||
return generate(ast);
|
||||
function makeSolver(
|
||||
result: ESTree.ArrowFunctionExpression,
|
||||
ident: ESTree.Identifier,
|
||||
): ESTree.ArrowFunctionExpression {
|
||||
return {
|
||||
type: "ArrowFunctionExpression",
|
||||
params: [ident],
|
||||
body: {
|
||||
type: "MemberExpression",
|
||||
object: {
|
||||
type: "CallExpression",
|
||||
callee: result,
|
||||
arguments: [
|
||||
{
|
||||
type: "ObjectExpression",
|
||||
properties: [
|
||||
{
|
||||
type: "Property",
|
||||
key: ident,
|
||||
value: ident,
|
||||
kind: "init",
|
||||
computed: false,
|
||||
method: false,
|
||||
shorthand: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
optional: false,
|
||||
},
|
||||
computed: false,
|
||||
property: ident,
|
||||
optional: false,
|
||||
},
|
||||
async: false,
|
||||
expression: true,
|
||||
generator: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function getFromPrepared(code: string): {
|
||||
@@ -108,3 +160,31 @@ export function getFromPrepared(code: string): {
|
||||
Function("_result", code)(resultObj);
|
||||
return resultObj;
|
||||
}
|
||||
|
||||
function multiTry(
|
||||
generators: ESTree.ArrowFunctionExpression[],
|
||||
): ESTree.ArrowFunctionExpression {
|
||||
return generateArrowFunction(`
|
||||
(_input) => {
|
||||
const _results = new Set();
|
||||
const errors = [];
|
||||
for (const _generator of ${generate({
|
||||
type: "ArrayExpression",
|
||||
elements: generators,
|
||||
} as ESTree.Node)}) {
|
||||
try {
|
||||
_results.add(_generator(_input));
|
||||
} catch (e) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
if (!_results.size) {
|
||||
throw \`no solutions: \${errors.join(", ")}\`;
|
||||
}
|
||||
if (_results.size !== 1) {
|
||||
throw \`invalid solutions: \${[..._results].map(x => JSON.stringify(x)).join(", ")}\`;
|
||||
}
|
||||
return _results.values().next().value;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
import { players, tests } from "./tests.ts";
|
||||
import { getCachePath } from "./utils.ts";
|
||||
import { getIO } from "./io.ts";
|
||||
|
||||
const io = await getIO();
|
||||
import { downloadCached } from "./utils.ts";
|
||||
|
||||
for (const test of tests) {
|
||||
const variants = test.variants ?? players.keys();
|
||||
for (const variant of variants) {
|
||||
const path = getCachePath(test.player, variant);
|
||||
if (await io.exists(path)) {
|
||||
continue;
|
||||
try {
|
||||
await downloadCached(test.player, variant);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
const playerPath = players.get(variant);
|
||||
const url = `https://www.youtube.com/s/player/${test.player}/${playerPath}`;
|
||||
console.log("Requesting", url);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
console.error(`Failed to request ${variant} player for ${test.player}`);
|
||||
continue;
|
||||
}
|
||||
await io.write(path, response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,6 @@ async function _getIO(): Promise<IO> {
|
||||
};
|
||||
}
|
||||
throw new Error(
|
||||
`unsupported runtime for testing${
|
||||
navigator.userAgent ? `: ${navigator.userAgent}` : ""
|
||||
}`,
|
||||
`unsupported runtime for testing${navigator.userAgent ? `: ${navigator.userAgent}` : ""}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,276 +10,103 @@ export const tests: {
|
||||
sig?: Step[];
|
||||
}[] = [
|
||||
{
|
||||
player: "3d3ba064",
|
||||
// 20522
|
||||
player: "74edf1a3",
|
||||
n: [
|
||||
{ input: "ZdZIqFPQK-Ty8wId", expected: "qmtUsIz04xxiNW" },
|
||||
{ input: "4GMrWHyKI5cEvhDO", expected: "N9gmEX7YhKTSmw" },
|
||||
{ input: "IlLiA21ny7gqA2m4p37", expected: "9nRTxrbM1f0yHg" },
|
||||
{ input: "eabGFpsUKuWHXGh6FR4", expected: "izmYqDEY6kl7Sg" },
|
||||
{ input: "eabGF/ps%UK=uWHXGh6FR4", expected: "LACmqlhaBpiPlgE-a" },
|
||||
],
|
||||
sig: [
|
||||
{
|
||||
input:
|
||||
"gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt",
|
||||
"NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz",
|
||||
expected:
|
||||
"ttJC2JfQdSswRAIgGBCxZyAfKyi0cjXCb3gqEctUw-NYdNmOEvaepit0zJAtIEsgOV2SXZjhSHMNy0NXNG_1kNyBf6HPuAuCduh-a7O",
|
||||
"NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hzMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzl",
|
||||
},
|
||||
{
|
||||
input:
|
||||
"\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49",
|
||||
expected:
|
||||
"\x00\x01\x02%\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x40\x41\x42\x49\x44\x45\x46\x47\x48\x43",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "5ec65609",
|
||||
n: [{ input: "0eRGgQWJGfT5rFHFj", expected: "4SvMpDQH-vBJCw" }],
|
||||
// 20523
|
||||
player: "901741ab",
|
||||
n: [{ input: "BQoJvGBkC2nj1ZZLK-", expected: "UMPovvBZRh-sjb" }],
|
||||
sig: [
|
||||
{
|
||||
input:
|
||||
"AAJAJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grH0rTMICA1mmDc0HoXgW3CAiAQQ4=CspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ=I",
|
||||
"NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz",
|
||||
expected:
|
||||
"AJfQdSswRQIhAMG5SN7-cAFChdrE7tLA6grI0rTMICA1mmDc0HoXgW3CAiAQQ4HCspfaF_vt82XH5yewvqcuEkvzeTsbRuHssRMyJQ==",
|
||||
"wgwCHlydB9Hg7PMegXoVzaoAXXB8woPSNZqRUC3Pe7vAEiApVSCMlhwmt5ON-8MB=5RPyyzdAM9MPM-kPfjgTxEK0IAhIgRwE0jiEJA",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "6742b2b9",
|
||||
n: [
|
||||
{ input: "_HPB-7GFg1VTkn9u", expected: "qUAsPryAO_ByYg" },
|
||||
{ input: "K1t_fcB6phzuq2SF", expected: "Y7PcOt3VE62mog" },
|
||||
],
|
||||
// 20524
|
||||
player: "e7573094",
|
||||
n: [{ input: "IlLiA21ny7gqA2m4p37", expected: "3KuQ3235dojTSjo4" }],
|
||||
sig: [
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"NJAJEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyyPRt=BM8-XO5tm5hlMCSVpAiEAv7eP3CURqZNSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=gwzz",
|
||||
expected:
|
||||
"AJfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHM8EjoCACIEQnz-nKN5RgG6iUTnNJC58csYPSrnS_SzricuUMJZGM",
|
||||
"yEij0EwRgIhAI0KExTgjfPk-MPM9MAdzyNPRt=BM8-XO5tm5hlMCSVNAiEAvpeP3CURqZJSPow8BXXAoazVoXgeMP7gH9BdylHCwgw=g",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "23ccdd25",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "orSsTqUaUO-j" },
|
||||
],
|
||||
// 20525
|
||||
player: "9fcf08e8",
|
||||
n: [{ input: "4JRSxxN0E_fLVnxmd", expected: "xhAoMP8xPcR5wg" }],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a",
|
||||
expected:
|
||||
"ZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hAU6wbTvorvVVMgIARwsSdQfJAN",
|
||||
"\x6a\x69\x68\x67\x66\x65\x64\x63\x62\x61\x60\x5f\x5e\x5d\x5c\x5b\x5a\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4f\x4e\x4d\x4c\x4b\x4a\x49\x48\x47\x46\x45\x44\x43\x42\x41\x40\x3f\x3e\x3d\x3c\x3b\x3a\x39\x38\x37\x36\x35\x34\x33\x32\x31\x30\x2f\x2e\x2d\x2c\x2b\x2a\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0f\x0e\x0d\x0c\x0b\x03\x09\x08\x07\x06\x05\x04\x0a",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "3597727b",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "PRwo5dDfisg0ejA2" },
|
||||
],
|
||||
// 20527
|
||||
player: "21cd2156",
|
||||
n: [{ input: "16EF3jx-Mr_TLuGH", expected: "OQJDc7IrlWCkfg" }],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a",
|
||||
expected:
|
||||
"AAJfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYuMS6SHM8Ej7CACIEQnz-nKN5RgG6iUTnNJC58csYPSroS_SzricuUMJZG",
|
||||
"\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x00\x46\x47\x48\x49\x4a\x4b\x6a\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x4c",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// tce causes exception even in browser
|
||||
player: "3752a005",
|
||||
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
|
||||
],
|
||||
// 20528 (tv & tv_es6 needed self.location.origin fix)
|
||||
player: "76ad2fe8",
|
||||
n: [{ input: "V8pdMGD0Sz_M0DRT", expected: "rBnTGCWGFpwByA" }],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a",
|
||||
expected:
|
||||
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"\x46\x66\x65\x64\x63\x62\x61\x60\x5f\x5e\x67\x6a\x5b\x5a\x59\x58\x57\x56\x55\x54\x53\x52\x51\x50\x4f\x4e\x4d\x4c\x4b\x4a\x49\x48\x47\x2c\x45\x44\x43\x42\x41\x40\x3f\x3e\x3d\x3c\x3b\x3a\x39\x38\x13\x36\x35\x34\x33\x32\x31\x30\x2f\x2e\x2d\x5d\x2b\x2a\x29\x28\x27\x26\x25\x24\x23\x22\x21\x20\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x0c\x12\x11\x10\x0f\x0e\x0d\x00\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x37",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// tce causes exception even in browser
|
||||
player: "afc7785b",
|
||||
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
|
||||
],
|
||||
// 20529 (tv & tv_es6 needed self.location.origin fix)
|
||||
player: "631d3938",
|
||||
n: [{ input: "KBx1qz7jMhxELa8c", expected: "ttPvh7WIptsgSw" }],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66",
|
||||
expected:
|
||||
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// tce causes exception even in browser
|
||||
player: "b9645327",
|
||||
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// tce causes exception even in browser
|
||||
player: "035b9195",
|
||||
variants: ["main", "tcc", "es5", "es6", "tv", "tv_es6", "phone", "tablet"],
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "j22ZtsqVsR0Dn" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"ZJM_ucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHG6S7uYq4TGjQXSD4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "6740c111",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "AVsXYE0uE1k8e" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHM8EjoCACIEQnz-MKN5RgG6iUTnNJC58csYPSrnS_SzricuUMJZGn",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "f6a4f3bc",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "H1NKYFbhlqZ" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYM7S6SHM8EjoCACIEQnz-nKM5RgG6iUTnNJC58cNYPSrnS_SzricuUMJZGu",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "b66835e2",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "H1NKYFbhlqZ" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"JfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYM7S6SHM8EjoCACIEQnz-nKM5RgG6iUTnNJC58cNYPSrnS_SzricuUMJZGu",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "4f8fa943",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "JWWr7hDSRpMq5" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"AAJfQdSswRAIgMVVvrovTbw6UNh99kPa4D_XQjGT4qYu7S6SHr8EjoCACIEQnz-nKN5RgG6iUTnNZC58csYPSMnS_SzricuUM",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "0004de42",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "OPd7UEsCDmCw4qD0" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJAA",
|
||||
expected:
|
||||
"ZJMUucirzS_SnrSPYsc85MJNnTUi6GgR5NCn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQ",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "2b83d2e0",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "0eRGgQWJGfT5rFHFj", expected: "euHbygrCMLksxd" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"MMGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKn-znQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJA",
|
||||
expected:
|
||||
"-MGZJMUucirzS_SnrSPYsc85CJNnTUi6GgR5NKnMznQEICACojE8MHS6S7uYq4TGjQX_D4aPk99hNU6wbTvorvVVMgIARwsSdQfJ",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "638ec5c6",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "ZdZIqFPQK-Ty8wId", expected: "1qov8-KM-yH" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt",
|
||||
expected:
|
||||
"MhudCuAuP-6fByOk1_GNXN7gNHHShjyXS2VOgsEItAJz0tipeav0OmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
player: "87644c66",
|
||||
n: [
|
||||
// Synthetic test
|
||||
{ input: "ZdZIqFPQK-Ty8wId", expected: "iF5NxEm1BYk" },
|
||||
],
|
||||
sig: [
|
||||
// Synthetic test
|
||||
{
|
||||
input:
|
||||
"gN7a-hudCuAuPH6fByOk1_GNXN0yNMHShjZXS2VOgsEItAJz0tipeavEOmNdYN-wUtcEqD3bCXjc0iyKfAyZxCBGgIARwsSdQfJ2CJtt",
|
||||
expected:
|
||||
"atJC2JfQdSswRAtgGBCxZyAfKyi0cjXCb3DqEctUw-NYdNmOEvIepit0zJAtIEsgOV2SXZjhSHMNy0NXNG_1kOyBf6HPuAuCduh-a7Ng",
|
||||
"\x19\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x00\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63",
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -289,12 +116,12 @@ export const players = new Map([
|
||||
["main", "player_ias.vflset/en_US/base.js"],
|
||||
["tcc", "player_ias_tcc.vflset/en_US/base.js"],
|
||||
["tce", "player_ias_tce.vflset/en_US/base.js"],
|
||||
["es5", "player_es5.vflset/en_US/base.js"],
|
||||
["es6", "player_es6.vflset/en_US/base.js"],
|
||||
["tv", "tv-player-ias.vflset/tv-player-ias.js"],
|
||||
["tv_es6", "tv-player-es6.vflset/tv-player-es6.js"],
|
||||
["phone", "player-plasma-ias-phone-en_US.vflset/base.js"],
|
||||
["tablet", "player-plasma-ias-tablet-en_US.vflset/base.js"],
|
||||
["es6_tcc", "player_es6_tcc.vflset/en_US/base.js"],
|
||||
["es6_tce", "player_es6_tce.vflset/en_US/base.js"],
|
||||
] as const);
|
||||
|
||||
export type Variant = typeof players extends Map<infer T, unknown> ? T : never;
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
import { type Variant } from "./tests.ts";
|
||||
import { getIO } from "./io.ts";
|
||||
import { players, type Variant } from "./tests.ts";
|
||||
|
||||
export function getCachePath(player: string, variant: Variant) {
|
||||
return `src/yt/solver/test/players/${player}-${variant}`;
|
||||
}
|
||||
|
||||
export async function downloadCached(player: string, variant: string) {
|
||||
const io = await getIO();
|
||||
|
||||
const playerPath = players.get(variant as Variant);
|
||||
if (!playerPath) {
|
||||
throw `Invalid player variant: ${variant}`;
|
||||
}
|
||||
const path = getCachePath(player, variant as Variant);
|
||||
if (!(await io.exists(path))) {
|
||||
const url = `https://www.youtube.com/s/player/${player}/${playerPath}`;
|
||||
console.log("Requesting", url);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw `Failed to request ${variant} player for ${player}`;
|
||||
}
|
||||
await io.write(path, response);
|
||||
}
|
||||
return await io.read(path);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user