From 57fb7a065073de5708abc56fa25a9d05721f41b8 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 1 Jul 2024 12:35:23 +0100 Subject: [PATCH] Initial bemo worker setup (#4017) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sets up preview deploys etc. for bemo worker. There's enough going on here that I wanted to make it its own PR. I'll rework david's spike on top of it once it's landed. ### Change Type - [x] `internal` — Does not affect user-facing stuff - [x] `chore` — Updating dependencies, other boring stuff --------- Co-authored-by: David Sheldrick --- .github/workflows/deploy-bemo.yml | 54 ++ .../{deploy.yml => deploy-dotcom.yml} | 17 +- apps/bemo-worker/.gitignore | 2 + apps/bemo-worker/README.md | 38 + apps/bemo-worker/package.json | 49 ++ apps/bemo-worker/src/BemoDO.ts | 38 + apps/bemo-worker/src/sentry.ts | 21 + apps/bemo-worker/src/types.ts | 12 + apps/bemo-worker/src/worker.test.ts | 5 + apps/bemo-worker/src/worker.ts | 37 + apps/bemo-worker/tsconfig.json | 26 + apps/bemo-worker/wrangler.toml | 79 ++ apps/dotcom-asset-upload/package.json | 2 +- apps/dotcom-asset-upload/wrangler.toml | 11 +- apps/dotcom-worker/package.json | 18 +- apps/dotcom-worker/scripts/cron.ts | 10 - apps/dotcom-worker/scripts/report-size.js | 45 - .../src/{lib => }/AlarmScheduler.test.ts | 0 .../src/{lib => }/AlarmScheduler.ts | 0 .../src/{lib => }/TLDrawDurableObject.ts | 20 +- apps/dotcom-worker/src/{lib => }/config.ts | 0 apps/dotcom-worker/src/{lib => }/r2.ts | 0 .../src/{lib => }/routes/createRoom.ts | 0 .../{lib => }/routes/createRoomSnapshot.ts | 0 .../{lib => }/routes/forwardRoomRequest.ts | 0 .../src/{lib => }/routes/getReadonlySlug.ts | 0 .../src/{lib => }/routes/getRoomHistory.ts | 0 .../routes/getRoomHistorySnapshot.ts | 0 .../src/{lib => }/routes/getRoomSnapshot.ts | 0 .../src/{lib => }/routes/joinExistingRoom.ts | 0 apps/dotcom-worker/src/{lib => }/types.ts | 0 .../utils/createPersistQueue.test.ts | 0 .../src/{lib => }/utils/createPersistQueue.ts | 0 .../{lib => }/utils/createSupabaseClient.ts | 0 .../src/{lib => }/utils/fourOhFour.ts | 0 .../src/{lib => }/utils/getSnapshotsTable.ts | 0 .../src/{lib => }/utils/roomIdIsTooLong.ts | 0 .../src/{lib => }/utils/roomOpenMode.ts | 0 .../src/{lib => }/utils/throttle.ts | 0 .../src/{lib => }/utils/validateSnapshot.ts | 0 apps/dotcom-worker/src/{lib => }/worker.ts | 9 +- apps/dotcom-worker/wrangler.toml | 2 +- apps/dotcom/sentry.client.config.ts | 1 + apps/health-worker/package.json | 4 +- apps/vscode/editor/package.json | 2 +- apps/vscode/extension/package.json | 2 +- package.json | 3 +- packages/utils/src/lib/control.ts | 2 +- scripts/deploy-bemo.ts | 120 +++ scripts/{deploy.ts => deploy-dotcom.ts} | 261 ++---- scripts/lib/deploy.ts | 184 +++++ scripts/lib/discord.ts | 70 ++ scripts/package.json | 5 +- .../dev-wrap.ts => scripts/workers/dev.ts | 77 +- yarn.lock | 771 +++++++++--------- 55 files changed, 1278 insertions(+), 719 deletions(-) create mode 100644 .github/workflows/deploy-bemo.yml rename .github/workflows/{deploy.yml => deploy-dotcom.yml} (77%) create mode 100644 apps/bemo-worker/.gitignore create mode 100644 apps/bemo-worker/README.md create mode 100644 apps/bemo-worker/package.json create mode 100644 apps/bemo-worker/src/BemoDO.ts create mode 100644 apps/bemo-worker/src/sentry.ts create mode 100644 apps/bemo-worker/src/types.ts create mode 100644 apps/bemo-worker/src/worker.test.ts create mode 100644 apps/bemo-worker/src/worker.ts create mode 100644 apps/bemo-worker/tsconfig.json create mode 100644 apps/bemo-worker/wrangler.toml delete mode 100644 apps/dotcom-worker/scripts/cron.ts delete mode 100644 apps/dotcom-worker/scripts/report-size.js rename apps/dotcom-worker/src/{lib => }/AlarmScheduler.test.ts (100%) rename apps/dotcom-worker/src/{lib => }/AlarmScheduler.ts (100%) rename apps/dotcom-worker/src/{lib => }/TLDrawDurableObject.ts (97%) rename apps/dotcom-worker/src/{lib => }/config.ts (100%) rename apps/dotcom-worker/src/{lib => }/r2.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/createRoom.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/createRoomSnapshot.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/forwardRoomRequest.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/getReadonlySlug.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/getRoomHistory.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/getRoomHistorySnapshot.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/getRoomSnapshot.ts (100%) rename apps/dotcom-worker/src/{lib => }/routes/joinExistingRoom.ts (100%) rename apps/dotcom-worker/src/{lib => }/types.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/createPersistQueue.test.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/createPersistQueue.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/createSupabaseClient.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/fourOhFour.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/getSnapshotsTable.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/roomIdIsTooLong.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/roomOpenMode.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/throttle.ts (100%) rename apps/dotcom-worker/src/{lib => }/utils/validateSnapshot.ts (100%) rename apps/dotcom-worker/src/{lib => }/worker.ts (95%) create mode 100644 scripts/deploy-bemo.ts rename scripts/{deploy.ts => deploy-dotcom.ts} (64%) create mode 100644 scripts/lib/deploy.ts create mode 100644 scripts/lib/discord.ts rename apps/dotcom-worker/scripts/dev-wrap.ts => scripts/workers/dev.ts (54%) diff --git a/.github/workflows/deploy-bemo.yml b/.github/workflows/deploy-bemo.yml new file mode 100644 index 000000000..8ab34c765 --- /dev/null +++ b/.github/workflows/deploy-bemo.yml @@ -0,0 +1,54 @@ +name: Deploy bemo + +# TODO: add some sort of production trigger +on: + pull_request: + push: + branches: + - main + +env: + CI: 1 + PRINT_GITHUB_ANNOTATIONS: 1 + TLDRAW_ENV: ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} +defaults: + run: + shell: bash + +jobs: + deploy: + name: Deploy bemo to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} + timeout-minutes: 15 + runs-on: ubuntu-latest-16-cores-open + environment: ${{ github.ref == 'refs/heads/production' && 'bemo-production' || 'bemo-canary' }} + concurrency: bemo-${{ github.ref == 'refs/heads/production' && 'production' || github.ref }} + + steps: + - name: Notify initial start + uses: MineBartekSA/discord-webhook@v2 + if: github.ref == 'refs/heads/production' + with: + webhook: ${{ secrets.DISCORD_DEPLOY_WEBHOOK_URL }} + content: 'Preparing ${{ env.TLDRAW_ENV }} bemo deploy: ${{ github.event.head_commit.message }} by ${{ github.event.head_commit.author.name }}' + + - name: Check out code + uses: actions/checkout@v3 + with: + submodules: true + + - uses: ./.github/actions/setup + + - name: Build types + run: yarn build-types + + - name: Deploy + run: yarn tsx scripts/deploy-bemo.ts + env: + RELEASE_COMMIT_HASH: ${{ github.sha }} + GH_TOKEN: ${{ github.token }} + + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + DISCORD_DEPLOY_WEBHOOK_URL: ${{ secrets.DISCORD_DEPLOY_WEBHOOK_URL }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_BEMO_WORKER_DSN: ${{ secrets.SENTRY_BEMO_WORKER_DSN }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy-dotcom.yml similarity index 77% rename from .github/workflows/deploy.yml rename to .github/workflows/deploy-dotcom.yml index 5cb008f6a..473185751 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy-dotcom.yml @@ -1,4 +1,4 @@ -name: Deploy +name: Deploy .com on: pull_request: @@ -17,11 +17,11 @@ defaults: jobs: deploy: - name: Deploy to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} + name: Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} timeout-minutes: 15 runs-on: ubuntu-latest-16-cores-open environment: ${{ github.ref == 'refs/heads/production' && 'deploy-production' || 'deploy-staging' }} - concurrency: ${{ github.ref == 'refs/heads/production' && 'deploy-production' || github.ref }} + concurrency: dotcom-${{ github.ref == 'refs/heads/production' && 'deploy-production' || github.ref }} steps: - name: Notify initial start @@ -29,14 +29,7 @@ jobs: if: github.ref == 'refs/heads/production' with: webhook: ${{ secrets.DISCORD_DEPLOY_WEBHOOK_URL }} - content: 'Preparing ${{ env.TLDRAW_ENV }} deploy: ${{ github.event.head_commit.message }} by ${{ github.event.head_commit.author.name }}' - component: | - { - "type": 2, - "style": 5, - "label": "Open in GitHub", - "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } + content: 'Preparing ${{ env.TLDRAW_ENV }} dotcom deploy: ${{ github.event.head_commit.message }} by ${{ github.event.head_commit.author.name }}' - name: Check out code uses: actions/checkout@v3 @@ -49,7 +42,7 @@ jobs: run: yarn build-types - name: Deploy - run: yarn tsx scripts/deploy.ts + run: yarn tsx scripts/deploy-dotcom.ts env: RELEASE_COMMIT_HASH: ${{ github.sha }} GH_TOKEN: ${{ github.token }} diff --git a/apps/bemo-worker/.gitignore b/apps/bemo-worker/.gitignore new file mode 100644 index 000000000..b3e55cbea --- /dev/null +++ b/apps/bemo-worker/.gitignore @@ -0,0 +1,2 @@ +build +.wrangler \ No newline at end of file diff --git a/apps/bemo-worker/README.md b/apps/bemo-worker/README.md new file mode 100644 index 000000000..f550359bb --- /dev/null +++ b/apps/bemo-worker/README.md @@ -0,0 +1,38 @@ +# bemo-worker + +``` +⠀⠀⠀⠀⠀⠀⢤⡴⠶⠷⠶⠶⠾⠷⠻⠶⠷⠿⠾⠶⠷⠿⠳⠷⠾⠾⠷⠷⠾⠾⠷⠿⠶⠿⠞⠷⠶⠷⢦⣤⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢠⡼⠟⠋⠤⣤⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠛⠻⣤⡤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡧⠀⠁⡀⢀⠉⠙⠠⣄⣀⠀⠀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣀⣘⣛⣧⣤⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⠐⠠⠀⣠⣤⡘⠀⠌⡈⣷⡶⠛⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠙⠉⠋⠛⠋⣶⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡧⢐⣶⣶⠙⠋⠃⣴⣮⠁⣿⠀⠀⠀⠀⢠⣄⣤⣠⣄⣤⣤⣤⣠⣤⣤⣤⣠⣤⣤⣤⣠⣤⣤⣤⣄⣤⣠⣄⣠⡄⠀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡗⢸⠏⢁⡶⣶⡶⠏⠉⡀⣿⠀⠀⠐⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠐⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡧⠰⣿⡾⠁⠉⠀⣾⣿⠄⣿⠀⠀⠂⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡧⠐⠉⡁⣰⣶⡆⠉⠉⠀⣿⠀⠀⡀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠠⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⢈⠐⠀⠀⠉⡀⢀⠁⠂⣿⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠛⣤⡼⠋⠀⠀⠀⠀⠀⠀⠀⠀⠛⢣⣤⠛⠀⠀⠀⢸⡇⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⣏⢠⣷⣾⣾⣤⣠⡀⠂⡁⣿⠀⠀⠈⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠶⣆⣀⣀⣰⠶⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⢀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⢸⣿⣿⣿⢿⣿⡃⠄⡀⣿⠀⠀⠐⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⠸⣟⣿⣻⣿⣿⡄⠀⠄⣿⠀⠀⠠⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣿⠀⠀⠀⠀⠀⠀⣤⣿⣿⣤ +⠀⠀⠀⠀⢸⡗⠰⣿⣿⣿⣿⣾⠂⠄⠂⣿⠀⠀⢀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠈⣿⠀⠀⠀⠀⠀⠀⣿⠀⢸⣯ +⠀⠀⠀⠀⢸⡏⠘⠉⣿⣿⣿⡿⠆⠀⡁⣿⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⣿⠀⠀⠀⠀⠀⠀⣿⠀⢸⣧ +⠀⠀⠀⠀⢸⣇⠨⣿⣿⣿⣿⣿⡁⠂⠄⣿⠀⠀⠂⠸⢧⣠⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⡼⠇⠀⠈⣿⠀⠀⠀⠀⠀⠀⣿⠀⢸⡿ +⠀⠀⠀⠀⢸⡧⠘⠉⠙⠿⠻⠛⠂⢀⠂⣿⠀⠀⢀⠀⠀⢁⢈⡈⣁⢈⡁⣈⢁⡈⢁⠈⠁⠁⠈⠈⠀⠁⠈⠁⠉⠈⠁⠈⠀⠁⠀⠀⠠⣿⣤⠀⠀⠀⠀⠀⣿⡀⣸⣿ +⠀⠀⠀⠀⢸⣇⣠⣢⣷⣶⣶⣦⡑⠀⠄⣿⠀⠀⠀⢰⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⠀⠀⠠⠀⠀⢀⣶⣶⠀⠀⠄⠐⠀⠐⣿⣼⠟⢣⣤⣤⠟⠁⣰⠿⠀ +⠀⣀⣰⣶⠾⠛⠛⠙⠛⠉⣿⣿⡀⠐⡀⣿⠀⠀⠄⠘⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠉⠀⠀⢀⠠⠀⠘⠛⠛⠁⠀⠀⠀⠄⠈⣿⠙⠶⢧⣀⣀⣰⡾⠋⠀⠀ +⣶⠋⠉⣘⣟⢿⣻⣟⡻⠻⠿⣿⠀⠄⡀⣿⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡀⠈⠀⠀⠀⡀⠀⠀⠀⡀⠐⠀⢀⠀⣿⠀⠀⠈⠉⠉⠉⠁⠀⠀⠀ +⠛⣦⣤⣤⣤⣤⣤⣤⣤⣤⠀⢹⣟⠀⡀⣿⠀⠀⠈⢀⣀⣻⡏⠉⣇⣀⡐⠀⠀⠄⠀⠀⠂⠀⢀⠀⣠⡼⠧⣄⠀⣠⣦⠄⠀⢀⠠⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⠠⠐⠠⠀⠛⠛⡀⠄⡀⣿⠀⠀⠠⢼⣇⣀⡀⢀⣀⣸⠇⠀⠀⠀⠀⠂⠀⠠⠀⠘⠛⠒⠒⠚⠻⣿⣂⠼⡇⠀⠀⢀⠠⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⢸⡇⠠⠁⠂⠡⠈⡀⠄⠂⠄⣿⠀⠀⠀⠀⠀⠹⢇⣠⡏⠀⠀⠀⠀⠁⠀⡀⠐⠀⠀⠀⣠⣶⣿⣿⣷⣬⡉⠁⠀⠀⢀⠀⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠸⢷⣄⠂⣁⠂⠡⢀⠐⡈⠀⣿⠀⠀⠈⠀⠀⢂⣀⡠⠀⠀⠐⠀⠁⡀⠄⠀⠀⠀⠐⠀⣿⣿⣿⣿⣷⣿⡇⠀⠀⠠⠀⠀⠠⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠘⢳⣤⡄⢁⠂⠐⡀⠁⣿⠀⠀⢀⠘⠛⠛⠛⠃⠀⠘⠛⠛⠛⠛⠀⠀⠀⠁⠀⠀⠈⠻⠿⠿⠿⠋⠀⠀⢀⠀⠀⠐⠀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠛⡶⢦⣀⣄⣿⠀⠀⡀⠀⠠⠀⠀⠀⡀⠀⢀⠀⢀⠀⠀⡀⠂⠀⠈⠀⡀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠈⠀⢀⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠘⠛⢻⣿⣤⡀⣁⣀⡀⣀⢂⣀⣁⣀⣈⡀⣈⣀⣀⣁⣀⡐⣀⣀⢁⡀⣂⢀⣀⢂⣀⣀⢀⢂⣀⣠⣼⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠛⠛⠛⠛⢻⣿⣻⣿⣛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⠛⣻⣟⣿⣿⣿⡛⠛⠛⠛⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⡿⣿⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣻⣿⣿⣿⣯⣷⡗⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⣿⢻⣧⠀⠀⠀⠀⠀⠀⠀⠀⢰⡞⣿⣿⡶⣯⣽⡿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠘⠛⠛⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣏⣿⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣶⡟⢩⣟⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠿⣧⣾⣿⣶⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +``` diff --git a/apps/bemo-worker/package.json b/apps/bemo-worker/package.json new file mode 100644 index 000000000..69acab7b0 --- /dev/null +++ b/apps/bemo-worker/package.json @@ -0,0 +1,49 @@ +{ + "name": "@tldraw/bemo-worker", + "description": "A tiny little drawing app (merge server).", + "version": "2.0.0-alpha.11", + "private": true, + "author": { + "name": "tldraw GB Ltd.", + "email": "hello@tldraw.com" + }, + "main": "./src/worker.ts", + "/* GOTCHA */": "files will include ./dist and index.d.ts by default, add any others you want to include in here", + "files": [], + "scripts": { + "dev": "yarn run -T tsx ../../scripts/workers/dev.ts", + "test-ci": "lazy inherit", + "test": "yarn run -T jest", + "test-coverage": "lazy inherit", + "check-bundle-size": "yarn run -T tsx ../../scripts/check-worker-bundle.ts --entry src/worker.ts --size-limit-bytes 350000", + "lint": "yarn run -T tsx ../../scripts/lint.ts" + }, + "dependencies": { + "@tldraw/dotcom-shared": "workspace:*", + "@tldraw/store": "workspace:*", + "@tldraw/tlschema": "workspace:*", + "@tldraw/tlsync": "workspace:*", + "@tldraw/utils": "workspace:*", + "itty-router": "^4.0.13", + "nanoid": "4.0.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "toucan-js": "^3.4.0" + }, + "devDependencies": { + "@cloudflare/workers-types": "^4.20240620.0", + "esbuild": "^0.21.5", + "lazyrepo": "0.0.0-alpha.27", + "typescript": "^5.3.3", + "wrangler": "3.62.0" + }, + "jest": { + "preset": "config/jest/node", + "moduleNameMapper": { + "^~(.*)": "/src/$1" + }, + "transformIgnorePatterns": [ + "node_modules/(?!(nanoid|escape-string-regexp)/)" + ] + } +} diff --git a/apps/bemo-worker/src/BemoDO.ts b/apps/bemo-worker/src/BemoDO.ts new file mode 100644 index 000000000..3a70c7f52 --- /dev/null +++ b/apps/bemo-worker/src/BemoDO.ts @@ -0,0 +1,38 @@ +import { DurableObject } from 'cloudflare:workers' +import { Router } from 'itty-router' +import { createSentry } from './sentry' +import { Environment } from './types' + +export class BemoDO extends DurableObject { + private reportError(e: unknown, request?: Request) { + const sentry = createSentry(this.ctx, this.env, request) + console.error(e) + // eslint-disable-next-line deprecation/deprecation + sentry.captureException(e) + } + + private readonly router = Router() + .get('/do', async () => { + return Response.json({ message: 'Hello from a durable object!' }) + }) + .get('/do/error', async () => { + this.doAnError() + }) + .all('*', async () => new Response('Not found', { status: 404 })) + + private doAnError() { + throw new Error('this is an error from a DO') + } + + override async fetch(request: Request>): Promise { + try { + return await this.router.handle(request) + } catch (error) { + this.reportError(error, request) + return new Response('Something went wrong', { + status: 500, + statusText: 'Internal Server Error', + }) + } + } +} diff --git a/apps/bemo-worker/src/sentry.ts b/apps/bemo-worker/src/sentry.ts new file mode 100644 index 000000000..88c7b16db --- /dev/null +++ b/apps/bemo-worker/src/sentry.ts @@ -0,0 +1,21 @@ +import { Toucan } from 'toucan-js' +import { Environment } from './types' + +interface Context { + waitUntil: ExecutionContext['waitUntil'] + request?: Request +} + +export function createSentry(ctx: Context, env: Environment, request?: Request) { + return new Toucan({ + dsn: env.SENTRY_DSN, + release: `${env.WORKER_NAME}.${env.CF_VERSION_METADATA.id}`, + environment: env.WORKER_NAME, + context: ctx, + request, + requestDataOptions: { + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + }, + }) +} diff --git a/apps/bemo-worker/src/types.ts b/apps/bemo-worker/src/types.ts new file mode 100644 index 000000000..76dc293db --- /dev/null +++ b/apps/bemo-worker/src/types.ts @@ -0,0 +1,12 @@ +import { BemoDO } from './BemoDO' + +export interface Environment { + // bindings + BEMO_DO: DurableObjectNamespace + + TLDRAW_ENV: string | undefined + SENTRY_DSN: string | undefined + IS_LOCAL: string | undefined + WORKER_NAME: string | undefined + CF_VERSION_METADATA: WorkerVersionMetadata +} diff --git a/apps/bemo-worker/src/worker.test.ts b/apps/bemo-worker/src/worker.test.ts new file mode 100644 index 000000000..c5621e357 --- /dev/null +++ b/apps/bemo-worker/src/worker.test.ts @@ -0,0 +1,5 @@ +describe('worker', () => { + it('works', () => { + // blank test to make ci happy + }) +}) diff --git a/apps/bemo-worker/src/worker.ts b/apps/bemo-worker/src/worker.ts new file mode 100644 index 000000000..eba42f694 --- /dev/null +++ b/apps/bemo-worker/src/worker.ts @@ -0,0 +1,37 @@ +/// +/// + +import { WorkerEntrypoint } from 'cloudflare:workers' +import { Router, createCors } from 'itty-router' +import { createSentry } from './sentry' +import { Environment } from './types' + +export { BemoDO } from './BemoDO' + +const cors = createCors({ origins: ['*'] }) + +export default class Worker extends WorkerEntrypoint { + private readonly router = Router() + .all('*', cors.preflight) + .get('/do', async (request) => { + const bemo = this.env.BEMO_DO.get(this.env.BEMO_DO.idFromName('bemo-do')) + const message = await (await bemo.fetch(request)).json() + return Response.json(message) + }) + .all('*', async () => new Response('Not found', { status: 404 })) + + override async fetch(request: Request): Promise { + try { + return await this.router.handle(request).then(cors.corsify) + } catch (error) { + const sentry = createSentry(this.ctx, this.env, request) + console.error(error) + // eslint-disable-next-line deprecation/deprecation + sentry.captureException(error) + return new Response('Something went wrong', { + status: 500, + statusText: 'Internal Server Error', + }) + } + } +} diff --git a/apps/bemo-worker/tsconfig.json b/apps/bemo-worker/tsconfig.json new file mode 100644 index 000000000..e7a2d4918 --- /dev/null +++ b/apps/bemo-worker/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../config/tsconfig.base.json", + "include": ["src", "scripts"], + "exclude": ["node_modules", "dist", ".tsbuild*"], + "compilerOptions": { + "noEmit": true, + "emitDeclarationOnly": false + }, + "references": [ + { + "path": "../../packages/dotcom-shared" + }, + { + "path": "../../packages/store" + }, + { + "path": "../../packages/tlschema" + }, + { + "path": "../../packages/tlsync" + }, + { + "path": "../../packages/utils" + } + ] +} diff --git a/apps/bemo-worker/wrangler.toml b/apps/bemo-worker/wrangler.toml new file mode 100644 index 000000000..c5fdc8e2b --- /dev/null +++ b/apps/bemo-worker/wrangler.toml @@ -0,0 +1,79 @@ +main = "src/worker.ts" +compatibility_date = "2024-06-25" +upload_source_maps = true + +[dev] +port = 8989 +ip = "0.0.0.0" + +# these migrations are append-only. you can't change them. if you do need to change something, do so +# by creating new migrations +[[migrations]] +tag = "v1" # Should be unique for each entry +new_classes = ["BemoDO"] + + +#################### Environment names #################### +# dev should never actually get deployed anywhere +[env.dev] +name = "dev-bemo" + +# we don't have a hard-coded name for preview. we instead have to generate it at build time and append it to this file. + +# staging is the same as a preview on main: +[env.staging] +name = "canary-bemo" +routes = [ + { pattern = "canary-demo.tldraw.xyz", custom_domain = true } +] + +# production gets the proper name +[env.production] +name = "production-bemo" +routes = [ + { pattern = "demo.tldraw.xyz", custom_domain = true } +] + +#################### Durable objects #################### +# durable objects have the same configuration in all environments: + +[durable_objects] +bindings = [ + { name = "BEMO_DO", class_name = "BemoDO" }, +] + +[env.dev.durable_objects] +bindings = [ + { name = "BEMO_DO", class_name = "BemoDO" }, +] + +[env.preview.durable_objects] +bindings = [ + { name = "BEMO_DO", class_name = "BemoDO" }, +] + +[env.staging.durable_objects] +bindings = [ + { name = "BEMO_DO", class_name = "BemoDO" }, +] + +[env.production.durable_objects] +bindings = [ + { name = "BEMO_DO", class_name = "BemoDO" }, +] + +#################### Version metadata #################### +[version_metadata] +binding = "CF_VERSION_METADATA" + +[env.dev.version_metadata] +binding = "CF_VERSION_METADATA" + +[env.preview.version_metadata] +binding = "CF_VERSION_METADATA" + +[env.staging.version_metadata] +binding = "CF_VERSION_METADATA" + +[env.production.version_metadata] +binding = "CF_VERSION_METADATA" \ No newline at end of file diff --git a/apps/dotcom-asset-upload/package.json b/apps/dotcom-asset-upload/package.json index 1265c3f59..f8f7fd106 100644 --- a/apps/dotcom-asset-upload/package.json +++ b/apps/dotcom-asset-upload/package.json @@ -23,7 +23,7 @@ "@cloudflare/workers-types": "^4.20240620.0", "@types/ws": "^8.5.9", "lazyrepo": "0.0.0-alpha.27", - "wrangler": "3.61.0" + "wrangler": "3.62.0" }, "jest": { "preset": "config/jest/node", diff --git a/apps/dotcom-asset-upload/wrangler.toml b/apps/dotcom-asset-upload/wrangler.toml index 8679d676d..dca7a8331 100644 --- a/apps/dotcom-asset-upload/wrangler.toml +++ b/apps/dotcom-asset-upload/wrangler.toml @@ -26,6 +26,9 @@ preview_bucket_name = 'uploads-preview' type = "analytics_engine" name = "MEASURE" +[[env.staging.analytics_engine_datasets]] +binding = "MEASURE" + # production settings [env.production] @@ -45,7 +48,13 @@ preview_bucket_name = 'uploads-preview' type = "analytics_engine" name = "MEASURE" +[[env.production.analytics_engine_datasets]] +binding = "MEASURE" + [[env.preview.r2_buckets]] binding = 'UPLOADS' bucket_name = 'uploads' -preview_bucket_name = 'uploads-preview' \ No newline at end of file +preview_bucket_name = 'uploads-preview' + +[[env.preview.analytics_engine_datasets]] +binding = "MEASURE" \ No newline at end of file diff --git a/apps/dotcom-worker/package.json b/apps/dotcom-worker/package.json index 5f8500ede..91df18265 100644 --- a/apps/dotcom-worker/package.json +++ b/apps/dotcom-worker/package.json @@ -7,18 +7,15 @@ "name": "tldraw GB Ltd.", "email": "hello@tldraw.com" }, - "main": "./src/lib/worker.ts", + "main": "./src/worker.ts", "/* GOTCHA */": "files will include ./dist and index.d.ts by default, add any others you want to include in here", "files": [], "scripts": { - "dev": "concurrently --kill-others yarn:dev-cron yarn:dev-wrangler yarn:report-size", - "dev-cron": "yarn run -T tsx ./scripts/cron.ts", - "dev-wrangler": "yarn run -T tsx ./scripts/dev-wrap.ts", - "report-size": "node scripts/report-size.js", + "dev": "yarn run -T tsx ../../scripts/workers/dev.ts", "test-ci": "lazy inherit", "test": "yarn run -T jest", "test-coverage": "lazy inherit", - "check-bundle-size": "yarn run -T tsx ../../scripts/check-worker-bundle.ts --entry src/lib/worker.ts --size-limit-bytes 350000", + "check-bundle-size": "yarn run -T tsx ../../scripts/check-worker-bundle.ts --entry src/worker.ts --size-limit-bytes 350000", "lint": "yarn run -T tsx ../../scripts/lint.ts" }, "dependencies": { @@ -29,21 +26,18 @@ "@tldraw/tlschema": "workspace:*", "@tldraw/tlsync": "workspace:*", "@tldraw/utils": "workspace:*", - "esbuild": "^0.18.4", "itty-router": "^4.0.13", "nanoid": "4.0.2", "react": "^18.2.0", "react-dom": "^18.2.0", - "strip-ansi": "^7.1.0", - "toucan-js": "^2.7.0" + "toucan-js": "^3.4.0" }, "devDependencies": { "@cloudflare/workers-types": "^4.20240620.0", - "concurrently": "^8.2.2", + "esbuild": "^0.21.5", "lazyrepo": "0.0.0-alpha.27", - "picocolors": "^1.0.0", "typescript": "^5.3.3", - "wrangler": "3.61.0" + "wrangler": "3.62.0" }, "jest": { "preset": "config/jest/node", diff --git a/apps/dotcom-worker/scripts/cron.ts b/apps/dotcom-worker/scripts/cron.ts deleted file mode 100644 index 417c32eb5..000000000 --- a/apps/dotcom-worker/scripts/cron.ts +++ /dev/null @@ -1,10 +0,0 @@ -const CRON_INTERVAL_MS = 10_000 - -setInterval(async () => { - try { - await fetch('http://127.0.0.1:8787/__scheduled') - } catch (err) { - // eslint-disable-next-line no-console - console.log('Error triggering cron:', err) - } -}, CRON_INTERVAL_MS) diff --git a/apps/dotcom-worker/scripts/report-size.js b/apps/dotcom-worker/scripts/report-size.js deleted file mode 100644 index 1378231eb..000000000 --- a/apps/dotcom-worker/scripts/report-size.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable no-undef */ -/* eslint-disable @typescript-eslint/no-var-requires */ -const { spawn } = require('child_process') -const colors = require('picocolors') - -class Monitor { - lastLineTime = Date.now() - nextTick = 0 - - size = 0 - - start() { - console.log('Spawning') - const proc = spawn('npx', ['esbuild', 'src/lib/worker.ts', '--bundle', '--minify', '--watch']) - // listen for lines on stdin - proc.stdout.on('data', (data) => { - this.size += data.length - this.lastLineTime = Date.now() - clearTimeout(this.nextTick) - this.nextTick = setTimeout(() => { - console.log( - colors.bold(colors.yellow('dotcom-worker')), - 'is roughly', - colors.bold(colors.cyan(Math.floor(this.size / 1024) + 'kb')), - '(minified)\n' - ) - this.size = 0 - }, 10) - }) - process.on('SIGINT', () => { - console.log('Int') - proc.kill() - }) - process.on('SIGTERM', () => { - console.log('Term') - proc.kill() - }) - process.on('exit', () => { - console.log('Exiting') - proc.kill() - }) - } -} - -new Monitor().start() diff --git a/apps/dotcom-worker/src/lib/AlarmScheduler.test.ts b/apps/dotcom-worker/src/AlarmScheduler.test.ts similarity index 100% rename from apps/dotcom-worker/src/lib/AlarmScheduler.test.ts rename to apps/dotcom-worker/src/AlarmScheduler.test.ts diff --git a/apps/dotcom-worker/src/lib/AlarmScheduler.ts b/apps/dotcom-worker/src/AlarmScheduler.ts similarity index 100% rename from apps/dotcom-worker/src/lib/AlarmScheduler.ts rename to apps/dotcom-worker/src/AlarmScheduler.ts diff --git a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts b/apps/dotcom-worker/src/TLDrawDurableObject.ts similarity index 97% rename from apps/dotcom-worker/src/lib/TLDrawDurableObject.ts rename to apps/dotcom-worker/src/TLDrawDurableObject.ts index 13cce46ac..ff5ac08ec 100644 --- a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts +++ b/apps/dotcom-worker/src/TLDrawDurableObject.ts @@ -18,7 +18,7 @@ import { } from '@tldraw/tlsync' import { assert, assertExists, exhaustiveSwitchError } from '@tldraw/utils' import { IRequest, Router } from 'itty-router' -import Toucan from 'toucan-js' +import { Toucan } from 'toucan-js' import { AlarmScheduler } from './AlarmScheduler' import { PERSIST_INTERVAL_MS } from './config' import { getR2KeyForRoom } from './r2' @@ -218,21 +218,17 @@ export class TLDrawDurableObject { const sentry = new Toucan({ dsn: this.sentryDSN, request: req, - allowedHeaders: ['user-agent'], - allowedSearchParams: /(.*)/, + requestDataOptions: { + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + }, }) try { - return await this.router.handle(req).catch((err) => { - console.error(err) - sentry.captureException(err) - - return new Response('Something went wrong', { - status: 500, - statusText: 'Internal Server Error', - }) - }) + return await this.router.handle(req) } catch (err) { + console.error(err) + // eslint-disable-next-line deprecation/deprecation sentry.captureException(err) return new Response('Something went wrong', { status: 500, diff --git a/apps/dotcom-worker/src/lib/config.ts b/apps/dotcom-worker/src/config.ts similarity index 100% rename from apps/dotcom-worker/src/lib/config.ts rename to apps/dotcom-worker/src/config.ts diff --git a/apps/dotcom-worker/src/lib/r2.ts b/apps/dotcom-worker/src/r2.ts similarity index 100% rename from apps/dotcom-worker/src/lib/r2.ts rename to apps/dotcom-worker/src/r2.ts diff --git a/apps/dotcom-worker/src/lib/routes/createRoom.ts b/apps/dotcom-worker/src/routes/createRoom.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/createRoom.ts rename to apps/dotcom-worker/src/routes/createRoom.ts diff --git a/apps/dotcom-worker/src/lib/routes/createRoomSnapshot.ts b/apps/dotcom-worker/src/routes/createRoomSnapshot.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/createRoomSnapshot.ts rename to apps/dotcom-worker/src/routes/createRoomSnapshot.ts diff --git a/apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts b/apps/dotcom-worker/src/routes/forwardRoomRequest.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts rename to apps/dotcom-worker/src/routes/forwardRoomRequest.ts diff --git a/apps/dotcom-worker/src/lib/routes/getReadonlySlug.ts b/apps/dotcom-worker/src/routes/getReadonlySlug.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/getReadonlySlug.ts rename to apps/dotcom-worker/src/routes/getReadonlySlug.ts diff --git a/apps/dotcom-worker/src/lib/routes/getRoomHistory.ts b/apps/dotcom-worker/src/routes/getRoomHistory.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/getRoomHistory.ts rename to apps/dotcom-worker/src/routes/getRoomHistory.ts diff --git a/apps/dotcom-worker/src/lib/routes/getRoomHistorySnapshot.ts b/apps/dotcom-worker/src/routes/getRoomHistorySnapshot.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/getRoomHistorySnapshot.ts rename to apps/dotcom-worker/src/routes/getRoomHistorySnapshot.ts diff --git a/apps/dotcom-worker/src/lib/routes/getRoomSnapshot.ts b/apps/dotcom-worker/src/routes/getRoomSnapshot.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/getRoomSnapshot.ts rename to apps/dotcom-worker/src/routes/getRoomSnapshot.ts diff --git a/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts b/apps/dotcom-worker/src/routes/joinExistingRoom.ts similarity index 100% rename from apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts rename to apps/dotcom-worker/src/routes/joinExistingRoom.ts diff --git a/apps/dotcom-worker/src/lib/types.ts b/apps/dotcom-worker/src/types.ts similarity index 100% rename from apps/dotcom-worker/src/lib/types.ts rename to apps/dotcom-worker/src/types.ts diff --git a/apps/dotcom-worker/src/lib/utils/createPersistQueue.test.ts b/apps/dotcom-worker/src/utils/createPersistQueue.test.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/createPersistQueue.test.ts rename to apps/dotcom-worker/src/utils/createPersistQueue.test.ts diff --git a/apps/dotcom-worker/src/lib/utils/createPersistQueue.ts b/apps/dotcom-worker/src/utils/createPersistQueue.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/createPersistQueue.ts rename to apps/dotcom-worker/src/utils/createPersistQueue.ts diff --git a/apps/dotcom-worker/src/lib/utils/createSupabaseClient.ts b/apps/dotcom-worker/src/utils/createSupabaseClient.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/createSupabaseClient.ts rename to apps/dotcom-worker/src/utils/createSupabaseClient.ts diff --git a/apps/dotcom-worker/src/lib/utils/fourOhFour.ts b/apps/dotcom-worker/src/utils/fourOhFour.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/fourOhFour.ts rename to apps/dotcom-worker/src/utils/fourOhFour.ts diff --git a/apps/dotcom-worker/src/lib/utils/getSnapshotsTable.ts b/apps/dotcom-worker/src/utils/getSnapshotsTable.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/getSnapshotsTable.ts rename to apps/dotcom-worker/src/utils/getSnapshotsTable.ts diff --git a/apps/dotcom-worker/src/lib/utils/roomIdIsTooLong.ts b/apps/dotcom-worker/src/utils/roomIdIsTooLong.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/roomIdIsTooLong.ts rename to apps/dotcom-worker/src/utils/roomIdIsTooLong.ts diff --git a/apps/dotcom-worker/src/lib/utils/roomOpenMode.ts b/apps/dotcom-worker/src/utils/roomOpenMode.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/roomOpenMode.ts rename to apps/dotcom-worker/src/utils/roomOpenMode.ts diff --git a/apps/dotcom-worker/src/lib/utils/throttle.ts b/apps/dotcom-worker/src/utils/throttle.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/throttle.ts rename to apps/dotcom-worker/src/utils/throttle.ts diff --git a/apps/dotcom-worker/src/lib/utils/validateSnapshot.ts b/apps/dotcom-worker/src/utils/validateSnapshot.ts similarity index 100% rename from apps/dotcom-worker/src/lib/utils/validateSnapshot.ts rename to apps/dotcom-worker/src/utils/validateSnapshot.ts diff --git a/apps/dotcom-worker/src/lib/worker.ts b/apps/dotcom-worker/src/worker.ts similarity index 95% rename from apps/dotcom-worker/src/lib/worker.ts rename to apps/dotcom-worker/src/worker.ts index 8fc45cb0b..90a20c7c3 100644 --- a/apps/dotcom-worker/src/lib/worker.ts +++ b/apps/dotcom-worker/src/worker.ts @@ -7,7 +7,7 @@ import { ROOM_PREFIX, } from '@tldraw/dotcom-shared' import { Router, createCors } from 'itty-router' -import Toucan from 'toucan-js' +import { Toucan } from 'toucan-js' import { createRoom } from './routes/createRoom' import { createRoomSnapshot } from './routes/createRoomSnapshot' import { forwardRoomRequest } from './routes/forwardRoomRequest' @@ -51,14 +51,17 @@ const Worker = { dsn: env.SENTRY_DSN, context, // Includes 'waitUntil', which is essential for Sentry logs to be delivered. Modules workers do not include 'request' in context -- you'll need to set it separately. request, // request is not included in 'context', so we set it here. - allowedHeaders: ['user-agent'], - allowedSearchParams: /(.*)/, + requestDataOptions: { + allowedHeaders: ['user-agent'], + allowedSearchParams: /(.*)/, + }, }) return router .handle(request, env, context) .catch((err) => { console.error(err) + // eslint-disable-next-line deprecation/deprecation sentry.captureException(err) return new Response('Something went wrong', { diff --git a/apps/dotcom-worker/wrangler.toml b/apps/dotcom-worker/wrangler.toml index d82806060..9fd7c39ff 100644 --- a/apps/dotcom-worker/wrangler.toml +++ b/apps/dotcom-worker/wrangler.toml @@ -1,4 +1,4 @@ -main = "src/lib/worker.ts" +main = "src/worker.ts" compatibility_date = "2024-06-19" [dev] diff --git a/apps/dotcom/sentry.client.config.ts b/apps/dotcom/sentry.client.config.ts index 5c058dda6..fdbdc2ec0 100644 --- a/apps/dotcom/sentry.client.config.ts +++ b/apps/dotcom/sentry.client.config.ts @@ -22,6 +22,7 @@ Sentry.init({ tracesSampleRate: 1.0, release: sentryReleaseName, environment: env, + // eslint-disable-next-line deprecation/deprecation integrations: [new ExtraErrorData({ depth: 10 }) as any], // ... // Note: if you want to override the automatic release value, do not set a diff --git a/apps/health-worker/package.json b/apps/health-worker/package.json index bc731e62c..b71d47e74 100644 --- a/apps/health-worker/package.json +++ b/apps/health-worker/package.json @@ -16,8 +16,8 @@ "@cloudflare/workers-types": "^4.20240620.0", "@types/node": "~20.11", "discord-api-types": "^0.37.67", - "esbuild": "^0.18.4", + "esbuild": "^0.21.5", "typescript": "^5.3.3", - "wrangler": "3.61.0" + "wrangler": "3.62.0" } } diff --git a/apps/vscode/editor/package.json b/apps/vscode/editor/package.json index 5037fb3a1..b9f430e16 100644 --- a/apps/vscode/editor/package.json +++ b/apps/vscode/editor/package.json @@ -41,7 +41,7 @@ "concurrently": "^8.2.2", "create-serve": "1.0.1", "dotenv": "^16.3.1", - "esbuild": "^0.18.4", + "esbuild": "^0.21.5", "fs-extra": "^11.1.0", "lazyrepo": "0.0.0-alpha.27", "react": "^18.2.0", diff --git a/apps/vscode/extension/package.json b/apps/vscode/extension/package.json index e1dcf6423..662fa18b4 100644 --- a/apps/vscode/extension/package.json +++ b/apps/vscode/extension/package.json @@ -137,7 +137,7 @@ "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "assert": "^2.0.0", - "esbuild": "^0.18.4", + "esbuild": "^0.21.5", "eslint": "^8.37.0", "fs-extra": "^11.1.0", "lazyrepo": "0.0.0-alpha.27", diff --git a/package.json b/package.json index 7e35f74d5..2ceb30899 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "clean": "scripts/clean.sh", "postinstall": "husky install && yarn refresh-assets", "refresh-assets": "lazy refresh-assets", - "dev": "LAZYREPO_PRETTY_OUTPUT=0 lazy run dev --filter='apps/examples' --filter='packages/tldraw'", + "dev": "LAZYREPO_PRETTY_OUTPUT=0 lazy run dev --filter='apps/examples' --filter='packages/tldraw' --filter='apps/bemo-worker'", "dev-vscode": "code ./apps/vscode/extension && lazy run dev --filter='apps/vscode/{extension,editor}'", "dev-app": "LAZYREPO_PRETTY_OUTPUT=0 lazy run dev --filter='apps/{dotcom,dotcom-asset-upload,dotcom-worker}' --filter='packages/tldraw'", "dev-docs": "LAZYREPO_PRETTY_OUTPUT=0 lazy run dev --filter='apps/docs'", @@ -120,6 +120,7 @@ "@sentry/cli": "^2.25.0", "@yarnpkg/types": "^4.0.0", "cross-env": "^7.0.3", + "esbuild": "^0.21.5", "mime": "^4.0.3", "purgecss": "^5.0.0", "svgo": "^3.0.2" diff --git a/packages/utils/src/lib/control.ts b/packages/utils/src/lib/control.ts index 1033671b5..a7823d56a 100644 --- a/packages/utils/src/lib/control.ts +++ b/packages/utils/src/lib/control.ts @@ -41,7 +41,7 @@ export const assert: (value: unknown, message?: string) => asserts value = omitF /** @internal */ export const assertExists = omitFromStackTrace((value: T, message?: string): NonNullable => { - // note that value == null is equivilent to value === null || value === undefined + // note that value == null is equivalent to value === null || value === undefined if (value == null) { throw new Error(message ?? 'value must be defined') } diff --git a/scripts/deploy-bemo.ts b/scripts/deploy-bemo.ts new file mode 100644 index 000000000..baa3ca4cd --- /dev/null +++ b/scripts/deploy-bemo.ts @@ -0,0 +1,120 @@ +import assert from 'assert' +import { readFileSync } from 'fs' +import path, { join } from 'path' +import toml from 'toml' +import { + createGithubDeployment, + getDeployInfo, + setWranglerPreviewConfig, + wranglerDeploy, +} from './lib/deploy' +import { Discord } from './lib/discord' +import { exec } from './lib/exec' +import { makeEnv } from './lib/makeEnv' +import { nicelog } from './lib/nicelog' + +const workerDir = path.relative(process.cwd(), path.resolve(__dirname, '../apps/bemo-worker')) + +// Do not use `process.env` directly in this script. Add your variable to `makeEnv` and use it via +// `env` instead. This makes sure that all required env vars are present. +const env = makeEnv([ + 'CLOUDFLARE_ACCOUNT_ID', + 'CLOUDFLARE_API_TOKEN', + 'DISCORD_DEPLOY_WEBHOOK_URL', + 'RELEASE_COMMIT_HASH', + 'TLDRAW_ENV', + 'GH_TOKEN', + 'SENTRY_AUTH_TOKEN', + 'SENTRY_BEMO_WORKER_DSN', +]) + +const discord = new Discord({ + webhookUrl: env.DISCORD_DEPLOY_WEBHOOK_URL, + shouldNotify: env.TLDRAW_ENV === 'production', + totalSteps: 3, +}) + +const { previewId, sha } = getDeployInfo() + +async function main() { + assert( + env.TLDRAW_ENV === 'staging' || env.TLDRAW_ENV === 'production' || env.TLDRAW_ENV === 'preview', + 'TLDRAW_ENV must be staging or production or preview' + ) + + await discord.message(`--- **${env.TLDRAW_ENV} bemo deploy pre-flight** ---`) + + await discord.step('setting up deploy', async () => { + await exec('yarn', ['lazy', 'prebuild']) + }) + + await discord.step('cloudflare deploy dry run', async () => { + await deployBemoWorker({ dryRun: true }) + }) + + // --- point of no return! do the deploy for real --- // + + await discord.message(`--- **pre-flight complete, starting real bemo deploy** ---`) + + // 2. deploy the cloudflare workers: + await discord.step('deploying bemo-worker to cloudflare', async () => { + await deployBemoWorker({ dryRun: false }) + }) + + // we set the domain in the wrangler.toml file since it's managed by cloudflare + const domain = toml.parse(readFileSync(join(workerDir, 'wrangler.toml')).toString())?.env[ + env.TLDRAW_ENV + ]?.routes?.[0]?.pattern + if (!domain) { + throw new Error('Could not find the domain in wrangler.toml') + } + + const deploymentUrl = `https://${domain}` + + nicelog('Creating deployment for', deploymentUrl) + await createGithubDeployment(env, { + app: 'bemo', + deploymentUrl, + sha, + }) + + await discord.message(`**Deploy complete!**`) +} + +let didUpdateBemoWorker = false +async function deployBemoWorker({ dryRun }: { dryRun: boolean }) { + const workerId = `${previewId ?? env.TLDRAW_ENV}-bemo` + if (previewId && !didUpdateBemoWorker) { + await setWranglerPreviewConfig(workerDir, { + name: workerId, + customDomain: `${previewId}-demo.tldraw.xyz`, + }) + didUpdateBemoWorker = true + } + + await wranglerDeploy({ + location: workerDir, + dryRun, + env: env.TLDRAW_ENV, + vars: { + WORKER_NAME: workerId, + TLDRAW_ENV: env.TLDRAW_ENV, + SENTRY_DSN: env.SENTRY_BEMO_WORKER_DSN, + }, + sentry: { + authToken: env.SENTRY_AUTH_TOKEN, + project: 'bemo-worker', + }, + }) +} + +main().catch(async (err) => { + // don't notify discord on preview builds + if (env.TLDRAW_ENV !== 'preview') { + await discord.message(`${Discord.AT_TEAM_MENTION} Deploy failed: ${err.stack}`, { + always: true, + }) + } + console.error(err) + process.exit(1) +}) diff --git a/scripts/deploy.ts b/scripts/deploy-dotcom.ts similarity index 64% rename from scripts/deploy.ts rename to scripts/deploy-dotcom.ts index 0920c5c4e..ff5f3e933 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy-dotcom.ts @@ -1,12 +1,18 @@ -import * as github from '@actions/github' import { GetObjectCommand, ListObjectsV2Command, S3Client } from '@aws-sdk/client-s3' import { Upload } from '@aws-sdk/lib-storage' import assert from 'assert' import { execSync } from 'child_process' -import { appendFileSync, existsSync, readdirSync, writeFileSync } from 'fs' -import path, { join } from 'path' +import { existsSync, readdirSync, writeFileSync } from 'fs' +import path from 'path' import { PassThrough } from 'stream' import * as tar from 'tar' +import { + createGithubDeployment, + getDeployInfo, + setWranglerPreviewConfig, + wranglerDeploy, +} from './lib/deploy' +import { Discord } from './lib/discord' import { exec } from './lib/exec' import { makeEnv } from './lib/makeEnv' import { nicelog } from './lib/nicelog' @@ -48,26 +54,13 @@ const env = makeEnv([ 'R2_ACCESS_KEY_SECRET', ]) -const githubPrNumber = process.env.GITHUB_REF?.match(/refs\/pull\/(\d+)\/merge/)?.[1] -function getPreviewId() { - if (env.TLDRAW_ENV !== 'preview') return undefined - if (githubPrNumber) return `pr-${githubPrNumber}` - return process.env.TLDRAW_PREVIEW_ID ?? undefined -} -const previewId = getPreviewId() - -if (env.TLDRAW_ENV === 'preview' && !previewId) { - throw new Error( - 'If running preview deploys from outside of a PR action, TLDRAW_PREVIEW_ID env var must be set' - ) -} -const sha = - // if the event is 'pull_request', github.context.sha is an ephemeral merge commit - // while the actual commit we want to create the deployment for is the 'head' of the PR. - github.context.eventName === 'pull_request' - ? github.context.payload.pull_request?.head.sha - : github.context.sha +const discord = new Discord({ + webhookUrl: env.DISCORD_DEPLOY_WEBHOOK_URL, + shouldNotify: env.TLDRAW_ENV === 'production', + totalSteps: 8, +}) +const { previewId, sha } = getDeployInfo() const sentryReleaseName = `${env.TLDRAW_ENV}-${previewId ? previewId + '-' : ''}-${sha}` async function main() { @@ -76,9 +69,9 @@ async function main() { 'TLDRAW_ENV must be staging or production or preview' ) - await discordMessage(`--- **${env.TLDRAW_ENV} deploy pre-flight** ---`) + await discord.message(`--- **${env.TLDRAW_ENV} dotcom deploy pre-flight** ---`) - await discordStep('[1/7] setting up deploy', async () => { + await discord.step('setting up deploy', async () => { // make sure the tldraw .css files are built: await exec('yarn', ['lazy', 'prebuild']) @@ -88,14 +81,14 @@ async function main() { // deploy pre-flight steps: // 1. get the dotcom app ready to go (env vars and pre-build) - await discordStep('[2/7] building dotcom app', async () => { + await discord.step('building dotcom app', async () => { await createSentryRelease() await prepareDotcomApp() await uploadSourceMaps() await coalesceWithPreviousAssets(`${dotcom}/.vercel/output/static/assets`) }) - await discordStep('[3/7] cloudflare deploy dry run', async () => { + await discord.step('cloudflare deploy dry run', async () => { await deployAssetUploadWorker({ dryRun: true }) await deployHealthWorker({ dryRun: true }) await deployTlsyncWorker({ dryRun: true }) @@ -103,22 +96,22 @@ async function main() { // --- point of no return! do the deploy for real --- // - await discordMessage(`--- **pre-flight complete, starting real deploy** ---`) + await discord.message(`--- **pre-flight complete, starting real dotcom deploy** ---`) // 2. deploy the cloudflare workers: - await discordStep('[4/7] deploying asset uploader to cloudflare', async () => { + await discord.step('deploying asset uploader to cloudflare', async () => { await deployAssetUploadWorker({ dryRun: false }) }) - await discordStep('[5/7] deploying multiplayer worker to cloudflare', async () => { + await discord.step('deploying multiplayer worker to cloudflare', async () => { await deployTlsyncWorker({ dryRun: false }) }) - await discordStep('[6/7] deploying health worker to cloudflare', async () => { + await discord.step('deploying health worker to cloudflare', async () => { await deployHealthWorker({ dryRun: false }) }) // 3. deploy the pre-build dotcom app: - const { deploymentUrl, inspectUrl } = await discordStep( - '[7/7] deploying dotcom app to vercel', + const { deploymentUrl, inspectUrl } = await discord.step( + 'deploying dotcom app to vercel', async () => { return await deploySpa() } @@ -128,7 +121,7 @@ async function main() { if (previewId) { const aliasDomain = `${previewId}-preview-deploy.tldraw.com` - await discordStep('[8/7] aliasing preview deployment', async () => { + await discord.step('aliasing preview deployment', async () => { await vercelCli('alias', ['set', deploymentUrl, aliasDomain]) }) @@ -136,9 +129,14 @@ async function main() { } nicelog('Creating deployment for', deploymentUrl) - await createGithubDeployment(deploymentAlias ?? deploymentUrl, inspectUrl) + await createGithubDeployment(env, { + app: 'dotcom', + deploymentUrl: deploymentAlias ?? deploymentUrl, + inspectUrl, + sha, + }) - await discordMessage(`**Deploy complete!**`) + await discord.message(`**Deploy complete!**`) } async function prepareDotcomApp() { @@ -167,21 +165,15 @@ async function prepareDotcomApp() { let didUpdateAssetUploadWorker = false async function deployAssetUploadWorker({ dryRun }: { dryRun: boolean }) { if (previewId && !didUpdateAssetUploadWorker) { - appendFileSync( - join(assetUpload, 'wrangler.toml'), - ` -[env.preview] -name = "${previewId}-tldraw-assets"` - ) + await setWranglerPreviewConfig(assetUpload, { name: `${previewId}-tldraw-assets` }) didUpdateAssetUploadWorker = true } - await exec('yarn', ['wrangler', 'deploy', dryRun ? '--dry-run' : null, '--env', env.TLDRAW_ENV], { - pwd: assetUpload, - env: { - NODE_ENV: 'production', - // wrangler needs CI=1 set to prevent it from trying to do interactive prompts - CI: '1', - }, + + await wranglerDeploy({ + location: assetUpload, + dryRun, + env: env.TLDRAW_ENV, + vars: {}, }) } @@ -189,79 +181,39 @@ let didUpdateTlsyncWorker = false async function deployTlsyncWorker({ dryRun }: { dryRun: boolean }) { const workerId = `${previewId ?? env.TLDRAW_ENV}-tldraw-multiplayer` if (previewId && !didUpdateTlsyncWorker) { - appendFileSync( - join(worker, 'wrangler.toml'), - ` -[env.preview] -name = "${previewId}-tldraw-multiplayer"` - ) + await setWranglerPreviewConfig(worker, { name: workerId }) didUpdateTlsyncWorker = true } - await exec( - 'yarn', - [ - 'wrangler', - 'deploy', - dryRun ? '--dry-run' : null, - '--env', - env.TLDRAW_ENV, - '--var', - `SUPABASE_URL:${env.SUPABASE_LITE_URL}`, - '--var', - `SUPABASE_KEY:${env.SUPABASE_LITE_ANON_KEY}`, - '--var', - `SENTRY_DSN:${env.WORKER_SENTRY_DSN}`, - '--var', - `TLDRAW_ENV:${env.TLDRAW_ENV}`, - '--var', - `APP_ORIGIN:${env.APP_ORIGIN}`, - '--var', - `WORKER_NAME:${workerId}`, - ], - { - pwd: worker, - env: { - NODE_ENV: 'production', - // wrangler needs CI=1 set to prevent it from trying to do interactive prompts - CI: '1', - }, - } - ) + await wranglerDeploy({ + location: worker, + dryRun, + env: env.TLDRAW_ENV, + vars: { + SUPABASE_URL: env.SUPABASE_LITE_URL, + SUPABASE_KEY: env.SUPABASE_LITE_ANON_KEY, + SENTRY_DSN: env.WORKER_SENTRY_DSN, + TLDRAW_ENV: env.TLDRAW_ENV, + APP_ORIGIN: env.APP_ORIGIN, + WORKER_NAME: workerId, + }, + }) } let didUpdateHealthWorker = false async function deployHealthWorker({ dryRun }: { dryRun: boolean }) { if (previewId && !didUpdateHealthWorker) { - appendFileSync( - join(healthWorker, 'wrangler.toml'), - ` -[env.preview] -name = "${previewId}-tldraw-health"` - ) + await setWranglerPreviewConfig(healthWorker, { name: `${previewId}-tldraw-health` }) didUpdateHealthWorker = true } - await exec( - 'yarn', - [ - 'wrangler', - 'deploy', - dryRun ? '--dry-run' : null, - '--env', - env.TLDRAW_ENV, - '--var', - `DISCORD_HEALTH_WEBHOOK_URL:${env.DISCORD_HEALTH_WEBHOOK_URL}`, - '--var', - `HEALTH_WORKER_UPDOWN_WEBHOOK_PATH:${env.HEALTH_WORKER_UPDOWN_WEBHOOK_PATH}`, - ], - { - pwd: healthWorker, - env: { - NODE_ENV: 'production', - // wrangler needs CI=1 set to prevent it from trying to do interactive prompts - CI: '1', - }, - } - ) + await wranglerDeploy({ + location: healthWorker, + dryRun, + env: env.TLDRAW_ENV, + vars: { + DISCORD_HEALTH_WEBHOOK_URL: env.DISCORD_HEALTH_WEBHOOK_URL, + HEALTH_WORKER_UPDOWN_WEBHOOK_PATH: env.HEALTH_WORKER_UPDOWN_WEBHOOK_PATH, + }, + }) } type ExecOpts = NonNullable[2]> @@ -293,61 +245,6 @@ async function vercelCli(command: string, args: string[], opts?: ExecOpts) { ) } -function sanitizeVariables(errorOutput: string): string { - const regex = /(--var\s+(\w+):[^ \n]+)/g - - const sanitizedOutput = errorOutput.replace(regex, (_, match) => { - const [variable] = match.split(':') - return `${variable}:*` - }) - - return sanitizedOutput -} - -async function discord(method: string, url: string, body: unknown): Promise { - const response = await fetch(`${env.DISCORD_DEPLOY_WEBHOOK_URL}${url}`, { - method, - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }) - if (!response.ok) { - throw new Error(`Discord webhook request failed: ${response.status} ${response.statusText}`) - } - return response.json() -} - -const AT_TEAM_MENTION = '<@&959380625100513310>' -async function discordMessage(content: string, { always = false }: { always?: boolean } = {}) { - const shouldNotify = env.TLDRAW_ENV === 'production' || always - if (!shouldNotify) { - return { - edit: () => { - // noop - }, - } - } - - const message = await discord('POST', '?wait=true', { content: sanitizeVariables(content) }) - - return { - edit: async (newContent: string) => { - await discord('PATCH', `/messages/${message.id}`, { content: sanitizeVariables(newContent) }) - }, - } -} - -async function discordStep(content: string, cb: () => Promise): Promise { - const message = await discordMessage(`${content}...`) - try { - const result = await cb() - await message.edit(`${content} ✅`) - return result - } catch (err) { - await message.edit(`${content} ❌`) - throw err - } -} - async function deploySpa(): Promise<{ deploymentUrl: string; inspectUrl: string }> { // both 'staging' and 'production' are deployed to vercel as 'production' deploys // in separate 'projects' @@ -371,32 +268,6 @@ async function deploySpa(): Promise<{ deploymentUrl: string; inspectUrl: string return { deploymentUrl, inspectUrl } } -// Creates a github 'deployment', which creates a 'View Deployment' button in the PR timeline. -async function createGithubDeployment(deploymentUrl: string, inspectUrl: string) { - const client = github.getOctokit(env.GH_TOKEN) - - const deployment = await client.rest.repos.createDeployment({ - owner: 'tldraw', - repo: 'tldraw', - ref: sha, - payload: { web_url: deploymentUrl }, - environment: env.TLDRAW_ENV, - transient_environment: true, - required_contexts: [], - auto_merge: false, - task: 'deploy', - }) - - await client.rest.repos.createDeploymentStatus({ - owner: 'tldraw', - repo: 'tldraw', - deployment_id: (deployment.data as any).id, - state: 'success', - environment_url: deploymentUrl, - log_url: inspectUrl, - }) -} - const sentryEnv = { SENTRY_AUTH_TOKEN: env.SENTRY_AUTH_TOKEN, SENTRY_ORG: 'tldraw', @@ -526,7 +397,9 @@ async function coalesceWithPreviousAssets(assetsDir: string) { main().catch(async (err) => { // don't notify discord on preview builds if (env.TLDRAW_ENV !== 'preview') { - await discordMessage(`${AT_TEAM_MENTION} Deploy failed: ${err.stack}`, { always: true }) + await discord.message(`${Discord.AT_TEAM_MENTION} Deploy failed: ${err.stack}`, { + always: true, + }) } console.error(err) process.exit(1) diff --git a/scripts/lib/deploy.ts b/scripts/lib/deploy.ts new file mode 100644 index 000000000..8551269ce --- /dev/null +++ b/scripts/lib/deploy.ts @@ -0,0 +1,184 @@ +import * as github from '@actions/github' +import { readFileSync } from 'fs' +import { appendFile } from 'fs/promises' +import { join } from 'path' +import { env } from 'process' +import toml from 'toml' +import { exec } from './exec' + +export function getDeployInfo() { + const githubPrNumber = process.env.GITHUB_REF?.match(/refs\/pull\/(\d+)\/merge/)?.[1] + + let previewId = process.env.TLDRAW_PREVIEW_ID + if (!previewId && env.TLDRAW_ENV === 'preview') { + if (githubPrNumber) { + previewId = `pr-${githubPrNumber}` + } else { + throw new Error( + 'If running preview deploys from outside of a PR action, TLDRAW_PREVIEW_ID env var must be set' + ) + } + } + + const sha: string | undefined = + // if the event is 'pull_request', github.context.sha is an ephemeral merge commit + // while the actual commit we want to create the deployment for is the 'head' of the PR. + github.context.eventName === 'pull_request' + ? github.context.payload.pull_request?.head.sha + : github.context.sha + + if (!sha) { + throw new Error('Could not determine the SHA of the commit to deploy') + } + + return { + githubPrNumber, + previewId, + sha, + } +} + +// Creates a github 'deployment', which creates a 'View Deployment' button in the PR timeline. +export async function createGithubDeployment( + env: { GH_TOKEN: string; TLDRAW_ENV: string }, + { + app, + deploymentUrl, + inspectUrl, + sha, + }: { app: string; deploymentUrl: string; inspectUrl?: string; sha: string } +) { + const client = github.getOctokit(env.GH_TOKEN) + + const deployment = await client.rest.repos.createDeployment({ + owner: 'tldraw', + repo: 'tldraw', + ref: sha, + payload: { web_url: deploymentUrl }, + environment: `${app}-${env.TLDRAW_ENV}`, + transient_environment: env.TLDRAW_ENV === 'preview', + production_environment: env.TLDRAW_ENV === 'production', + required_contexts: [], + auto_merge: false, + task: 'deploy', + }) + + await client.rest.repos.createDeploymentStatus({ + owner: 'tldraw', + repo: 'tldraw', + deployment_id: (deployment.data as any).id, + state: 'success', + environment_url: deploymentUrl, + log_url: inspectUrl, + }) +} + +/** Deploy a worker to wrangler, returning the deploy ID */ +export async function wranglerDeploy({ + location, + dryRun, + env, + vars, + sentry, +}: { + location: string + dryRun: boolean + env: string + vars: Record + sentry?: { + authToken: string + project: string + release?: string + } +}) { + const varsArray = [] + for (const [key, value] of Object.entries(vars)) { + varsArray.push('--var', `${key}:${value}`) + } + + const out = await exec( + 'yarn', + [ + 'wrangler', + 'deploy', + dryRun ? '--dry-run' : null, + '--env', + env, + '--outdir', + '.wrangler/dist', + ...varsArray, + ], + { + pwd: location, + env: { + NODE_ENV: 'production', + // wrangler needs CI=1 set to prevent it from trying to do interactive prompts + CI: '1', + }, + } + ) + + if (dryRun) return + + const versionMatch = out.match(/Current Version ID: (.+)/) + if (!versionMatch) { + throw new Error('Could not find the deploy ID in wrangler output') + } + + const workerName = toml.parse(readFileSync(join(location, 'wrangler.toml')).toString())?.env?.[ + env + ]?.name + + if (!workerName) { + throw new Error('Could not find the worker name in wrangler output') + } + + if (sentry) { + const release = sentry.release ?? `${workerName}.${versionMatch[1]}` + + const sentryEnv = { + SENTRY_AUTH_TOKEN: sentry.authToken, + SENTRY_ORG: 'tldraw', + SENTRY_PROJECT: sentry.project, + } + + // create a sentry release: + exec('yarn', ['run', '-T', 'sentry-cli', 'releases', 'new', release], { + pwd: location, + env: sentryEnv, + }) + + // upload sourcemaps to the release: + exec( + 'yarn', + [ + 'run', + '-T', + 'sentry-cli', + 'releases', + 'files', + release, + 'upload-sourcemaps', + '.wrangler/dist', + ], + { + pwd: location, + env: sentryEnv, + } + ) + } +} + +export async function setWranglerPreviewConfig( + location: string, + { name, customDomain }: { name: string; customDomain?: string } +) { + await appendFile( + join(location, 'wrangler.toml'), + ` +[env.preview] +name = "${name}" +${customDomain ? `routes = [ { pattern = "${customDomain}", custom_domain = true} ]` : ''} +` + ) +} diff --git a/scripts/lib/discord.ts b/scripts/lib/discord.ts new file mode 100644 index 000000000..ea9da00bc --- /dev/null +++ b/scripts/lib/discord.ts @@ -0,0 +1,70 @@ +function sanitizeVariables(errorOutput: string): string { + const regex = /(--var\s+(\w+):[^ \n]+)/g + + const sanitizedOutput = errorOutput.replace(regex, (_, match) => { + const [variable] = match.split(':') + return `${variable}:*` + }) + + return sanitizedOutput +} + +export class Discord { + static AT_TEAM_MENTION = '<@&959380625100513310>' + + constructor(opts: { webhookUrl: string; shouldNotify: boolean; totalSteps?: number }) { + this.webhookUrl = opts.webhookUrl + this.shouldNotify = opts.shouldNotify + this.totalSteps = opts.totalSteps ?? 0 + } + + webhookUrl: string + shouldNotify: boolean + totalSteps: number + currentStep = 0 + + private async send(method: string, url: string, body: unknown): Promise { + const response = await fetch(`${this.webhookUrl}${url}`, { + method, + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }) + if (!response.ok) { + throw new Error(`Discord webhook request failed: ${response.status} ${response.statusText}`) + } + return response.json() + } + + async message(content: string, { always = false }: { always?: boolean } = {}) { + if (!always && !this.shouldNotify) { + return { + edit: () => { + // noop + }, + } + } + + const message = await this.send('POST', '?wait=true', { content: sanitizeVariables(content) }) + + return { + edit: async (newContent: string) => { + await this.send('PATCH', `/messages/${message.id}`, { + content: sanitizeVariables(newContent), + }) + }, + } + } + + async step(content: string, cb: () => Promise): Promise { + this.currentStep++ + const message = await this.message(`[${this.currentStep}/${this.totalSteps}] ${content}...`) + try { + const result = await cb() + await message.edit(`${content} ✅`) + return result + } catch (err) { + await message.edit(`${content} ❌`) + throw err + } + } +} diff --git a/scripts/package.json b/scripts/package.json index b49be8566..5ee9bb32b 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -35,7 +35,7 @@ "@typescript-eslint/utils": "^5.59.0", "ast-types": "^0.14.2", "cross-fetch": "^3.1.5", - "esbuild": "^0.18.4", + "esbuild": "^0.21.5", "eslint": "^8.37.0", "glob": "^8.0.3", "gray-matter": "^4.0.3", @@ -59,6 +59,7 @@ "ignore": "^5.2.4", "minimist": "^1.2.8", "tar": "^7.0.1", - "tmp": "^0.2.3" + "tmp": "^0.2.3", + "toml": "^3.0.0" } } diff --git a/apps/dotcom-worker/scripts/dev-wrap.ts b/scripts/workers/dev.ts similarity index 54% rename from apps/dotcom-worker/scripts/dev-wrap.ts rename to scripts/workers/dev.ts index 0e79b198f..34b30659e 100644 --- a/apps/dotcom-worker/scripts/dev-wrap.ts +++ b/scripts/workers/dev.ts @@ -1,14 +1,11 @@ +import { ChildProcessWithoutNullStreams, spawn } from 'child_process' +import kleur from 'kleur' +import stripAnsi from 'strip-ansi' + // at the time of writing, workerd will regularly crash with a segfault // but the error is not caught by the process, so it will just hang // this script wraps the process, tailing the logs and restarting the process // if we encounter the string 'Segmentation fault' - -import { ChildProcessWithoutNullStreams, spawn } from 'child_process' -import stripAnsi from 'strip-ansi' - -// eslint-disable-next-line no-console -const log = console.log - class MiniflareMonitor { private process: ChildProcessWithoutNullStreams | null = null @@ -19,7 +16,7 @@ class MiniflareMonitor { public start(): void { this.stop() // Ensure any existing process is stopped - log(`Starting wrangler...`) + console.log(`Starting wrangler...`) this.process = spawn(this.command, this.args, { env: { NODE_ENV: 'development', @@ -42,12 +39,12 @@ class MiniflareMonitor { console.error('Segmentation fault detected. Restarting Miniflare...') this.restart() } else if (!err) { - log(output.replace('[mf:inf]', '')) // or handle the output differently + console.log(output.replace('[mf:inf]', '')) // or handle the output differently } } private restart(): void { - log('Restarting wrangler...') + console.log('Restarting wrangler...') this.stop() setTimeout(() => this.start(), 3000) // Restart after a short delay } @@ -60,7 +57,60 @@ class MiniflareMonitor { } } -const monitor = new MiniflareMonitor('wrangler', [ +class SizeReporter { + lastLineTime = Date.now() + nextTick?: NodeJS.Timeout + + size = 0 + + start() { + console.log('Spawning size reporter...') + const proc = spawn('yarn', [ + 'run', + '-T', + 'esbuild', + 'src/worker.ts', + '--bundle', + '--minify', + '--watch', + '--external:cloudflare:*', + '--target=esnext', + '--format=esm', + ]) + // listen for lines on stdin + proc.stdout.on('data', (data) => { + this.size += data.length + this.lastLineTime = Date.now() + clearTimeout(this.nextTick) + this.nextTick = setTimeout(() => { + console.log( + kleur.bold(kleur.yellow('worker')), + 'is roughly', + kleur.bold(kleur.cyan(Math.floor(this.size / 1024) + 'kb')), + '(minified)\n' + ) + this.size = 0 + }, 10) + }) + proc.stderr.on('data', (data) => { + console.log(data.toString()) + }) + process.on('SIGINT', () => { + console.log('Int') + proc.kill() + }) + process.on('SIGTERM', () => { + console.log('Term') + proc.kill() + }) + process.on('exit', () => { + console.log('Exiting') + proc.kill() + }) + } +} + +new MiniflareMonitor('wrangler', [ 'dev', '--env', 'dev', @@ -69,5 +119,6 @@ const monitor = new MiniflareMonitor('wrangler', [ 'info', '--var', 'IS_LOCAL:true', -]) -monitor.start() +]).start() + +new SizeReporter().start() diff --git a/yarn.lock b/yarn.lock index 26f71ae5d..a62687fbd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,46 +1283,46 @@ __metadata: languageName: node linkType: hard -"@cloudflare/kv-asset-handler@npm:0.3.3": - version: 0.3.3 - resolution: "@cloudflare/kv-asset-handler@npm:0.3.3" +"@cloudflare/kv-asset-handler@npm:0.3.4": + version: 0.3.4 + resolution: "@cloudflare/kv-asset-handler@npm:0.3.4" dependencies: mime: "npm:^3.0.0" - checksum: 020ef0a6f7f70f8cdcecd5d8c6cd3938a80205c5e4561255d8f6d6ad6be4bf231961a62c6a8d0cf94dab1cea249cc81064b8670fdbac2eb13a006b1f34a759c4 + checksum: f02840c2da8e75f3dbfe769f3ba99b99fb87b438c518c06c279334882ce7745ba5dd7ab66a07695dde0596e297758ce66761f9aac2365e7dfb83d7001cd44afa languageName: node linkType: hard -"@cloudflare/workerd-darwin-64@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "@cloudflare/workerd-darwin-64@npm:1.20240610.1" +"@cloudflare/workerd-darwin-64@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "@cloudflare/workerd-darwin-64@npm:1.20240620.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@cloudflare/workerd-darwin-arm64@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "@cloudflare/workerd-darwin-arm64@npm:1.20240610.1" +"@cloudflare/workerd-darwin-arm64@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "@cloudflare/workerd-darwin-arm64@npm:1.20240620.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@cloudflare/workerd-linux-64@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "@cloudflare/workerd-linux-64@npm:1.20240610.1" +"@cloudflare/workerd-linux-64@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "@cloudflare/workerd-linux-64@npm:1.20240620.1" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@cloudflare/workerd-linux-arm64@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "@cloudflare/workerd-linux-arm64@npm:1.20240610.1" +"@cloudflare/workerd-linux-arm64@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "@cloudflare/workerd-linux-arm64@npm:1.20240620.1" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@cloudflare/workerd-windows-64@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "@cloudflare/workerd-windows-64@npm:1.20240610.1" +"@cloudflare/workerd-windows-64@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "@cloudflare/workerd-windows-64@npm:1.20240620.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1600,16 +1600,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-arm64@npm:0.17.19" - conditions: os=android & cpu=arm64 +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm64@npm:0.18.20" +"@esbuild/android-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm64@npm:0.17.19" conditions: os=android & cpu=arm64 languageName: node linkType: hard @@ -1628,16 +1628,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-arm@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-arm@npm:0.17.19" - conditions: os=android & cpu=arm +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-arm@npm:0.18.20" +"@esbuild/android-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-arm@npm:0.17.19" conditions: os=android & cpu=arm languageName: node linkType: hard @@ -1656,16 +1656,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/android-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/android-x64@npm:0.17.19" - conditions: os=android & cpu=x64 +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/android-x64@npm:0.18.20" +"@esbuild/android-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/android-x64@npm:0.17.19" conditions: os=android & cpu=x64 languageName: node linkType: hard @@ -1684,16 +1684,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/darwin-arm64@npm:0.17.19" - conditions: os=darwin & cpu=arm64 +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-arm64@npm:0.18.20" +"@esbuild/darwin-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-arm64@npm:0.17.19" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard @@ -1712,16 +1712,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/darwin-x64@npm:0.17.19" - conditions: os=darwin & cpu=x64 +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/darwin-x64@npm:0.18.20" +"@esbuild/darwin-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/darwin-x64@npm:0.17.19" conditions: os=darwin & cpu=x64 languageName: node linkType: hard @@ -1740,16 +1740,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/freebsd-arm64@npm:0.17.19" - conditions: os=freebsd & cpu=arm64 +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-arm64@npm:0.18.20" +"@esbuild/freebsd-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-arm64@npm:0.17.19" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard @@ -1768,16 +1768,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/freebsd-x64@npm:0.17.19" - conditions: os=freebsd & cpu=x64 +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/freebsd-x64@npm:0.18.20" +"@esbuild/freebsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/freebsd-x64@npm:0.17.19" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard @@ -1796,16 +1796,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-arm64@npm:0.17.19" - conditions: os=linux & cpu=arm64 +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm64@npm:0.18.20" +"@esbuild/linux-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm64@npm:0.17.19" conditions: os=linux & cpu=arm64 languageName: node linkType: hard @@ -1824,16 +1824,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-arm@npm:0.17.19" - conditions: os=linux & cpu=arm +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-arm@npm:0.18.20" +"@esbuild/linux-arm@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-arm@npm:0.17.19" conditions: os=linux & cpu=arm languageName: node linkType: hard @@ -1852,16 +1852,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-ia32@npm:0.17.19" - conditions: os=linux & cpu=ia32 +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ia32@npm:0.18.20" +"@esbuild/linux-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ia32@npm:0.17.19" conditions: os=linux & cpu=ia32 languageName: node linkType: hard @@ -1880,16 +1880,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-loong64@npm:0.17.19" - conditions: os=linux & cpu=loong64 +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-loong64@npm:0.18.20" +"@esbuild/linux-loong64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-loong64@npm:0.17.19" conditions: os=linux & cpu=loong64 languageName: node linkType: hard @@ -1908,16 +1908,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-mips64el@npm:0.17.19" - conditions: os=linux & cpu=mips64el +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-mips64el@npm:0.18.20" +"@esbuild/linux-mips64el@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-mips64el@npm:0.17.19" conditions: os=linux & cpu=mips64el languageName: node linkType: hard @@ -1936,16 +1936,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-ppc64@npm:0.17.19" - conditions: os=linux & cpu=ppc64 +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-ppc64@npm:0.18.20" +"@esbuild/linux-ppc64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-ppc64@npm:0.17.19" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard @@ -1964,16 +1964,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-riscv64@npm:0.17.19" - conditions: os=linux & cpu=riscv64 +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-riscv64@npm:0.18.20" +"@esbuild/linux-riscv64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-riscv64@npm:0.17.19" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard @@ -1992,16 +1992,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-s390x@npm:0.17.19" - conditions: os=linux & cpu=s390x +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-s390x@npm:0.18.20" +"@esbuild/linux-s390x@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-s390x@npm:0.17.19" conditions: os=linux & cpu=s390x languageName: node linkType: hard @@ -2020,16 +2020,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/linux-x64@npm:0.17.19" - conditions: os=linux & cpu=x64 +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/linux-x64@npm:0.18.20" +"@esbuild/linux-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/linux-x64@npm:0.17.19" conditions: os=linux & cpu=x64 languageName: node linkType: hard @@ -2048,16 +2048,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/netbsd-x64@npm:0.17.19" - conditions: os=netbsd & cpu=x64 +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/netbsd-x64@npm:0.18.20" +"@esbuild/netbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/netbsd-x64@npm:0.17.19" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard @@ -2076,16 +2076,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/openbsd-x64@npm:0.17.19" - conditions: os=openbsd & cpu=x64 +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/openbsd-x64@npm:0.18.20" +"@esbuild/openbsd-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/openbsd-x64@npm:0.17.19" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard @@ -2104,16 +2104,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/sunos-x64@npm:0.17.19" - conditions: os=sunos & cpu=x64 +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/sunos-x64@npm:0.18.20" +"@esbuild/sunos-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/sunos-x64@npm:0.17.19" conditions: os=sunos & cpu=x64 languageName: node linkType: hard @@ -2132,16 +2132,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-arm64@npm:0.17.19" - conditions: os=win32 & cpu=arm64 +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-arm64@npm:0.18.20" +"@esbuild/win32-arm64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-arm64@npm:0.17.19" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard @@ -2160,16 +2160,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-ia32@npm:0.17.19" - conditions: os=win32 & cpu=ia32 +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-ia32@npm:0.18.20" +"@esbuild/win32-ia32@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-ia32@npm:0.17.19" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard @@ -2188,16 +2188,16 @@ __metadata: languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.17.19": - version: 0.17.19 - resolution: "@esbuild/win32-x64@npm:0.17.19" - conditions: os=win32 & cpu=x64 +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.18.20": - version: 0.18.20 - resolution: "@esbuild/win32-x64@npm:0.18.20" +"@esbuild/win32-x64@npm:0.17.19": + version: 0.17.19 + resolution: "@esbuild/win32-x64@npm:0.17.19" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2216,6 +2216,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -4919,16 +4926,13 @@ __metadata: languageName: node linkType: hard -"@sentry/core@npm:6.19.6": - version: 6.19.6 - resolution: "@sentry/core@npm:6.19.6" +"@sentry/core@npm:7.112.2": + version: 7.112.2 + resolution: "@sentry/core@npm:7.112.2" dependencies: - "@sentry/hub": "npm:6.19.6" - "@sentry/minimal": "npm:6.19.6" - "@sentry/types": "npm:6.19.6" - "@sentry/utils": "npm:6.19.6" - tslib: "npm:^1.9.3" - checksum: 36e0c3da5163a5ba6735328bbff18150ec5b3afe752684c82004fa3e5410f85f1eb240c684f501a945c299624db920ddfd2f65c292504067acefa97956d781ee + "@sentry/types": "npm:7.112.2" + "@sentry/utils": "npm:7.112.2" + checksum: db998cb2a8d6fb95d4e55a25c3be84e09dc71373e5532ccdb1067c82b10c45269b26f2468d8285f7d17f1cf192ba48806c761e247fa3ed3afb60ae1d559178b0 languageName: node linkType: hard @@ -4942,37 +4946,15 @@ __metadata: languageName: node linkType: hard -"@sentry/hub@npm:6.19.6": - version: 6.19.6 - resolution: "@sentry/hub@npm:6.19.6" +"@sentry/integrations@npm:7.112.2, @sentry/integrations@npm:^7.34.0": + version: 7.112.2 + resolution: "@sentry/integrations@npm:7.112.2" dependencies: - "@sentry/types": "npm:6.19.6" - "@sentry/utils": "npm:6.19.6" - tslib: "npm:^1.9.3" - checksum: d064080c2dad1adb4c0f2a54745f370e3debeda5a0ecfbe28e83a4e4bffdb2b7e42bd80de2e0cd253a97a87c55aa6cdc46a6a181bf897b55a88ceba79ae62ca7 - languageName: node - linkType: hard - -"@sentry/integrations@npm:^7.34.0": - version: 7.93.0 - resolution: "@sentry/integrations@npm:7.93.0" - dependencies: - "@sentry/core": "npm:7.93.0" - "@sentry/types": "npm:7.93.0" - "@sentry/utils": "npm:7.93.0" + "@sentry/core": "npm:7.112.2" + "@sentry/types": "npm:7.112.2" + "@sentry/utils": "npm:7.112.2" localforage: "npm:^1.8.1" - checksum: 0ca677fcae67c474f0927eef21950ccb26fc7a5790692acc9963c8eccaa6d464a9c6988bda6602de7739387f78e78ff0d3bcbff3244168578cb7549de6dddcbd - languageName: node - linkType: hard - -"@sentry/minimal@npm:6.19.6": - version: 6.19.6 - resolution: "@sentry/minimal@npm:6.19.6" - dependencies: - "@sentry/hub": "npm:6.19.6" - "@sentry/types": "npm:6.19.6" - tslib: "npm:^1.9.3" - checksum: 4f8422641d4ee4c0c78b6a126c89883810b5b723c795eba91f6c1c5d4f562bce05cc1b7389106f7486a177a06fca008eb6c4f71bd233c682d9f0052ff84e0855 + checksum: fbb4852516e801ff3d1ec3e913a4c0237cb4418dfbec82ba70a86cceaf9dfa0db54df38fee4ce461cf07cf7896a3c8be8cca6128be6a42a09601b91719711a0a languageName: node linkType: hard @@ -5003,10 +4985,10 @@ __metadata: languageName: node linkType: hard -"@sentry/types@npm:6.19.6": - version: 6.19.6 - resolution: "@sentry/types@npm:6.19.6" - checksum: 75d6a41cae6fff9c6f4f9020bff18a1298856e05afa1be83a6ba492e124e9fb54abc0bf45fe55222109b21119c9d0742496b247af3ea9e15c1453c4f8784525b +"@sentry/types@npm:7.112.2": + version: 7.112.2 + resolution: "@sentry/types@npm:7.112.2" + checksum: 4ac8d0727f159adaba0da39f1bc5508153f4ad0f2df716ab221973bdf962fe44c3966253b40d50219d77c28d089a8d8899ade0369178416a6cb469f9d107efbf languageName: node linkType: hard @@ -5017,13 +4999,12 @@ __metadata: languageName: node linkType: hard -"@sentry/utils@npm:6.19.6": - version: 6.19.6 - resolution: "@sentry/utils@npm:6.19.6" +"@sentry/utils@npm:7.112.2": + version: 7.112.2 + resolution: "@sentry/utils@npm:7.112.2" dependencies: - "@sentry/types": "npm:6.19.6" - tslib: "npm:^1.9.3" - checksum: 8b12d34951538593606002cf6fa76fb6ae96c317c2709f5b5bff7aed45389c4676b15a4371faa7d18ffb0bf33db950404e7979bde6eed629708148bd71fd6918 + "@sentry/types": "npm:7.112.2" + checksum: 7d641278c78fc6e7e707b9908859708c863cd90e9ad24e1c3973ee81757254560852a43c076552615f89fbe61c668f20027ea385125b6c14fe2e164bb9e57538 languageName: node linkType: hard @@ -6009,6 +5990,28 @@ __metadata: languageName: unknown linkType: soft +"@tldraw/bemo-worker@workspace:apps/bemo-worker": + version: 0.0.0-use.local + resolution: "@tldraw/bemo-worker@workspace:apps/bemo-worker" + dependencies: + "@cloudflare/workers-types": "npm:^4.20240620.0" + "@tldraw/dotcom-shared": "workspace:*" + "@tldraw/store": "workspace:*" + "@tldraw/tlschema": "workspace:*" + "@tldraw/tlsync": "workspace:*" + "@tldraw/utils": "workspace:*" + esbuild: "npm:^0.21.5" + itty-router: "npm:^4.0.13" + lazyrepo: "npm:0.0.0-alpha.27" + nanoid: "npm:4.0.2" + react: "npm:^18.2.0" + react-dom: "npm:^18.2.0" + toucan-js: "npm:^3.4.0" + typescript: "npm:^5.3.3" + wrangler: "npm:3.62.0" + languageName: unknown + linkType: soft + "@tldraw/bookmark-extractor@workspace:apps/dotcom-bookmark-extractor": version: 0.0.0-use.local resolution: "@tldraw/bookmark-extractor@workspace:apps/dotcom-bookmark-extractor" @@ -6100,18 +6103,15 @@ __metadata: "@tldraw/tlschema": "workspace:*" "@tldraw/tlsync": "workspace:*" "@tldraw/utils": "workspace:*" - concurrently: "npm:^8.2.2" - esbuild: "npm:^0.18.4" + esbuild: "npm:^0.21.5" itty-router: "npm:^4.0.13" lazyrepo: "npm:0.0.0-alpha.27" nanoid: "npm:4.0.2" - picocolors: "npm:^1.0.0" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" - strip-ansi: "npm:^7.1.0" - toucan-js: "npm:^2.7.0" + toucan-js: "npm:^3.4.0" typescript: "npm:^5.3.3" - wrangler: "npm:3.61.0" + wrangler: "npm:3.62.0" languageName: unknown linkType: soft @@ -6170,6 +6170,7 @@ __metadata: "@yarnpkg/types": "npm:^4.0.0" auto: "npm:^11.1.1" cross-env: "npm:^7.0.3" + esbuild: "npm:^0.21.5" eslint: "npm:^8.37.0" eslint-config-prettier: "npm:^8.8.0" eslint-plugin-deprecation: "npm:^2.0.0" @@ -6213,7 +6214,7 @@ __metadata: "@typescript-eslint/utils": "npm:^5.59.0" ast-types: "npm:^0.14.2" cross-fetch: "npm:^3.1.5" - esbuild: "npm:^0.18.4" + esbuild: "npm:^0.21.5" eslint: "npm:^8.37.0" glob: "npm:^8.0.3" gray-matter: "npm:^4.0.3" @@ -6229,6 +6230,7 @@ __metadata: svgo: "npm:^3.0.2" tar: "npm:^7.0.1" tmp: "npm:^0.2.3" + toml: "npm:^3.0.0" typescript: "npm:^5.3.3" languageName: unknown linkType: soft @@ -6351,7 +6353,7 @@ __metadata: concurrently: "npm:^8.2.2" create-serve: "npm:1.0.1" dotenv: "npm:^16.3.1" - esbuild: "npm:^0.18.4" + esbuild: "npm:^0.21.5" fs-extra: "npm:^11.1.0" lazyrepo: "npm:0.0.0-alpha.27" react: "npm:^18.2.0" @@ -6565,13 +6567,6 @@ __metadata: languageName: node linkType: hard -"@types/cookie@npm:0.5.0": - version: 0.5.0 - resolution: "@types/cookie@npm:0.5.0" - checksum: e585d7b1b13bb92214d644997e7e67afdc577c6025ebaa348abcc66620afb6cd007e6db3ab0c886b44c2065c8a73e4b89d120b4e52fd43960f8f80b7ddc62a9d - languageName: node - linkType: hard - "@types/core-js@npm:^2.5.5": version: 2.5.8 resolution: "@types/core-js@npm:2.5.8" @@ -9620,7 +9615,7 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.5.0, cookie@npm:^0.5.0": +"cookie@npm:^0.5.0": version: 0.5.0 resolution: "cookie@npm:0.5.0" checksum: aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 @@ -9874,6 +9869,13 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:^3.6.0": + version: 3.6.0 + resolution: "date-fns@npm:3.6.0" + checksum: cac35c58926a3b5d577082ff2b253612ec1c79eb6754fddef46b6a8e826501ea2cb346ecbd211205f1ba382ddd1f9d8c3f00bf433ad63cc3063454d294e3a6b8 + languageName: node + linkType: hard + "debounce@npm:^1.2.1": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -10326,7 +10328,7 @@ __metadata: itty-cors: "npm:^0.3.4" itty-router: "npm:^4.0.13" lazyrepo: "npm:0.0.0-alpha.27" - wrangler: "npm:3.61.0" + wrangler: "npm:3.62.0" languageName: unknown linkType: soft @@ -10598,15 +10600,6 @@ __metadata: languageName: node linkType: hard -"error-stack-parser@npm:^2.0.6": - version: 2.1.4 - resolution: "error-stack-parser@npm:2.1.4" - dependencies: - stackframe: "npm:^1.3.4" - checksum: 23db33135bfc6ba701e5eee45e1bb9bd2fe33c5d4f9927440d9a499c7ac538f91f455fcd878611361269893c56734419252c40d8105eb3b023cf8b0fc2ebb64e - languageName: node - linkType: hard - "es-abstract@npm:^1.22.1": version: 1.22.3 resolution: "es-abstract@npm:1.22.3" @@ -11068,83 +11061,6 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:^0.18.4": - version: 0.18.20 - resolution: "esbuild@npm:0.18.20" - dependencies: - "@esbuild/android-arm": "npm:0.18.20" - "@esbuild/android-arm64": "npm:0.18.20" - "@esbuild/android-x64": "npm:0.18.20" - "@esbuild/darwin-arm64": "npm:0.18.20" - "@esbuild/darwin-x64": "npm:0.18.20" - "@esbuild/freebsd-arm64": "npm:0.18.20" - "@esbuild/freebsd-x64": "npm:0.18.20" - "@esbuild/linux-arm": "npm:0.18.20" - "@esbuild/linux-arm64": "npm:0.18.20" - "@esbuild/linux-ia32": "npm:0.18.20" - "@esbuild/linux-loong64": "npm:0.18.20" - "@esbuild/linux-mips64el": "npm:0.18.20" - "@esbuild/linux-ppc64": "npm:0.18.20" - "@esbuild/linux-riscv64": "npm:0.18.20" - "@esbuild/linux-s390x": "npm:0.18.20" - "@esbuild/linux-x64": "npm:0.18.20" - "@esbuild/netbsd-x64": "npm:0.18.20" - "@esbuild/openbsd-x64": "npm:0.18.20" - "@esbuild/sunos-x64": "npm:0.18.20" - "@esbuild/win32-arm64": "npm:0.18.20" - "@esbuild/win32-ia32": "npm:0.18.20" - "@esbuild/win32-x64": "npm:0.18.20" - dependenciesMeta: - "@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-x64": - optional: true - "@esbuild/openbsd-x64": - 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: 1f723ec71c3aa196473bf3298316eedc3f62d523924652dfeb60701b609792f918fc60db84b420d1d8ba9bfa7d69de2fc1d3157ba47c028bdae5d507a26a3c64 - languageName: node - linkType: hard - "esbuild@npm:^0.20.1": version: 0.20.2 resolution: "esbuild@npm:0.20.2" @@ -11225,6 +11141,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.5": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + 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-x64": + optional: true + "@esbuild/openbsd-x64": + 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: d2ff2ca84d30cce8e871517374d6c2290835380dc7cd413b2d49189ed170d45e407be14de2cb4794cf76f75cf89955c4714726ebd3de7444b3046f5cab23ab6b + languageName: node + linkType: hard + "esbuild@npm:~0.19.10": version: 0.19.11 resolution: "esbuild@npm:0.19.11" @@ -13344,9 +13340,9 @@ __metadata: "@tldraw/utils": "workspace:*" "@types/node": "npm:~20.11" discord-api-types: "npm:^0.37.67" - esbuild: "npm:^0.18.4" + esbuild: "npm:^0.21.5" typescript: "npm:^5.3.3" - wrangler: "npm:3.61.0" + wrangler: "npm:3.62.0" languageName: unknown linkType: soft @@ -14430,9 +14426,9 @@ __metadata: linkType: hard "itty-router@npm:^4.0.13": - version: 4.0.27 - resolution: "itty-router@npm:4.0.27" - checksum: ebb959388b1033f3d80ba2575c2d90fa649c1d5370d977879513cc46e8fd78159b7140d2a66853af6be98f7d740f8609a2c5aa7381506eaa1f1a46268fd2a95f + version: 4.2.2 + resolution: "itty-router@npm:4.2.2" + checksum: ead44fd46ea358776dc2bb120970eff5ab0acb10ad82c384eba9b361c6eba7f5971408f80cbc3655004cb12ae53dd77a85de236bdb215cef896c2589f5096854 languageName: node linkType: hard @@ -17138,9 +17134,9 @@ __metadata: languageName: node linkType: hard -"miniflare@npm:3.20240610.1": - version: 3.20240610.1 - resolution: "miniflare@npm:3.20240610.1" +"miniflare@npm:3.20240620.0": + version: 3.20240620.0 + resolution: "miniflare@npm:3.20240620.0" dependencies: "@cspotcode/source-map-support": "npm:0.8.1" acorn: "npm:^8.8.0" @@ -17150,13 +17146,13 @@ __metadata: glob-to-regexp: "npm:^0.4.1" stoppable: "npm:^1.1.0" undici: "npm:^5.28.4" - workerd: "npm:1.20240610.1" + workerd: "npm:1.20240620.1" ws: "npm:^8.14.2" youch: "npm:^3.2.2" zod: "npm:^3.22.3" bin: miniflare: bootstrap.js - checksum: ebd4d979294af03838c86275503f9f9c6d55fd4f17aafbd07421252660521ae48229358fa9ea06a1d24c052ce0de471c75213dbf6ad19e78a8b641b092881b5c + checksum: 94d31f7b5efdf9838fba040b569576e053a273b138797831c32c5a64c53ed086c063114bbb9356d7b8b34830af4cfc4495fad1ea9aab4c9c9ed54c727aceada4 languageName: node linkType: hard @@ -20584,13 +20580,6 @@ __metadata: languageName: node linkType: hard -"source-map@npm:0.5.6": - version: 0.5.6 - resolution: "source-map@npm:0.5.6" - checksum: c62fe98e106c762307eea3a982242c1a76a31bc762da10fe2dda12252d423c163e0cd45d313330c8bd040cc5121702511138252308f72b8a9273825e81e4db30 - languageName: node - linkType: hard - "source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.1": version: 0.6.1 resolution: "source-map@npm:0.6.1" @@ -20739,15 +20728,6 @@ __metadata: languageName: node linkType: hard -"stack-generator@npm:^2.0.5": - version: 2.0.10 - resolution: "stack-generator@npm:2.0.10" - dependencies: - stackframe: "npm:^1.3.4" - checksum: 4fc3978a934424218a0aa9f398034e1f78153d5ff4f4ff9c62478c672debb47dd58de05b09fc3900530cbb526d72c93a6e6c9353bacc698e3b1c00ca3dda0c47 - languageName: node - linkType: hard - "stack-utils@npm:^2.0.3": version: 2.0.6 resolution: "stack-utils@npm:2.0.6" @@ -20757,34 +20737,6 @@ __metadata: languageName: node linkType: hard -"stackframe@npm:^1.3.4": - version: 1.3.4 - resolution: "stackframe@npm:1.3.4" - checksum: 29ca71c1fd17974c1c178df0236b1407bc65f6ea389cc43dec000def6e42ff548d4453de9a85b76469e2ae2b2abdd802c6b6f3db947c05794efbd740d1cf4121 - languageName: node - linkType: hard - -"stacktrace-gps@npm:^3.0.4": - version: 3.1.2 - resolution: "stacktrace-gps@npm:3.1.2" - dependencies: - source-map: "npm:0.5.6" - stackframe: "npm:^1.3.4" - checksum: 21cb60ce0990f7a661e964cf4bdef1e70dda2286fb628fbd0fd1e69e8925138433d08ed84969de2d396b3b91515e15336a502f777c26587db89f3933d6f63f9b - languageName: node - linkType: hard - -"stacktrace-js@npm:2.0.2": - version: 2.0.2 - resolution: "stacktrace-js@npm:2.0.2" - dependencies: - error-stack-parser: "npm:^2.0.6" - stack-generator: "npm:^2.0.5" - stacktrace-gps: "npm:^3.0.4" - checksum: e5f60a09852687e4a9206927fe1078e24d63e00a71a2dcddd67940e9504a54931a3454439d5b4e3e0e62aeb979be810573e8d3332fbef0dbfa335a8781b4b57c - languageName: node - linkType: hard - "stacktracey@npm:^2.1.8": version: 2.1.8 resolution: "stacktracey@npm:2.1.8" @@ -21424,7 +21376,7 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^5.57.0" "@typescript-eslint/parser": "npm:^5.57.0" assert: "npm:^2.0.0" - esbuild: "npm:^0.18.4" + esbuild: "npm:^0.21.5" eslint: "npm:^8.37.0" fs-extra: "npm:^11.1.0" lazyrepo: "npm:0.0.0-alpha.27" @@ -21527,18 +21479,22 @@ __metadata: languageName: node linkType: hard -"toucan-js@npm:^2.7.0": - version: 2.7.0 - resolution: "toucan-js@npm:2.7.0" +"toml@npm:^3.0.0": + version: 3.0.0 + resolution: "toml@npm:3.0.0" + checksum: cfef0966868d552bd02e741f30945a611f70841b7cddb07ea2b17441fe32543985bc0a7c0dcf7971af26fcaf8a17712a485d911f46bfe28644536e9a71a2bd09 + languageName: node + linkType: hard + +"toucan-js@npm:^3.4.0": + version: 3.4.0 + resolution: "toucan-js@npm:3.4.0" dependencies: - "@sentry/core": "npm:6.19.6" - "@sentry/hub": "npm:6.19.6" - "@sentry/types": "npm:6.19.6" - "@sentry/utils": "npm:6.19.6" - "@types/cookie": "npm:0.5.0" - cookie: "npm:0.5.0" - stacktrace-js: "npm:2.0.2" - checksum: 84082e0a86551123bdec369af03569109effd38881be65296e94bdca9d9fb615c673f24c8487f6eda249ab5e0e09b45809d28c6e7c83506e6b168a6f51ce9b5d + "@sentry/core": "npm:7.112.2" + "@sentry/integrations": "npm:7.112.2" + "@sentry/types": "npm:7.112.2" + "@sentry/utils": "npm:7.112.2" + checksum: e931a758c2fc70de5453198d002e368d31fa345a768d40fedad17471bf4a843fce2db5587099a66e62ffb0a99011d830122623d9652014034cff48b2fb629adf languageName: node linkType: hard @@ -21823,7 +21779,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^1.11.1, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": +"tslib@npm:^1.11.1, tslib@npm:^1.8.1, tslib@npm:^1.9.0": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb @@ -23162,15 +23118,15 @@ __metadata: languageName: node linkType: hard -"workerd@npm:1.20240610.1": - version: 1.20240610.1 - resolution: "workerd@npm:1.20240610.1" +"workerd@npm:1.20240620.1": + version: 1.20240620.1 + resolution: "workerd@npm:1.20240620.1" dependencies: - "@cloudflare/workerd-darwin-64": "npm:1.20240610.1" - "@cloudflare/workerd-darwin-arm64": "npm:1.20240610.1" - "@cloudflare/workerd-linux-64": "npm:1.20240610.1" - "@cloudflare/workerd-linux-arm64": "npm:1.20240610.1" - "@cloudflare/workerd-windows-64": "npm:1.20240610.1" + "@cloudflare/workerd-darwin-64": "npm:1.20240620.1" + "@cloudflare/workerd-darwin-arm64": "npm:1.20240620.1" + "@cloudflare/workerd-linux-64": "npm:1.20240620.1" + "@cloudflare/workerd-linux-arm64": "npm:1.20240620.1" + "@cloudflare/workerd-windows-64": "npm:1.20240620.1" dependenciesMeta: "@cloudflare/workerd-darwin-64": optional: true @@ -23184,7 +23140,7 @@ __metadata: optional: true bin: workerd: bin/workerd - checksum: c37cd30c25fbdc7f97a296cf4b1a8ad2dbb65621a9c4b4bb24cb8fc00d9674c6610c5d2e5dc87c6cda83aa7b3b23a63d84b924ec1d9a3881622a9284590723f6 + checksum: 0ea5331eca365dd900c3609cad8b8cb20cbf7985074deb5717442cc76d6b3574e22e8bbfba4327046a346e46b6e384ed32d648646c14cde0f5cbb99c046148f6 languageName: node linkType: hard @@ -23195,18 +23151,19 @@ __metadata: languageName: node linkType: hard -"wrangler@npm:3.61.0": - version: 3.61.0 - resolution: "wrangler@npm:3.61.0" +"wrangler@npm:3.62.0": + version: 3.62.0 + resolution: "wrangler@npm:3.62.0" dependencies: - "@cloudflare/kv-asset-handler": "npm:0.3.3" + "@cloudflare/kv-asset-handler": "npm:0.3.4" "@esbuild-plugins/node-globals-polyfill": "npm:^0.2.3" "@esbuild-plugins/node-modules-polyfill": "npm:^0.2.2" blake3-wasm: "npm:^2.1.5" chokidar: "npm:^3.5.3" + date-fns: "npm:^3.6.0" esbuild: "npm:0.17.19" fsevents: "npm:~2.3.2" - miniflare: "npm:3.20240610.1" + miniflare: "npm:3.20240620.0" nanoid: "npm:^3.3.3" path-to-regexp: "npm:^6.2.0" resolve: "npm:^1.22.8" @@ -23216,7 +23173,7 @@ __metadata: unenv: "npm:unenv-nightly@1.10.0-1717606461.a117952" xxhash-wasm: "npm:^1.0.1" peerDependencies: - "@cloudflare/workers-types": ^4.20240605.0 + "@cloudflare/workers-types": ^4.20240620.0 dependenciesMeta: fsevents: optional: true @@ -23226,7 +23183,7 @@ __metadata: bin: wrangler: bin/wrangler.js wrangler2: bin/wrangler.js - checksum: 91594c182fbfa65ffb1d3946829c3a51258d2ce6d7c83f0447f043e3bdb237096c4c69eda5e028f1e9742d8c0ddeae01c87512f438ab3635c5db9e923da3412b + checksum: c5c9f0260eeafbdab56739c33281cdd8ef6f1d4e8109c57c44cbc60b09aa272757a7a4e8236f8922372b5e929b47a20e44be003a5779b998e963543165c7fda2 languageName: node linkType: hard