diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 622bf9587..620e757c9 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,6 +4,12 @@ This pull request … +### Changelog + + + +- + ### Testing diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28d23a03d..d7e5d1e11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -93,38 +93,38 @@ jobs: uses: tj-actions/changed-files@v45 with: files: | - plugins/*/src/** - plugins/*/test/** - plugins/*/*.test.ts - plugins/*/*.test.tsx - plugins/*/vitest.config.ts - plugins/*/test-setup.ts + {plugins,packages}/*/src/** + {plugins,packages}/*/test/** + {plugins,packages}/*/*.test.ts + {plugins,packages}/*/*.test.tsx + {plugins,packages}/*/vitest.config.ts + {plugins,packages}/*/test-setup.ts - name: Install dependencies if: steps.changed-files.outputs.any_changed == 'true' run: yarn - - name: Get changed plugins + - name: Get changed workspaces if: steps.changed-files.outputs.any_changed == 'true' - id: changed-plugins + id: changed-workspaces run: | - # Extract unique plugin names from changed files - PLUGINS=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | \ - grep -E '^plugins/[^/]+/' | \ - cut -d'/' -f2 | \ + # Extract unique workspace paths from changed files + WORKSPACES=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | \ + grep -oE '(plugins|packages)/[^/]+' | \ sort -u | \ tr '\n' ' ') - echo "plugins=$PLUGINS" >> $GITHUB_OUTPUT - echo "Changed plugins: $PLUGINS" + echo "workspaces=$WORKSPACES" >> $GITHUB_OUTPUT + echo "Changed workspaces: $WORKSPACES" - - name: Run tests for changed plugins - if: steps.changed-files.outputs.any_changed == 'true' && steps.changed-plugins.outputs.plugins != '' + - name: Run tests for changed workspaces + if: steps.changed-files.outputs.any_changed == 'true' && steps.changed-workspaces.outputs.workspaces != '' run: | - for plugin in ${{ steps.changed-plugins.outputs.plugins }}; do - echo "Checking tests for plugin: $plugin" - if [ -f "plugins/$plugin/package.json" ] && grep -q '"check-vitest"' "plugins/$plugin/package.json"; then - yarn workspace $plugin check-vitest + for workspace in ${{ steps.changed-workspaces.outputs.workspaces }}; do + echo "Checking tests for workspace: $workspace" + if [ -f "$workspace/package.json" ] && grep -q '"check-vitest"' "$workspace/package.json"; then + name=$(jq -r '.name' "$workspace/package.json") + yarn workspace "$name" check-vitest else - echo "No check-vitest script found for $plugin, skipping..." + echo "No check-vitest script found for $workspace, skipping..." fi done diff --git a/.github/workflows/shippy.yml b/.github/workflows/shippy.yml index ac9d0e9c9..d3bb94b01 100644 --- a/.github/workflows/shippy.yml +++ b/.github/workflows/shippy.yml @@ -7,6 +7,8 @@ on: - edited - ready_for_review - synchronize + - labeled + - unlabeled workflow_dispatch: # NOTE: To prevent GitHub from adding PRs to the merge queue before check is done, # make sure that there is a ruleset that requires the “Shippy check to pass. @@ -24,11 +26,32 @@ jobs: runs-on: ubuntu-latest if: github.event.pull_request.draft == false && github.event.pull_request.user.login != 'dependabot[bot]' steps: - - name: Check PR description + - name: Check if Submit on merge label is present + id: check-label uses: actions/github-script@v7 with: script: | - const prBody = context.payload.pull_request.body?.trim() - if (!prBody) { - core.setFailed("❌ PR description is required.") - } + const labels = context.payload.pull_request.labels || [] + const hasSubmitLabel = labels.some(label => label.name === 'Submit on merge') + core.setOutput('require_changelog', hasSubmitLabel ? 'true' : 'false') + + - name: Checkout repository + uses: actions/checkout@v4 + with: + sparse-checkout: | + scripts + package.json + yarn.lock + .yarnrc.yml + .yarn + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .tool-versions + + - name: Validate PR body + run: yarn dlx tsx scripts/validate-pr-body.ts + env: + PR_BODY: ${{ github.event.pull_request.body }} + REQUIRE_CHANGELOG: ${{ steps.check-label.outputs.require_changelog }} diff --git a/.github/workflows/submit-on-merge.yml b/.github/workflows/submit-on-merge.yml new file mode 100644 index 000000000..bcfef2feb --- /dev/null +++ b/.github/workflows/submit-on-merge.yml @@ -0,0 +1,64 @@ +name: Submit on Merge + +on: + pull_request: + types: + - closed + branches: + - main + +jobs: + submit: + name: Submit Changed Plugins + runs-on: ubuntu-latest + # Only run if PR was merged (not just closed) and has "Submit on merge" label + if: | + github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'Submit on merge') + # FIXME: Should be production + environment: development + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for git tags and diff + + - name: Configure git identity + run: | + git config --global user.email "marketplace@framer.team" + git config --global user.name "Framer Marketplace" + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .tool-versions + + - name: Install dependencies + run: yarn install + + - name: Build framer-plugin-tools + working-directory: packages/plugin-tools + run: yarn build + + - name: Write PR body to file + run: cat <<< "$PR_BODY" > /tmp/pr-body.txt + env: + PR_BODY: ${{ github.event.pull_request.body }} + + - name: Submit changed plugins + run: | + export CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }}) + yarn tsx scripts/submit-on-merge.ts + env: + DEBUG: "1" + PR_BODY_FILE: /tmp/pr-body.txt + SESSION_TOKEN: ${{ secrets.SESSION_TOKEN }} + FRAMER_ADMIN_SECRET: ${{ secrets.FRAMER_ADMIN_SECRET }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_ERROR_WEBHOOK_URL: ${{ secrets.SLACK_ERROR_WEBHOOK_URL }} + RETOOL_URL: ${{ secrets.RETOOL_URL }} + # FIXME: Should be production + FRAMER_ENV: development + GITHUB_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/submit-plugin.yml b/.github/workflows/submit-plugin.yml new file mode 100644 index 000000000..cec0ab0de --- /dev/null +++ b/.github/workflows/submit-plugin.yml @@ -0,0 +1,124 @@ +name: Submit Plugin + +on: + # Manual trigger from GitHub UI + workflow_dispatch: + inputs: + plugin_path: + description: 'Plugin directory (e.g., plugins/csv-import)' + required: true + type: string + changelog: + description: 'Changelog for this release' + required: true + type: string + environment: + description: 'Environment (development/production)' + required: true + default: 'development' + type: choice + options: + - development + - production + dry_run: + description: 'Dry run (skip submission and tagging)' + required: false + default: false + type: boolean + + # Reusable workflow - can be called from other repos (e.g., framer/workshop) + workflow_call: + inputs: + plugin_path: + description: 'Plugin directory (e.g., plugins/csv-import)' + required: true + type: string + changelog: + description: 'Changelog for this release' + required: true + type: string + environment: + description: 'Environment (development/production)' + required: true + default: 'development' + type: string + dry_run: + description: 'Dry run (skip submission and tagging)' + required: false + default: false + type: boolean + secrets: + SESSION_TOKEN: + description: 'Framer session cookie' + required: true + FRAMER_ADMIN_SECRET: + description: 'Framer admin API key' + required: true + SLACK_WEBHOOK_URL: + description: 'Slack webhook URL for notifications' + required: false + RETOOL_URL: + description: 'Retool dashboard URL for Slack notifications' + required: false + SLACK_ERROR_WEBHOOK_URL: + description: 'Slack webhook URL for error notifications' + required: false + +jobs: + submit: + name: Submit Plugin to Marketplace + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for git tags and diff + + - name: Configure git identity + run: | + git config --global user.email "marketplace@framer.team" + git config --global user.name "Framer Marketplace" + + - name: Validate plugin path + run: | + if [ ! -d "${{ github.workspace }}/${{ inputs.plugin_path }}" ]; then + echo "Error: Plugin path '${{ inputs.plugin_path }}' does not exist" + echo "" + echo "Available plugins:" + ls -1 plugins/ + exit 1 + fi + if [ ! -f "${{ github.workspace }}/${{ inputs.plugin_path }}/framer.json" ]; then + echo "Error: No framer.json found in '${{ inputs.plugin_path }}'" + exit 1 + fi + echo "Plugin path validated: ${{ inputs.plugin_path }}" + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version-file: .tool-versions + + - name: Install dependencies + run: yarn install + + - name: Build framer-plugin-tools + run: yarn turbo run build --filter=framer-plugin-tools + + - name: Submit plugin + run: yarn tsx scripts/submit-plugin.ts + env: + PLUGIN_PATH: ${{ github.workspace }}/${{ inputs.plugin_path }} + REPO_ROOT: ${{ github.workspace }} + CHANGELOG: ${{ inputs.changelog }} + SESSION_TOKEN: ${{ secrets.SESSION_TOKEN }} + FRAMER_ADMIN_SECRET: ${{ secrets.FRAMER_ADMIN_SECRET }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_ERROR_WEBHOOK_URL: ${{ secrets.SLACK_ERROR_WEBHOOK_URL }} + RETOOL_URL: ${{ secrets.RETOOL_URL }} + FRAMER_ENV: ${{ inputs.environment }} + GITHUB_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + DRY_RUN: ${{ inputs.dry_run }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.yarn/cache/@babel-generator-npm-8.0.0-rc.1-7b4577a751-1949ed7a07.zip b/.yarn/cache/@babel-generator-npm-8.0.0-rc.1-7b4577a751-1949ed7a07.zip new file mode 100644 index 000000000..dcc273dbd Binary files /dev/null and b/.yarn/cache/@babel-generator-npm-8.0.0-rc.1-7b4577a751-1949ed7a07.zip differ diff --git a/.yarn/cache/@babel-helper-string-parser-npm-8.0.0-rc.1-826f1bb41e-9c7b34ecce.zip b/.yarn/cache/@babel-helper-string-parser-npm-8.0.0-rc.1-826f1bb41e-9c7b34ecce.zip new file mode 100644 index 000000000..0793d4190 Binary files /dev/null and b/.yarn/cache/@babel-helper-string-parser-npm-8.0.0-rc.1-826f1bb41e-9c7b34ecce.zip differ diff --git a/.yarn/cache/@babel-helper-validator-identifier-npm-8.0.0-rc.1-13fd699081-75d6d5201c.zip b/.yarn/cache/@babel-helper-validator-identifier-npm-8.0.0-rc.1-13fd699081-75d6d5201c.zip new file mode 100644 index 000000000..e555aeed6 Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-identifier-npm-8.0.0-rc.1-13fd699081-75d6d5201c.zip differ diff --git a/.yarn/cache/@babel-parser-npm-8.0.0-rc.1-d05e9b70b4-d0c5baf877.zip b/.yarn/cache/@babel-parser-npm-8.0.0-rc.1-d05e9b70b4-d0c5baf877.zip new file mode 100644 index 000000000..857b57b0f Binary files /dev/null and b/.yarn/cache/@babel-parser-npm-8.0.0-rc.1-d05e9b70b4-d0c5baf877.zip differ diff --git a/.yarn/cache/@babel-types-npm-8.0.0-rc.1-35e137a67f-34def05264.zip b/.yarn/cache/@babel-types-npm-8.0.0-rc.1-35e137a67f-34def05264.zip new file mode 100644 index 000000000..fecf4166d Binary files /dev/null and b/.yarn/cache/@babel-types-npm-8.0.0-rc.1-35e137a67f-34def05264.zip differ diff --git a/.yarn/cache/@commander-js-extra-typings-npm-13.1.0-360957fb64-cdb7f854ac.zip b/.yarn/cache/@commander-js-extra-typings-npm-13.1.0-360957fb64-cdb7f854ac.zip new file mode 100644 index 000000000..74ec7b5d0 Binary files /dev/null and b/.yarn/cache/@commander-js-extra-typings-npm-13.1.0-360957fb64-cdb7f854ac.zip differ diff --git a/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip b/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip new file mode 100644 index 000000000..b97b75b57 Binary files /dev/null and b/.yarn/cache/@emnapi-core-npm-1.8.1-9be0a25589-904ea60c91.zip differ diff --git a/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip new file mode 100644 index 000000000..669c0bafe Binary files /dev/null and b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-26725e202d.zip differ diff --git a/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip new file mode 100644 index 000000000..df4de2225 Binary files /dev/null and b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10.zip differ diff --git a/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10.zip b/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10.zip new file mode 100644 index 000000000..987fc4966 Binary files /dev/null and b/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10.zip differ diff --git a/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10.zip b/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10.zip new file mode 100644 index 000000000..32c8cc871 Binary files /dev/null and b/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10.zip differ diff --git a/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip b/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip new file mode 100644 index 000000000..eea4066e3 Binary files /dev/null and b/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10.zip differ diff --git a/.yarn/cache/@esbuild-win32-arm64-npm-0.27.2-78a0e828ec-10.zip b/.yarn/cache/@esbuild-win32-arm64-npm-0.27.2-78a0e828ec-10.zip new file mode 100644 index 000000000..e3bec141d Binary files /dev/null and b/.yarn/cache/@esbuild-win32-arm64-npm-0.27.2-78a0e828ec-10.zip differ diff --git a/.yarn/cache/@esbuild-win32-x64-npm-0.27.2-fb03408001-10.zip b/.yarn/cache/@esbuild-win32-x64-npm-0.27.2-fb03408001-10.zip new file mode 100644 index 000000000..549aacedc Binary files /dev/null and b/.yarn/cache/@esbuild-win32-x64-npm-0.27.2-fb03408001-10.zip differ diff --git a/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip new file mode 100644 index 000000000..e130971fd Binary files /dev/null and b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-902f8261dc.zip differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip new file mode 100644 index 000000000..d61ababcd Binary files /dev/null and b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-da0283270e.zip differ diff --git a/.yarn/cache/@napi-rs-wasm-runtime-npm-1.1.1-c9debf141f-080e7f2aef.zip b/.yarn/cache/@napi-rs-wasm-runtime-npm-1.1.1-c9debf141f-080e7f2aef.zip new file mode 100644 index 000000000..db34c520d Binary files /dev/null and b/.yarn/cache/@napi-rs-wasm-runtime-npm-1.1.1-c9debf141f-080e7f2aef.zip differ diff --git a/.yarn/cache/@oxc-project-types-npm-0.112.0-e7acfb5018-5954982169.zip b/.yarn/cache/@oxc-project-types-npm-0.112.0-e7acfb5018-5954982169.zip new file mode 100644 index 000000000..f66ae9f97 Binary files /dev/null and b/.yarn/cache/@oxc-project-types-npm-0.112.0-e7acfb5018-5954982169.zip differ diff --git a/.yarn/cache/@quansync-fs-npm-1.0.0-869f097647-8a27892b13.zip b/.yarn/cache/@quansync-fs-npm-1.0.0-869f097647-8a27892b13.zip new file mode 100644 index 000000000..7281201bb Binary files /dev/null and b/.yarn/cache/@quansync-fs-npm-1.0.0-869f097647-8a27892b13.zip differ diff --git a/.yarn/cache/@rolldown-binding-darwin-arm64-npm-1.0.0-rc.3-c3196f4d78-10.zip b/.yarn/cache/@rolldown-binding-darwin-arm64-npm-1.0.0-rc.3-c3196f4d78-10.zip new file mode 100644 index 000000000..9a6ccb913 Binary files /dev/null and b/.yarn/cache/@rolldown-binding-darwin-arm64-npm-1.0.0-rc.3-c3196f4d78-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-darwin-x64-npm-1.0.0-rc.3-edaa9164af-10.zip b/.yarn/cache/@rolldown-binding-darwin-x64-npm-1.0.0-rc.3-edaa9164af-10.zip new file mode 100644 index 000000000..1b4cc9c39 Binary files /dev/null and b/.yarn/cache/@rolldown-binding-darwin-x64-npm-1.0.0-rc.3-edaa9164af-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-linux-arm64-gnu-npm-1.0.0-rc.3-194ce4c287-10.zip b/.yarn/cache/@rolldown-binding-linux-arm64-gnu-npm-1.0.0-rc.3-194ce4c287-10.zip new file mode 100644 index 000000000..225a9b1df Binary files /dev/null and b/.yarn/cache/@rolldown-binding-linux-arm64-gnu-npm-1.0.0-rc.3-194ce4c287-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-linux-arm64-musl-npm-1.0.0-rc.3-fd6342d84f-10.zip b/.yarn/cache/@rolldown-binding-linux-arm64-musl-npm-1.0.0-rc.3-fd6342d84f-10.zip new file mode 100644 index 000000000..858f884c2 Binary files /dev/null and b/.yarn/cache/@rolldown-binding-linux-arm64-musl-npm-1.0.0-rc.3-fd6342d84f-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-linux-x64-gnu-npm-1.0.0-rc.3-fb6aa24536-10.zip b/.yarn/cache/@rolldown-binding-linux-x64-gnu-npm-1.0.0-rc.3-fb6aa24536-10.zip new file mode 100644 index 000000000..270ae9b19 Binary files /dev/null and b/.yarn/cache/@rolldown-binding-linux-x64-gnu-npm-1.0.0-rc.3-fb6aa24536-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-linux-x64-musl-npm-1.0.0-rc.3-b285db285c-10.zip b/.yarn/cache/@rolldown-binding-linux-x64-musl-npm-1.0.0-rc.3-b285db285c-10.zip new file mode 100644 index 000000000..eaf4f51ea Binary files /dev/null and b/.yarn/cache/@rolldown-binding-linux-x64-musl-npm-1.0.0-rc.3-b285db285c-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-win32-arm64-msvc-npm-1.0.0-rc.3-9076c881e2-10.zip b/.yarn/cache/@rolldown-binding-win32-arm64-msvc-npm-1.0.0-rc.3-9076c881e2-10.zip new file mode 100644 index 000000000..0ba96e657 Binary files /dev/null and b/.yarn/cache/@rolldown-binding-win32-arm64-msvc-npm-1.0.0-rc.3-9076c881e2-10.zip differ diff --git a/.yarn/cache/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.3-cda6ed4bb8-10.zip b/.yarn/cache/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.3-cda6ed4bb8-10.zip new file mode 100644 index 000000000..3fabbba8d Binary files /dev/null and b/.yarn/cache/@rolldown-binding-win32-x64-msvc-npm-1.0.0-rc.3-cda6ed4bb8-10.zip differ diff --git a/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-rc.3-790b1e278c-b181a693b7.zip b/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-rc.3-790b1e278c-b181a693b7.zip new file mode 100644 index 000000000..aa5cfb7d8 Binary files /dev/null and b/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-rc.3-790b1e278c-b181a693b7.zip differ diff --git a/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.57.1-30fcad3f8c-10.zip b/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.57.1-30fcad3f8c-10.zip new file mode 100644 index 000000000..fbdb3a060 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.57.1-30fcad3f8c-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.57.1-a79270fa64-10.zip b/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.57.1-a79270fa64-10.zip new file mode 100644 index 000000000..0f69fe496 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.57.1-a79270fa64-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.57.1-fd27dea33b-10.zip b/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.57.1-fd27dea33b-10.zip new file mode 100644 index 000000000..ce22eddef Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.57.1-fd27dea33b-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.57.1-3dce1fd7b1-10.zip b/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.57.1-3dce1fd7b1-10.zip new file mode 100644 index 000000000..505a36abe Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.57.1-3dce1fd7b1-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.57.1-667d72ac2f-10.zip b/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.57.1-667d72ac2f-10.zip new file mode 100644 index 000000000..a2bb10949 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.57.1-667d72ac2f-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.57.1-1bc4af3cb5-10.zip b/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.57.1-1bc4af3cb5-10.zip new file mode 100644 index 000000000..60174e053 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.57.1-1bc4af3cb5-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-win32-arm64-msvc-npm-4.57.1-36312bb667-10.zip b/.yarn/cache/@rollup-rollup-win32-arm64-msvc-npm-4.57.1-36312bb667-10.zip new file mode 100644 index 000000000..8373ce50e Binary files /dev/null and b/.yarn/cache/@rollup-rollup-win32-arm64-msvc-npm-4.57.1-36312bb667-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-win32-x64-gnu-npm-4.57.1-ab351abab0-10.zip b/.yarn/cache/@rollup-rollup-win32-x64-gnu-npm-4.57.1-ab351abab0-10.zip new file mode 100644 index 000000000..f1a73acdd Binary files /dev/null and b/.yarn/cache/@rollup-rollup-win32-x64-gnu-npm-4.57.1-ab351abab0-10.zip differ diff --git a/.yarn/cache/@rollup-rollup-win32-x64-msvc-npm-4.57.1-57e2356b3a-10.zip b/.yarn/cache/@rollup-rollup-win32-x64-msvc-npm-4.57.1-57e2356b3a-10.zip new file mode 100644 index 000000000..5728375ed Binary files /dev/null and b/.yarn/cache/@rollup-rollup-win32-x64-msvc-npm-4.57.1-57e2356b3a-10.zip differ diff --git a/.yarn/cache/@types-adm-zip-npm-0.5.7-b19d96a568-24e9842bd6.zip b/.yarn/cache/@types-adm-zip-npm-0.5.7-b19d96a568-24e9842bd6.zip new file mode 100644 index 000000000..568da9afe Binary files /dev/null and b/.yarn/cache/@types-adm-zip-npm-0.5.7-b19d96a568-24e9842bd6.zip differ diff --git a/.yarn/cache/@types-jsesc-npm-2.5.1-3d8289fff0-25407775ed.zip b/.yarn/cache/@types-jsesc-npm-2.5.1-3d8289fff0-25407775ed.zip new file mode 100644 index 000000000..d1c21e278 Binary files /dev/null and b/.yarn/cache/@types-jsesc-npm-2.5.1-3d8289fff0-25407775ed.zip differ diff --git a/.yarn/cache/@types-node-npm-22.19.7-d4e0361572-0a5c9cc3bd.zip b/.yarn/cache/@types-node-npm-22.19.7-d4e0361572-0a5c9cc3bd.zip new file mode 100644 index 000000000..8c7de71a4 Binary files /dev/null and b/.yarn/cache/@types-node-npm-22.19.7-d4e0361572-0a5c9cc3bd.zip differ diff --git a/.yarn/cache/@types-node-npm-22.19.8-a20ecb429d-a61c68d434.zip b/.yarn/cache/@types-node-npm-22.19.8-a20ecb429d-a61c68d434.zip new file mode 100644 index 000000000..f744c46eb Binary files /dev/null and b/.yarn/cache/@types-node-npm-22.19.8-a20ecb429d-a61c68d434.zip differ diff --git a/.yarn/cache/@types-ws-npm-8.18.1-61dc106ff0-1ce05e3174.zip b/.yarn/cache/@types-ws-npm-8.18.1-61dc106ff0-1ce05e3174.zip new file mode 100644 index 000000000..5c915f403 Binary files /dev/null and b/.yarn/cache/@types-ws-npm-8.18.1-61dc106ff0-1ce05e3174.zip differ diff --git a/.yarn/cache/@typescript-ata-npm-0.9.8-0663e9063b-c0f9daf781.zip b/.yarn/cache/@typescript-ata-npm-0.9.8-0663e9063b-c0f9daf781.zip new file mode 100644 index 000000000..500bfe18e Binary files /dev/null and b/.yarn/cache/@typescript-ata-npm-0.9.8-0663e9063b-c0f9daf781.zip differ diff --git a/.yarn/cache/@vitest-expect-npm-4.0.18-03919ccd0b-2115bff1bb.zip b/.yarn/cache/@vitest-expect-npm-4.0.18-03919ccd0b-2115bff1bb.zip new file mode 100644 index 000000000..3db069f11 Binary files /dev/null and b/.yarn/cache/@vitest-expect-npm-4.0.18-03919ccd0b-2115bff1bb.zip differ diff --git a/.yarn/cache/@vitest-mocker-npm-4.0.18-118c87f90e-46f584a4c1.zip b/.yarn/cache/@vitest-mocker-npm-4.0.18-118c87f90e-46f584a4c1.zip new file mode 100644 index 000000000..9705f5fa8 Binary files /dev/null and b/.yarn/cache/@vitest-mocker-npm-4.0.18-118c87f90e-46f584a4c1.zip differ diff --git a/.yarn/cache/@vitest-pretty-format-npm-4.0.18-a73855e4a4-4cafc7c985.zip b/.yarn/cache/@vitest-pretty-format-npm-4.0.18-a73855e4a4-4cafc7c985.zip new file mode 100644 index 000000000..933564838 Binary files /dev/null and b/.yarn/cache/@vitest-pretty-format-npm-4.0.18-a73855e4a4-4cafc7c985.zip differ diff --git a/.yarn/cache/@vitest-runner-npm-4.0.18-3dbdf3fb30-d7deebf086.zip b/.yarn/cache/@vitest-runner-npm-4.0.18-3dbdf3fb30-d7deebf086.zip new file mode 100644 index 000000000..fd61fc011 Binary files /dev/null and b/.yarn/cache/@vitest-runner-npm-4.0.18-3dbdf3fb30-d7deebf086.zip differ diff --git a/.yarn/cache/@vitest-snapshot-npm-4.0.18-35134202ed-50aa5fb7fc.zip b/.yarn/cache/@vitest-snapshot-npm-4.0.18-35134202ed-50aa5fb7fc.zip new file mode 100644 index 000000000..3dfd6c15d Binary files /dev/null and b/.yarn/cache/@vitest-snapshot-npm-4.0.18-35134202ed-50aa5fb7fc.zip differ diff --git a/.yarn/cache/@vitest-spy-npm-4.0.18-296c59dce4-f7b1618ae1.zip b/.yarn/cache/@vitest-spy-npm-4.0.18-296c59dce4-f7b1618ae1.zip new file mode 100644 index 000000000..cabab6646 Binary files /dev/null and b/.yarn/cache/@vitest-spy-npm-4.0.18-296c59dce4-f7b1618ae1.zip differ diff --git a/.yarn/cache/@vitest-utils-npm-4.0.18-b1c99a49e0-e8b2ad7bc3.zip b/.yarn/cache/@vitest-utils-npm-4.0.18-b1c99a49e0-e8b2ad7bc3.zip new file mode 100644 index 000000000..c61d50e0f Binary files /dev/null and b/.yarn/cache/@vitest-utils-npm-4.0.18-b1c99a49e0-e8b2ad7bc3.zip differ diff --git a/.yarn/cache/ansis-npm-4.2.0-35ae97bdc2-493e15fad2.zip b/.yarn/cache/ansis-npm-4.2.0-35ae97bdc2-493e15fad2.zip new file mode 100644 index 000000000..0719e6447 Binary files /dev/null and b/.yarn/cache/ansis-npm-4.2.0-35ae97bdc2-493e15fad2.zip differ diff --git a/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-6737469ba3.zip b/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-6737469ba3.zip new file mode 100644 index 000000000..e93b1e228 Binary files /dev/null and b/.yarn/cache/any-promise-npm-1.3.0-f34eeaa7e7-6737469ba3.zip differ diff --git a/.yarn/cache/ast-kit-npm-3.0.0-beta.1-eee5b0fb06-63c8f80f71.zip b/.yarn/cache/ast-kit-npm-3.0.0-beta.1-eee5b0fb06-63c8f80f71.zip new file mode 100644 index 000000000..b50f29a39 Binary files /dev/null and b/.yarn/cache/ast-kit-npm-3.0.0-beta.1-eee5b0fb06-63c8f80f71.zip differ diff --git a/.yarn/cache/birpc-npm-4.0.0-2cc419e494-f4418e2a04.zip b/.yarn/cache/birpc-npm-4.0.0-2cc419e494-f4418e2a04.zip new file mode 100644 index 000000000..982376952 Binary files /dev/null and b/.yarn/cache/birpc-npm-4.0.0-2cc419e494-f4418e2a04.zip differ diff --git a/.yarn/cache/bundle-require-npm-5.1.0-022b2c8e1b-735e022005.zip b/.yarn/cache/bundle-require-npm-5.1.0-022b2c8e1b-735e022005.zip new file mode 100644 index 000000000..6d3fbfaba Binary files /dev/null and b/.yarn/cache/bundle-require-npm-5.1.0-022b2c8e1b-735e022005.zip differ diff --git a/.yarn/cache/chai-npm-6.2.2-e1795cadaa-13cda42cc4.zip b/.yarn/cache/chai-npm-6.2.2-e1795cadaa-13cda42cc4.zip new file mode 100644 index 000000000..0accfad37 Binary files /dev/null and b/.yarn/cache/chai-npm-6.2.2-e1795cadaa-13cda42cc4.zip differ diff --git a/.yarn/cache/chokidar-npm-4.0.3-962354fbb4-bf2a575ea5.zip b/.yarn/cache/chokidar-npm-4.0.3-962354fbb4-bf2a575ea5.zip new file mode 100644 index 000000000..0085cb689 Binary files /dev/null and b/.yarn/cache/chokidar-npm-4.0.3-962354fbb4-bf2a575ea5.zip differ diff --git a/.yarn/cache/chokidar-npm-5.0.0-2f70d31c86-a1c2a4ee6e.zip b/.yarn/cache/chokidar-npm-5.0.0-2f70d31c86-a1c2a4ee6e.zip new file mode 100644 index 000000000..de48a7b82 Binary files /dev/null and b/.yarn/cache/chokidar-npm-5.0.0-2f70d31c86-a1c2a4ee6e.zip differ diff --git a/.yarn/cache/commander-npm-13.1.0-bdbbfaaf9d-d3b4b79e6b.zip b/.yarn/cache/commander-npm-13.1.0-bdbbfaaf9d-d3b4b79e6b.zip new file mode 100644 index 000000000..5ff7f5b04 Binary files /dev/null and b/.yarn/cache/commander-npm-13.1.0-bdbbfaaf9d-d3b4b79e6b.zip differ diff --git a/.yarn/cache/commander-npm-14.0.3-93ab31471d-dfa9ebe2a4.zip b/.yarn/cache/commander-npm-14.0.3-93ab31471d-dfa9ebe2a4.zip new file mode 100644 index 000000000..9b63f2535 Binary files /dev/null and b/.yarn/cache/commander-npm-14.0.3-93ab31471d-dfa9ebe2a4.zip differ diff --git a/.yarn/cache/commander-npm-4.1.1-22a0fe921b-3b2dc4125f.zip b/.yarn/cache/commander-npm-4.1.1-22a0fe921b-3b2dc4125f.zip new file mode 100644 index 000000000..c893cc7fc Binary files /dev/null and b/.yarn/cache/commander-npm-4.1.1-22a0fe921b-3b2dc4125f.zip differ diff --git a/.yarn/cache/confbox-npm-0.1.8-8396039b68-4ebcfb1c6a.zip b/.yarn/cache/confbox-npm-0.1.8-8396039b68-4ebcfb1c6a.zip new file mode 100644 index 000000000..190ec9ef4 Binary files /dev/null and b/.yarn/cache/confbox-npm-0.1.8-8396039b68-4ebcfb1c6a.zip differ diff --git a/.yarn/cache/consola-npm-3.4.2-133d72719e-32192c9f50.zip b/.yarn/cache/consola-npm-3.4.2-133d72719e-32192c9f50.zip new file mode 100644 index 000000000..51736da15 Binary files /dev/null and b/.yarn/cache/consola-npm-3.4.2-133d72719e-32192c9f50.zip differ diff --git a/.yarn/cache/defu-npm-6.1.4-c791c7f2cc-aeffdb4730.zip b/.yarn/cache/defu-npm-6.1.4-c791c7f2cc-aeffdb4730.zip new file mode 100644 index 000000000..df708b6ab Binary files /dev/null and b/.yarn/cache/defu-npm-6.1.4-c791c7f2cc-aeffdb4730.zip differ diff --git a/.yarn/cache/dts-resolver-npm-2.1.3-5deb33a062-9dfa79be6f.zip b/.yarn/cache/dts-resolver-npm-2.1.3-5deb33a062-9dfa79be6f.zip new file mode 100644 index 000000000..a095b39b8 Binary files /dev/null and b/.yarn/cache/dts-resolver-npm-2.1.3-5deb33a062-9dfa79be6f.zip differ diff --git a/.yarn/cache/empathic-npm-2.0.0-440d97be6e-90f47d93f8.zip b/.yarn/cache/empathic-npm-2.0.0-440d97be6e-90f47d93f8.zip new file mode 100644 index 000000000..daca95502 Binary files /dev/null and b/.yarn/cache/empathic-npm-2.0.0-440d97be6e-90f47d93f8.zip differ diff --git a/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-7f1229328b.zip b/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-7f1229328b.zip new file mode 100644 index 000000000..18b308c08 Binary files /dev/null and b/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-7f1229328b.zip differ diff --git a/.yarn/cache/expect-type-npm-1.3.0-95a4384745-a5fada3d0c.zip b/.yarn/cache/expect-type-npm-1.3.0-95a4384745-a5fada3d0c.zip new file mode 100644 index 000000000..20a597e23 Binary files /dev/null and b/.yarn/cache/expect-type-npm-1.3.0-95a4384745-a5fada3d0c.zip differ diff --git a/.yarn/cache/fix-dts-default-cjs-exports-npm-1.0.1-421fe0399f-3324418bb6.zip b/.yarn/cache/fix-dts-default-cjs-exports-npm-1.0.1-421fe0399f-3324418bb6.zip new file mode 100644 index 000000000..e5fb69592 Binary files /dev/null and b/.yarn/cache/fix-dts-default-cjs-exports-npm-1.0.1-421fe0399f-3324418bb6.zip differ diff --git a/.yarn/cache/framer-plugin-npm-3.10.3-f82e9d58a5-c677a26146.zip b/.yarn/cache/framer-plugin-npm-3.10.3-f82e9d58a5-c677a26146.zip new file mode 100644 index 000000000..0d9ed6da3 Binary files /dev/null and b/.yarn/cache/framer-plugin-npm-3.10.3-f82e9d58a5-c677a26146.zip differ diff --git a/.yarn/cache/framer-plugin-tools-npm-1.0.0-09c6263530-5f6b731038.zip b/.yarn/cache/framer-plugin-tools-npm-1.0.0-09c6263530-5f6b731038.zip deleted file mode 100644 index a03f5dc85..000000000 Binary files a/.yarn/cache/framer-plugin-tools-npm-1.0.0-09c6263530-5f6b731038.zip and /dev/null differ diff --git a/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip b/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip new file mode 100644 index 000000000..521c2617f Binary files /dev/null and b/.yarn/cache/get-tsconfig-npm-4.13.0-009b232bdd-3603c6da30.zip differ diff --git a/.yarn/cache/get-tsconfig-npm-4.13.2-7292f60580-7d7b2bd6ad.zip b/.yarn/cache/get-tsconfig-npm-4.13.2-7292f60580-7d7b2bd6ad.zip new file mode 100644 index 000000000..2461938df Binary files /dev/null and b/.yarn/cache/get-tsconfig-npm-4.13.2-7292f60580-7d7b2bd6ad.zip differ diff --git a/.yarn/cache/hookable-npm-6.0.1-a0fed3cec4-9fccaaa07d.zip b/.yarn/cache/hookable-npm-6.0.1-a0fed3cec4-9fccaaa07d.zip new file mode 100644 index 000000000..3d2a8b02e Binary files /dev/null and b/.yarn/cache/hookable-npm-6.0.1-a0fed3cec4-9fccaaa07d.zip differ diff --git a/.yarn/cache/import-without-cache-npm-0.2.5-ce20052738-b58c16deaa.zip b/.yarn/cache/import-without-cache-npm-0.2.5-ce20052738-b58c16deaa.zip new file mode 100644 index 000000000..31d362c05 Binary files /dev/null and b/.yarn/cache/import-without-cache-npm-0.2.5-ce20052738-b58c16deaa.zip differ diff --git a/.yarn/cache/joycon-npm-3.1.1-3033e0e5f4-4b36e34791.zip b/.yarn/cache/joycon-npm-3.1.1-3033e0e5f4-4b36e34791.zip new file mode 100644 index 000000000..e36528235 Binary files /dev/null and b/.yarn/cache/joycon-npm-3.1.1-3033e0e5f4-4b36e34791.zip differ diff --git a/.yarn/cache/jsesc-npm-3.1.0-2f4f998cd7-20bd37a142.zip b/.yarn/cache/jsesc-npm-3.1.0-2f4f998cd7-20bd37a142.zip new file mode 100644 index 000000000..0701df326 Binary files /dev/null and b/.yarn/cache/jsesc-npm-3.1.0-2f4f998cd7-20bd37a142.zip differ diff --git a/.yarn/cache/lilconfig-npm-3.1.3-74a77377bb-b932ce1af9.zip b/.yarn/cache/lilconfig-npm-3.1.3-74a77377bb-b932ce1af9.zip new file mode 100644 index 000000000..8b9c8cd32 Binary files /dev/null and b/.yarn/cache/lilconfig-npm-3.1.3-74a77377bb-b932ce1af9.zip differ diff --git a/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-0c37f9f7fa.zip b/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-0c37f9f7fa.zip new file mode 100644 index 000000000..273106a73 Binary files /dev/null and b/.yarn/cache/lines-and-columns-npm-1.2.4-d6c7cc5799-0c37f9f7fa.zip differ diff --git a/.yarn/cache/load-tsconfig-npm-0.2.5-70feef5c98-b3176f6f0c.zip b/.yarn/cache/load-tsconfig-npm-0.2.5-70feef5c98-b3176f6f0c.zip new file mode 100644 index 000000000..b16725bda Binary files /dev/null and b/.yarn/cache/load-tsconfig-npm-0.2.5-70feef5c98-b3176f6f0c.zip differ diff --git a/.yarn/cache/lodash-npm-4.17.21-6382451519-c08619c038.zip b/.yarn/cache/lodash-npm-4.17.23-50bdb1c01a-82504c8825.zip similarity index 65% rename from .yarn/cache/lodash-npm-4.17.21-6382451519-c08619c038.zip rename to .yarn/cache/lodash-npm-4.17.23-50bdb1c01a-82504c8825.zip index 5c76f21a6..8050b2fb0 100644 Binary files a/.yarn/cache/lodash-npm-4.17.21-6382451519-c08619c038.zip and b/.yarn/cache/lodash-npm-4.17.23-50bdb1c01a-82504c8825.zip differ diff --git a/.yarn/cache/magic-string-npm-0.30.21-9a226cb21e-57d5691f41.zip b/.yarn/cache/magic-string-npm-0.30.21-9a226cb21e-57d5691f41.zip new file mode 100644 index 000000000..53485dc72 Binary files /dev/null and b/.yarn/cache/magic-string-npm-0.30.21-9a226cb21e-57d5691f41.zip differ diff --git a/.yarn/cache/mlly-npm-1.8.0-448698f313-4db690a421.zip b/.yarn/cache/mlly-npm-1.8.0-448698f313-4db690a421.zip new file mode 100644 index 000000000..0fd3cf77e Binary files /dev/null and b/.yarn/cache/mlly-npm-1.8.0-448698f313-4db690a421.zip differ diff --git a/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-8427de0ece.zip b/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-8427de0ece.zip new file mode 100644 index 000000000..faf79cab2 Binary files /dev/null and b/.yarn/cache/mz-npm-2.7.0-ec3cef4ec2-8427de0ece.zip differ diff --git a/.yarn/cache/obug-npm-2.1.1-029730d296-bdcf921336.zip b/.yarn/cache/obug-npm-2.1.1-029730d296-bdcf921336.zip new file mode 100644 index 000000000..ca87e6388 Binary files /dev/null and b/.yarn/cache/obug-npm-2.1.1-029730d296-bdcf921336.zip differ diff --git a/.yarn/cache/pirates-npm-4.0.7-5e4ee2f078-2427f37136.zip b/.yarn/cache/pirates-npm-4.0.7-5e4ee2f078-2427f37136.zip new file mode 100644 index 000000000..09e815a1f Binary files /dev/null and b/.yarn/cache/pirates-npm-4.0.7-5e4ee2f078-2427f37136.zip differ diff --git a/.yarn/cache/pkg-types-npm-1.3.1-832c9cd162-6d491f2244.zip b/.yarn/cache/pkg-types-npm-1.3.1-832c9cd162-6d491f2244.zip new file mode 100644 index 000000000..b0eafe50e Binary files /dev/null and b/.yarn/cache/pkg-types-npm-1.3.1-832c9cd162-6d491f2244.zip differ diff --git a/.yarn/cache/postcss-load-config-npm-6.0.1-50722afd05-1691cfc949.zip b/.yarn/cache/postcss-load-config-npm-6.0.1-50722afd05-1691cfc949.zip new file mode 100644 index 000000000..6b91d0558 Binary files /dev/null and b/.yarn/cache/postcss-load-config-npm-6.0.1-50722afd05-1691cfc949.zip differ diff --git a/.yarn/cache/prettier-npm-3.8.1-04022a855f-3da1cf8c1e.zip b/.yarn/cache/prettier-npm-3.8.1-04022a855f-3da1cf8c1e.zip new file mode 100644 index 000000000..d29087728 Binary files /dev/null and b/.yarn/cache/prettier-npm-3.8.1-04022a855f-3da1cf8c1e.zip differ diff --git a/.yarn/cache/quansync-npm-1.0.0-0707dd9045-fba7a8e87a.zip b/.yarn/cache/quansync-npm-1.0.0-0707dd9045-fba7a8e87a.zip new file mode 100644 index 000000000..c024033bb Binary files /dev/null and b/.yarn/cache/quansync-npm-1.0.0-0707dd9045-fba7a8e87a.zip differ diff --git a/.yarn/cache/readdirp-npm-4.1.2-3440472afe-7b817c2659.zip b/.yarn/cache/readdirp-npm-4.1.2-3440472afe-7b817c2659.zip new file mode 100644 index 000000000..7ea4264a0 Binary files /dev/null and b/.yarn/cache/readdirp-npm-4.1.2-3440472afe-7b817c2659.zip differ diff --git a/.yarn/cache/readdirp-npm-5.0.0-82b01a282e-a17a591b51.zip b/.yarn/cache/readdirp-npm-5.0.0-82b01a282e-a17a591b51.zip new file mode 100644 index 000000000..f62693664 Binary files /dev/null and b/.yarn/cache/readdirp-npm-5.0.0-82b01a282e-a17a591b51.zip differ diff --git a/.yarn/cache/resolve-from-npm-5.0.0-15c9db4d33-be18a5e4d7.zip b/.yarn/cache/resolve-from-npm-5.0.0-15c9db4d33-be18a5e4d7.zip new file mode 100644 index 000000000..eca225319 Binary files /dev/null and b/.yarn/cache/resolve-from-npm-5.0.0-15c9db4d33-be18a5e4d7.zip differ diff --git a/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip b/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip new file mode 100644 index 000000000..8e3561c41 Binary files /dev/null and b/.yarn/cache/resolve-pkg-maps-npm-1.0.0-135b70c854-0763150adf.zip differ diff --git a/.yarn/cache/rolldown-npm-1.0.0-rc.3-6317e18d22-28c88da3dc.zip b/.yarn/cache/rolldown-npm-1.0.0-rc.3-6317e18d22-28c88da3dc.zip new file mode 100644 index 000000000..4178d5744 Binary files /dev/null and b/.yarn/cache/rolldown-npm-1.0.0-rc.3-6317e18d22-28c88da3dc.zip differ diff --git a/.yarn/cache/rolldown-plugin-dts-npm-0.22.1-538d81df8c-e180a99005.zip b/.yarn/cache/rolldown-plugin-dts-npm-0.22.1-538d81df8c-e180a99005.zip new file mode 100644 index 000000000..3b04c7809 Binary files /dev/null and b/.yarn/cache/rolldown-plugin-dts-npm-0.22.1-538d81df8c-e180a99005.zip differ diff --git a/.yarn/cache/rollup-npm-4.57.1-8b254d8a63-0451371339.zip b/.yarn/cache/rollup-npm-4.57.1-8b254d8a63-0451371339.zip new file mode 100644 index 000000000..d3287fa34 Binary files /dev/null and b/.yarn/cache/rollup-npm-4.57.1-8b254d8a63-0451371339.zip differ diff --git a/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-8dbc3168e0.zip b/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-8dbc3168e0.zip new file mode 100644 index 000000000..c94393ee4 Binary files /dev/null and b/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-8dbc3168e0.zip differ diff --git a/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip b/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip new file mode 100644 index 000000000..84e26314f Binary files /dev/null and b/.yarn/cache/source-map-npm-0.7.6-a3854be193-c8d2da7c57.zip differ diff --git a/.yarn/cache/std-env-npm-3.10.0-30d3e2646f-19c9cda4f3.zip b/.yarn/cache/std-env-npm-3.10.0-30d3e2646f-19c9cda4f3.zip new file mode 100644 index 000000000..8803cc08f Binary files /dev/null and b/.yarn/cache/std-env-npm-3.10.0-30d3e2646f-19c9cda4f3.zip differ diff --git a/.yarn/cache/sucrase-npm-3.35.1-9a5f68e2af-539f5c6ebc.zip b/.yarn/cache/sucrase-npm-3.35.1-9a5f68e2af-539f5c6ebc.zip new file mode 100644 index 000000000..f1655abaa Binary files /dev/null and b/.yarn/cache/sucrase-npm-3.35.1-9a5f68e2af-539f5c6ebc.zip differ diff --git a/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-dba7cc8a23.zip b/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-dba7cc8a23.zip new file mode 100644 index 000000000..59a2bc6ce Binary files /dev/null and b/.yarn/cache/thenify-all-npm-1.6.0-96309bbc8b-dba7cc8a23.zip differ diff --git a/.yarn/cache/thenify-npm-3.3.1-030bedb22c-486e1283a8.zip b/.yarn/cache/thenify-npm-3.3.1-030bedb22c-486e1283a8.zip new file mode 100644 index 000000000..2c3ccdb73 Binary files /dev/null and b/.yarn/cache/thenify-npm-3.3.1-030bedb22c-486e1283a8.zip differ diff --git a/.yarn/cache/tinyexec-npm-1.0.2-321b713e56-cb709ed424.zip b/.yarn/cache/tinyexec-npm-1.0.2-321b713e56-cb709ed424.zip new file mode 100644 index 000000000..4e06ed7d2 Binary files /dev/null and b/.yarn/cache/tinyexec-npm-1.0.2-321b713e56-cb709ed424.zip differ diff --git a/.yarn/cache/tinyrainbow-npm-3.0.3-06ed35d14d-169cc63c15.zip b/.yarn/cache/tinyrainbow-npm-3.0.3-06ed35d14d-169cc63c15.zip new file mode 100644 index 000000000..55660b3fd Binary files /dev/null and b/.yarn/cache/tinyrainbow-npm-3.0.3-06ed35d14d-169cc63c15.zip differ diff --git a/.yarn/cache/tree-kill-npm-1.2.2-3da0e5a759-49117f5f41.zip b/.yarn/cache/tree-kill-npm-1.2.2-3da0e5a759-49117f5f41.zip new file mode 100644 index 000000000..c9ef40137 Binary files /dev/null and b/.yarn/cache/tree-kill-npm-1.2.2-3da0e5a759-49117f5f41.zip differ diff --git a/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-9f7346b9e2.zip b/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-9f7346b9e2.zip new file mode 100644 index 000000000..be45589c8 Binary files /dev/null and b/.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-9f7346b9e2.zip differ diff --git a/.yarn/cache/tsdown-npm-0.20.3-11b719e36b-3d511dea76.zip b/.yarn/cache/tsdown-npm-0.20.3-11b719e36b-3d511dea76.zip new file mode 100644 index 000000000..c9168d04e Binary files /dev/null and b/.yarn/cache/tsdown-npm-0.20.3-11b719e36b-3d511dea76.zip differ diff --git a/.yarn/cache/tsup-npm-8.5.1-41f4f7d59b-f1927ec2dd.zip b/.yarn/cache/tsup-npm-8.5.1-41f4f7d59b-f1927ec2dd.zip new file mode 100644 index 000000000..59f92d172 Binary files /dev/null and b/.yarn/cache/tsup-npm-8.5.1-41f4f7d59b-f1927ec2dd.zip differ diff --git a/.yarn/cache/tsx-npm-4.21.0-3bc9626d81-7afedeff85.zip b/.yarn/cache/tsx-npm-4.21.0-3bc9626d81-7afedeff85.zip new file mode 100644 index 000000000..27615df9a Binary files /dev/null and b/.yarn/cache/tsx-npm-4.21.0-3bc9626d81-7afedeff85.zip differ diff --git a/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip b/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip new file mode 100644 index 000000000..0eabff58d Binary files /dev/null and b/.yarn/cache/typescript-npm-5.9.3-48715be868-c089d9d3da.zip differ diff --git a/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip b/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip new file mode 100644 index 000000000..6cd392703 Binary files /dev/null and b/.yarn/cache/typescript-patch-6fda4d02cf-696e1b017b.zip differ diff --git a/.yarn/cache/ufo-npm-1.6.3-29bac69d97-79803984f3.zip b/.yarn/cache/ufo-npm-1.6.3-29bac69d97-79803984f3.zip new file mode 100644 index 000000000..a6554f993 Binary files /dev/null and b/.yarn/cache/ufo-npm-1.6.3-29bac69d97-79803984f3.zip differ diff --git a/.yarn/cache/unconfig-core-npm-7.4.2-b40a0ca292-837d196508.zip b/.yarn/cache/unconfig-core-npm-7.4.2-b40a0ca292-837d196508.zip new file mode 100644 index 000000000..3f7ff8f9e Binary files /dev/null and b/.yarn/cache/unconfig-core-npm-7.4.2-b40a0ca292-837d196508.zip differ diff --git a/.yarn/cache/unrun-npm-0.2.27-11dabf0dfa-70a589218b.zip b/.yarn/cache/unrun-npm-0.2.27-11dabf0dfa-70a589218b.zip new file mode 100644 index 000000000..fc2ac917c Binary files /dev/null and b/.yarn/cache/unrun-npm-0.2.27-11dabf0dfa-70a589218b.zip differ diff --git a/.yarn/cache/vite-npm-7.3.1-330baf2f0d-62e48ffa42.zip b/.yarn/cache/vite-npm-7.3.1-330baf2f0d-62e48ffa42.zip new file mode 100644 index 000000000..26ec0ade3 Binary files /dev/null and b/.yarn/cache/vite-npm-7.3.1-330baf2f0d-62e48ffa42.zip differ diff --git a/.yarn/cache/vitest-npm-4.0.18-52f42bdace-6c6464ebcf.zip b/.yarn/cache/vitest-npm-4.0.18-52f42bdace-6c6464ebcf.zip new file mode 100644 index 000000000..df66e7cbf Binary files /dev/null and b/.yarn/cache/vitest-npm-4.0.18-52f42bdace-6c6464ebcf.zip differ diff --git a/.yarn/cache/ws-npm-8.19.0-c967c046a5-26e4901e93.zip b/.yarn/cache/ws-npm-8.19.0-c967c046a5-26e4901e93.zip new file mode 100644 index 000000000..457091195 Binary files /dev/null and b/.yarn/cache/ws-npm-8.19.0-c967c046a5-26e4901e93.zip differ diff --git a/assets/code-link.png b/assets/code-link.png new file mode 100644 index 000000000..0796fb10f Binary files /dev/null and b/assets/code-link.png differ diff --git a/package.json b/package.json index 97e4a16c2..fe4600ccd 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "plugins/*" ], "scripts": { + "test:scripts": "vitest run scripts/", "check": "turbo run --continue check-biome check-eslint check-prettier check-svelte check-typescript check-vitest", "dev": "turbo run dev --concurrency=40", "fix-biome": "turbo run --continue check-biome -- --write", @@ -22,16 +23,22 @@ "g:dev": "cd $INIT_CWD && run g:vite", "g:preview": "cd $INIT_CWD && run g:vite preview", "g:vite": "cd $INIT_CWD && NODE_OPTIONS='--no-warnings=ExperimentalWarning' vite --config ${VITE_CONFIG_PATH:-$PROJECT_CWD/packages/vite-config/src/index.ts}", + "g:pack": "cd $INIT_CWD && framer-plugin-tools pack", "preview": "turbo run preview --concurrency=40" }, "devDependencies": { "@biomejs/biome": "^2.2.4", "@framer/eslint-config": "workspace:*", "@framer/vite-config": "workspace:*", + "@types/node": "^22.15.21", "eslint": "^9.35.0", + "framer-plugin-tools": "workspace:*", "jiti": "^2.5.1", + "tsx": "^4.19.0", "turbo": "^2.5.6", "typescript": "^5.9.2", - "vite": "^7.1.11" + "valibot": "^1.2.0", + "vite": "^7.1.11", + "vitest": "^3.2.4" } } diff --git a/packages/code-link-cli/README.md b/packages/code-link-cli/README.md new file mode 100644 index 000000000..66b29ab73 --- /dev/null +++ b/packages/code-link-cli/README.md @@ -0,0 +1,3 @@ +# Framer Code Link CLI + +Two-way syncing Framer of code components between Framer and your computer. diff --git a/packages/code-link-cli/package.json b/packages/code-link-cli/package.json new file mode 100644 index 000000000..4ef5ad6c3 --- /dev/null +++ b/packages/code-link-cli/package.json @@ -0,0 +1,40 @@ +{ + "name": "framer-code-link", + "version": "0.7.0", + "description": "CLI tool for syncing Framer code components - controller-centric architecture", + "main": "dist/index.mjs", + "type": "module", + "bin": "./dist/index.mjs", + "files": [ + "dist" + ], + "scripts": { + "dev": "NODE_ENV=development tsx src/index.ts", + "build": "tsdown", + "start": "node dist/index.mjs", + "test": "vitest run" + }, + "keywords": [ + "framer", + "sync", + "code-components" + ], + "author": "", + "license": "MIT", + "dependencies": { + "@typescript/ata": "^0.9.8", + "chokidar": "^5.0.0", + "commander": "^14.0.3", + "prettier": "^3.7.4", + "typescript": "^5.9.3", + "ws": "^8.18.3" + }, + "devDependencies": { + "@code-link/shared": "workspace:*", + "@types/node": "^22.19.2", + "@types/ws": "^8.18.1", + "tsdown": "^0.20.1", + "tsx": "^4.21.0", + "vitest": "^4.0.15" + } +} diff --git a/packages/code-link-cli/src/controller.test.ts b/packages/code-link-cli/src/controller.test.ts new file mode 100644 index 000000000..081accb6d --- /dev/null +++ b/packages/code-link-cli/src/controller.test.ts @@ -0,0 +1,626 @@ +import { describe, expect, it } from "vitest" +import type { WebSocket } from "ws" +import { transition } from "./controller.ts" +import { DEFAULT_REMOTE_DRIFT_MS, filterEchoedFiles } from "./helpers/files.ts" +import { createHashTracker } from "./utils/hash-tracker.ts" + +// Readable coverage of core controller functionality + +const mockSocket = {} as WebSocket + +function disconnectedState() { + return { + mode: "disconnected" as const, + socket: null, + pendingRemoteChanges: [], + } +} + +function watchingState() { + return { + mode: "watching" as const, + socket: mockSocket, + pendingRemoteChanges: [], + } +} + +function handshakingState() { + return { + mode: "handshaking" as const, + socket: mockSocket, + pendingRemoteChanges: [], + } +} + +function snapshotProcessingState() { + return { + mode: "snapshot_processing" as const, + socket: mockSocket, + pendingRemoteChanges: [], + } +} + +function conflictResolutionState( + pendingConflicts: { + fileName: string + localContent: string | null + remoteContent: string | null + localModifiedAt?: number + remoteModifiedAt?: number + lastSyncedAt?: number + localClean?: boolean + }[] +) { + return { + mode: "conflict_resolution" as const, + socket: mockSocket, + pendingConflicts, + pendingRemoteChanges: [], + } +} + +describe("Code Link", () => { + // FIRST-TIME SYNC + // When CLI connects to a project for the first time + + describe("First-Time Sync", () => { + it("downloads new files from Framer", () => { + const state = snapshotProcessingState() + const result = transition(state, { + type: "CONFLICTS_DETECTED", + conflicts: [], + safeWrites: [ + { name: "Button.tsx", content: "export const Button = () => ", + }, + }) + + expect(result.effects.some(e => e.type === "SEND_LOCAL_CHANGE")).toBe(true) + const effect = result.effects.find(e => e.type === "SEND_LOCAL_CHANGE") + expect(effect).toMatchObject({ fileName: "Button.tsx" }) + }) + + it("pulls Framer edits to disk", () => { + const state = watchingState() + const result = transition(state, { + type: "REMOTE_FILE_CHANGE", + file: { name: "Button.tsx", content: "updated from framer", modifiedAt: Date.now() }, + }) + + expect(result.effects.some(e => e.type === "WRITE_FILES")).toBe(true) + }) + + it("ignores changes during initial sync", () => { + // Changes arriving during snapshot processing are ignored - snapshot handles reconciliation + const state = snapshotProcessingState() + const result = transition(state, { + type: "REMOTE_FILE_CHANGE", + file: { name: "Button.tsx", content: "late arrival", modifiedAt: Date.now() }, + }) + + expect(result.state.pendingRemoteChanges).toHaveLength(0) + expect(result.effects.some(e => e.type === "WRITE_FILES")).toBe(false) + expect(result.effects.some(e => e.type === "LOG")).toBe(true) + }) + + it("creates new local file and uploads to Framer", () => { + const state = watchingState() + const result = transition(state, { + type: "WATCHER_EVENT", + event: { + kind: "add", + relativePath: "NewComponent.tsx", + content: "export const New = () =>
New
", + }, + }) + + expect(result.effects.some(e => e.type === "SEND_LOCAL_CHANGE")).toBe(true) + }) + }) + + // FOLDER STRUCTURES + // Nested paths like components/Button.tsx + + describe("Folder Structures", () => { + it("downloads files to nested paths", () => { + const state = snapshotProcessingState() + const result = transition(state, { + type: "CONFLICTS_DETECTED", + conflicts: [], + safeWrites: [ + { + name: "components/Button.tsx", + content: "export const Button = () => + + + ) +} + +interface DeletePanelProps { + files: PendingDelete[] + onConfirm: () => void + onKeep: () => void +} + +function DeletePanel({ files, onConfirm, onKeep }: DeletePanelProps) { + const multiple = files.length > 1 + const text = multiple + ? { + title: "Confirm Deletions", + description: + "The following code files were deleted locally and will be permanently removed from this Project.", + } + : { + title: "Confirm Deletion", + description: "Code file was deleted locally and will be permanently removed from this Project.", + } + + const lines = files.map(file => file.content?.split("\n").length ?? 0) + + if (files.length === 0 || files[0] === undefined) return null + + return ( +
+
+
+

{text.title}

+

{text.description}

+
+ {multiple ? ( + <> +
+
+
+
File
+
Lines
+
+
+
+
    + {files.map((file, index) => ( +
  • +
    {file.fileName}
    +
    + -{lines[index]} +
    +
  • + ))} +
+ + ) : ( +
+
{files[0].fileName}
+
+ -{lines[0]} +
+
+ )} + +
+
+ + +
+
+ ) +} + +interface ConflictPanelProps { + conflicts: ConflictSummary[] + onResolve: (choice: "local" | "remote") => void +} + +function ConflictPanel({ conflicts, onResolve }: ConflictPanelProps) { + return ( +
+
+
+

Resolve Conflicts

+

The following code files have changed in Framer and locally. Select which set of changes to keep.

+
+
+
+
+
File
+
Local
+
Framer
+
+
+
+
    + {conflicts.map(conflict => { + // Show unique lines on each side + const diff = + conflict.localContent !== null && conflict.remoteContent !== null + ? computeLineDiff(conflict.remoteContent, conflict.localContent) + : null + + // diff.added = lines only in local + // diff.removed = lines only in remote + + const LocalBadge = () => { + if (conflict.localContent === null) { + return deleted + } + if (!diff || diff.added === 0) { + return ±0 + } + return +{diff.added} + } + + const FramerBadge = () => { + if (conflict.remoteContent === null) { + return deleted + } + if (!diff || diff.removed === 0) { + return ±0 + } + return +{diff.removed} + } + + return ( +
  • +
    {conflict.fileName}
    +
    + +
    +
    + +
    +
  • + ) + })} +
+
+
+ + +
+
+ ) +} + +function createMessageHandler({ + dispatch, + api, + syncTracker, +}: { + dispatch: (action: Action) => void + api: CodeFilesAPI + syncTracker: SyncTracker +}) { + return async function handleMessage(message: CliToPluginMessage, socket: WebSocket) { + log.debug("Handling message:", message.type) + + switch (message.type) { + case "request-files": + log.debug("Publishing snapshot to CLI") + await api.publishSnapshot(socket) + dispatch({ + type: "set-mode", + mode: "syncing", + }) + break + case "file-change": + log.debug("Applying remote change:", message.fileName) + await api.applyRemoteChange(message.fileName, message.content, socket) + syncTracker.remember(message.fileName, message.content) + dispatch({ type: "set-mode", mode: "idle" }) + break + case "file-delete": + if (message.requireConfirmation) { + log.debug(`Delete requires confirmation for ${message.fileNames.length} file(s)`) + const files: PendingDelete[] = [] + for (const fileName of message.fileNames) { + const content = await api.readCurrentContent(fileName) + // Only include files that exist in Framer (have content to restore) + if (content !== undefined) { + files.push({ fileName, content }) + } + } + if (files.length === 0) { + // No files exist in Framer, nothing to confirm + break + } + dispatch({ + type: "pending-deletes", + files, + }) + } else { + for (const fileName of message.fileNames) { + log.debug("Deleting file:", fileName) + await api.applyRemoteDelete(fileName) + } + } + break + case "conflicts-detected": + log.debug(`Received ${message.conflicts.length} conflicts from CLI`) + dispatch({ type: "conflicts", conflicts: message.conflicts }) + break + case "conflict-version-request": { + log.debug(`Fetching conflict versions for ${message.conflicts.length} files`) + const versions = await api.fetchConflictVersions(message.conflicts) + log.debug(`Sending version response for ${versions.length} files`) + socket.send( + JSON.stringify({ + type: "conflict-version-response", + versions, + }) + ) + break + } + case "sync-complete": + log.debug("Sync complete, transitioning to idle") + dispatch({ type: "set-mode", mode: "idle" }) + break + default: + log.warn("Unknown message type:", (message as unknown as { type: string }).type) + break + } + } +} diff --git a/plugins/code-link/src/api.ts b/plugins/code-link/src/api.ts new file mode 100644 index 000000000..9904d6a7c --- /dev/null +++ b/plugins/code-link/src/api.ts @@ -0,0 +1,189 @@ +import { canonicalFileName, ensureExtension, type SyncTracker } from "@code-link/shared" +import { framer } from "framer-plugin" +import * as log from "./utils/logger" + +/** + * Plugin API Handlers + * + * Tries to be as stateless as possible. + */ + +export class CodeFilesAPI { + private lastSnapshot = new Map() + + private async getCodeFilesWithCanonicalNames() { + // Always all files instead of single file calls. + // The API internally does that anyways. + // Also ensures everything is fresh. + let codeFiles + try { + codeFiles = await framer.getCodeFiles() + } catch (err) { + log.error("Failed to fetch code files", err) + return [] + } + + return codeFiles.map(file => { + const source = file.path || file.name + return { + name: canonicalFileName(source), + content: file.content, + } + }) + } + + async publishSnapshot(socket: WebSocket) { + const files = await this.getCodeFilesWithCanonicalNames() + socket.send(JSON.stringify({ type: "file-list", files })) + this.lastSnapshot.clear() + files.forEach(file => this.lastSnapshot.set(file.name, file.content)) + } + + async handleFramerFilesChanged(socket: WebSocket, tracker: SyncTracker) { + const files = await this.getCodeFilesWithCanonicalNames() + const seen = new Set() + + for (const file of files) { + seen.add(file.name) + + const previous = this.lastSnapshot.get(file.name) + if (previous !== file.content) { + // Generally only a small number of files change. + // So we just send each change one by one. + socket.send( + JSON.stringify({ + type: "file-change", + fileName: file.name, + content: file.content, + }) + ) + tracker.remember(file.name, file.content) + this.lastSnapshot.set(file.name, file.content) + } + } + + for (const fileName of Array.from(this.lastSnapshot.keys())) { + if (!seen.has(fileName)) { + socket.send( + JSON.stringify({ + type: "file-delete", + fileNames: [fileName], + requireConfirmation: false, + }) + ) + this.lastSnapshot.delete(fileName) + } + } + } + + async applyRemoteChange(fileName: string, content: string, socket: WebSocket) { + const normalizedName = canonicalFileName(fileName) + // Update snapshot BEFORE upsert to prevent race with file subscription + this.lastSnapshot.set(normalizedName, content) + + const updatedAt = await upsertFramerFile(fileName, content) + // Send file-synced message with timestamp + const syncTimestamp = updatedAt ?? Date.now() + log.debug( + `Confirming sync for ${fileName} with timestamp ${new Date(syncTimestamp).toISOString()} (${syncTimestamp})` + ) + socket.send( + JSON.stringify({ + type: "file-synced", + fileName: normalizedName, + remoteModifiedAt: syncTimestamp, + }) + ) + } + + async applyRemoteDelete(fileName: string) { + await deleteFramerFile(fileName) + this.lastSnapshot.delete(canonicalFileName(fileName)) + } + + async readCurrentContent(fileName: string) { + const files = await this.getCodeFilesWithCanonicalNames() + const normalizedName = canonicalFileName(fileName) + return files.find(file => file.name === normalizedName)?.content + } + + async fetchConflictVersions(requests: { fileName: string; lastSyncedAt?: number }[]) { + log.debug(`Fetching versions for ${requests.length} files`) + + let codeFiles + try { + codeFiles = await framer.getCodeFiles() + } catch (err) { + log.error("Failed to fetch code files", err) + return requests.map(r => ({ + fileName: r.fileName, + latestRemoteVersionMs: undefined, + })) + } + + const versionPromises = requests.map(async request => { + const file = codeFiles.find( + f => canonicalFileName(f.path || f.name) === canonicalFileName(request.fileName) + ) + + if (!file) { + log.warn(`File ${request.fileName} not found in Framer`) + return { + fileName: request.fileName, + latestRemoteVersionMs: undefined, + } + } + + try { + // We need to find the timestamp for the last save to know if we can auto-resolve safetly + const versions = await file.getVersions() + if (versions.length > 0 && versions[0]?.createdAt) { + const latestRemoteVersionMs = Date.parse(versions[0].createdAt) + log.debug(`${request.fileName}: ${versions[0].createdAt} (${latestRemoteVersionMs})`) + return { + fileName: request.fileName, + latestRemoteVersionMs, + } + } + } catch (err) { + log.error(`Failed to fetch versions for ${request.fileName}`, err) + } + + return { + fileName: request.fileName, + latestRemoteVersionMs: undefined, + } + }) + + const results = await Promise.all(versionPromises) + log.debug(`Returning version data for ${String(results.length)} files`) + return results + } +} + +async function upsertFramerFile(fileName: string, content: string): Promise { + const normalisedName = canonicalFileName(fileName) + const codeFiles = await framer.getCodeFiles() + const existing = codeFiles.find(file => canonicalFileName(file.path || file.name) === normalisedName) + + if (existing) { + await existing.setFileContent(content) + return Date.now() + } + + await framer.createCodeFile(ensureExtension(normalisedName), content, { + editViaPlugin: false, + }) + + return Date.now() +} + +async function deleteFramerFile(fileName: string) { + const normalisedName = canonicalFileName(fileName) + const codeFiles = await framer.getCodeFiles() + const existing = codeFiles.find(file => canonicalFileName(file.path || file.name) === normalisedName) + + if (existing) { + await existing.remove() + } +} diff --git a/plugins/code-link/src/main.tsx b/plugins/code-link/src/main.tsx new file mode 100644 index 000000000..e3db46486 --- /dev/null +++ b/plugins/code-link/src/main.tsx @@ -0,0 +1,21 @@ +import "framer-plugin/framer.css" +import "./App.css" + +import React from "react" +import ReactDOM from "react-dom/client" +import { App } from "./App.tsx" +import { LogLevel, setLogLevel } from "./utils/logger" + +// Enable debug logging in development +if (import.meta.env.DEV) { + setLogLevel(LogLevel.DEBUG) +} + +const root = document.getElementById("root") +if (!root) throw new Error("Root element not found") + +ReactDOM.createRoot(root).render( + + + +) diff --git a/plugins/code-link/src/utils/clipboard.ts b/plugins/code-link/src/utils/clipboard.ts new file mode 100644 index 000000000..983461011 --- /dev/null +++ b/plugins/code-link/src/utils/clipboard.ts @@ -0,0 +1,22 @@ +export async function copyToClipboard(text: string): Promise { + // Try execCommand first (no permissions needed) + if (execCommandCopy(text)) return + // Fall back to modern API if execCommand fails + await navigator.clipboard.writeText(text) +} +function execCommandCopy(text: string): boolean { + try { + const textarea = document.createElement("textarea") + textarea.value = text + textarea.style.position = "fixed" + textarea.style.opacity = "0" + document.body.appendChild(textarea) + textarea.select() + // eslint-disable-next-line @typescript-eslint/no-deprecated + const success = document.execCommand("copy") + document.body.removeChild(textarea) + return success + } catch { + return false + } +} diff --git a/plugins/code-link/src/utils/diffing.ts b/plugins/code-link/src/utils/diffing.ts new file mode 100644 index 000000000..0b8d68b69 --- /dev/null +++ b/plugins/code-link/src/utils/diffing.ts @@ -0,0 +1,19 @@ +/** Compute line-based diff: lines added/removed going from `from` to `to` */ +export function computeLineDiff(from: string, to: string): { added: number; removed: number } { + const fromLines = from.split("\n") + const toLines = to.split("\n") + const fromSet = new Set(fromLines) + const toSet = new Set(toLines) + + let added = 0 + let removed = 0 + + for (const line of toLines) { + if (!fromSet.has(line)) added++ + } + for (const line of fromLines) { + if (!toSet.has(line)) removed++ + } + + return { added, removed } +} diff --git a/plugins/code-link/src/utils/logger.ts b/plugins/code-link/src/utils/logger.ts new file mode 100644 index 000000000..eef07abc8 --- /dev/null +++ b/plugins/code-link/src/utils/logger.ts @@ -0,0 +1,40 @@ +/** + * Logging utilities for consistent output + */ + +export enum LogLevel { + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, +} + +let currentLevel = LogLevel.INFO + +export function setLogLevel(level: LogLevel): void { + currentLevel = level +} + +export function debug(message: string, ...args: unknown[]): void { + if (currentLevel <= LogLevel.DEBUG) { + console.debug(`[DEBUG] ${message}`, ...args) + } +} + +export function info(message: string, ...args: unknown[]): void { + if (currentLevel <= LogLevel.INFO) { + console.info(`[INFO] ${message}`, ...args) + } +} + +export function warn(message: string, ...args: unknown[]): void { + if (currentLevel <= LogLevel.WARN) { + console.warn(`[WARN] ${message}`, ...args) + } +} + +export function error(message: string, ...args: unknown[]): void { + if (currentLevel <= LogLevel.ERROR) { + console.error(`[ERROR] ${message}`, ...args) + } +} diff --git a/plugins/code-link/src/utils/useConstant.ts b/plugins/code-link/src/utils/useConstant.ts new file mode 100644 index 000000000..4b33338ac --- /dev/null +++ b/plugins/code-link/src/utils/useConstant.ts @@ -0,0 +1,10 @@ +import { useRef } from "react" + +// Only init the constant once +export function useConstant(init: () => T): T { + const ref = useRef(null) + + ref.current ??= init() + + return ref.current +} diff --git a/plugins/code-link/src/vite-env.d.ts b/plugins/code-link/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/plugins/code-link/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/plugins/code-link/tsconfig.json b/plugins/code-link/tsconfig.json new file mode 100644 index 000000000..69ad5d606 --- /dev/null +++ b/plugins/code-link/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "*"] +} diff --git a/plugins/code-versions/package.json b/plugins/code-versions/package.json index 51bfbb76c..9a2cd134f 100644 --- a/plugins/code-versions/package.json +++ b/plugins/code-versions/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript", "check-vitest": "run g:check-vitest", "test-watch": "vitest" diff --git a/plugins/color-extract/package.json b/plugins/color-extract/package.json index a4876675b..9b13c57b7 100644 --- a/plugins/color-extract/package.json +++ b/plugins/color-extract/package.json @@ -10,7 +10,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/concentric/package.json b/plugins/concentric/package.json index 1a032235b..58ed1391e 100644 --- a/plugins/concentric/package.json +++ b/plugins/concentric/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/csv-import/package.json b/plugins/csv-import/package.json index 1281b9e56..437c5ad0b 100644 --- a/plugins/csv-import/package.json +++ b/plugins/csv-import/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript", "autofix": "run check-biome --fix && run g:check-eslint --fix" }, diff --git a/plugins/csv-import/src/routes/FieldMapper.tsx b/plugins/csv-import/src/routes/FieldMapper.tsx index 88e8fdf4a..99e2e3259 100644 --- a/plugins/csv-import/src/routes/FieldMapper.tsx +++ b/plugins/csv-import/src/routes/FieldMapper.tsx @@ -37,6 +37,9 @@ function calculatePossibleSlugFields(mappings: FieldMappingItem[], csvRecords: R return mappings.filter(m => isValidSlugColumn(m.inferredField.columnName, csvRecords)).map(m => m.inferredField) } +const caseInsensitiveEquals = (a: string | undefined | null, b: string | undefined | null) => + a?.toLocaleLowerCase() === b?.toLocaleLowerCase() + export function FieldMapper({ collection, csvRecords, onSubmit }: FieldMapperProps) { const [existingFields, setExistingFields] = useState([]) const [mappings, setMappings] = useState([]) @@ -58,7 +61,8 @@ export function FieldMapper({ collection, csvRecords, onSubmit }: FieldMapperPro // Existing Slug field match against CSV column if any const matchedSlugColumnName = collection.slugFieldName - ? inferredFields.find(field => field.columnName === collection.slugFieldName)?.columnName + ? inferredFields.find(field => caseInsensitiveEquals(field.columnName, collection.slugFieldName)) + ?.columnName : undefined // Column we will suggest as slug field on the UI diff --git a/plugins/design-system/package.json b/plugins/design-system/package.json index c67a466f2..26ee6e042 100644 --- a/plugins/design-system/package.json +++ b/plugins/design-system/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/dither/package.json b/plugins/dither/package.json index 2409bf68f..bf428cdba 100644 --- a/plugins/dither/package.json +++ b/plugins/dither/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/doodles/package.json b/plugins/doodles/package.json index c89f33cce..058118dd1 100644 --- a/plugins/doodles/package.json +++ b/plugins/doodles/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/flip-image/package.json b/plugins/flip-image/package.json index b6a69ef01..ccba1e543 100644 --- a/plugins/flip-image/package.json +++ b/plugins/flip-image/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/global-search/package.json b/plugins/global-search/package.json index ddc08860c..9e40b5b92 100644 --- a/plugins/global-search/package.json +++ b/plugins/global-search/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript", "check-vitest": "run g:check-vitest" }, diff --git a/plugins/google-search-console/package.json b/plugins/google-search-console/package.json index 17656be68..2ba3dcd6a 100644 --- a/plugins/google-search-console/package.json +++ b/plugins/google-search-console/package.json @@ -8,7 +8,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/google-sheets/package.json b/plugins/google-sheets/package.json index 7adb90fb4..c1725c4f6 100644 --- a/plugins/google-sheets/package.json +++ b/plugins/google-sheets/package.json @@ -7,7 +7,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/greenhouse/package.json b/plugins/greenhouse/package.json index e08ee9e6c..deccec000 100644 --- a/plugins/greenhouse/package.json +++ b/plugins/greenhouse/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/hubspot/package.json b/plugins/hubspot/package.json index 69a5edada..684fa13c9 100644 --- a/plugins/hubspot/package.json +++ b/plugins/hubspot/package.json @@ -8,7 +8,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/locale-sync/package.json b/plugins/locale-sync/package.json index bd9f338f8..430adb6c6 100644 --- a/plugins/locale-sync/package.json +++ b/plugins/locale-sync/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/notion/package.json b/plugins/notion/package.json index b818bb1ee..2163612a1 100644 --- a/plugins/notion/package.json +++ b/plugins/notion/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "framer-plugin-tools pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { @@ -21,7 +21,6 @@ }, "devDependencies": { "@types/react": "^18.3.24", - "@types/react-dom": "^18.3.7", - "framer-plugin-tools": "^1.0.0" + "@types/react-dom": "^18.3.7" } } diff --git a/plugins/phosphor/package.json b/plugins/phosphor/package.json index e49ceba0b..c8ef95bdf 100644 --- a/plugins/phosphor/package.json +++ b/plugins/phosphor/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/photobooth/package.json b/plugins/photobooth/package.json index a6572b29e..21bb3f6f3 100644 --- a/plugins/photobooth/package.json +++ b/plugins/photobooth/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/pong/package.json b/plugins/pong/package.json index 7e36616f5..8d83c8c6f 100644 --- a/plugins/pong/package.json +++ b/plugins/pong/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/prco/package.json b/plugins/prco/package.json index 6fefe758b..71e9acb7b 100644 --- a/plugins/prco/package.json +++ b/plugins/prco/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/recruitee/package.json b/plugins/recruitee/package.json index a03d2af3d..7e7de188b 100644 --- a/plugins/recruitee/package.json +++ b/plugins/recruitee/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/redirect-sync/package.json b/plugins/redirect-sync/package.json index 2cf7ee87b..980feb13f 100644 --- a/plugins/redirect-sync/package.json +++ b/plugins/redirect-sync/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { diff --git a/plugins/renamer/package.json b/plugins/renamer/package.json index d420df012..c658af48c 100644 --- a/plugins/renamer/package.json +++ b/plugins/renamer/package.json @@ -9,7 +9,7 @@ "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", "preview": "run g:preview", - "pack": "framer-plugin-tools pack", + "pack": "run g:pack", "check-typescript": "run g:check-typescript" }, "dependencies": { @@ -20,7 +20,6 @@ }, "devDependencies": { "@types/react": "^18.3.24", - "@types/react-dom": "^18.3.7", - "framer-plugin-tools": "^1.0.0" + "@types/react-dom": "^18.3.7" } } diff --git a/plugins/rss-feeds/package.json b/plugins/rss-feeds/package.json index 3847adb0a..6293b9906 100644 --- a/plugins/rss-feeds/package.json +++ b/plugins/rss-feeds/package.json @@ -8,7 +8,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/threshold/package.json b/plugins/threshold/package.json index 52d44684d..e07f0642c 100644 --- a/plugins/threshold/package.json +++ b/plugins/threshold/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/tidyup/package.json b/plugins/tidyup/package.json index 7c076e734..0d244c4d1 100644 --- a/plugins/tidyup/package.json +++ b/plugins/tidyup/package.json @@ -8,7 +8,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/plugins/unsplash/package.json b/plugins/unsplash/package.json index e3fac29c7..c3dae6416 100644 --- a/plugins/unsplash/package.json +++ b/plugins/unsplash/package.json @@ -9,7 +9,7 @@ "build": "run g:build", "check-biome": "run g:check-biome", "check-eslint": "run g:check-eslint", - "pack": "npx framer-plugin-tools@latest pack", + "pack": "run g:pack", "preview": "run g:preview", "check-typescript": "run g:check-typescript" }, diff --git a/scripts/lib/parse-pr.test.ts b/scripts/lib/parse-pr.test.ts new file mode 100644 index 000000000..bade440d7 --- /dev/null +++ b/scripts/lib/parse-pr.test.ts @@ -0,0 +1,266 @@ +import { describe, expect, it } from "vitest" +import { extractChangelog, parseChangedPlugins } from "./parse-pr" + +describe("extractChangelog", () => { + it("extracts changelog content from PR body", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Changelog + +- Added support for multiple locations +- Fixed bug with slug generation + +### Testing + +- Test case 1` + + expect(extractChangelog(prBody)).toBe( + "- Added support for multiple locations\n- Fixed bug with slug generation" + ) + }) + + it("returns null for empty PR body", () => { + expect(extractChangelog("")).toBeNull() + expect(extractChangelog(null as unknown as string)).toBeNull() + }) + + it("returns null when changelog section is missing", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Testing + +- Test case 1` + + expect(extractChangelog(prBody)).toBeNull() + }) + + it("returns null when changelog is just a placeholder dash", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Changelog + +- + +### Testing + +- Test case 1` + + expect(extractChangelog(prBody)).toBeNull() + }) + + it("returns null when changelog section is empty", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Changelog + +### Testing + +- Test case 1` + + expect(extractChangelog(prBody)).toBeNull() + }) + + it("handles changelog at end of PR body (no following section)", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Changelog + +- Fixed a critical bug +- Improved performance` + + expect(extractChangelog(prBody)).toBe("- Fixed a critical bug\n- Improved performance") + }) + + it("handles ## headings after changelog", () => { + const prBody = `### Description + +This PR adds a new feature. + +### Changelog + +- Added new feature + +## Additional Notes + +Some notes here.` + + expect(extractChangelog(prBody)).toBe("- Added new feature") + }) + + it("is case insensitive for heading", () => { + const prBody = `### CHANGELOG + +- Fixed bug` + + expect(extractChangelog(prBody)).toBe("- Fixed bug") + }) + + it("supports plain text content (not just bullet lists)", () => { + const prBody = `### Changelog + +Fixed a critical bug in the authentication flow that was causing users to be logged out unexpectedly. + +### Testing` + + expect(extractChangelog(prBody)).toBe( + "Fixed a critical bug in the authentication flow that was causing users to be logged out unexpectedly." + ) + }) + + it("trims whitespace from changelog content", () => { + const prBody = `### Changelog + + - Added feature with extra whitespace + +### Testing` + + expect(extractChangelog(prBody)).toBe("- Added feature with extra whitespace") + }) + + it("extracts changelog with HTML comments (PR template)", () => { + const prBody = `### Description + +MAde some changes + +### Changelog + + + +- Just testing changelog extraction +- I hope its formatted nicely +- It better be + +### Testing + + + +- [x] Description of test case one + - [x] Step 1 + - [x] Step 2 + - [x] Step 3 +- [x] Description of test case two + - [x] Step 1 + - [x] Step 2 + - [x] Step 3 + +` + + const result = extractChangelog(prBody) + expect(result).toContain("- Just testing changelog extraction") + expect(result).toContain("- I hope its formatted nicely") + expect(result).toContain("- It better be") + }) + + it("handles PR body with leading whitespace from YAML indentation", () => { + // This simulates what happens when YAML heredoc adds indentation + // The regex still matches, but captures too much because indented headings + // don't match the lookahead pattern + const prBody = ` ### Description + + MAde some changes + + ### Changelog + + + + - Just testing changelog extraction + + ### Testing` + + const result = extractChangelog(prBody) + // It finds content (not null) but includes ### Testing because it's indented + expect(result).toContain("Just testing changelog extraction") + // Bug: indented ### Testing is included because lookahead doesn't match + expect(result).toContain("### Testing") + }) + + it("handles CRLF line endings from GitHub API", () => { + // GitHub's API can return PR bodies with Windows-style line endings + const prBody = + "### Description\r\n\r\nSome description\r\n\r\n### Changelog\r\n\r\n- Item one\r\n- Item two\r\n\r\n### Testing\r\n\r\n- Test case" + + const result = extractChangelog(prBody) + expect(result).toContain("- Item one") + expect(result).toContain("- Item two") + expect(result).not.toContain("### Testing") + }) + + it("strips HTML comments from changelog", () => { + const prBody = `### Changelog + + + +- Actual changelog item + +### Testing` + + const result = extractChangelog(prBody) + expect(result).toBe("- Actual changelog item") + expect(result).not.toContain("") + }) +}) + +describe("parseChangedPlugins", () => { + it("extracts plugin names from changed files", () => { + const changedFiles = "plugins/csv-import/src/index.ts plugins/csv-import/package.json" + expect(parseChangedPlugins(changedFiles)).toEqual(["csv-import"]) + }) + + it("returns unique plugin names when multiple files changed in same plugin", () => { + const changedFiles = "plugins/airtable/src/App.tsx plugins/airtable/src/utils.ts plugins/airtable/package.json" + expect(parseChangedPlugins(changedFiles)).toEqual(["airtable"]) + }) + + it("returns multiple plugins sorted alphabetically", () => { + const changedFiles = "plugins/csv-import/src/index.ts plugins/airtable/src/App.tsx plugins/ashby/framer.json" + expect(parseChangedPlugins(changedFiles)).toEqual(["airtable", "ashby", "csv-import"]) + }) + + it("ignores files outside plugins directory", () => { + const changedFiles = + "scripts/submit-plugin.ts packages/plugin-tools/src/index.ts plugins/csv-import/src/index.ts README.md" + expect(parseChangedPlugins(changedFiles)).toEqual(["csv-import"]) + }) + + it("returns empty array when no plugin files changed", () => { + const changedFiles = "scripts/submit-plugin.ts README.md .github/workflows/ci.yml" + expect(parseChangedPlugins(changedFiles)).toEqual([]) + }) + + it("returns empty array for empty input", () => { + expect(parseChangedPlugins("")).toEqual([]) + expect(parseChangedPlugins(" ")).toEqual([]) + }) + + it("handles files at root of plugins directory (should not match)", () => { + // Files directly in plugins/ without a subdirectory should not match + const changedFiles = "plugins/.DS_Store plugins/README.md" + expect(parseChangedPlugins(changedFiles)).toEqual([]) + }) + + it("handles deeply nested files", () => { + const changedFiles = "plugins/airtable/src/components/Button/index.tsx" + expect(parseChangedPlugins(changedFiles)).toEqual(["airtable"]) + }) + + it("handles newline-separated files", () => { + const changedFiles = "plugins/csv-import/src/index.ts\nplugins/airtable/src/App.tsx" + expect(parseChangedPlugins(changedFiles)).toEqual(["airtable", "csv-import"]) + }) + + it("handles tab-separated files", () => { + const changedFiles = "plugins/csv-import/src/index.ts\tplugins/airtable/src/App.tsx" + expect(parseChangedPlugins(changedFiles)).toEqual(["airtable", "csv-import"]) + }) +}) diff --git a/scripts/lib/parse-pr.ts b/scripts/lib/parse-pr.ts new file mode 100644 index 000000000..4147890c6 --- /dev/null +++ b/scripts/lib/parse-pr.ts @@ -0,0 +1,67 @@ +/** + * Pure functions for parsing PR data. + * These are extracted for testability. + */ + +/** + * Extracts the changelog content from a PR body. + * Looks for a "### Changelog" section and extracts content until the next heading. + * + * @param prBody - The full PR body text + * @returns The changelog content, or null if not found or empty + */ +export function extractChangelog(prBody: string): string | null { + if (!prBody) { + return null + } + + // Normalize line endings (GitHub API can return CRLF) + const normalizedBody = prBody.replace(/\r\n/g, "\n") + + // Match ### Changelog section until next heading (## or ###) or end of string + // Use [ \t]* instead of \s* to avoid matching newlines before the capture group + const changelogPattern = /### Changelog[ \t]*\n([\s\S]*?)(?=\n### |\n## |$)/i + const match = normalizedBody.match(changelogPattern) + let changelog = match?.[1]?.trim() + + // Return null for empty or placeholder content + if (!changelog || changelog === "-") { + return null + } + + // Strip HTML comments (from PR templates) + changelog = changelog.replace(//g, "").trim() + + // Check again after stripping comments + if (!changelog || changelog === "-") { + return null + } + + return changelog +} + +/** + * Parses a list of changed file paths and extracts unique plugin names. + * Only includes files under the `plugins/` directory. + * + * @param changedFiles - Space-separated list of changed file paths + * @returns Array of unique plugin directory names, sorted alphabetically + */ +export function parseChangedPlugins(changedFiles: string): string[] { + if (!changedFiles) { + return [] + } + + const files = changedFiles.split(/\s+/).filter(Boolean) + const pluginNames = new Set() + + for (const file of files) { + // Match files in plugins/* directory (e.g., "plugins/csv-import/src/index.ts") + const match = file.match(/^plugins\/([^/]+)\//) + if (match?.[1]) { + pluginNames.add(match[1]) + } + } + + return Array.from(pluginNames).sort() +} diff --git a/scripts/submit-on-merge.ts b/scripts/submit-on-merge.ts new file mode 100644 index 000000000..8ad1a1144 --- /dev/null +++ b/scripts/submit-on-merge.ts @@ -0,0 +1,200 @@ +#!/usr/bin/env yarn tsx + +/** + * Submit on Merge Script + * + * Orchestrates multi-plugin submission by detecting changed plugins from a PR + * and calling submit-plugin.ts for each one with the changelog from the PR body. + * + * Usage: yarn tsx scripts/submit-on-merge.ts + * + * Environment Variables: + * PR_BODY_FILE - Path to file containing PR body text + * CHANGED_FILES - Space-separated list of changed files from the workflow + * REPO_ROOT - Root of the git repository (optional, defaults to parent of scripts/) + * + * Plus all environment variables required by submit-plugin.ts: + * SESSION_TOKEN, FRAMER_ADMIN_SECRET, SLACK_WEBHOOK_URL, etc. + */ + +import { execSync } from "node:child_process" +import { existsSync, readFileSync } from "node:fs" +import { join, resolve } from "node:path" +import { extractChangelog, parseChangedPlugins } from "./lib/parse-pr" + +// ============================================================================ +// Configuration +// ============================================================================ + +const REPO_ROOT = process.env.REPO_ROOT ?? resolve(__dirname, "..") +const PLUGINS_DIR = join(REPO_ROOT, "plugins") + +// ============================================================================ +// Logging +// ============================================================================ + +const DEBUG = process.env.DEBUG === "1" || process.env.DEBUG === "true" + +const log = { + info: (msg: string) => { + console.log(`[INFO] ${msg}`) + }, + success: (msg: string) => { + console.log(`[SUCCESS] ${msg}`) + }, + error: (msg: string) => { + console.error(`[ERROR] ${msg}`) + }, + warn: (msg: string) => { + console.warn(`[WARN] ${msg}`) + }, + step: (msg: string) => { + console.log(`\n=== ${msg} ===`) + }, + debug: (msg: string) => { + if (!DEBUG) return + console.log(`[DEBUG] ${msg}`) + }, +} + +// ============================================================================ +// Plugin Detection +// ============================================================================ + +function getChangedPlugins(changedFiles: string): string[] { + // Parse plugin names from changed files (pure function from lib) + const pluginNames = parseChangedPlugins(changedFiles) + + // Filter to only plugins that have framer.json (valid plugins) + const validPlugins: string[] = [] + for (const name of pluginNames) { + const framerJsonPath = join(PLUGINS_DIR, name, "framer.json") + if (existsSync(framerJsonPath)) { + validPlugins.push(name) + } else { + log.warn(`Skipping ${name}: no framer.json found`) + } + } + + return validPlugins +} + +// ============================================================================ +// Plugin Submission +// ============================================================================ + +function submitPlugin(pluginName: string, changelog: string): void { + const pluginPath = join(PLUGINS_DIR, pluginName) + + log.step(`Submitting plugin: ${pluginName}`) + log.info(`Path: ${pluginPath}`) + + try { + execSync("yarn tsx scripts/submit-plugin.ts", { + cwd: REPO_ROOT, + env: { + ...process.env, + PLUGIN_PATH: pluginPath, + CHANGELOG: changelog, + REPO_ROOT: REPO_ROOT, + }, + stdio: "inherit", + }) + log.success(`Plugin ${pluginName} submitted successfully`) + } catch (error) { + // execSync throws on non-zero exit, re-throw to stop the process + throw new Error( + `Failed to submit plugin ${pluginName}: ${error instanceof Error ? error.message : String(error)}` + ) + } +} + +// ============================================================================ +// Main +// ============================================================================ + +function run(): void { + console.log("=".repeat(60)) + console.log("Submit on Merge - Multi-Plugin Submission") + console.log("=".repeat(60)) + + // 1. Validate required environment variables + log.step("Configuration") + const prBodyFile = process.env.PR_BODY_FILE + const changedFiles = process.env.CHANGED_FILES + + if (!prBodyFile) { + throw new Error("Missing required environment variable: PR_BODY_FILE") + } + + if (!changedFiles) { + throw new Error("Missing required environment variable: CHANGED_FILES") + } + + if (!existsSync(prBodyFile)) { + throw new Error(`PR_BODY_FILE does not exist: ${prBodyFile}`) + } + + const prBody = readFileSync(prBodyFile, "utf-8") + + log.info(`Dry run: ${process.env.DRY_RUN === "true" ? "yes" : "no"}`) + log.debug(`PR body file: ${prBodyFile}`) + log.debug(`PR body length: ${prBody.length} chars`) + log.debug(`PR body (first 500 chars):\n${prBody.slice(0, 500)}`) + + // 2. Extract changelog from PR body + log.step("Extracting Changelog") + const changelog = extractChangelog(prBody) + log.debug(`Extracted changelog: ${changelog ? `"${changelog.slice(0, 200)}..."` : "null"}`) + + if (!changelog) { + log.error(`Full PR body for debugging:\n---\n${prBody}\n---`) + throw new Error("No changelog found in PR body. Expected a '### Changelog' section with content.") + } + + log.info(`Changelog:\n${changelog}`) + + // 3. Detect changed plugins + log.step("Detecting Changed Plugins") + const plugins = getChangedPlugins(changedFiles) + + if (plugins.length === 0) { + log.warn("No valid plugins found in changed files. Nothing to submit.") + return + } + + log.info(`Found ${plugins.length} plugin(s) to submit: ${plugins.join(", ")}`) + + // 4. Submit each plugin sequentially + log.step("Submitting Plugins") + let successCount = 0 + let failCount = 0 + + for (const plugin of plugins) { + try { + submitPlugin(plugin, changelog) + successCount++ + } catch (error) { + failCount++ + log.error(`Failed to submit ${plugin}: ${error instanceof Error ? error.message : String(error)}`) + // Continue with other plugins instead of stopping + } + } + + // 5. Summary + console.log("\n" + "=".repeat(60)) + if (failCount === 0) { + log.success(`All ${successCount} plugin(s) submitted successfully!`) + } else { + log.error(`Completed with errors: ${successCount} succeeded, ${failCount} failed`) + process.exit(1) + } + console.log("=".repeat(60)) +} + +try { + run() +} catch (error) { + log.error(error instanceof Error ? error.message : String(error)) + process.exit(1) +} diff --git a/scripts/submit-plugin.ts b/scripts/submit-plugin.ts new file mode 100644 index 000000000..221c9237a --- /dev/null +++ b/scripts/submit-plugin.ts @@ -0,0 +1,483 @@ +#!/usr/bin/env yarn tsx + +/** + * Plugin Submission Script + * + * Builds, packs, and submits a plugin to the Framer marketplace. + * + * Usage: yarn tsx scripts/submit-plugin.ts + * + * Environment Variables: + * PLUGIN_PATH - Path to the plugin directory (required) + * CHANGELOG - Changelog text (required) + * SESSION_TOKEN - Framer session cookie (required unless DRY_RUN) + * FRAMER_ADMIN_SECRET - Framer admin API key (required unless DRY_RUN) + * SLACK_WEBHOOK_URL - Slack workflow webhook for success notifications (optional) + * SLACK_ERROR_WEBHOOK_URL - Slack workflow webhook for error notifications (optional) + * RETOOL_URL - Retool dashboard URL for Slack notifications (optional) + * GITHUB_RUN_URL - GitHub Actions run URL for error notifications (optional) + * FRAMER_ENV - Environment: "production" or "development" (default: production) + * DRY_RUN - Skip submission and tagging when "true" (optional) + * REPO_ROOT - Root of the git repository (default: parent of scripts/) + */ + +import { execSync } from "node:child_process" +import { existsSync, readFileSync } from "node:fs" +import { join, resolve } from "node:path" +import { runPluginBuildScript, zipPluginDistribution } from "framer-plugin-tools" +import * as v from "valibot" + +// ============================================================================ +// Schemas - Environment Variables +// ============================================================================ + +const FramerEnvSchema = v.picklist(["production", "development"]) + +const EnvSchema = v.object({ + PLUGIN_PATH: v.pipe(v.string(), v.minLength(1)), + CHANGELOG: v.pipe(v.string(), v.minLength(1)), + SLACK_WEBHOOK_URL: v.optional(v.string()), + SLACK_ERROR_WEBHOOK_URL: v.optional(v.string()), + RETOOL_URL: v.optional(v.string()), + GITHUB_RUN_URL: v.optional(v.string()), + FRAMER_ENV: v.optional(FramerEnvSchema, "production"), + DRY_RUN: v.optional(v.string()), + REPO_ROOT: v.optional(v.string()), + SESSION_TOKEN: v.pipe(v.string(), v.minLength(1)), + FRAMER_ADMIN_SECRET: v.pipe(v.string(), v.minLength(1)), +}) + +// ============================================================================ +// Schemas - API Responses +// ============================================================================ + +const AccessTokenResponseSchema = v.object({ + accessToken: v.string(), + expiresAt: v.string(), + expiresInSeconds: v.number(), +}) + +const PluginVersionSchema = v.object({ + id: v.string(), + name: v.string(), + modes: v.array(v.string()), + icon: v.nullable(v.string()), + prettyVersion: v.number(), + status: v.string(), + releaseNotes: v.nullable(v.string()), + reviewedAt: v.nullable(v.string()), + url: v.string(), + createdAt: v.string(), +}) + +const PluginSchema = v.object({ + id: v.string(), + manifestId: v.string(), + description: v.nullable(v.string()), + ownerType: v.string(), + ownerId: v.string(), + createdAt: v.string(), + updatedAt: v.string(), + external: v.boolean(), + currentVersion: v.nullable(PluginVersionSchema), + lastCreatedVersion: v.nullable(PluginVersionSchema), +}) +type Plugin = v.InferOutput + +const PluginsResponseSchema = v.object({ + plugins: v.array(PluginSchema), +}) + +const SubmissionResponseSchema = v.object({ + version: v.number(), + // FIXME: THIS SHOULD BE DEPLOYED: + // SEE: https://github.com/framer/creators/pull/2487/files + versionId: v.fallback(v.string(), ""), + internalPluginId: v.string(), + slug: v.string(), +}) +type SubmissionResponse = v.InferOutput + +// ============================================================================ +// Schemas - File Contents +// ============================================================================ + +const FramerJsonSchema = v.object({ + id: v.string(), + name: v.string(), +}) + +// ============================================================================ +// Types +// ============================================================================ + +type FramerEnv = v.InferOutput +type FramerJson = v.InferOutput + +interface EnvironmentUrls { + apiBase: string + creatorsApiBase: string + framerAppUrl: string + marketplaceBaseUrl: string +} + +type Environment = v.InferOutput + +const ENVIRONMENT_URLS: Record = { + production: { + apiBase: "https://api.framer.com", + creatorsApiBase: "https://framer.com/marketplace", + framerAppUrl: "https://framer.com", + marketplaceBaseUrl: "https://framer.com/marketplace", + }, + development: { + apiBase: "https://api.development.framer.com", + creatorsApiBase: "https://marketplace.development.framer.com", + framerAppUrl: "https://development.framer.com", + marketplaceBaseUrl: "https://marketplace.development.framer.com/marketplace", + }, +} + +function getURL(env: Environment, key: keyof EnvironmentUrls): string { + return ENVIRONMENT_URLS[env.FRAMER_ENV][key] +} + +// ============================================================================ +// Logging +// ============================================================================ + +const log = { + info: (msg: string) => { + console.log(`[INFO] ${msg}`) + }, + success: (msg: string) => { + console.log(`[SUCCESS] ${msg}`) + }, + error: (msg: string) => { + console.error(`[ERROR] ${msg}`) + }, + step: (msg: string) => { + console.log(`\n=== ${msg} ===`) + }, +} + +// ============================================================================ +// Configuration +// ============================================================================ + +function getEnvironment(): Environment { + const result = v.safeParse(EnvSchema, process.env) + + if (!result.success) { + const issues = result.issues.map(issue => { + const path = issue.path?.map(p => p.key).join(".") ?? "unknown" + return `${path}: ${issue.message}` + }) + throw new Error(`Invalid environment variables:\n${issues.join("\n")}`) + } + + return result.output +} + +// ============================================================================ +// Framer API Operations +// ============================================================================ + +async function getAccessToken(env: Environment): Promise { + if (!env.SESSION_TOKEN) { + throw new Error("Session token is required") + } + + const response = await fetch(`${getURL(env, "apiBase")}/auth/web/access-token`, { + headers: { + Cookie: `session=${env.SESSION_TOKEN}`, + }, + }) + + if (!response.ok) { + if (response.status === 401) { + throw new Error("Session expired. Please update your SESSION_TOKEN.") + } + throw new Error(`Failed to get access token: ${response.statusText}`) + } + + const data = v.parse(AccessTokenResponseSchema, await response.json()) + return data.accessToken +} + +async function fetchMyPlugins(env: Environment): Promise { + const accessToken = await getAccessToken(env) + + const response = await fetch(`${getURL(env, "apiBase")}/site/v1/plugins/me`, { + headers: { + Authorization: `Bearer ${accessToken}`, + }, + }) + + if (!response.ok) { + if (response.status === 401) { + throw new Error("Session expired. Please update your SESSION_TOKEN.") + } + throw new Error(`Failed to fetch plugins: ${response.statusText}`) + } + + const data = v.parse(PluginsResponseSchema, await response.json()) + return data.plugins +} + +// ============================================================================ +// Plugin Operations +// ============================================================================ + +function loadFramerJsonFile(pluginPath: string): FramerJson { + const framerJsonPath = join(pluginPath, "framer.json") + + if (!existsSync(framerJsonPath)) { + throw new Error(`framer.json not found at ${framerJsonPath}`) + } + + const framerJson = v.parse(FramerJsonSchema, JSON.parse(readFileSync(framerJsonPath, "utf-8"))) + + return framerJson +} + +async function submitPlugin(zipFilePath: string, plugin: Plugin, env: Environment): Promise { + if (!env.SESSION_TOKEN || !env.FRAMER_ADMIN_SECRET) { + throw new Error("Session token and Framer admin secret are required for submission") + } + + const url = `${getURL(env, "creatorsApiBase")}/api/admin/plugin/${plugin.id}/versions/` + + log.info(`Submitting to: ${url}`) + + const zipBuffer = readFileSync(zipFilePath) + const blob = new Blob([zipBuffer], { type: "application/zip" }) + + const formData = new FormData() + formData.append("file", blob, "plugin.zip") + formData.append("content", env.CHANGELOG) + + const response = await fetch(url, { + method: "POST", + headers: { + Cookie: `session=${env.SESSION_TOKEN}`, + Authorization: `Bearer ${env.FRAMER_ADMIN_SECRET}`, + }, + body: formData, + }) + + if (!response.ok) { + const errorText = await response.text() + throw new Error(`API submission failed: ${response.status} ${response.statusText}\n${errorText}`) + } + + const result = v.parse(SubmissionResponseSchema, await response.json()) + log.success(`Submitted! Version: ${result.version}`) + + return result +} + +// ============================================================================ +// Git Tagging +// ============================================================================ + +function createGitTag(pluginName: string, version: number, repoRoot: string, env: Environment): void { + const tagName = `${pluginName.toLowerCase().replace(/\s+/g, "-")}-v${version.toString()}` + + log.info(`Creating git tag: ${tagName}`) + + try { + // Delete existing tag if it exists (e.g., from a rejected submission) + try { + execSync(`git tag -d "${tagName}"`, { cwd: repoRoot, stdio: "pipe" }) + execSync(`git push origin --delete "${tagName}"`, { cwd: repoRoot, stdio: "pipe" }) + } catch { + // Tag doesn't exist, that's fine + } + + // Create annotated tag with changelog as message + const escapedChangelog = env.CHANGELOG.trim().replace(/'/g, "'\\''") + execSync(`git tag -a "${tagName}" -m "${escapedChangelog}"`, { + cwd: repoRoot, + stdio: "inherit", + }) + + // Push tag + execSync(`git push origin "${tagName}"`, { + cwd: repoRoot, + stdio: "inherit", + }) + + log.success(`Tag ${tagName} created and pushed`) + } catch (error) { + // Don't fail the whole process if tagging fails + log.error(`Failed to create/push tag: ${error instanceof Error ? error.message : String(error)}`) + } +} + +// ============================================================================ +// Slack Notifications +// ============================================================================ + +interface SlackWorkflowPayload { + pluginName: string + retoolUrl?: string + marketplacePreviewUrl: string + pluginVersion: string + pluginReviewUrl: string + changelog: string +} + +async function sendSlackNotification( + framerJson: FramerJson, + submissionResult: SubmissionResponse, + env: Environment +): Promise { + const payload: SlackWorkflowPayload = { + pluginName: framerJson.name, + pluginVersion: submissionResult.version.toString(), + marketplacePreviewUrl: `${getURL(env, "marketplaceBaseUrl")}/plugins/${submissionResult.slug}/preview`, + pluginReviewUrl: `${getURL(env, "framerAppUrl")}/projects/new?plugin=${submissionResult.internalPluginId}&pluginVersion=${submissionResult.versionId}`, + changelog: env.CHANGELOG, + retoolUrl: env.RETOOL_URL, + } + + if (!env.SLACK_WEBHOOK_URL) return + + try { + const response = await fetch(env.SLACK_WEBHOOK_URL, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }) + + if (!response.ok) { + log.error(`Slack notification failed: ${response.status}`) + } else { + log.success("Slack notification sent") + } + } catch (err) { + log.error(`Slack notification error: ${err instanceof Error ? err.message : String(err)}`) + } +} + +async function sendErrorNotification( + errorMessage: string, + pluginName: string | undefined, + env: Environment +): Promise { + if (!env.SLACK_ERROR_WEBHOOK_URL) return + + const payload = { + githubActionRunUrl: env.GITHUB_RUN_URL ?? "N/A (not running in GitHub Actions)", + errorMessage, + pluginName: pluginName ?? "Unknown", + } + + try { + const response = await fetch(env.SLACK_ERROR_WEBHOOK_URL, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }) + + if (!response.ok) { + log.error(`Error notification failed: ${response.status}`) + } else { + log.success("Error notification sent") + } + } catch (err) { + log.error(`Error notification error: ${err instanceof Error ? err.message : String(err)}`) + } +} + +async function main(): Promise { + console.log("=".repeat(60)) + console.log("Submitting Plugin to Framer Marketplace") + console.log("=".repeat(60)) + + log.step("Configuration") + const env = getEnvironment() + let framerJson: FramerJson | undefined + // REPO_ROOT can be overridden when script is run from a different repo + const repoRoot = process.env.REPO_ROOT ?? resolve(__dirname, "..") + + try { + log.info(`Plugin path: ${env.PLUGIN_PATH}`) + log.info(`Environment: ${env.FRAMER_ENV}`) + log.info(`API base: ${getURL(env, "creatorsApiBase")}`) + log.info(`Dry run: ${String(env.DRY_RUN)}`) + + if (!existsSync(env.PLUGIN_PATH)) { + throw new Error(`Plugin path does not exist: ${env.PLUGIN_PATH}`) + } + + log.step("Loading Plugin Info") + framerJson = loadFramerJsonFile(env.PLUGIN_PATH) + log.info(`Name: ${framerJson.name}`) + log.info(`Manifest ID: ${framerJson.id}`) + + // 4. Fetch user's plugins to find the database plugin ID + log.step("Fetching Plugin from Framer") + const plugins = await fetchMyPlugins(env) + const matchedPlugin = plugins.find(p => p.manifestId === framerJson?.id) + + if (!matchedPlugin) { + throw new Error( + `No plugin found with manifest ID "${framerJson.id}". ` + + `Make sure you have created this plugin on Framer first.` + ) + } + + const plugin = matchedPlugin + log.info(`Found plugin with ID: ${plugin.id}`) + + log.step("Changelog") + log.info(`Changelog:\n${env.CHANGELOG}`) + + log.step("Building & Packing Plugin") + + log.info("Building plugin...") + await runPluginBuildScript(env.PLUGIN_PATH) + + log.info(`Creating plugin.zip...`) + const zipFilePath = zipPluginDistribution({ + cwd: env.PLUGIN_PATH, + distPath: "dist", + zipFileName: "plugin.zip", + }) + + if (env.DRY_RUN) { + log.step("DRY RUN - Skipping Submission") + log.info("Plugin is built and packed. Would submit to API in real run.") + log.info(`Would submit with changelog:\n${env.CHANGELOG}`) + return + } + + log.step("Submitting to Framer API") + const submissionResult = await submitPlugin(zipFilePath, plugin, env) + + log.step("Creating Git Tag") + createGitTag(framerJson.name, submissionResult.version, repoRoot, env) + + if (env.SLACK_WEBHOOK_URL) { + log.step("Sending Slack Notification") + await sendSlackNotification(framerJson, submissionResult, env) + } + + console.log("\n" + "=".repeat(60)) + log.success("Done!") + console.log("=".repeat(60)) + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + log.error(errorMessage) + + if (!env.DRY_RUN) { + await sendErrorNotification(errorMessage, framerJson?.name, env) + } + + process.exit(1) + } +} + +void main() diff --git a/scripts/validate-pr-body.ts b/scripts/validate-pr-body.ts new file mode 100644 index 000000000..2f5a96925 --- /dev/null +++ b/scripts/validate-pr-body.ts @@ -0,0 +1,41 @@ +#!/usr/bin/env yarn tsx + +/** + * Validates PR body for changelog content. + * Used by the Shippy workflow to check PRs with "Submit on merge" label. + * + * Usage: yarn tsx scripts/validate-pr-body.ts + * + * Environment Variables: + * PR_BODY - The PR body text to validate + * REQUIRE_CHANGELOG - Set to "true" to require changelog (when Submit on merge label is present) + * + * Exit codes: + * 0 - Validation passed + * 1 - Validation failed + */ + +import { extractChangelog } from "./lib/parse-pr" + +const prBody = process.env.PR_BODY?.trim() +const requireChangelog = process.env.REQUIRE_CHANGELOG === "true" + +if (!prBody) { + console.log("❌ PR description is required.") + process.exit(1) +} + +if (requireChangelog) { + const changelog = extractChangelog(prBody) + + if (!changelog) { + console.log( + "❌ Changelog required when 'Submit on merge' label is applied. Add content to the '### Changelog' section in your PR description." + ) + process.exit(1) + } + + console.log("Changelog validation passed") +} + +console.log("PR body validation passed") diff --git a/starters/cms/package.json b/starters/cms/package.json index 4ea06ed3e..153eb5cd7 100644 --- a/starters/cms/package.json +++ b/starters/cms/package.json @@ -11,7 +11,7 @@ "check-eslint": "DEBUG='eslint:eslint' eslint --max-warnings 0 .", "check-prettier": "prettier --check .", "check-typescript": "tsc", - "pack": "framer-plugin-tools pack", + "pack": "run g:pack", "preview": "vite preview" }, "dependencies": { @@ -27,7 +27,6 @@ "eslint": "^9.35.0", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", - "framer-plugin-tools": "^1.0.0", "globals": "^16.4.0", "jiti": "^2.5.1", "prettier": "^3.6.2", diff --git a/turbo.json b/turbo.json index 9313aa303..ff979a2df 100644 --- a/turbo.json +++ b/turbo.json @@ -31,6 +31,10 @@ "cache": false, "persistent": true }, - "check-vitest": {} + "check-vitest": {}, + "pack": { + "dependsOn": ["framer-plugin-tools#build"], + "cache": false + } } } diff --git a/yarn.lock b/yarn.lock index 763a923dd..b70a69129 100644 --- a/yarn.lock +++ b/yarn.lock @@ -51,6 +51,34 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:8.0.0-rc.1": + version: 8.0.0-rc.1 + resolution: "@babel/generator@npm:8.0.0-rc.1" + dependencies: + "@babel/parser": "npm:^8.0.0-rc.1" + "@babel/types": "npm:^8.0.0-rc.1" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + "@types/jsesc": "npm:^2.5.0" + jsesc: "npm:^3.0.2" + checksum: 10/1949ed7a0731e2825b263b8095be9fba0ed6fc1bb4dc1c6ea9fa554cb6d34aed3f9bf72ff1ce343bc31dbe604ebb0138b98f4b77c496ae31e6576ef6a9c0dd20 + languageName: node + linkType: hard + +"@babel/helper-string-parser@npm:^8.0.0-rc.1": + version: 8.0.0-rc.1 + resolution: "@babel/helper-string-parser@npm:8.0.0-rc.1" + checksum: 10/9c7b34ecce6a1a03a3a2fbd2f09f46bb47a961f432ee2c279e120855c40258b1715cd1bf2ed27618c03ee13d4310356381ad123ec37648d2756c5594bd128682 + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:8.0.0-rc.1, @babel/helper-validator-identifier@npm:^8.0.0-rc.1": + version: 8.0.0-rc.1 + resolution: "@babel/helper-validator-identifier@npm:8.0.0-rc.1" + checksum: 10/75d6d5201c64fec916b539210b77f41585b3fc31f197c17a874e1ace818014080dba5909eb24f84daad451810f2e9b7f09a2b3f23978b9c9c9875ed63d3f83fb + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-validator-identifier@npm:7.27.1" @@ -58,6 +86,17 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:8.0.0-rc.1, @babel/parser@npm:^8.0.0-beta.4, @babel/parser@npm:^8.0.0-rc.1": + version: 8.0.0-rc.1 + resolution: "@babel/parser@npm:8.0.0-rc.1" + dependencies: + "@babel/types": "npm:^8.0.0-rc.1" + bin: + parser: ./bin/babel-parser.js + checksum: 10/d0c5baf877a0ee9e0b0626f21f22d4911405abf66504b102c7544aff8a0925e33d8841934ceb834f3d989f7992fffcaff7be8d433b5779ed1924e1692c182016 + languageName: node + linkType: hard + "@babel/runtime@npm:^7.12.5": version: 7.27.6 resolution: "@babel/runtime@npm:7.27.6" @@ -65,6 +104,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:8.0.0-rc.1, @babel/types@npm:^8.0.0-rc.1": + version: 8.0.0-rc.1 + resolution: "@babel/types@npm:8.0.0-rc.1" + dependencies: + "@babel/helper-string-parser": "npm:^8.0.0-rc.1" + "@babel/helper-validator-identifier": "npm:^8.0.0-rc.1" + checksum: 10/34def05264164b579c8648a9b44449b567a79c4f34b285353d1e225c0d012a2931747547f05781a41ce99806f43920e2ca6319bd628be09b44ae9dce77576ec3 + languageName: node + linkType: hard + "@biomejs/biome@npm:^2.2.4": version: 2.2.4 resolution: "@biomejs/biome@npm:2.2.4" @@ -156,6 +205,24 @@ __metadata: languageName: node linkType: hard +"@code-link/shared@workspace:*, @code-link/shared@workspace:packages/code-link-shared": + version: 0.0.0-use.local + resolution: "@code-link/shared@workspace:packages/code-link-shared" + dependencies: + typescript: "npm:^5.9.3" + vitest: "npm:^4.0.15" + languageName: unknown + linkType: soft + +"@commander-js/extra-typings@npm:^13.1.0": + version: 13.1.0 + resolution: "@commander-js/extra-typings@npm:13.1.0" + peerDependencies: + commander: ~13.1.0 + checksum: 10/cdb7f854ac6c0b60c073ae928f2b836517ae7c1a8e86eb603144337fc87087ab9adebce67ed60d35beb82d80ef834ec40e7c20ef6053f4b115def21f1cd1d25f + languageName: node + linkType: hard + "@emnapi/core@npm:^1.4.3, @emnapi/core@npm:^1.4.5": version: 1.5.0 resolution: "@emnapi/core@npm:1.5.0" @@ -166,6 +233,16 @@ __metadata: languageName: node linkType: hard +"@emnapi/core@npm:^1.7.1": + version: 1.8.1 + resolution: "@emnapi/core@npm:1.8.1" + dependencies: + "@emnapi/wasi-threads": "npm:1.1.0" + tslib: "npm:^2.4.0" + checksum: 10/904ea60c91fc7d8aeb4a8f2c433b8cfb47c50618f2b6f37429fc5093c857c6381c60628a5cfbc3a7b0d75b0a288f21d4ed2d4533e82f92c043801ef255fd6a5c + languageName: node + linkType: hard + "@emnapi/runtime@npm:^1.4.3, @emnapi/runtime@npm:^1.4.5": version: 1.5.0 resolution: "@emnapi/runtime@npm:1.5.0" @@ -175,6 +252,15 @@ __metadata: languageName: node linkType: hard +"@emnapi/runtime@npm:^1.7.1": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/26725e202d4baefdc4a6ba770f703dfc80825a27c27a08c22bac1e1ce6f8f75c47b4fe9424d9b63239463c33ef20b650f08d710da18dfa1164a95e5acb865dba + languageName: node + linkType: hard + "@emnapi/wasi-threads@npm:1.1.0, @emnapi/wasi-threads@npm:^1.0.4": version: 1.1.0 resolution: "@emnapi/wasi-threads@npm:1.1.0" @@ -191,6 +277,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/aix-ppc64@npm:0.27.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-arm64@npm:0.25.9" @@ -198,6 +291,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm64@npm:0.27.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-arm@npm:0.25.9" @@ -205,6 +305,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm@npm:0.27.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/android-x64@npm:0.25.9" @@ -212,6 +319,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-x64@npm:0.27.2" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/darwin-arm64@npm:0.25.9" @@ -219,6 +333,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-arm64@npm:0.27.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/darwin-x64@npm:0.25.9" @@ -226,6 +347,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-x64@npm:0.27.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/freebsd-arm64@npm:0.25.9" @@ -233,6 +361,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-arm64@npm:0.27.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/freebsd-x64@npm:0.25.9" @@ -240,6 +375,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-x64@npm:0.27.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-arm64@npm:0.25.9" @@ -247,6 +389,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm64@npm:0.27.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-arm@npm:0.25.9" @@ -254,6 +403,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm@npm:0.27.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-ia32@npm:0.25.9" @@ -261,6 +417,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ia32@npm:0.27.2" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-loong64@npm:0.25.9" @@ -268,6 +431,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-loong64@npm:0.27.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-mips64el@npm:0.25.9" @@ -275,6 +445,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-mips64el@npm:0.27.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-ppc64@npm:0.25.9" @@ -282,6 +459,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ppc64@npm:0.27.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-riscv64@npm:0.25.9" @@ -289,6 +473,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-riscv64@npm:0.27.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-s390x@npm:0.25.9" @@ -296,6 +487,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-s390x@npm:0.27.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/linux-x64@npm:0.25.9" @@ -303,6 +501,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-x64@npm:0.27.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/netbsd-arm64@npm:0.25.9" @@ -310,6 +515,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-arm64@npm:0.27.2" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/netbsd-x64@npm:0.25.9" @@ -317,6 +529,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-x64@npm:0.27.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/openbsd-arm64@npm:0.25.9" @@ -324,6 +543,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-arm64@npm:0.27.2" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/openbsd-x64@npm:0.25.9" @@ -331,6 +557,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-x64@npm:0.27.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openharmony-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/openharmony-arm64@npm:0.25.9" @@ -338,6 +571,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openharmony-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openharmony-arm64@npm:0.27.2" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/sunos-x64@npm:0.25.9" @@ -345,6 +585,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/sunos-x64@npm:0.27.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-arm64@npm:0.25.9" @@ -352,6 +599,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-arm64@npm:0.27.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-ia32@npm:0.25.9" @@ -359,6 +613,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-ia32@npm:0.27.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.25.9": version: 0.25.9 resolution: "@esbuild/win32-x64@npm:0.25.9" @@ -366,6 +627,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-x64@npm:0.27.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0": version: 4.9.0 resolution: "@eslint-community/eslint-utils@npm:4.9.0" @@ -601,6 +869,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/gen-mapping@npm:^0.3.12, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10/902f8261dcf450b4af7b93f9656918e02eec80a2169e155000cb2059f90113dd98f3ccf6efc6072cee1dd84cac48cade51da236972d942babc40e4c23da4d62a + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.8 resolution: "@jridgewell/gen-mapping@npm:0.3.8" @@ -636,7 +914,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.5": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0, @jridgewell/sourcemap-codec@npm:^1.5.5": version: 1.5.5 resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" checksum: 10/5d9d207b462c11e322d71911e55e21a4e2772f71ffe8d6f1221b8eb5ae6774458c1d242f897fb0814e8714ca9a6b498abfa74dfe4f434493342902b1a48b33a5 @@ -653,6 +931,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10/da0283270e691bdb5543806077548532791608e52386cfbbf3b9e8fb00457859d1bd01d512851161c886eb3a2f3ce6fd9bcf25db8edf3bddedd275bd4a88d606 + languageName: node + linkType: hard + "@napi-rs/wasm-runtime@npm:^0.2.12": version: 0.2.12 resolution: "@napi-rs/wasm-runtime@npm:0.2.12" @@ -664,6 +952,17 @@ __metadata: languageName: node linkType: hard +"@napi-rs/wasm-runtime@npm:^1.1.1": + version: 1.1.1 + resolution: "@napi-rs/wasm-runtime@npm:1.1.1" + dependencies: + "@emnapi/core": "npm:^1.7.1" + "@emnapi/runtime": "npm:^1.7.1" + "@tybys/wasm-util": "npm:^0.10.1" + checksum: 10/080e7f2aefb84e09884d21c650a2cbafdf25bfd2634693791b27e36eec0ddaa3c1656a943f8c913ac75879a0b04e68f8a827897ee655ab54a93169accf05b194 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -720,6 +1019,13 @@ __metadata: languageName: node linkType: hard +"@oxc-project/types@npm:=0.112.0": + version: 0.112.0 + resolution: "@oxc-project/types@npm:0.112.0" + checksum: 10/59549821692604d6715791bb28f06c973e9664fc3a08b0b992b3079058f66c5b9b5ce8c63fd0056ff4da2c6943eaf71ff071c9bad1cb4ee2346d388014c7ec9e + languageName: node + linkType: hard + "@phosphor-icons/core@npm:^2.1.1": version: 2.1.1 resolution: "@phosphor-icons/core@npm:2.1.1" @@ -751,6 +1057,15 @@ __metadata: languageName: node linkType: hard +"@quansync/fs@npm:^1.0.0": + version: 1.0.0 + resolution: "@quansync/fs@npm:1.0.0" + dependencies: + quansync: "npm:^1.0.0" + checksum: 10/8a27892b1330c01e1312e09e9fd92f676fa89d13fa5a201cb5b9b2f99347ef6bac67a2f6f69fe3e64612427eabf45f88b4294cc5d5d33e0031bb5263b5cd37c9 + languageName: node + linkType: hard + "@radix-ui/number@npm:1.1.1": version: 1.1.1 resolution: "@radix-ui/number@npm:1.1.1" @@ -2068,6 +2383,99 @@ __metadata: languageName: node linkType: hard +"@rolldown/binding-android-arm64@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-android-arm64@npm:1.0.0-rc.3" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-rc.3" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-darwin-x64@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-rc.3" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-rc.3" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.3" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.3" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.3" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.3" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.3" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.3" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.3" + dependencies: + "@napi-rs/wasm-runtime": "npm:^1.1.1" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.3" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.3" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rolldown/pluginutils@npm:1.0.0-beta.32": version: 1.0.0-beta.32 resolution: "@rolldown/pluginutils@npm:1.0.0-beta.32" @@ -2075,6 +2483,13 @@ __metadata: languageName: node linkType: hard +"@rolldown/pluginutils@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "@rolldown/pluginutils@npm:1.0.0-rc.3" + checksum: 10/b181a693b70e0e5de736458d46b31f72862cd7f36f955656f61ccbf4de11d9206bc3b55404317a65e5714559490444e9fdd83b4097706496e96b082fb584d049 + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-android-arm-eabi@npm:4.50.2" @@ -2082,6 +2497,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.57.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-android-arm64@npm:4.50.2" @@ -2089,6 +2511,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-android-arm64@npm:4.57.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-darwin-arm64@npm:4.50.2" @@ -2096,6 +2525,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.57.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-darwin-x64@npm:4.50.2" @@ -2103,6 +2539,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.57.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-arm64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-freebsd-arm64@npm:4.50.2" @@ -2110,6 +2553,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.57.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-x64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-freebsd-x64@npm:4.50.2" @@ -2117,6 +2567,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.57.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.2" @@ -2124,6 +2581,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.57.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.50.2" @@ -2131,6 +2595,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.57.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.50.2" @@ -2138,13 +2609,27 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.50.2": +"@rollup/rollup-linux-arm64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.57.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.50.2" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.57.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-loong64-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.50.2" @@ -2152,6 +2637,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-loong64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.57.1" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-loong64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.57.1" + conditions: os=linux & cpu=loong64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-ppc64-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.50.2" @@ -2159,6 +2658,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-ppc64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.57.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-ppc64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.57.1" + conditions: os=linux & cpu=ppc64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.50.2" @@ -2166,6 +2679,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.57.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-musl@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.50.2" @@ -2173,6 +2693,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.57.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.50.2" @@ -2180,6 +2707,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.57.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.50.2" @@ -2187,6 +2721,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.57.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-linux-x64-musl@npm:4.50.2" @@ -2194,6 +2735,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.57.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-openbsd-x64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openbsd-x64@npm:4.57.1" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-openharmony-arm64@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-openharmony-arm64@npm:4.50.2" @@ -2201,6 +2756,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-openharmony-arm64@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.57.1" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.50.2" @@ -2208,6 +2770,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.57.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.50.2" @@ -2215,6 +2784,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.57.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-gnu@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.57.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.50.2": version: 4.50.2 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.50.2" @@ -2222,6 +2805,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.57.1": + version: 4.57.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.57.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@standard-schema/spec@npm:^1.0.0": version: 1.0.0 resolution: "@standard-schema/spec@npm:1.0.0" @@ -2630,7 +3220,7 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.10.0": +"@tybys/wasm-util@npm:^0.10.0, @tybys/wasm-util@npm:^0.10.1": version: 0.10.1 resolution: "@tybys/wasm-util@npm:0.10.1" dependencies: @@ -2639,6 +3229,15 @@ __metadata: languageName: node linkType: hard +"@types/adm-zip@npm:^0.5.7": + version: 0.5.7 + resolution: "@types/adm-zip@npm:0.5.7" + dependencies: + "@types/node": "npm:*" + checksum: 10/24e9842bd6838879c60fe833af267489d8bc6b582d5feac6179543bf7a0b01a749931a9c6f21a20b8454e83925937a63bae0190493fa269d33a35c6daf4df209 + languageName: node + linkType: hard + "@types/aria-query@npm:^5.0.1": version: 5.0.4 resolution: "@types/aria-query@npm:5.0.4" @@ -2738,6 +3337,13 @@ __metadata: languageName: node linkType: hard +"@types/jsesc@npm:^2.5.0": + version: 2.5.1 + resolution: "@types/jsesc@npm:2.5.1" + checksum: 10/25407775ed621790d2eec0cc51e194bd0d67a82e39204fd9748899c249ef965e17d9e6560f6c658773714f6d45a259465f3639790bb55750ebb168ee23801596 + languageName: node + linkType: hard + "@types/json-schema@npm:^7.0.15": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" @@ -2773,6 +3379,24 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^22.0.0": + version: 22.19.7 + resolution: "@types/node@npm:22.19.7" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10/0a5c9cc3bdd2a2d8105735b136e280a2dec90136679adfe82faa7e4de375dcc6b4cebaa6b2de35cc6b37e5e135cdc9486373d574782a4ca22f5eeab299111aa6 + languageName: node + linkType: hard + +"@types/node@npm:^22.15.21, @types/node@npm:^22.19.2": + version: 22.19.8 + resolution: "@types/node@npm:22.19.8" + dependencies: + undici-types: "npm:~6.21.0" + checksum: 10/a61c68d434871d4a13496e3607502b2ff8e2ff69dca7e09228de5bea3bc95eb627d09243a8cff8e0bf9ff1fa13baaf0178531748f59ae81f0569c7a2f053bfa5 + languageName: node + linkType: hard + "@types/papaparse@npm:^5.3.16": version: 5.3.16 resolution: "@types/papaparse@npm:5.3.16" @@ -2838,6 +3462,15 @@ __metadata: languageName: node linkType: hard +"@types/ws@npm:^8.18.1": + version: 8.18.1 + resolution: "@types/ws@npm:8.18.1" + dependencies: + "@types/node": "npm:*" + checksum: 10/1ce05e3174dcacf28dae0e9b854ef1c9a12da44c7ed73617ab6897c5cbe4fccbb155a20be5508ae9a7dde2f83bd80f5cf3baa386b934fc4b40889ec963e94f3a + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:8.44.0": version: 8.44.0 resolution: "@typescript-eslint/eslint-plugin@npm:8.44.0" @@ -2975,6 +3608,15 @@ __metadata: languageName: node linkType: hard +"@typescript/ata@npm:^0.9.8": + version: 0.9.8 + resolution: "@typescript/ata@npm:0.9.8" + peerDependencies: + typescript: ">=4.4.4" + checksum: 10/c0f9daf7818fff7f94030387e6bb6e8e270b1d6191ce2937040f039fedb977f5c96363610bb4ff99cb061b87a4b00213a5b79b28d85759ed876984e802b01cd9 + languageName: node + linkType: hard + "@vitejs/plugin-react-swc@npm:^4.0.1": version: 4.0.1 resolution: "@vitejs/plugin-react-swc@npm:4.0.1" @@ -3000,6 +3642,20 @@ __metadata: languageName: node linkType: hard +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" + dependencies: + "@standard-schema/spec": "npm:^1.0.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + chai: "npm:^6.2.1" + tinyrainbow: "npm:^3.0.3" + checksum: 10/2115bff1bbcad460ce72032022e4dbcf8572c4b0fe07ca60f5644a8d96dd0dfa112986b5a1a5c5705f4548119b3b829c45d1de0838879211e0d6bb276b4ece73 + languageName: node + linkType: hard + "@vitest/mocker@npm:3.2.4": version: 3.2.4 resolution: "@vitest/mocker@npm:3.2.4" @@ -3019,6 +3675,25 @@ __metadata: languageName: node linkType: hard +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" + dependencies: + "@vitest/spy": "npm:4.0.18" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10/46f584a4c1180dfb513137bc8db6e2e3b53e141adfe964307297e98321652d86a3f2a52d80cda1f810205bd5fdcab789bb8b52a532e68f175ef1e20be398218d + languageName: node + linkType: hard + "@vitest/pretty-format@npm:3.2.4, @vitest/pretty-format@npm:^3.2.4": version: 3.2.4 resolution: "@vitest/pretty-format@npm:3.2.4" @@ -3028,6 +3703,15 @@ __metadata: languageName: node linkType: hard +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" + dependencies: + tinyrainbow: "npm:^3.0.3" + checksum: 10/4cafc7c9853097345bd94e8761bf47c2c04e00d366ac56d79928182787ff83c512c96f1dc2ce9b6aeed4d3a8c23ce12254da203783108d3c096bc398eed2a62d + languageName: node + linkType: hard + "@vitest/runner@npm:3.2.4": version: 3.2.4 resolution: "@vitest/runner@npm:3.2.4" @@ -3039,6 +3723,16 @@ __metadata: languageName: node linkType: hard +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" + dependencies: + "@vitest/utils": "npm:4.0.18" + pathe: "npm:^2.0.3" + checksum: 10/d7deebf086d7e084f449733ecea6c9c81737a18aafece318cbe7500e45debea00fa9dbf9315fd38aa88550dd5240a791b885ac71665f89b154d71a6c63da5836 + languageName: node + linkType: hard + "@vitest/snapshot@npm:3.2.4": version: 3.2.4 resolution: "@vitest/snapshot@npm:3.2.4" @@ -3050,6 +3744,17 @@ __metadata: languageName: node linkType: hard +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10/50aa5fb7fca45c499c145cc2f20e53b8afb0990b53ff4a4e6447dd6f147437edc5316f22e2d82119e154c3cf7c59d44898e7b2faf7ba614ac1051cbe4d662a77 + languageName: node + linkType: hard + "@vitest/spy@npm:3.2.4": version: 3.2.4 resolution: "@vitest/spy@npm:3.2.4" @@ -3059,6 +3764,13 @@ __metadata: languageName: node linkType: hard +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10/f7b1618ae13790105771dd2a8c973c63c018366fcc69b50f15ce5d12f9ac552efd3c1e6e5ae4ebdb6023d0b8d8f31fef2a0b1b77334284928db45c80c63de456 + languageName: node + linkType: hard + "@vitest/ui@npm:^3.2.4": version: 3.2.4 resolution: "@vitest/ui@npm:3.2.4" @@ -3087,6 +3799,16 @@ __metadata: languageName: node linkType: hard +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" + dependencies: + "@vitest/pretty-format": "npm:4.0.18" + tinyrainbow: "npm:^3.0.3" + checksum: 10/e8b2ad7bc35b2bc5590f9dc1d1a67644755da416b47ab7099a6f26792903fa0aacb81e6ba99f0f03858d9d3a1d76eeba65150a1a0849690a40817424e749c367 + languageName: node + linkType: hard + "abbrev@npm:^3.0.0": version: 3.0.1 resolution: "abbrev@npm:3.0.1" @@ -3191,6 +3913,20 @@ __metadata: languageName: node linkType: hard +"ansis@npm:^4.2.0": + version: 4.2.0 + resolution: "ansis@npm:4.2.0" + checksum: 10/493e15fad267bd6e3e275d6886c3b3c96a075784d9eae3e16d16383d488e94cc3deb1b357e1246f572599767360548ef9e5b7eab9b72e4ee3f7bad9ce6bc8797 + languageName: node + linkType: hard + +"any-promise@npm:^1.0.0": + version: 1.3.0 + resolution: "any-promise@npm:1.3.0" + checksum: 10/6737469ba353b5becf29e4dc3680736b9caa06d300bda6548812a8fee63ae7d336d756f88572fa6b5219aed36698d808fa55f62af3e7e6845c7a1dc77d240edb + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -3260,6 +3996,17 @@ __metadata: languageName: node linkType: hard +"ast-kit@npm:^3.0.0-beta.1": + version: 3.0.0-beta.1 + resolution: "ast-kit@npm:3.0.0-beta.1" + dependencies: + "@babel/parser": "npm:^8.0.0-beta.4" + estree-walker: "npm:^3.0.3" + pathe: "npm:^2.0.3" + checksum: 10/63c8f80f71d905a3ca23a2cd02e9e9bba4e617353db80e58e4a48ca31f5a51c594e3d5bf7d1b61faf98b5f4c9a4db52bd2e8fa69e01e5b17a737b10abbd087f9 + languageName: node + linkType: hard + "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -3310,6 +4057,13 @@ __metadata: languageName: node linkType: hard +"birpc@npm:^4.0.0": + version: 4.0.0 + resolution: "birpc@npm:4.0.0" + checksum: 10/f4418e2a0451f41eb6f20b3c9a4d6c007b335bbc0fe1d6eddf44bc2fd2d44f26594a3b0a24fc43107b0288a2a56959507b37478faed20e3da0d2587ed0fa1557 + languageName: node + linkType: hard + "blurhash@npm:^2.0.5": version: 2.0.5 resolution: "blurhash@npm:2.0.5" @@ -3386,6 +4140,17 @@ __metadata: languageName: node linkType: hard +"bundle-require@npm:^5.1.0": + version: 5.1.0 + resolution: "bundle-require@npm:5.1.0" + dependencies: + load-tsconfig: "npm:^0.2.3" + peerDependencies: + esbuild: ">=0.18" + checksum: 10/735e0220055b9bdac20bea48ec1e10dc3a205232c889ef54767900bebdc721959c4ccb221e4ea434d7ddcd693a8a4445c3d0598e4040ee313ce0ac3aae3e6178 + languageName: node + linkType: hard + "cac@npm:^6.7.14": version: 6.7.14 resolution: "cac@npm:6.7.14" @@ -3440,6 +4205,13 @@ __metadata: languageName: node linkType: hard +"chai@npm:^6.2.1": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10/13cda42cc40aa46da04a41cf7e5c61df6b6ae0b4e8a8c8b40e04d6947e4d7951377ea8c14f9fa7fe5aaa9e8bd9ba414f11288dc958d4cee6f5221b9436f2778f + languageName: node + linkType: hard + "chalk@npm:^4.0.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" @@ -3490,6 +4262,24 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^4.0.3": + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" + dependencies: + readdirp: "npm:^4.0.1" + checksum: 10/bf2a575ea5596000e88f5db95461a9d59ad2047e939d5a4aac59dd472d126be8f1c1ff3c7654b477cf532d18f42a97279ef80ee847972fd2a25410bf00b80b59 + languageName: node + linkType: hard + +"chokidar@npm:^5.0.0": + version: 5.0.0 + resolution: "chokidar@npm:5.0.0" + dependencies: + readdirp: "npm:^5.0.0" + checksum: 10/a1c2a4ee6ee81ba6409712c295a47be055fb9de1186dfbab33c1e82f28619de962ba02fc5f9d433daaedc96c35747460d8b2079ac2907de2c95e3f7cce913113 + languageName: node + linkType: hard + "chownr@npm:^3.0.0": version: 3.0.0 resolution: "chownr@npm:3.0.0" @@ -3546,7 +4336,6 @@ __metadata: eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-react-refresh: "npm:^0.4.20" framer-plugin: "npm:^3.6.0" - framer-plugin-tools: "npm:^1.0.0" globals: "npm:^16.4.0" jiti: "npm:^2.5.1" prettier: "npm:^3.6.2" @@ -3560,6 +4349,19 @@ __metadata: languageName: unknown linkType: soft +"code-link@workspace:plugins/code-link": + version: 0.0.0-use.local + resolution: "code-link@workspace:plugins/code-link" + dependencies: + "@code-link/shared": "workspace:*" + "@types/react": "npm:^18.3.24" + "@types/react-dom": "npm:^18.3.7" + framer-plugin: "npm:3.10.3" + react: "npm:^18.3.1" + react-dom: "npm:^18.3.1" + languageName: unknown + linkType: soft + "code-versions@workspace:plugins/code-versions": version: 0.0.0-use.local resolution: "code-versions@workspace:plugins/code-versions" @@ -3639,6 +4441,27 @@ __metadata: languageName: node linkType: hard +"commander@npm:^13.1.0": + version: 13.1.0 + resolution: "commander@npm:13.1.0" + checksum: 10/d3b4b79e6be8471ddadacbb8cd441fe82154d7da7393b50e76165a9e29ccdb74fa911a186437b9a211d0fc071db6051915c94fb8ef16d77511d898e9dbabc6af + languageName: node + linkType: hard + +"commander@npm:^14.0.3": + version: 14.0.3 + resolution: "commander@npm:14.0.3" + checksum: 10/dfa9ebe2a433d277de5cb0252d23b10a543d245d892db858d23b516336a835c50fd4f52bee4cd13c705cc8acb6f03dc632c73dd806f7d06d3353eb09953dd17a + languageName: node + linkType: hard + +"commander@npm:^4.0.0": + version: 4.1.1 + resolution: "commander@npm:4.1.1" + checksum: 10/3b2dc4125f387dab73b3294dbcb0ab2a862f9c0ad748ee2b27e3544d25325b7a8cdfbcc228d103a98a716960b14478114a5206b5415bd48cdafa38797891562c + languageName: node + linkType: hard + "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -3662,6 +4485,20 @@ __metadata: languageName: unknown linkType: soft +"confbox@npm:^0.1.8": + version: 0.1.8 + resolution: "confbox@npm:0.1.8" + checksum: 10/4ebcfb1c6a3b25276734ec5722e88768eb61fc02f98e11960b845c5c62bc27fd05f493d2a8244d9675b24ef95afe4c0d511cdcad02c72f5eeea463cc26687999 + languageName: node + linkType: hard + +"consola@npm:^3.4.0": + version: 3.4.2 + resolution: "consola@npm:3.4.2" + checksum: 10/32192c9f50d7cac27c5d7c4ecd3ff3679aea863e6bf5bd6a9cc2b05d1cd78addf5dae71df08c54330c142be8e7fbd46f051030129b57c6aacdd771efe409c4b2 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" @@ -3854,6 +4691,13 @@ __metadata: languageName: node linkType: hard +"defu@npm:^6.1.4": + version: 6.1.4 + resolution: "defu@npm:6.1.4" + checksum: 10/aeffdb47300f45b4fdef1c5bd3880ac18ea7a1fd5b8a8faf8df29350ff03bf16dd34f9800205cab513d476e4c0a3783aa0cff0a433aff0ac84a67ddc4c8a2d64 + languageName: node + linkType: hard + "delayed-stream@npm:~1.0.0": version: 1.0.0 resolution: "delayed-stream@npm:1.0.0" @@ -3986,6 +4830,18 @@ __metadata: languageName: unknown linkType: soft +"dts-resolver@npm:^2.1.3": + version: 2.1.3 + resolution: "dts-resolver@npm:2.1.3" + peerDependencies: + oxc-resolver: ">=11.0.0" + peerDependenciesMeta: + oxc-resolver: + optional: true + checksum: 10/9dfa79be6f5a4dabc318274a6069cc237e3121307afa604bada4e8cbbf5c30403d916ec49059ce473b18fed1a28eb1d13353bb0fb82c4231b5cb4d332ff12f51 + languageName: node + linkType: hard + "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -4014,6 +4870,13 @@ __metadata: languageName: node linkType: hard +"empathic@npm:^2.0.0": + version: 2.0.0 + resolution: "empathic@npm:2.0.0" + checksum: 10/90f47d93f8d1db3aa00ce1bfae2940bf76379dbb34bd562edbd92c3564a173cb1d6bd3cadb645fad0224839c25886abde801155d9b972dda6add7a5cc8b35d48 + languageName: node + linkType: hard + "encoding-sniffer@npm:^0.2.1": version: 0.2.1 resolution: "encoding-sniffer@npm:0.2.1" @@ -4193,51 +5056,140 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1, escalade@npm:^3.2.0": - version: 3.2.0 - resolution: "escalade@npm:3.2.0" - checksum: 10/9d7169e3965b2f9ae46971afa392f6e5a25545ea30f2e2dd99c9b0a95a3f52b5653681a84f5b2911a413ddad2d7a93d3514165072f349b5ffc59c75a899970d6 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 10/98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^5.2.0": - version: 5.2.0 - resolution: "eslint-plugin-react-hooks@npm:5.2.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - checksum: 10/ebb79e9cf69ae06e3a7876536653c5e556b5fd8cd9dc49577f10a6e728360e7b6f5ce91f4339b33e93b26e3bb23805418f8b5e75db80baddd617b1dffe73bed1 - languageName: node - linkType: hard - -"eslint-plugin-react-refresh@npm:^0.4.20": - version: 0.4.20 - resolution: "eslint-plugin-react-refresh@npm:0.4.20" - peerDependencies: - eslint: ">=8.40" - checksum: 10/88aec8eeaf96f1a09df72a2134dc36dd8ef22a3ceb1ccba7865e63a128596e6be31942925edf896dcd12d0d51b8cb77530293ef4e738b600955a5a5c913f52d8 - languageName: node - linkType: hard - -"eslint-scope@npm:^8.4.0": - version: 8.4.0 - resolution: "eslint-scope@npm:8.4.0" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^5.2.0" - checksum: 10/e8e611701f65375e034c62123946e628894f0b54aa8cb11abe224816389abe5cd74cf16b62b72baa36504f22d1a958b9b8b0169b82397fe2e7997674c0d09b06 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.4.3": - version: 3.4.3 - resolution: "eslint-visitor-keys@npm:3.4.3" +"esbuild@npm:^0.27.0, esbuild@npm:~0.27.0": + version: 0.27.2 + resolution: "esbuild@npm:0.27.2" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.2" + "@esbuild/android-arm": "npm:0.27.2" + "@esbuild/android-arm64": "npm:0.27.2" + "@esbuild/android-x64": "npm:0.27.2" + "@esbuild/darwin-arm64": "npm:0.27.2" + "@esbuild/darwin-x64": "npm:0.27.2" + "@esbuild/freebsd-arm64": "npm:0.27.2" + "@esbuild/freebsd-x64": "npm:0.27.2" + "@esbuild/linux-arm": "npm:0.27.2" + "@esbuild/linux-arm64": "npm:0.27.2" + "@esbuild/linux-ia32": "npm:0.27.2" + "@esbuild/linux-loong64": "npm:0.27.2" + "@esbuild/linux-mips64el": "npm:0.27.2" + "@esbuild/linux-ppc64": "npm:0.27.2" + "@esbuild/linux-riscv64": "npm:0.27.2" + "@esbuild/linux-s390x": "npm:0.27.2" + "@esbuild/linux-x64": "npm:0.27.2" + "@esbuild/netbsd-arm64": "npm:0.27.2" + "@esbuild/netbsd-x64": "npm:0.27.2" + "@esbuild/openbsd-arm64": "npm:0.27.2" + "@esbuild/openbsd-x64": "npm:0.27.2" + "@esbuild/openharmony-arm64": "npm:0.27.2" + "@esbuild/sunos-x64": "npm:0.27.2" + "@esbuild/win32-arm64": "npm:0.27.2" + "@esbuild/win32-ia32": "npm:0.27.2" + "@esbuild/win32-x64": "npm:0.27.2" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10/7f1229328b0efc63c4184a61a7eb303df1e99818cc1d9e309fb92600703008e69821e8e984e9e9f54a627da14e0960d561db3a93029482ef96dc82dd267a60c2 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1, escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10/9d7169e3965b2f9ae46971afa392f6e5a25545ea30f2e2dd99c9b0a95a3f52b5653681a84f5b2911a413ddad2d7a93d3514165072f349b5ffc59c75a899970d6 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 10/98b48897d93060f2322108bf29db0feba7dd774be96cd069458d1453347b25ce8682ecc39859d4bca2203cc0ab19c237bcc71755eff49a0f8d90beadeeba5cc5 + languageName: node + linkType: hard + +"eslint-plugin-react-hooks@npm:^5.2.0": + version: 5.2.0 + resolution: "eslint-plugin-react-hooks@npm:5.2.0" + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + checksum: 10/ebb79e9cf69ae06e3a7876536653c5e556b5fd8cd9dc49577f10a6e728360e7b6f5ce91f4339b33e93b26e3bb23805418f8b5e75db80baddd617b1dffe73bed1 + languageName: node + linkType: hard + +"eslint-plugin-react-refresh@npm:^0.4.20": + version: 0.4.20 + resolution: "eslint-plugin-react-refresh@npm:0.4.20" + peerDependencies: + eslint: ">=8.40" + checksum: 10/88aec8eeaf96f1a09df72a2134dc36dd8ef22a3ceb1ccba7865e63a128596e6be31942925edf896dcd12d0d51b8cb77530293ef4e738b600955a5a5c913f52d8 + languageName: node + linkType: hard + +"eslint-scope@npm:^8.4.0": + version: 8.4.0 + resolution: "eslint-scope@npm:8.4.0" + dependencies: + esrecurse: "npm:^4.3.0" + estraverse: "npm:^5.2.0" + checksum: 10/e8e611701f65375e034c62123946e628894f0b54aa8cb11abe224816389abe5cd74cf16b62b72baa36504f22d1a958b9b8b0169b82397fe2e7997674c0d09b06 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 10/3f357c554a9ea794b094a09bd4187e5eacd1bc0d0653c3adeb87962c548e6a1ab8f982b86963ae1337f5d976004146536dcee5d0e2806665b193fbfbf1a9231b languageName: node linkType: hard @@ -4365,6 +5317,13 @@ __metadata: languageName: node linkType: hard +"expect-type@npm:^1.2.2": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10/a5fada3d0c621649261f886e7d93e6bf80ce26d8a86e5d517e38301b8baec8450ab2cb94ba6e7a0a6bf2fc9ee55f54e1b06938ef1efa52ddcfeffbfa01acbbcc + languageName: node + linkType: hard + "exponential-backoff@npm:^3.1.1": version: 3.1.2 resolution: "exponential-backoff@npm:3.1.2" @@ -4478,6 +5437,17 @@ __metadata: languageName: node linkType: hard +"fix-dts-default-cjs-exports@npm:^1.0.0": + version: 1.0.1 + resolution: "fix-dts-default-cjs-exports@npm:1.0.1" + dependencies: + magic-string: "npm:^0.30.17" + mlly: "npm:^1.7.4" + rollup: "npm:^4.34.8" + checksum: 10/3324418bb63c93b6b22a808e242d220caba804860c24218b2912abc4525525334fcdcb62d22be6472a8d84ee2ad4165bc79554140c3369eb11d23220cdd986ce + languageName: node + linkType: hard + "flat-cache@npm:^4.0.0": version: 4.0.1 resolution: "flat-cache@npm:4.0.1" @@ -4541,6 +5511,27 @@ __metadata: languageName: node linkType: hard +"framer-code-link@workspace:packages/code-link-cli": + version: 0.0.0-use.local + resolution: "framer-code-link@workspace:packages/code-link-cli" + dependencies: + "@code-link/shared": "workspace:*" + "@types/node": "npm:^22.19.2" + "@types/ws": "npm:^8.18.1" + "@typescript/ata": "npm:^0.9.8" + chokidar: "npm:^5.0.0" + commander: "npm:^14.0.3" + prettier: "npm:^3.7.4" + tsdown: "npm:^0.20.1" + tsx: "npm:^4.21.0" + typescript: "npm:^5.9.3" + vitest: "npm:^4.0.15" + ws: "npm:^8.18.3" + bin: + framer-code-link: ./dist/index.mjs + languageName: unknown + linkType: soft + "framer-motion@npm:^12.23.12": version: 12.23.12 resolution: "framer-motion@npm:12.23.12" @@ -4563,16 +5554,22 @@ __metadata: languageName: node linkType: hard -"framer-plugin-tools@npm:^1.0.0": - version: 1.0.0 - resolution: "framer-plugin-tools@npm:1.0.0" +"framer-plugin-tools@workspace:*, framer-plugin-tools@workspace:packages/plugin-tools": + version: 0.0.0-use.local + resolution: "framer-plugin-tools@workspace:packages/plugin-tools" dependencies: + "@commander-js/extra-typings": "npm:^13.1.0" + "@types/adm-zip": "npm:^0.5.7" + "@types/node": "npm:^22.0.0" adm-zip: "npm:^0.5.16" + commander: "npm:^13.1.0" + tsup: "npm:^8.0.0" + typescript: "npm:^5.9.2" + vitest: "npm:^3.2.4" bin: - framer-plugin-tools: index.js - checksum: 10/5f6b731038cfd23ea1e9a4b4de48a903c9e97ddc43b3598004554adba91e0fbc14efec6e6e9089a752380ffb4635f563575e6d4c6fb36597cbdb43e9edf17de8 - languageName: node - linkType: hard + framer-plugin-tools: dist/cli.js + languageName: unknown + linkType: soft "framer-plugin@npm:3.10.2-alpha.0": version: 3.10.2-alpha.0 @@ -4584,6 +5581,16 @@ __metadata: languageName: node linkType: hard +"framer-plugin@npm:3.10.3": + version: 3.10.3 + resolution: "framer-plugin@npm:3.10.3" + peerDependencies: + react: ^18.2.0 + react-dom: ^18.2.0 + checksum: 10/c677a261461cc3a79605cd74fc9de746de7c32e531a0c6a7aba0d5794af1c6c194cdea3576a6e74034c0228e7cc5a8ca8b0e40c213fe85e0dacece7cc01ce6c2 + languageName: node + linkType: hard + "framer-plugin@npm:3.7.0-alpha.0": version: 3.7.0-alpha.0 resolution: "framer-plugin@npm:3.7.0-alpha.0" @@ -4683,6 +5690,24 @@ __metadata: languageName: node linkType: hard +"get-tsconfig@npm:^4.13.1": + version: 4.13.2 + resolution: "get-tsconfig@npm:4.13.2" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10/7d7b2bd6ad1503004169a0fea8934e588ce421b79e4dd7cb20f77ee9d1a2f8b31ce5eddbb6d2b1b73a37cd367da4c4f64ef163544d400d17c98b534ba224fd6e + languageName: node + linkType: hard + +"get-tsconfig@npm:^4.7.5": + version: 4.13.0 + resolution: "get-tsconfig@npm:4.13.0" + dependencies: + resolve-pkg-maps: "npm:^1.0.0" + checksum: 10/3603c6da30e312636e4c20461e779114c9126601d1eca70ee4e36e3e3c00e3c21892d2d920027333afa2cc9e20998a436b14abe03a53cde40742581cb0e9ceb2 + languageName: node + linkType: hard + "glob-parent@npm:^5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" @@ -4852,6 +5877,13 @@ __metadata: languageName: node linkType: hard +"hookable@npm:^6.0.1": + version: 6.0.1 + resolution: "hookable@npm:6.0.1" + checksum: 10/9fccaaa07dabaadc2fa4f15afa00548b89dd8042a1165b94cb95118324b59b824e94686c5c9f710f74b87e860b885e2e31dfd086ca1008b011cc59993c65a93b + languageName: node + linkType: hard + "htmlparser2@npm:^10.0.0": version: 10.0.0 resolution: "htmlparser2@npm:10.0.0" @@ -4959,6 +5991,13 @@ __metadata: languageName: node linkType: hard +"import-without-cache@npm:^0.2.5": + version: 0.2.5 + resolution: "import-without-cache@npm:0.2.5" + checksum: 10/b58c16deaa0c97f08b1c34798d22a2b1108dfe9d6319dc3250fa8c6d0c5221d1bda899471546faf58a5968c919f177b1df3670a6fb49dfafbeceed0830ec86d6 + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -5063,6 +6102,13 @@ __metadata: languageName: node linkType: hard +"joycon@npm:^3.1.1": + version: 3.1.1 + resolution: "joycon@npm:3.1.1" + checksum: 10/4b36e3479144ec196425f46b3618f8a96ce7e1b658f091a309cd4906215f5b7a402d7df331a3e0a09681381a658d0c5f039cb3cf6907e0a1e17ed847f5d37775 + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -5095,6 +6141,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^3.0.2": + version: 3.1.0 + resolution: "jsesc@npm:3.1.0" + bin: + jsesc: bin/jsesc + checksum: 10/20bd37a142eca5d1794f354db8f1c9aeb54d85e1f5c247b371de05d23a9751ecd7bd3a9c4fc5298ea6fa09a100dafb4190fa5c98c6610b75952c3487f3ce7967 + languageName: node + linkType: hard + "json-buffer@npm:3.0.1": version: 3.0.1 resolution: "json-buffer@npm:3.0.1" @@ -5245,6 +6300,27 @@ __metadata: languageName: node linkType: hard +"lilconfig@npm:^3.1.1": + version: 3.1.3 + resolution: "lilconfig@npm:3.1.3" + checksum: 10/b932ce1af94985f0efbe8896e57b1f814a48c8dbd7fc0ef8469785c6303ed29d0090af3ccad7e36b626bfca3a4dc56cc262697e9a8dd867623cf09a39d54e4c3 + languageName: node + linkType: hard + +"lines-and-columns@npm:^1.1.6": + version: 1.2.4 + resolution: "lines-and-columns@npm:1.2.4" + checksum: 10/0c37f9f7fa212b38912b7145e1cd16a5f3cd34d782441c3e6ca653485d326f58b3caccda66efce1c5812bde4961bbde3374fae4b0d11bf1226152337f3894aa5 + languageName: node + linkType: hard + +"load-tsconfig@npm:^0.2.3": + version: 0.2.5 + resolution: "load-tsconfig@npm:0.2.5" + checksum: 10/b3176f6f0c86dbdbbc7e337440a803b0b4407c55e2e1cfc53bd3db68e0211448f36428a6075ecf5e286db5d1bf791da756fc0ac4d2447717140fb6a5218ecfb4 + languageName: node + linkType: hard + "locale-sync@workspace:plugins/locale-sync": version: 0.0.0-use.local resolution: "locale-sync@workspace:plugins/locale-sync" @@ -5288,9 +6364,9 @@ __metadata: linkType: hard "lodash@npm:^4.0.1, lodash@npm:^4.17.15": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532 + version: 4.17.23 + resolution: "lodash@npm:4.17.23" + checksum: 10/82504c88250f58da7a5a4289f57a4f759c44946c005dd232821c7688b5fcfbf4a6268f6a6cdde4b792c91edd2f3b5398c1d2a0998274432cff76def48735e233 languageName: node linkType: hard @@ -5337,6 +6413,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10/57d5691f41ed40d962d8bd300148114f53db67fadbff336207db10a99f2bdf4a1be9cac3a68ee85dba575912ee1d4402e4396408196ec2d3afd043b076156221 + languageName: node + linkType: hard + "make-fetch-happen@npm:^14.0.3": version: 14.0.3 resolution: "make-fetch-happen@npm:14.0.3" @@ -5529,6 +6614,18 @@ __metadata: languageName: node linkType: hard +"mlly@npm:^1.7.4": + version: 1.8.0 + resolution: "mlly@npm:1.8.0" + dependencies: + acorn: "npm:^8.15.0" + pathe: "npm:^2.0.3" + pkg-types: "npm:^1.3.1" + ufo: "npm:^1.6.1" + checksum: 10/4db690a421076d5fe88331679f702b77a4bfc9fe3f324bc6150270fb0b69ecd4b5e43570b8e4573dde341515b3eac4daa720a6ac9f2715c210b670852641ab1c + languageName: node + linkType: hard + "motion-dom@npm:^12.23.12": version: 12.23.12 resolution: "motion-dom@npm:12.23.12" @@ -5580,6 +6677,17 @@ __metadata: languageName: node linkType: hard +"mz@npm:^2.7.0": + version: 2.7.0 + resolution: "mz@npm:2.7.0" + dependencies: + any-promise: "npm:^1.0.0" + object-assign: "npm:^4.0.1" + thenify-all: "npm:^1.0.0" + checksum: 10/8427de0ece99a07e9faed3c0c6778820d7543e3776f9a84d22cf0ec0a8eb65f6e9aee9c9d353ff9a105ff62d33a9463c6ca638974cc652ee8140cd1e35951c87 + languageName: node + linkType: hard + "nanoid@npm:^3.3.11": version: 3.3.11 resolution: "nanoid@npm:3.3.11" @@ -5663,7 +6771,6 @@ __metadata: "@types/react": "npm:^18.3.24" "@types/react-dom": "npm:^18.3.7" framer-plugin: "npm:3.10.2-alpha.0" - framer-plugin-tools: "npm:^1.0.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" valibot: "npm:^1.2.0" @@ -5679,13 +6786,20 @@ __metadata: languageName: node linkType: hard -"object-assign@npm:^4.1.1": +"object-assign@npm:^4.0.1, object-assign@npm:^4.1.1": version: 4.1.1 resolution: "object-assign@npm:4.1.1" checksum: 10/fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10/bdcf9213361786688019345f3452b95a1dc73710e4b403c82a1994b98bad6abc31b26cb72a482128c5fd53ea9daf6fbb7d0e0e7b2b7e9c8be6d779deeccee07f + languageName: node + linkType: hard + "ogl@npm:^1.0.11": version: 1.0.11 resolution: "ogl@npm:1.0.11" @@ -5823,7 +6937,7 @@ __metadata: languageName: node linkType: hard -"pathe@npm:^2.0.3": +"pathe@npm:^2.0.1, pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" checksum: 10/01e9a69928f39087d96e1751ce7d6d50da8c39abf9a12e0ac2389c42c83bc76f78c45a475bd9026a02e6a6f79be63acc75667df855862fe567d99a00a540d23d @@ -5888,6 +7002,24 @@ __metadata: languageName: node linkType: hard +"pirates@npm:^4.0.1": + version: 4.0.7 + resolution: "pirates@npm:4.0.7" + checksum: 10/2427f371366081ae42feb58214f04805d6b41d6b84d74480ebcc9e0ddbd7105a139f7c653daeaf83ad8a1a77214cf07f64178e76de048128fec501eab3305a96 + languageName: node + linkType: hard + +"pkg-types@npm:^1.3.1": + version: 1.3.1 + resolution: "pkg-types@npm:1.3.1" + dependencies: + confbox: "npm:^0.1.8" + mlly: "npm:^1.7.4" + pathe: "npm:^2.0.1" + checksum: 10/6d491f2244597b24fb59a50e3c258f27da3839555d2a4e112b31bcf536e9359fc4edc98639cd74d2cf16fcd4269e5a09d99fc05d89e2acc896a2f027c2f6ec44 + languageName: node + linkType: hard + "plugins@workspace:.": version: 0.0.0-use.local resolution: "plugins@workspace:." @@ -5895,11 +7027,16 @@ __metadata: "@biomejs/biome": "npm:^2.2.4" "@framer/eslint-config": "workspace:*" "@framer/vite-config": "workspace:*" + "@types/node": "npm:^22.15.21" eslint: "npm:^9.35.0" + framer-plugin-tools: "workspace:*" jiti: "npm:^2.5.1" + tsx: "npm:^4.19.0" turbo: "npm:^2.5.6" typescript: "npm:^5.9.2" + valibot: "npm:^1.2.0" vite: "npm:^7.1.11" + vitest: "npm:^3.2.4" languageName: unknown linkType: soft @@ -5932,6 +7069,29 @@ __metadata: languageName: unknown linkType: soft +"postcss-load-config@npm:^6.0.1": + version: 6.0.1 + resolution: "postcss-load-config@npm:6.0.1" + dependencies: + lilconfig: "npm:^3.1.1" + peerDependencies: + jiti: ">=1.21.0" + postcss: ">=8.0.9" + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + checksum: 10/1691cfc94948a9373d4f7b3b7a8500cfaf8cb2dcc2107c14f90f2a711a9892a362b0866894ac5bb723455fa685a15116d9ed3252188689c4502b137c19d6bdc4 + languageName: node + linkType: hard + "postcss@npm:^8.5.6": version: 8.5.6 resolution: "postcss@npm:8.5.6" @@ -5972,6 +7132,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.7.4": + version: 3.8.1 + resolution: "prettier@npm:3.8.1" + bin: + prettier: bin/prettier.cjs + checksum: 10/3da1cf8c1ef9bea828aa618553696c312e951f810bee368f6887109b203f18ee869fe88f66e65f9cf60b7cb1f2eae859892c860a300c062ff8ec69c381fc8dbd + languageName: node + linkType: hard + "pretty-format@npm:^27.0.2": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -6039,6 +7208,13 @@ __metadata: languageName: node linkType: hard +"quansync@npm:^1.0.0": + version: 1.0.0 + resolution: "quansync@npm:1.0.0" + checksum: 10/fba7a8e87ae8ed99648aba16ce5fbe0fb8a1ae00b18407447f0273feab413b6e50f1fcdfb106e88da700766c80d89c4303e2f0685baee2f10f055e6b2a5879cf + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -6332,6 +7508,20 @@ __metadata: languageName: node linkType: hard +"readdirp@npm:^4.0.1": + version: 4.1.2 + resolution: "readdirp@npm:4.1.2" + checksum: 10/7b817c265940dba90bb9c94d82920d76c3a35ea2d67f9f9d8bd936adcfe02d50c802b14be3dd2e725e002dddbe2cc1c7a0edfb1bc3a365c9dfd5a61e612eea1e + languageName: node + linkType: hard + +"readdirp@npm:^5.0.0": + version: 5.0.0 + resolution: "readdirp@npm:5.0.0" + checksum: 10/a17a591b51d8b912083660df159e8bd17305dc1a9ef27c869c818bd95ff59e3a6496f97e91e724ef433e789d559d24e39496ea1698822eb5719606dc9c1a923d + languageName: node + linkType: hard + "recharts@npm:^3.2.0": version: 3.2.0 resolution: "recharts@npm:3.2.0" @@ -6423,7 +7613,6 @@ __metadata: "@types/react-dom": "npm:^18.3.7" classnames: "npm:^2.5.1" framer-plugin: "npm:^3.7.0" - framer-plugin-tools: "npm:^1.0.0" react: "npm:^18.3.1" react-dom: "npm:^18.3.1" languageName: unknown @@ -6450,6 +7639,20 @@ __metadata: languageName: node linkType: hard +"resolve-from@npm:^5.0.0": + version: 5.0.0 + resolution: "resolve-from@npm:5.0.0" + checksum: 10/be18a5e4d76dd711778664829841cde690971d02b6cbae277735a09c1c28f407b99ef6ef3cd585a1e6546d4097b28df40ed32c4a287b9699dcf6d7f208495e23 + languageName: node + linkType: hard + +"resolve-pkg-maps@npm:^1.0.0": + version: 1.0.0 + resolution: "resolve-pkg-maps@npm:1.0.0" + checksum: 10/0763150adf303040c304009231314d1e84c6e5ebfa2d82b7d94e96a6e82bacd1dcc0b58ae257315f3c8adb89a91d8d0f12928241cba2df1680fbe6f60bf99b0e + languageName: node + linkType: hard + "retry@npm:^0.12.0": version: 0.12.0 resolution: "retry@npm:0.12.0" @@ -6464,25 +7667,199 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.43.0": - version: 4.50.2 - resolution: "rollup@npm:4.50.2" +"rolldown-plugin-dts@npm:^0.22.1": + version: 0.22.1 + resolution: "rolldown-plugin-dts@npm:0.22.1" dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.50.2" - "@rollup/rollup-android-arm64": "npm:4.50.2" - "@rollup/rollup-darwin-arm64": "npm:4.50.2" - "@rollup/rollup-darwin-x64": "npm:4.50.2" - "@rollup/rollup-freebsd-arm64": "npm:4.50.2" - "@rollup/rollup-freebsd-x64": "npm:4.50.2" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.50.2" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.50.2" - "@rollup/rollup-linux-arm64-gnu": "npm:4.50.2" - "@rollup/rollup-linux-arm64-musl": "npm:4.50.2" - "@rollup/rollup-linux-loong64-gnu": "npm:4.50.2" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.50.2" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.50.2" - "@rollup/rollup-linux-riscv64-musl": "npm:4.50.2" - "@rollup/rollup-linux-s390x-gnu": "npm:4.50.2" + "@babel/generator": "npm:8.0.0-rc.1" + "@babel/helper-validator-identifier": "npm:8.0.0-rc.1" + "@babel/parser": "npm:8.0.0-rc.1" + "@babel/types": "npm:8.0.0-rc.1" + ast-kit: "npm:^3.0.0-beta.1" + birpc: "npm:^4.0.0" + dts-resolver: "npm:^2.1.3" + get-tsconfig: "npm:^4.13.1" + obug: "npm:^2.1.1" + peerDependencies: + "@ts-macro/tsc": ^0.3.6 + "@typescript/native-preview": ">=7.0.0-dev.20250601.1" + rolldown: ^1.0.0-rc.3 + typescript: ^5.0.0 + vue-tsc: ~3.2.0 + peerDependenciesMeta: + "@ts-macro/tsc": + optional: true + "@typescript/native-preview": + optional: true + typescript: + optional: true + vue-tsc: + optional: true + checksum: 10/e180a99005428e5ce80076cf0801dc6276a75b686739779a5c0b6da85400b1da19858d6280427bca84afeaff5ef251a748d034a0c9d64268c5bc5b8d25415178 + languageName: node + linkType: hard + +"rolldown@npm:1.0.0-rc.3": + version: 1.0.0-rc.3 + resolution: "rolldown@npm:1.0.0-rc.3" + dependencies: + "@oxc-project/types": "npm:=0.112.0" + "@rolldown/binding-android-arm64": "npm:1.0.0-rc.3" + "@rolldown/binding-darwin-arm64": "npm:1.0.0-rc.3" + "@rolldown/binding-darwin-x64": "npm:1.0.0-rc.3" + "@rolldown/binding-freebsd-x64": "npm:1.0.0-rc.3" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0-rc.3" + "@rolldown/binding-linux-arm64-gnu": "npm:1.0.0-rc.3" + "@rolldown/binding-linux-arm64-musl": "npm:1.0.0-rc.3" + "@rolldown/binding-linux-x64-gnu": "npm:1.0.0-rc.3" + "@rolldown/binding-linux-x64-musl": "npm:1.0.0-rc.3" + "@rolldown/binding-openharmony-arm64": "npm:1.0.0-rc.3" + "@rolldown/binding-wasm32-wasi": "npm:1.0.0-rc.3" + "@rolldown/binding-win32-arm64-msvc": "npm:1.0.0-rc.3" + "@rolldown/binding-win32-x64-msvc": "npm:1.0.0-rc.3" + "@rolldown/pluginutils": "npm:1.0.0-rc.3" + dependenciesMeta: + "@rolldown/binding-android-arm64": + optional: true + "@rolldown/binding-darwin-arm64": + optional: true + "@rolldown/binding-darwin-x64": + optional: true + "@rolldown/binding-freebsd-x64": + optional: true + "@rolldown/binding-linux-arm-gnueabihf": + optional: true + "@rolldown/binding-linux-arm64-gnu": + optional: true + "@rolldown/binding-linux-arm64-musl": + optional: true + "@rolldown/binding-linux-x64-gnu": + optional: true + "@rolldown/binding-linux-x64-musl": + optional: true + "@rolldown/binding-openharmony-arm64": + optional: true + "@rolldown/binding-wasm32-wasi": + optional: true + "@rolldown/binding-win32-arm64-msvc": + optional: true + "@rolldown/binding-win32-x64-msvc": + optional: true + bin: + rolldown: bin/cli.mjs + checksum: 10/28c88da3dc1b95125e177c4fd0757faffdd4b2fa81ef0a0ba6e75f5e4c4c49c5a3fe88dd7fffe9f7091d514cd25fa0a038d03acbe7068651b1b43a5257edfd03 + languageName: node + linkType: hard + +"rollup@npm:^4.34.8": + version: 4.57.1 + resolution: "rollup@npm:4.57.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.57.1" + "@rollup/rollup-android-arm64": "npm:4.57.1" + "@rollup/rollup-darwin-arm64": "npm:4.57.1" + "@rollup/rollup-darwin-x64": "npm:4.57.1" + "@rollup/rollup-freebsd-arm64": "npm:4.57.1" + "@rollup/rollup-freebsd-x64": "npm:4.57.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.57.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.57.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.57.1" + "@rollup/rollup-linux-loong64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-loong64-musl": "npm:4.57.1" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-ppc64-musl": "npm:4.57.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-riscv64-musl": "npm:4.57.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.57.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.57.1" + "@rollup/rollup-linux-x64-musl": "npm:4.57.1" + "@rollup/rollup-openbsd-x64": "npm:4.57.1" + "@rollup/rollup-openharmony-arm64": "npm:4.57.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.57.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.57.1" + "@rollup/rollup-win32-x64-gnu": "npm:4.57.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.57.1" + "@types/estree": "npm:1.0.8" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loong64-gnu": + optional: true + "@rollup/rollup-linux-loong64-musl": + optional: true + "@rollup/rollup-linux-ppc64-gnu": + optional: true + "@rollup/rollup-linux-ppc64-musl": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-openbsd-x64": + optional: true + "@rollup/rollup-openharmony-arm64": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-gnu": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10/0451371339e593967c979e498fac4dfd0ba15fadf0dac96875940796307a00d62ab68460366a65f4872ae8edd9339e3d9501e8e5764c1f23e25e0951f75047c6 + languageName: node + linkType: hard + +"rollup@npm:^4.43.0": + version: 4.50.2 + resolution: "rollup@npm:4.50.2" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.50.2" + "@rollup/rollup-android-arm64": "npm:4.50.2" + "@rollup/rollup-darwin-arm64": "npm:4.50.2" + "@rollup/rollup-darwin-x64": "npm:4.50.2" + "@rollup/rollup-freebsd-arm64": "npm:4.50.2" + "@rollup/rollup-freebsd-x64": "npm:4.50.2" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.50.2" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.50.2" + "@rollup/rollup-linux-arm64-gnu": "npm:4.50.2" + "@rollup/rollup-linux-arm64-musl": "npm:4.50.2" + "@rollup/rollup-linux-loong64-gnu": "npm:4.50.2" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.50.2" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.50.2" + "@rollup/rollup-linux-riscv64-musl": "npm:4.50.2" + "@rollup/rollup-linux-s390x-gnu": "npm:4.50.2" "@rollup/rollup-linux-x64-gnu": "npm:4.50.2" "@rollup/rollup-linux-x64-musl": "npm:4.50.2" "@rollup/rollup-openharmony-arm64": "npm:4.50.2" @@ -6601,6 +7978,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.7.3 + resolution: "semver@npm:7.7.3" + bin: + semver: bin/semver.js + checksum: 10/8dbc3168e057a38fc322af909c7f5617483c50caddba135439ff09a754b20bdd6482a5123ff543dad4affa488ecf46ec5fb56d61312ad20bb140199b88dfaea9 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -6677,6 +8063,13 @@ __metadata: languageName: node linkType: hard +"source-map@npm:^0.7.6": + version: 0.7.6 + resolution: "source-map@npm:0.7.6" + checksum: 10/c8d2da7c57c14f3fd7568f764b39ad49bbf9dd7632b86df3542b31fed117d4af2fb74a4f886fc06baf7a510fee68e37998efc3080aacdac951c36211dc29a7a3 + languageName: node + linkType: hard + "sprintf-js@npm:^1.1.3": version: 1.1.3 resolution: "sprintf-js@npm:1.1.3" @@ -6700,6 +8093,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.10.0": + version: 3.10.0 + resolution: "std-env@npm:3.10.0" + checksum: 10/19c9cda4f370b1ffae2b8b08c72167d8c3e5cfa972aaf5c6873f85d0ed2faa729407f5abb194dc33380708c00315002febb6f1e1b484736bfcf9361ad366013a + languageName: node + linkType: hard + "std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" @@ -6772,6 +8172,24 @@ __metadata: languageName: node linkType: hard +"sucrase@npm:^3.35.0": + version: 3.35.1 + resolution: "sucrase@npm:3.35.1" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.2" + commander: "npm:^4.0.0" + lines-and-columns: "npm:^1.1.6" + mz: "npm:^2.7.0" + pirates: "npm:^4.0.1" + tinyglobby: "npm:^0.2.11" + ts-interface-checker: "npm:^0.1.9" + bin: + sucrase: bin/sucrase + sucrase-node: bin/sucrase-node + checksum: 10/539f5c6ebc1ff8d449a89eb52b8c8944a730b9840ddadbd299a7d89ebcf16c3f4bc9aa59e1f2e112a502e5cf1508f7e02065f0e97c0435eb9a7058e997dfff5a + languageName: node + linkType: hard + "supports-color@npm:^7.1.0": version: 7.2.0 resolution: "supports-color@npm:7.2.0" @@ -6815,6 +8233,24 @@ __metadata: languageName: node linkType: hard +"thenify-all@npm:^1.0.0": + version: 1.6.0 + resolution: "thenify-all@npm:1.6.0" + dependencies: + thenify: "npm:>= 3.1.0 < 4" + checksum: 10/dba7cc8a23a154cdcb6acb7f51d61511c37a6b077ec5ab5da6e8b874272015937788402fd271fdfc5f187f8cb0948e38d0a42dcc89d554d731652ab458f5343e + languageName: node + linkType: hard + +"thenify@npm:>= 3.1.0 < 4": + version: 3.3.1 + resolution: "thenify@npm:3.3.1" + dependencies: + any-promise: "npm:^1.0.0" + checksum: 10/486e1283a867440a904e36741ff1a177faa827cf94d69506f7e3ae4187b9afdf9ec368b3d8da225c192bfe2eb943f3f0080594156bf39f21b57cd1411e2e7f6d + languageName: node + linkType: hard + "threshold@workspace:plugins/threshold": version: 0.0.0-use.local resolution: "threshold@workspace:plugins/threshold" @@ -6870,7 +8306,14 @@ __metadata: languageName: node linkType: hard -"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10/cb709ed4240e873d3816e67f851d445f5676e0ae3a52931a60ff571d93d388da09108c8057b62351766133ee05ff3159dd56c3a0fbd39a5933c6639ce8771405 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.11, tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.14, tinyglobby@npm:^0.2.15": version: 0.2.15 resolution: "tinyglobby@npm:0.2.15" dependencies: @@ -6894,6 +8337,13 @@ __metadata: languageName: node linkType: hard +"tinyrainbow@npm:^3.0.3": + version: 3.0.3 + resolution: "tinyrainbow@npm:3.0.3" + checksum: 10/169cc63c15e1378674180f3207c82c05bfa58fc79992e48792e8d97b4b759012f48e95297900ede24a81f0087cf329a0d85bb81109739eacf03c650127b3f6c1 + languageName: node + linkType: hard + "tinyspy@npm:^4.0.3": version: 4.0.3 resolution: "tinyspy@npm:4.0.3" @@ -6924,6 +8374,15 @@ __metadata: languageName: node linkType: hard +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 10/49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7 + languageName: node + linkType: hard + "ts-api-utils@npm:^2.1.0": version: 2.1.0 resolution: "ts-api-utils@npm:2.1.0" @@ -6933,6 +8392,13 @@ __metadata: languageName: node linkType: hard +"ts-interface-checker@npm:^0.1.9": + version: 0.1.13 + resolution: "ts-interface-checker@npm:0.1.13" + checksum: 10/9f7346b9e25bade7a1050c001ec5a4f7023909c0e1644c5a96ae20703a131627f081479e6622a4ecee2177283d0069e651e507bedadd3904fc4010ab28ffce00 + languageName: node + linkType: hard + "ts-pattern@npm:^5.8.0": version: 5.8.0 resolution: "ts-pattern@npm:5.8.0" @@ -6940,6 +8406,52 @@ __metadata: languageName: node linkType: hard +"tsdown@npm:^0.20.1": + version: 0.20.3 + resolution: "tsdown@npm:0.20.3" + dependencies: + ansis: "npm:^4.2.0" + cac: "npm:^6.7.14" + defu: "npm:^6.1.4" + empathic: "npm:^2.0.0" + hookable: "npm:^6.0.1" + import-without-cache: "npm:^0.2.5" + obug: "npm:^2.1.1" + picomatch: "npm:^4.0.3" + rolldown: "npm:1.0.0-rc.3" + rolldown-plugin-dts: "npm:^0.22.1" + semver: "npm:^7.7.3" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tree-kill: "npm:^1.2.2" + unconfig-core: "npm:^7.4.2" + unrun: "npm:^0.2.27" + peerDependencies: + "@arethetypeswrong/core": ^0.18.1 + "@vitejs/devtools": "*" + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + "@arethetypeswrong/core": + optional: true + "@vitejs/devtools": + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + bin: + tsdown: dist/run.mjs + checksum: 10/3d511dea766ebdd3b1c4387aa86a7093a2e4fe131c6283a73453545ffdf48f30f1a3694c4a9a45068a58ccab3d886ddfd3a89b898b0b5e5f7469a72da8ecc49e + languageName: node + linkType: hard + "tslib@npm:^2.0.0, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.7.0, tslib@npm:^2.8.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -6947,6 +8459,64 @@ __metadata: languageName: node linkType: hard +"tsup@npm:^8.0.0": + version: 8.5.1 + resolution: "tsup@npm:8.5.1" + dependencies: + bundle-require: "npm:^5.1.0" + cac: "npm:^6.7.14" + chokidar: "npm:^4.0.3" + consola: "npm:^3.4.0" + debug: "npm:^4.4.0" + esbuild: "npm:^0.27.0" + fix-dts-default-cjs-exports: "npm:^1.0.0" + joycon: "npm:^3.1.1" + picocolors: "npm:^1.1.1" + postcss-load-config: "npm:^6.0.1" + resolve-from: "npm:^5.0.0" + rollup: "npm:^4.34.8" + source-map: "npm:^0.7.6" + sucrase: "npm:^3.35.0" + tinyexec: "npm:^0.3.2" + tinyglobby: "npm:^0.2.11" + tree-kill: "npm:^1.2.2" + peerDependencies: + "@microsoft/api-extractor": ^7.36.0 + "@swc/core": ^1 + postcss: ^8.4.12 + typescript: ">=4.5.0" + peerDependenciesMeta: + "@microsoft/api-extractor": + optional: true + "@swc/core": + optional: true + postcss: + optional: true + typescript: + optional: true + bin: + tsup: dist/cli-default.js + tsup-node: dist/cli-node.js + checksum: 10/f1927ec2dda93b218b39cd1cac1040902eef66e026261f5c265197c2f660cb5b9e1fb89353d50de5c6a5616463c02800e87e1daad7620b9c9051221d93c66824 + languageName: node + linkType: hard + +"tsx@npm:^4.19.0, tsx@npm:^4.21.0": + version: 4.21.0 + resolution: "tsx@npm:4.21.0" + dependencies: + esbuild: "npm:~0.27.0" + fsevents: "npm:~2.3.3" + get-tsconfig: "npm:^4.7.5" + dependenciesMeta: + fsevents: + optional: true + bin: + tsx: dist/cli.mjs + checksum: 10/7afedeff855ba98c47dc28b33d7e8e253c4dc1f791938db402d79c174bdf806b897c1a5f91e5b1259c112520c816f826b4c5d98f0bad7e95b02dec66fedb64d2 + languageName: node + linkType: hard + "turbo-darwin-64@npm:2.5.6": version: 2.5.6 resolution: "turbo-darwin-64@npm:2.5.6" @@ -7052,6 +8622,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.9.3": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10/c089d9d3da2729fd4ac517f9b0e0485914c4b3c26f80dc0cffcb5de1719a17951e92425d55db59515c1a7ddab65808466debb864d0d56dcf43f27007d0709594 + languageName: node + linkType: hard + "typescript@patch:typescript@npm%3A^5.9.2#optional!builtin": version: 5.9.2 resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" @@ -7062,6 +8642,33 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.9.3#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10/696e1b017bc2635f4e0c94eb4435357701008e2f272f553d06e35b494b8ddc60aa221145e286c28ace0c89ee32827a28c2040e3a69bdc108b1a5dc8fb40b72e3 + languageName: node + linkType: hard + +"ufo@npm:^1.6.1": + version: 1.6.3 + resolution: "ufo@npm:1.6.3" + checksum: 10/79803984f3e414567273a666183d6a50d1bec0d852100a98f55c1e393cb705e3b88033e04029dd651714e6eec99e1b00f54fdc13f32404968251a16f8898cfe5 + languageName: node + linkType: hard + +"unconfig-core@npm:^7.4.2": + version: 7.4.2 + resolution: "unconfig-core@npm:7.4.2" + dependencies: + "@quansync/fs": "npm:^1.0.0" + quansync: "npm:^1.0.0" + checksum: 10/837d196508e11be4b182560448f07ca7506db9d2f607d43738f6d64d6a3182a6c71b73339de94ea05ee60cfcdfd29e59e0806902267967ffe522cae60b5b4b4d + languageName: node + linkType: hard + "undici-types@npm:~6.21.0": version: 6.21.0 resolution: "undici-types@npm:6.21.0" @@ -7101,6 +8708,22 @@ __metadata: languageName: node linkType: hard +"unrun@npm:^0.2.27": + version: 0.2.27 + resolution: "unrun@npm:0.2.27" + dependencies: + rolldown: "npm:1.0.0-rc.3" + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + bin: + unrun: dist/cli.mjs + checksum: 10/70a589218b74c837f7190f69d58a95f426f2679bacb1df61635df6f98922a89bd22655a8852652fb1ad5770b6aafcb7e507d37c2e028c5ea2c57fd0d56bf02cb + languageName: node + linkType: hard + "unsplash@workspace:plugins/unsplash": version: 0.0.0-use.local resolution: "unsplash@workspace:plugins/unsplash" @@ -7324,6 +8947,61 @@ __metadata: languageName: node linkType: hard +"vite@npm:^6.0.0 || ^7.0.0": + version: 7.3.1 + resolution: "vite@npm:7.3.1" + dependencies: + esbuild: "npm:^0.27.0" + fdir: "npm:^6.5.0" + fsevents: "npm:~2.3.3" + picomatch: "npm:^4.0.3" + postcss: "npm:^8.5.6" + rollup: "npm:^4.43.0" + tinyglobby: "npm:^0.2.15" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + jiti: ">=1.21.0" + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10/62e48ffa4283b688f0049005405a004447ad38ffc99a0efea4c3aa9b7eed739f7402b43f00668c0ee5a895b684dc953d62f0722d8a92c5b2f6c95f051bceb208 + languageName: node + linkType: hard + "vite@npm:^7.1.11": version: 7.1.11 resolution: "vite@npm:7.1.11" @@ -7435,6 +9113,65 @@ __metadata: languageName: node linkType: hard +"vitest@npm:^4.0.15": + version: 4.0.18 + resolution: "vitest@npm:4.0.18" + dependencies: + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + es-module-lexer: "npm:^1.7.0" + expect-type: "npm:^1.2.2" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^3.10.0" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.0.3" + vite: "npm:^6.0.0 || ^7.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 + happy-dom: "*" + jsdom: "*" + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + bin: + vitest: vitest.mjs + checksum: 10/6c6464ebcf3af83546862896fd1b5f10cb6607261bffce39df60033a288b8c1687ae1dd20002b6e4997a7a05303376d1eb58ce20afe63be052529a4378a8c165 + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -7551,6 +9288,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.18.3": + version: 8.19.0 + resolution: "ws@npm:8.19.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 10/26e4901e93abaf73af9f26a93707c95b4845e91a7a347ec8c569e6e9be7f9df066f6c2b817b2d685544e208207898a750b78461e6e8d810c11a370771450c31b + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8"