migrate from yarn 1 to pnpm

- switch root package manager to pnpm 10.33.4 via packageManager field
- add .npmrc with node-linker=hoisted for RN/Expo compatibility
- convert yarn resolutions to pnpm.overrides; pin psl@1.9.0 and @types/psl@1.1.1
  to keep types resolving under exports-aware resolution
- pin react-compiler-runtime and babel-plugin-react-compiler to real rc.3 (the
  deprecated "Wrong version name was published" tag would otherwise resolve)
- add pnpm.onlyBuiltDependencies allowlist for @sentry/cli, core-js-pure,
  esbuild, unrs-resolver
- regenerate pnpm-lock.yaml; delete yarn.lock; drop postinstall-postinstall
- update all workflows, Dockerfile, Dockerfile.embedr (root-level), Makefile,
  conductor.json; bskyembed/bskylink/bskyogcard/dev-env stay on yarn
- update docs (CLAUDE.md, docs/build.md, docs/testing.md, docs/localization.md,
  bskyweb/README.md, scripts/push-notification/README.md, BlueskyClip/README.md)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-05-12 15:02:41 +03:00
parent e52b7df39b
commit bcc71abee6
33 changed files with 19632 additions and 17115 deletions
+3 -3
View File
@@ -1,9 +1,9 @@
{ {
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(yarn typecheck *)", "Bash(pnpm typecheck *)",
"Bash(yarn lint *)", "Bash(pnpm lint *)",
"Bash(yarn test *)" "Bash(pnpm test *)"
] ]
} }
} }
+8 -6
View File
@@ -32,11 +32,13 @@ jobs:
with: with:
fetch-depth: 5 fetch-depth: 5
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 🪛 Setup jq - name: 🪛 Setup jq
uses: dcarbone/install-jq-action@v2 uses: dcarbone/install-jq-action@v2
@@ -49,7 +51,7 @@ jobs:
token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
- name: ⛏️ Setup EAS local builds - name: ⛏️ Setup EAS local builds
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- uses: actions/setup-java@v4 - uses: actions/setup-java@v4
with: with:
@@ -57,10 +59,10 @@ jobs:
java-version: "17" java-version: "17"
- name: ⚙️ Install dependencies - name: ⚙️ Install dependencies
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build 2>&1 | tee i18n.log run: pnpm intl:build 2>&1 | tee i18n.log
- name: Check for i18n compilation errors - name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
@@ -88,7 +90,7 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn use-build-number-with-bump pnpm use-build-number-with-bump
eas build -p android eas build -p android
--profile $PROFILE --profile $PROFILE
--local --output build.aab --non-interactive --local --output build.aab --non-interactive
@@ -162,7 +164,7 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn use-build-number-with-bump pnpm use-build-number-with-bump
eas build -p android eas build -p android
--profile production-apk --profile production-apk
--local --output build.apk --non-interactive --local --output build.apk --non-interactive
+11 -9
View File
@@ -32,11 +32,13 @@ jobs:
with: with:
fetch-depth: 5 fetch-depth: 5
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 🪛 Setup jq - name: 🪛 Setup jq
uses: dcarbone/install-jq-action@v2 uses: dcarbone/install-jq-action@v2
@@ -49,10 +51,10 @@ jobs:
token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
- name: ⛏️ Setup EAS local builds - name: ⛏️ Setup EAS local builds
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- name: ⚙️ Install dependencies - name: ⚙️ Install dependencies
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
- uses: maxim-lobanov/setup-xcode@v1 - uses: maxim-lobanov/setup-xcode@v1
with: with:
@@ -68,12 +70,12 @@ jobs:
id: pods-cache id: pods-cache
with: with:
path: ./ios/Pods path: ./ios/Pods
# We'll use the yarn.lock for our hash since we don't yet have a Podfile.lock. Pod versions will not # We'll use the pnpm-lock.yaml for our hash since we don't yet have a Podfile.lock. Pod versions will not
# change unless the yarn version changes as well. # change unless the pnpm version changes as well.
key: ${{ runner.os }}-pods-${{ hashFiles('yarn.lock') }} key: ${{ runner.os }}-pods-${{ hashFiles('pnpm-lock.yaml') }}
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build 2>&1 | tee i18n.log run: pnpm intl:build 2>&1 | tee i18n.log
- name: Check for i18n compilation errors - name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
@@ -100,7 +102,7 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn use-build-number-with-bump pnpm use-build-number-with-bump
eas build -p ios eas build -p ios
--profile $PROFILE --profile $PROFILE
--local --output build.tar.gz --non-interactive --local --output build.tar.gz --non-interactive
@@ -148,7 +150,7 @@ jobs:
SENTRY_ORG=blueskyweb SENTRY_ORG=blueskyweb
SENTRY_PROJECT=app SENTRY_PROJECT=app
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
yarn sentry-cli debug-files upload "$BUILD_DIR/Bluesky.app.dSYM.zip" --include-sources pnpm sentry-cli debug-files upload "$BUILD_DIR/Bluesky.app.dSYM.zip" --include-sources
- name: 📚 Get version from package.json - name: 📚 Get version from package.json
id: get-build-info id: get-build-info
+29 -23
View File
@@ -56,11 +56,13 @@ jobs:
if: ${{ github.ref != 'refs/heads/main' }} if: ${{ github.ref != 'refs/heads/main' }}
run: git fetch origin main:main --depth 100 run: git fetch origin main:main --depth 100
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 📷 Check fingerprint and install dependencies - name: 📷 Check fingerprint and install dependencies
id: fingerprint id: fingerprint
@@ -70,22 +72,22 @@ jobs:
previous-commit-tag: ${{ inputs.runtimeVersion }} previous-commit-tag: ${{ inputs.runtimeVersion }}
- name: Lint check - name: Lint check
run: yarn lint run: pnpm lint
- name: Lint lockfile - name: Lint lockfile
run: yarn lockfile-lint run: pnpm lockfile-lint
- name: Prettier check - name: Prettier check
run: yarn prettier --check . run: pnpm prettier --check .
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build 2>&1 | tee i18n.log run: pnpm intl:build 2>&1 | tee i18n.log
- name: Check for i18n compilation errors - name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
- name: Type check - name: Type check
run: yarn typecheck run: pnpm typecheck
- name: 🔨 Setup EAS - name: 🔨 Setup EAS
uses: expo/expo-github-action@main uses: expo/expo-github-action@main
@@ -97,7 +99,7 @@ jobs:
- name: ⛏️ Setup Expo - name: ⛏️ Setup Expo
if: ${{ !steps.fingerprint.outputs.includes-changes }} if: ${{ !steps.fingerprint.outputs.includes-changes }}
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- name: 🪛 Setup jq - name: 🪛 Setup jq
if: ${{ !steps.fingerprint.outputs.includes-changes }} if: ${{ !steps.fingerprint.outputs.includes-changes }}
@@ -130,11 +132,11 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn export pnpm export
- name: 📦 Package Bundle and 🚀 Deploy - name: 📦 Package Bundle and 🚀 Deploy
if: ${{ !steps.fingerprint.outputs.includes-changes }} if: ${{ !steps.fingerprint.outputs.includes-changes }}
run: yarn use-build-number bash scripts/bundleUpdate.sh run: pnpm use-build-number bash scripts/bundleUpdate.sh
env: env:
DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }} DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
RUNTIME_VERSION: ${{ inputs.runtimeVersion }} RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
@@ -176,11 +178,13 @@ jobs:
with: with:
fetch-depth: 5 fetch-depth: 5
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 🔨 Setup EAS - name: 🔨 Setup EAS
uses: expo/expo-github-action@main uses: expo/expo-github-action@main
@@ -190,10 +194,10 @@ jobs:
token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
- name: ⛏️ Setup EAS local builds - name: ⛏️ Setup EAS local builds
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- name: ⚙️ Install dependencies - name: ⚙️ Install dependencies
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
- uses: maxim-lobanov/setup-xcode@v1 - uses: maxim-lobanov/setup-xcode@v1
with: with:
@@ -209,12 +213,12 @@ jobs:
id: pods-cache id: pods-cache
with: with:
path: ./ios/Pods path: ./ios/Pods
# We'll use the yarn.lock for our hash since we don't yet have a Podfile.lock. Pod versions will not # We'll use the pnpm-lock.yaml for our hash since we don't yet have a Podfile.lock. Pod versions will not
# change unless the yarn version changes as well. # change unless the pnpm version changes as well.
key: ${{ runner.os }}-pods-${{ hashFiles('yarn.lock') }} key: ${{ runner.os }}-pods-${{ hashFiles('pnpm-lock.yaml') }}
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build run: pnpm intl:build
# EXPO_PUBLIC_ENV is handled in eas.json # EXPO_PUBLIC_ENV is handled in eas.json
- name: Env - name: Env
@@ -236,7 +240,7 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn use-build-number-with-bump pnpm use-build-number-with-bump
eas build -p ios eas build -p ios
--profile testflight --profile testflight
--local --output build.tar.gz --non-interactive --local --output build.tar.gz --non-interactive
@@ -284,7 +288,7 @@ jobs:
SENTRY_ORG=blueskyweb SENTRY_ORG=blueskyweb
SENTRY_PROJECT=app SENTRY_PROJECT=app
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
yarn sentry-cli debug-files upload "$BUILD_DIR/Bluesky.app.dSYM.zip" --include-sources pnpm sentry-cli debug-files upload "$BUILD_DIR/Bluesky.app.dSYM.zip" --include-sources
- name: ⬇️ Restore Cache - name: ⬇️ Restore Cache
id: get-base-commit id: get-base-commit
@@ -324,11 +328,13 @@ jobs:
with: with:
fetch-depth: 5 fetch-depth: 5
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 🔨 Setup EAS - name: 🔨 Setup EAS
uses: expo/expo-github-action@main uses: expo/expo-github-action@main
@@ -338,7 +344,7 @@ jobs:
token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
- name: ⛏️ Setup EAS local builds - name: ⛏️ Setup EAS local builds
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- uses: actions/setup-java@v4 - uses: actions/setup-java@v4
with: with:
@@ -346,10 +352,10 @@ jobs:
java-version: "17" java-version: "17"
- name: ⚙️ Install dependencies - name: ⚙️ Install dependencies
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build run: pnpm intl:build
# EXPO_PUBLIC_ENV is handled in eas.json # EXPO_PUBLIC_ENV is handled in eas.json
- name: Env - name: Env
@@ -372,7 +378,7 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn use-build-number-with-bump pnpm use-build-number-with-bump
eas build -p android eas build -p android
--profile testflight-android --profile testflight-android
--local --output build.apk --non-interactive --local --output build.apk --non-interactive
+15 -13
View File
@@ -41,46 +41,48 @@ jobs:
v=$(grep -oE '"node":[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"' eas.json | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u) v=$(grep -oE '"node":[[:space:]]*"[0-9]+\.[0-9]+\.[0-9]+"' eas.json | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
check "eas.json" "$v" check "eas.json" "$v"
exit $rc exit $rc
- uses: pnpm/action-setup@v4
- name: Install node - name: Install node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: Yarn install - name: pnpm install
uses: Wandalen/wretry.action@master uses: Wandalen/wretry.action@master
with: with:
command: yarn --frozen-lockfile command: pnpm install --frozen-lockfile
attempt_limit: 3 attempt_limit: 3
attempt_delay: 2000 attempt_delay: 2000
- name: Lint check - name: Lint check
run: yarn lint run: pnpm lint
- name: Lint lockfile - name: Lint lockfile
run: yarn lockfile-lint run: pnpm lockfile-lint
- name: Prettier check - name: Prettier check
run: yarn prettier --check . run: pnpm prettier --check .
- name: Check & compile i18n - name: Check & compile i18n
run: yarn intl:build run: pnpm intl:build
- name: Type check - name: Type check
run: yarn typecheck run: pnpm typecheck
testing: testing:
name: Run tests name: Run tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out Git repository - name: Check out Git repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- name: Install node - name: Install node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: Yarn install - name: pnpm install
uses: Wandalen/wretry.action@master uses: Wandalen/wretry.action@master
with: with:
command: yarn --frozen-lockfile command: pnpm install --frozen-lockfile
attempt_limit: 3 attempt_limit: 3
attempt_delay: 2000 attempt_delay: 2000
- name: Check & compile i18n - name: Check & compile i18n
run: yarn intl:build run: pnpm intl:build
- name: Run tests - name: Run tests
run: | run: |
NODE_ENV=test yarn test --forceExit NODE_ENV=test pnpm test --forceExit
@@ -19,19 +19,20 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ssh-key: ${{secrets.GH_ACTION_DEPLOY_KEY}} ssh-key: ${{secrets.GH_ACTION_DEPLOY_KEY}}
- uses: pnpm/action-setup@v4
- name: Install node - name: Install node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: Yarn install - name: pnpm install
uses: Wandalen/wretry.action@master uses: Wandalen/wretry.action@master
with: with:
command: yarn --frozen-lockfile command: pnpm install --frozen-lockfile
attempt_limit: 3 attempt_limit: 3
attempt_delay: 2000 attempt_delay: 2000
- name: Extract language strings - name: Extract language strings
run: yarn intl:extract run: pnpm intl:extract
- name: Create commit - name: Create commit
uses: stefanzweifel/git-auto-commit-action@v5 uses: stefanzweifel/git-auto-commit-action@v5
with: with:
+11 -9
View File
@@ -117,29 +117,31 @@ jobs:
with: with:
ref: ${{ steps.pr-info.outputs.head-sha }} ref: ${{ steps.pr-info.outputs.head-sha }}
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: Install dependencies - name: Install dependencies
run: yarn install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Lint check - name: Lint check
run: yarn lint run: pnpm lint
- name: Lint lockfile - name: Lint lockfile
run: yarn lockfile-lint run: pnpm lockfile-lint
- name: 🔤 Compile translations - name: 🔤 Compile translations
run: yarn intl:build 2>&1 | tee i18n.log run: pnpm intl:build 2>&1 | tee i18n.log
- name: Check for i18n compilation errors - name: Check for i18n compilation errors
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
- name: Type check - name: Type check
run: yarn typecheck run: pnpm typecheck
- name: 🔨 Setup EAS - name: 🔨 Setup EAS
uses: expo/expo-github-action@main uses: expo/expo-github-action@main
@@ -149,7 +151,7 @@ jobs:
token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
- name: ⛏️ Setup Expo - name: ⛏️ Setup Expo
run: yarn global add eas-cli-local-build-plugin run: pnpm add -g eas-cli-local-build-plugin
- name: 🪛 Setup jq - name: 🪛 Setup jq
uses: dcarbone/install-jq-action@v2 uses: dcarbone/install-jq-action@v2
@@ -175,10 +177,10 @@ jobs:
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }} SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }} SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
yarn export pnpm export
- name: 📦 Package Bundle and 🚀 Deploy - name: 📦 Package Bundle and 🚀 Deploy
run: yarn use-build-number bash scripts/bundleUpdate.sh run: pnpm use-build-number bash scripts/bundleUpdate.sh
env: env:
DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }} DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
CHANNEL_NAME: pull-request-${{ github.event.issue.number }} CHANNEL_NAME: pull-request-${{ github.event.issue.number }}
+12 -8
View File
@@ -28,11 +28,13 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: Ensure tracking relevant branches and checkout base - name: Ensure tracking relevant branches and checkout base
env: env:
@@ -56,12 +58,12 @@ jobs:
git config --global user.email "github-actions[bot]@users.noreply.github.com" git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]" git config --global user.name "github-actions[bot]"
git merge --no-edit $HEAD_REF git merge --no-edit $HEAD_REF
yarn install pnpm install
yarn intl:build pnpm intl:build
- name: 🔦 Generate stats file for PR - name: 🔦 Generate stats file for PR
run: | run: |
yarn generate-webpack-stats-file pnpm generate-webpack-stats-file
mv stats.json ../stats-new.json mv stats.json ../stats-new.json
- name: ⬇️ Get base stats from cache - name: ⬇️ Get base stats from cache
@@ -80,9 +82,9 @@ jobs:
- name: 🔦 Generate stats file from base commit - name: 🔦 Generate stats file from base commit
if: ${{ !steps.get-base-stats.outputs.cache-hit }} if: ${{ !steps.get-base-stats.outputs.cache-hit }}
run: | run: |
yarn install pnpm install
yarn intl:build pnpm intl:build
yarn generate-webpack-stats-file pnpm generate-webpack-stats-file
mv stats.json stats-base.json mv stats.json stats-base.json
- name: Get diff - name: Get diff
@@ -116,11 +118,13 @@ jobs:
run: git fetch origin main:main --depth 100 run: git fetch origin main:main --depth 100
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
- uses: pnpm/action-setup@v4
- name: 🔧 Setup Node - name: 🔧 Setup Node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: yarn cache: pnpm
- name: 📷 Check fingerprint and install dependencies - name: 📷 Check fingerprint and install dependencies
id: fingerprint id: fingerprint
@@ -7,8 +7,8 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
verify-yarn-lock: verify-pnpm-lock:
name: No manual yarn.lock edits name: No manual pnpm-lock.yaml edits
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out PR HEAD - name: Check out PR HEAD
@@ -21,28 +21,30 @@ jobs:
BASE_REF: ${{ github.base_ref }} BASE_REF: ${{ github.base_ref }}
run: git fetch origin $BASE_REF --depth=1 run: git fetch origin $BASE_REF --depth=1
- uses: pnpm/action-setup@v4
- name: Install node - name: Install node
uses: actions/setup-node@v6 uses: actions/setup-node@v6
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
- name: Reset yarn.lock to base - name: Reset pnpm-lock.yaml to base
env: env:
BASE_REF: ${{ github.base_ref }} BASE_REF: ${{ github.base_ref }}
run: git show "origin/$BASE_REF:yarn.lock" > yarn.lock run: git show "origin/$BASE_REF:pnpm-lock.yaml" > pnpm-lock.yaml
- name: Yarn install - name: pnpm install
uses: Wandalen/wretry.action@master uses: Wandalen/wretry.action@master
with: with:
# Fine to skip scripts since we don't run any code # Fine to skip scripts since we don't run any code
command: yarn install --ignore-scripts command: pnpm install --ignore-scripts
attempt_limit: 3 attempt_limit: 3
attempt_delay: 2000 attempt_delay: 2000
- name: Verify yarn.lock - name: Verify pnpm-lock.yaml
run: | run: |
git diff --quiet --exit-code || { git diff --quiet --exit-code || {
echo '::error::`yarn.lock` does not match what Yarn would generate given the base `yarn.lock` and the head `package.json`.' echo '::error::`pnpm-lock.yaml` does not match what pnpm would generate given the base `pnpm-lock.yaml` and the head `package.json`.'
echo '::error:: - If this is intentional, you can ignore this check.' echo '::error:: - If this is intentional, you can ignore this check.'
echo '::error:: - If this is unintentional, apply the following diff:' echo '::error:: - If this is unintentional, apply the following diff:'
git --no-pager diff git --no-pager diff
+3
View File
@@ -0,0 +1,3 @@
node-linker=hoisted
auto-install-peers=true
strict-peer-dependencies=false
+14 -14
View File
@@ -22,25 +22,25 @@ Prefer using the latest features available for each of these libraries (exact ve
```bash ```bash
# Development # Development
yarn start # Start Expo dev server pnpm start # Start Expo dev server
yarn web # Start web version pnpm web # Start web version
yarn android # Run on Android pnpm android # Run on Android
yarn ios # Run on iOS pnpm ios # Run on iOS
# Testing & Quality # Testing & Quality
# IMPORTANT: Always use these yarn scripts, never call the underlying tools directly # IMPORTANT: Always use these pnpm scripts, never call the underlying tools directly
yarn test # Run Jest tests pnpm test # Run Jest tests
yarn lint # Run ESLint pnpm lint # Run ESLint
yarn typecheck # Run TypeScript type checking pnpm typecheck # Run TypeScript type checking
# Internationalization # Internationalization
# DO NOT run these commands - extraction and compilation are handled by CI # DO NOT run these commands - extraction and compilation are handled by CI
yarn intl:extract # Extract translation strings (nightly CI job) pnpm intl:extract # Extract translation strings (nightly CI job)
yarn intl:compile # Compile translations for runtime (nightly CI job) pnpm intl:compile # Compile translations for runtime (nightly CI job)
# Build # Build
yarn build-web # Build web version pnpm build-web # Build web version
yarn prebuild # Generate native projects pnpm prebuild # Generate native projects
``` ```
## Project Structure ## Project Structure
@@ -503,8 +503,8 @@ function MyComponent() {
```bash ```bash
# DO NOT run these commands - extraction and compilation are handled by a nightly CI job # DO NOT run these commands - extraction and compilation are handled by a nightly CI job
yarn intl:extract # Extract new strings to locale files pnpm intl:extract # Extract new strings to locale files
yarn intl:compile # Compile translations for runtime pnpm intl:compile # Compile translations for runtime
``` ```
## State Management ## State Management
+4 -4
View File
@@ -65,11 +65,11 @@ RUN \. "$NVM_DIR/nvm.sh" && \
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER" >> .env && \ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$EXPO_PUBLIC_BUNDLE_IDENTIFIER" >> .env && \
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \ echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env && \
echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env && \ echo "EXPO_PUBLIC_SENTRY_DSN=$EXPO_PUBLIC_SENTRY_DSN" >> .env && \
npm install --global yarn && \ npm install --global pnpm@10.33.4 && \
yarn && \ pnpm install --frozen-lockfile && \
yarn intl:build 2>&1 | tee i18n.log && \ pnpm intl:build 2>&1 | tee i18n.log && \
if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi && \ if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compile errors!\n\n"; fi && \
SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER yarn build-web SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN SENTRY_RELEASE=$EXPO_PUBLIC_RELEASE_VERSION SENTRY_DIST=$EXPO_PUBLIC_BUNDLE_IDENTIFIER pnpm build-web
# DEBUG # DEBUG
RUN find ./bskyweb/static && find ./web-build/static RUN find ./bskyweb/static && find ./web-build/static
+4 -4
View File
@@ -29,11 +29,11 @@ RUN mkdir --parents $NVM_DIR && \
RUN \. "$NVM_DIR/nvm.sh" && \ RUN \. "$NVM_DIR/nvm.sh" && \
nvm install $NODE_VERSION && \ nvm install $NODE_VERSION && \
nvm use $NODE_VERSION && \ nvm use $NODE_VERSION && \
npm install --global yarn && \ npm install --global pnpm@10.33.4 yarn && \
yarn && \ pnpm install --frozen-lockfile && \
cd bskyembed && yarn install --frozen-lockfile && cd .. && \ cd bskyembed && yarn install --frozen-lockfile && cd .. && \
yarn intl:build && \ pnpm intl:build && \
yarn build-embed pnpm build-embed
# DEBUG # DEBUG
RUN find ./bskyweb/embedr-static && find ./bskyweb/embedr-templates && find ./bskyembed/dist RUN find ./bskyweb/embedr-static && find ./bskyweb/embedr-templates && find ./bskyembed/dist
+11 -11
View File
@@ -10,33 +10,33 @@ help: ## Print info about all commands
.PHONY: build-web .PHONY: build-web
build-web: ## Compile web bundle, copy to bskyweb directory build-web: ## Compile web bundle, copy to bskyweb directory
yarn intl:build pnpm intl:build
yarn build-web pnpm build-web
.PHONY: build-web-embed .PHONY: build-web-embed
build-web-embed: ## Compile web embed bundle, copy to bskyweb/embedr* directories build-web-embed: ## Compile web embed bundle, copy to bskyweb/embedr* directories
yarn intl:build pnpm intl:build
yarn build-embed pnpm build-embed
.PHONY: test .PHONY: test
test: ## Run all tests test: ## Run all tests
NODE_ENV=test yarn test NODE_ENV=test pnpm test
.PHONY: lint .PHONY: lint
lint: ## Run style checks and verify syntax lint: ## Run style checks and verify syntax
yarn run lint pnpm run lint
#.PHONY: fmt #.PHONY: fmt
#fmt: ## Run syntax re-formatting #fmt: ## Run syntax re-formatting
# yarn prettier # pnpm prettier
.PHONY: deps .PHONY: deps
deps: ## Installs dependent libs using 'yarn install' deps: ## Installs dependent libs using 'pnpm install'
yarn install --frozen-lockfile pnpm install --frozen-lockfile
cd bskyembed && yarn install --frozen-lockfile cd bskyembed && yarn install --frozen-lockfile
.PHONY: nvm-setup .PHONY: nvm-setup
nvm-setup: ## Use NVM to install and activate node+yarn nvm-setup: ## Use NVM to install and activate node+pnpm
nvm install 20 nvm install 20
nvm use 20 nvm use 20
npm install --global yarn npm install --global pnpm
+5 -5
View File
@@ -10,13 +10,13 @@ like:
# install nodejs # install nodejs
nvm install nvm install
nvm use nvm use
npm install --global yarn npm install --global pnpm
# setup tools and deps (in top level of this repo) # setup tools and deps (in top level of this repo)
yarn install --frozen-lockfile pnpm install --frozen-lockfile
# run yarn web dev server, if you wanted # run pnpm web dev server, if you wanted
yarn web pnpm web
``` ```
Then build and copy over the big 'ol `bundle.web.js` file: Then build and copy over the big 'ol `bundle.web.js` file:
@@ -24,7 +24,7 @@ Then build and copy over the big 'ol `bundle.web.js` file:
```bash ```bash
# in the top level of this repo # in the top level of this repo
yarn build-web pnpm build-web
``` ```
### Golang Daemon ### Golang Daemon
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"scripts": { "scripts": {
"setup": "yarn install", "setup": "pnpm install --frozen-lockfile",
"run": "yarn web --port $CONDUCTOR_PORT" "run": "pnpm web --port $CONDUCTOR_PORT"
} }
} }
+17 -17
View File
@@ -2,8 +2,8 @@
## Running Web App ## Running Web App
- `yarn` - `pnpm install`
- `yarn web` - `pnpm web`
You're all set! You're all set!
@@ -36,7 +36,7 @@ This is NOT required when developing for web.
### Running the Native App ### Running the Native App
- iOS: `yarn ios` - iOS: `pnpm ios`
- Xcode must be installed for this to run. - Xcode must be installed for this to run.
- A simulator must be preconfigured in Xcode settings. - A simulator must be preconfigured in Xcode settings.
- if no iOS versions are available, install the iOS runtime at `Xcode > Settings > Platforms`. - if no iOS versions are available, install the iOS runtime at `Xcode > Settings > Platforms`.
@@ -48,22 +48,22 @@ This is NOT required when developing for web.
- In addition, ensure Xcode Command Line Tools are installed using `xcode-select --install`. - In addition, ensure Xcode Command Line Tools are installed using `xcode-select --install`.
- Expo will require you to configure Xcode Signing. Follow the linked instructions. Error messages in Xcode related to the signing process can be safely ignored when installing on the iOS Simulator; Expo merely requires the profile to exist in order to install the app on the Simulator. - Expo will require you to configure Xcode Signing. Follow the linked instructions. Error messages in Xcode related to the signing process can be safely ignored when installing on the iOS Simulator; Expo merely requires the profile to exist in order to install the app on the Simulator.
- Make sure you do have a certificate: open Xcode > Settings > Accounts > (sign-in) > Manage Certificates > + > Apple Development > Done. - Make sure you do have a certificate: open Xcode > Settings > Accounts > (sign-in) > Manage Certificates > + > Apple Development > Done.
- If you still encounter issues, try `rm -rf ios` before trying to build again (`yarn ios`) - If you still encounter issues, try `rm -rf ios` before trying to build again (`pnpm ios`)
- Android: `yarn android` - Android: `pnpm android`
- Install "Android Studio" - Install "Android Studio"
- Make sure you have the Android SDK installed (Android Studio > Tools > Android SDK). - Make sure you have the Android SDK installed (Android Studio > Tools > Android SDK).
- In "SDK Platforms": "Android x" (where x is Android's current version). - In "SDK Platforms": "Android x" (where x is Android's current version).
- In "SDK Tools": "Android SDK Build-Tools" and "Android Emulator" are required. - In "SDK Tools": "Android SDK Build-Tools" and "Android Emulator" are required.
- Add `export ANDROID_HOME=/Users/<your_username>/Library/Android/sdk` to your `.zshrc` or `.bashrc` (and restart your terminal). - Add `export ANDROID_HOME=/Users/<your_username>/Library/Android/sdk` to your `.zshrc` or `.bashrc` (and restart your terminal).
- Setup an emulator (Android Studio > Tools > Device Manager). - Setup an emulator (Android Studio > Tools > Device Manager).
- Web: `yarn web` (see the top of this file). - Web: `pnpm web` (see the top of this file).
After you do `yarn ios` and `yarn android` once, you can later just run `yarn web` and then press either `i` or `a` to open iOS and Android emulators respectively which is much faster. However, if you make native changes, you'll have to do `yarn prebuild -p ios` and `yarn prebuild -p android` and then `yarn ios` and `yarn android` again before you can continue with the same workflow. After you do `pnpm ios` and `pnpm android` once, you can later just run `pnpm web` and then press either `i` or `a` to open iOS and Android emulators respectively which is much faster. However, if you make native changes, you'll have to do `pnpm prebuild -p ios` and `pnpm prebuild -p android` and then `pnpm ios` and `pnpm android` again before you can continue with the same workflow.
### Tips ### Tips
- Copy the `.env.example` to `.env` and fill in any necessary tokens. (The Sentry token is NOT required; see instructions below if you want to enable Sentry.) - Copy the `.env.example` to `.env` and fill in any necessary tokens. (The Sentry token is NOT required; see instructions below if you want to enable Sentry.)
- To run on the device, add `--device` to the command (e.g. `yarn android --device`). To build in production mode (slower build, faster app), also add `--variant release` on Android or `--configuration Release` on iOS. - To run on the device, add `--device` to the command (e.g. `pnpm android --device`). To build in production mode (slower build, faster app), also add `--variant release` on Android or `--configuration Release` on iOS.
- If you want to use Expo EAS on your own builds without ejecting from Expo, make sure to change the `owner` and `extra.eas.projectId` properties. If you do not have an Expo account, you may remove these properties. - If you want to use Expo EAS on your own builds without ejecting from Expo, make sure to change the `owner` and `extra.eas.projectId` properties. If you do not have an Expo account, you may remove these properties.
- `npx react-native info` Checks what has been installed. - `npx react-native info` Checks what has been installed.
- If the Android simulator frequently hangs or is very sluggish, [bump its memory limit](https://stackoverflow.com/a/40068396) - If the Android simulator frequently hangs or is very sluggish, [bump its memory limit](https://stackoverflow.com/a/40068396)
@@ -74,10 +74,10 @@ After you do `yarn ios` and `yarn android` once, you can later just run `yarn we
### Running E2E Tests ### Running E2E Tests
- Start in various console tabs: - Start in various console tabs:
- `yarn e2e:mock-server` - `pnpm e2e:mock-server`
- `yarn e2e:start` - `pnpm e2e:start`
- Run once: `yarn e2e:build` - Run once: `pnpm e2e:build`
- Each test run: `yarn e2e:run` - Each test run: `pnpm e2e:run`
### Adding Sentry ### Adding Sentry
@@ -85,7 +85,7 @@ Adding Sentry is NOT required. You can keep `SENTRY_AUTH_TOKEN=` in `.env` which
However, if you're a part of the Bluesky team and want to enable Sentry, fill in `SENTRY_AUTH_TOKEN` in your `.env`. It can be created on the Sentry dashboard using [these instructions](https://docs.expo.dev/guides/using-sentry/#sign-up-for-a-sentry-account-and-create-a-project). However, if you're a part of the Bluesky team and want to enable Sentry, fill in `SENTRY_AUTH_TOKEN` in your `.env`. It can be created on the Sentry dashboard using [these instructions](https://docs.expo.dev/guides/using-sentry/#sign-up-for-a-sentry-account-and-create-a-project).
If you change `SENTRY_AUTH_TOKEN`, you need to do `yarn prebuild` before running `yarn ios` or `yarn android` again. If you change `SENTRY_AUTH_TOKEN`, you need to do `pnpm prebuild` before running `pnpm ios` or `pnpm android` again.
### Adding bitdrift ### Adding bitdrift
@@ -95,7 +95,7 @@ However, if you're a part of the Bluesky team and want to enable bitdrift, fill
### Adding and Updating Locales ### Adding and Updating Locales
- `yarn intl:build` -> you will also need to run this anytime `./src/locale/{locale}/messages.po` change - `pnpm intl:build` -> you will also need to run this anytime `./src/locale/{locale}/messages.po` change
## Running the Backend Locally ## Running the Backend Locally
@@ -112,7 +112,7 @@ This is NOT required for app development but if you also want to develop the Blu
- Launch a Postgres database on port 5432 - Launch a Postgres database on port 5432
- `cd packages/dev-env && pnpm start` - `cd packages/dev-env && pnpm start`
Run the account with the AppView proxy DID passed in as an environment variable: `EXPO_PUBLIC_BLUESKY_PROXY_DID=did:plc:dw4kbjf5mn7nhenabiqpkyh3 yarn start` Run the account with the AppView proxy DID passed in as an environment variable: `EXPO_PUBLIC_BLUESKY_PROXY_DID=did:plc:dw4kbjf5mn7nhenabiqpkyh3 pnpm start`
Then, when logging in or creating an account, point it to the localhost port of the devserver. Then, when logging in or creating an account, point it to the localhost port of the devserver.
@@ -123,7 +123,7 @@ The Go server in this repository is only used for serving the web app in product
### Prerequisites ### Prerequisites
- [Go](https://go.dev/) - [Go](https://go.dev/)
- [Yarn](https://yarnpkg.com/) - [pnpm](https://pnpm.io/)
### Steps ### Steps
@@ -131,7 +131,7 @@ To run the build with Go, use staging credentials, your own, or any other accoun
``` ```
cd social-app cd social-app
yarn && yarn build-web pnpm install && pnpm build-web
cd bskyweb/ cd bskyweb/
go mod tidy go mod tidy
go build -v -tags timetzdata -o bskyweb ./cmd/bskyweb go build -v -tags timetzdata -o bskyweb ./cmd/bskyweb
+8 -8
View File
@@ -42,20 +42,20 @@ Install the [Crowdin CLI](https://crowdin.github.io/crowdin-cli/). You will need
### English source-file sync with Crowdin ### English source-file sync with Crowdin
Every night, a GitHub action will run `yarn intl:extract` to update the english `messages.po` file. This will be automatically synced with Crowdin. Crowdin should notify all subscribed users of new translations. Every night, a GitHub action will run `pnpm intl:extract` to update the english `messages.po` file. This will be automatically synced with Crowdin. Crowdin should notify all subscribed users of new translations.
### Release process ### Release process
1. Pull main and create a branch. 1. Pull main and create a branch.
1. Run `yarn intl:release` to fetch all translation updates from Crowdin and extract all `.po` files so that they're synced with the latest code. Commit that. 1. Run `pnpm intl:release` to fetch all translation updates from Crowdin and extract all `.po` files so that they're synced with the latest code. Commit that.
1. Create a PR, ensure the translations all look correct, and merge. 1. Create a PR, ensure the translations all look correct, and merge.
1. If needed: 1. If needed:
1. Merge all approved translation PRs (contributions from outside crowdin). 1. Merge all approved translation PRs (contributions from outside crowdin).
1. Run `yarn intl:push` to sync Crowdin with the state of the repo. 1. Run `pnpm intl:push` to sync Crowdin with the state of the repo.
### Testing the translations in Crowdin ### Testing the translations in Crowdin
You can run `yarn intl:pull` to pull the currently-approved translations from Crowdin. You can run `pnpm intl:pull` to pull the currently-approved translations from Crowdin.
## Developers ## Developers
@@ -118,15 +118,15 @@ function sayHello() {
} }
``` ```
We can then run `yarn intl:extract` to update the catalog in `src/locale/locales/{locale}/messages.po`. This will add the new string to the catalog. We can then run `pnpm intl:extract` to update the catalog in `src/locale/locales/{locale}/messages.po`. This will add the new string to the catalog.
We can then run `yarn intl:compile` to update the translation files in `src/locale/locales/{locale}/messages.js`. This will add the new string to the translation files. We can then run `pnpm intl:compile` to update the translation files in `src/locale/locales/{locale}/messages.js`. This will add the new string to the translation files.
The configuration for translations is defined in `lingui.config.js` The configuration for translations is defined in `lingui.config.js`
So the workflow is as follows: So the workflow is as follows:
1. Wrap messages in Trans macro 1. Wrap messages in Trans macro
2. Run `yarn intl:extract` command to generate message catalogs 2. Run `pnpm intl:extract` command to generate message catalogs
3. Translate message catalogs (send them to translators usually) 3. Translate message catalogs (send them to translators usually)
4. Run `yarn intl:compile` to create runtime catalogs 4. Run `pnpm intl:compile` to create runtime catalogs
5. Load runtime catalog 5. Load runtime catalog
6. Enjoy translated app! 6. Enjoy translated app!
+6 -6
View File
@@ -25,13 +25,13 @@ adb reverse tcp:3000 tcp:3000
### Running Maestro tests ### Running Maestro tests
- In one tab, run `yarn e2e:mock-server` - In one tab, run `pnpm e2e:mock-server`
- In a second tab, run `yarn e2e:build` - In a second tab, run `pnpm e2e:build`
- In a third tab, run `yarn e2e:run` - In a third tab, run `pnpm e2e:run`
## Using Flashlight for Performance Testing ## Using Flashlight for Performance Testing
1. Make sure Maestro is installed (optional: only for automated testing) by following the instructions above 1. Make sure Maestro is installed (optional: only for automated testing) by following the instructions above
2. Install Flashlight by following [these instructions](https://docs.flashlight.dev/) 2. Install Flashlight by following [these instructions](https://docs.flashlight.dev/)
3. The simplest way to get started is by running `yarn perf:measure` which will run a live preview of the performance test results. You can [see a demo here](https://github.com/bamlab/flashlight/assets/4534323/4038a342-f145-4c3b-8cde-17949bf52612) 3. The simplest way to get started is by running `pnpm perf:measure` which will run a live preview of the performance test results. You can [see a demo here](https://github.com/bamlab/flashlight/assets/4534323/4038a342-f145-4c3b-8cde-17949bf52612)
4. The `yarn perf:test:measure` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml` and give the results in `.perf/results.json` which can be viewed by running `yarn:perf:results` 4. The `pnpm perf:test:measure` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml` and give the results in `.perf/results.json` which can be viewed by running `pnpm perf:results`
5. You can also run your own tests by running `yarn perf:test <path_to_test>` where `<path_to_test>` is the path to your test file. For example, `yarn perf:test __e2e__/maestro/scroll.yaml` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml`. 5. You can also run your own tests by running `pnpm perf:test <path_to_test>` where `<path_to_test>` is the path to your test file. For example, `pnpm perf:test __e2e__/maestro/scroll.yaml` will run the `scroll.yaml` test located in `__e2e__/maestro/scroll.yaml`.
+2 -2
View File
@@ -126,9 +126,9 @@ modules/BlueskyClip/
## Development Notes ## Development Notes
- The App Clip is built as part of the main Xcode project when running `yarn prebuild` - The App Clip is built as part of the main Xcode project when running `pnpm prebuild`
- Source files are copied during the prebuild process, not directly referenced - Source files are copied during the prebuild process, not directly referenced
- Changes to Swift files require running `yarn prebuild` to take effect - Changes to Swift files require running `pnpm prebuild` to take effect
- The App Clip shares the same version number as the main app - The App Clip shares the same version number as the main app
- App Clips have a 15MB size limit (enforced by Apple) - App Clips have a 15MB size limit (enforced by Apple)
- Users can convert an App Clip session into a full app install without losing data (via shared App Group) - Users can convert an App Clip session into a full app install without losing data (via shared App Group)
+51 -40
View File
@@ -5,7 +5,7 @@
"engines": { "engines": {
"node": ">=24.15.0" "node": ">=24.15.0"
}, },
"packageManager": "yarn@1.22.22", "packageManager": "pnpm@10.33.4",
"expo": { "expo": {
"autolinking": { "autolinking": {
"android": { "android": {
@@ -27,7 +27,7 @@
}, },
"scripts": { "scripts": {
"prepare": "is-ci || husky install", "prepare": "is-ci || husky install",
"postinstall": "patch-package && yarn intl:compile-if-needed", "postinstall": "patch-package && pnpm intl:compile-if-needed",
"prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean", "prebuild": "EXPO_NO_GIT_STATUS=1 expo prebuild --clean",
"android": "expo run:android", "android": "expo run:android",
"android:prod": "expo run:android --variant release", "android:prod": "expo run:android --variant release",
@@ -37,10 +37,10 @@
"use-build-number": "./scripts/useBuildNumberEnv.sh", "use-build-number": "./scripts/useBuildNumberEnv.sh",
"use-build-number-with-bump": "./scripts/useBuildNumberEnvWithBump.sh", "use-build-number-with-bump": "./scripts/useBuildNumberEnvWithBump.sh",
"build-web": "expo export:web && node ./scripts/post-web-build.js", "build-web": "expo export:web && node ./scripts/post-web-build.js",
"build-all": "yarn intl:build && yarn use-build-number-with-bump eas build --platform all", "build-all": "pnpm intl:build && pnpm use-build-number-with-bump eas build --platform all",
"build-ios": "yarn use-build-number-with-bump eas build -p ios", "build-ios": "pnpm use-build-number-with-bump eas build -p ios",
"build-android": "yarn use-build-number-with-bump eas build -p android", "build-android": "pnpm use-build-number-with-bump eas build -p android",
"build": "yarn use-build-number-with-bump eas build", "build": "pnpm use-build-number-with-bump eas build",
"build-embed": "cd bskyembed && yarn build && yarn build-snippet && cd .. && node ./scripts/post-embed-build.js", "build-embed": "cd bskyembed && yarn build && yarn build-snippet && cd .. && node ./scripts/post-embed-build.js",
"start": "expo start --dev-client", "start": "expo start --dev-client",
"start:prod": "expo start --dev-client --no-dev --minify", "start:prod": "expo start --dev-client --no-dev --minify",
@@ -59,25 +59,25 @@
"e2e:run": "maestro test", "e2e:run": "maestro test",
"perf:test": "NODE_ENV=test maestro test", "perf:test": "NODE_ENV=test maestro test",
"perf:test:run": "NODE_ENV=test maestro test __e2e__/perf-test.yml", "perf:test:run": "NODE_ENV=test maestro test __e2e__/perf-test.yml",
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand \"yarn perf:test\" --duration 150000 --resultsFilePath .perf/results.json", "perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand \"pnpm perf:test\" --duration 150000 --resultsFilePath .perf/results.json",
"perf:test:results": "NODE_ENV=test flashlight report .perf/results.json", "perf:test:results": "NODE_ENV=test flashlight report .perf/results.json",
"perf:measure": "NODE_ENV=test flashlight measure", "perf:measure": "NODE_ENV=test flashlight measure",
"intl:build": "yarn intl:extract:all && yarn intl:compile", "intl:build": "pnpm intl:extract:all && pnpm intl:compile",
"intl:extract": "lingui extract --clean --locale en", "intl:extract": "lingui extract --clean --locale en",
"intl:extract:all": "lingui extract --clean", "intl:extract:all": "lingui extract --clean",
"intl:compile": "lingui compile", "intl:compile": "lingui compile",
"intl:compile-if-needed": "is-ci || [ -f src/locale/locales/en/messages.ts ] || yarn intl:compile", "intl:compile-if-needed": "is-ci || [ -f src/locale/locales/en/messages.ts ] || pnpm intl:compile",
"intl:pull": "crowdin download translations --verbose -b main", "intl:pull": "crowdin download translations --verbose -b main",
"intl:push": "crowdin push translations --verbose -b main", "intl:push": "crowdin push translations --verbose -b main",
"intl:push-sources": "crowdin push sources --verbose -b main", "intl:push-sources": "crowdin push sources --verbose -b main",
"intl:release": "yarn intl:pull && yarn intl:extract:all", "intl:release": "pnpm intl:pull && pnpm intl:extract:all",
"nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android", "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android",
"update-extensions": "bash scripts/updateExtensions.sh", "update-extensions": "bash scripts/updateExtensions.sh",
"export": "npx expo export --dump-sourcemap && yarn upload-native-sourcemaps", "export": "npx expo export --dump-sourcemap && pnpm upload-native-sourcemaps",
"upload-native-sourcemaps": "npx sentry-expo-upload-sourcemaps dist", "upload-native-sourcemaps": "npx sentry-expo-upload-sourcemaps dist",
"make-deploy-bundle": "bash scripts/bundleUpdate.sh", "make-deploy-bundle": "bash scripts/bundleUpdate.sh",
"generate-webpack-stats-file": "EXPO_PUBLIC_GENERATE_STATS=1 yarn build-web", "generate-webpack-stats-file": "EXPO_PUBLIC_GENERATE_STATS=1 pnpm build-web",
"open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web", "open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 pnpm build-web",
"icons:optimize": "svgo -f ./assets/icons" "icons:optimize": "svgo -f ./assets/icons"
}, },
"dependencies": { "dependencies": {
@@ -148,7 +148,7 @@
"emoji-mart": "^5.6.0", "emoji-mart": "^5.6.0",
"emoji-regex": "^10.4.0", "emoji-regex": "^10.4.0",
"eventemitter3": "^5.0.1", "eventemitter3": "^5.0.1",
"expo": "^54.0.33", "expo": "54.0.34",
"expo-application": "~7.0.8", "expo-application": "~7.0.8",
"expo-blur": "~15.0.8", "expo-blur": "~15.0.8",
"expo-build-properties": "~1.0.10", "expo-build-properties": "~1.0.10",
@@ -171,7 +171,7 @@
"expo-localization": "~17.0.8", "expo-localization": "~17.0.8",
"expo-location": "~19.0.8", "expo-location": "~19.0.8",
"expo-media-library": "~18.2.1", "expo-media-library": "~18.2.1",
"expo-notifications": "~0.32.16", "expo-notifications": "~0.32.17",
"expo-paste-input": "^0.1.15", "expo-paste-input": "^0.1.15",
"expo-privacy-sensitive": "^0.1.0", "expo-privacy-sensitive": "^0.1.0",
"expo-screen-orientation": "~9.0.8", "expo-screen-orientation": "~9.0.8",
@@ -179,7 +179,7 @@
"expo-sms": "^14.0.7", "expo-sms": "^14.0.7",
"expo-splash-screen": "~31.0.13", "expo-splash-screen": "~31.0.13",
"expo-system-ui": "~6.0.9", "expo-system-ui": "~6.0.9",
"expo-updates": "~29.0.16", "expo-updates": "~29.0.17",
"expo-video": "~3.0.16", "expo-video": "~3.0.16",
"expo-video-thumbnails": "^10.0.8", "expo-video-thumbnails": "^10.0.8",
"expo-web-browser": "~15.0.10", "expo-web-browser": "~15.0.10",
@@ -200,21 +200,20 @@
"nanoid": "^5.0.5", "nanoid": "^5.0.5",
"normalize-url": "^8.0.0", "normalize-url": "^8.0.0",
"patch-package": "^8.0.1", "patch-package": "^8.0.1",
"postinstall-postinstall": "^2.1.0",
"psl": "^1.9.0", "psl": "^1.9.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "19.1.0", "react": "19.1.0",
"react-compiler-runtime": "^19.1.0-rc.1", "react-compiler-runtime": "19.1.0-rc.3",
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-hotkeys-hook": "5.2.4", "react-hotkeys-hook": "5.2.4",
"react-image-crop": "^11.0.7", "react-image-crop": "^11.0.7",
"react-is": "19", "react-is": "19",
"react-keyed-flatten-children": "^5.0.0", "react-keyed-flatten-children": "^5.0.0",
"react-native": "0.81.5", "react-native": "0.81.5",
"react-native-compressor": "^1.13.0", "react-native-compressor": "1.13.0",
"react-native-date-picker": "^5.0.13", "react-native-date-picker": "^5.0.13",
"react-native-device-attest": "^0.1.6", "react-native-device-attest": "^0.1.6",
"react-native-drawer-layout": "^4.2.2", "react-native-drawer-layout": "^4.2.3",
"react-native-edge-to-edge": "^1.6.0", "react-native-edge-to-edge": "^1.6.0",
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-keyboard-controller": "^1.21.7", "react-native-keyboard-controller": "^1.21.7",
@@ -230,14 +229,14 @@
"react-native-view-shot": "^4.0.3", "react-native-view-shot": "^4.0.3",
"react-native-web": "^0.21.0", "react-native-web": "^0.21.0",
"react-native-web-webview": "^1.0.2", "react-native-web-webview": "^1.0.2",
"react-native-webview": "^13.13.5", "react-native-webview": "^13.15.0",
"react-remove-scroll-bar": "^2.3.8", "react-remove-scroll-bar": "^2.3.8",
"react-responsive": "^10.0.1", "react-responsive": "^10.0.1",
"react-textarea-autosize": "^8.5.3", "react-textarea-autosize": "^8.5.3",
"setimmediate": "^1.0.5", "setimmediate": "^1.0.5",
"slugify": "^1.6.9", "slugify": "^1.6.9",
"sonner": "^2.0.7", "sonner": "^2.0.7",
"sonner-native": "^0.21.0", "sonner-native": "0.21.0",
"tippy.js": "^6.3.7", "tippy.js": "^6.3.7",
"tlds": "^1.234.0", "tlds": "^1.234.0",
"tldts": "^6.1.46", "tldts": "^6.1.46",
@@ -262,12 +261,12 @@
"@types/lodash.debounce": "^4.0.7", "@types/lodash.debounce": "^4.0.7",
"@types/lodash.shuffle": "^4.2.7", "@types/lodash.shuffle": "^4.2.7",
"@types/psl": "^1.1.1", "@types/psl": "^1.1.1",
"@types/react": "^19.1.12", "@types/react": "^19.1.17",
"@types/react-dom": "^19.1.9", "@types/react-dom": "^19.1.11",
"@typescript/native-preview": "^7.0.0-dev.20260428.1", "@typescript/native-preview": "^7.0.0-dev.20260428.1",
"babel-jest": "^29.7.0", "babel-jest": "^29.7.0",
"babel-plugin-module-resolver": "^5.0.2", "babel-plugin-module-resolver": "^5.0.2",
"babel-plugin-react-compiler": "^19.1.0-rc.3", "babel-plugin-react-compiler": "19.1.0-rc.3",
"babel-preset-expo": "~54.0.10", "babel-preset-expo": "~54.0.10",
"eslint": "^9.39.2", "eslint": "^9.39.2",
"eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-typescript": "^4.4.4",
@@ -275,8 +274,8 @@
"eslint-plugin-import-x": "^4.16.2", "eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-lingui": "^0.12.0", "eslint-plugin-lingui": "^0.12.0",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-compiler": "^19.1.0-rc.2", "eslint-plugin-react-compiler": "19.1.0-rc.2",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-native": "^5.0.0", "eslint-plugin-react-native": "^5.0.0",
"eslint-plugin-react-native-a11y": "^3.5.1", "eslint-plugin-react-native-a11y": "^3.5.1",
"eslint-plugin-simple-import-sort": "^13.0.0", "eslint-plugin-simple-import-sort": "^13.0.0",
@@ -298,18 +297,30 @@
"typescript-eslint": "^8.58.0", "typescript-eslint": "^8.58.0",
"webpack-bundle-analyzer": "^4.10.1" "webpack-bundle-analyzer": "^4.10.1"
}, },
"resolutions": { "pnpm": {
"@react-native/babel-preset": "0.81.5", "overrides": {
"@react-native/normalize-colors": "0.81.5", "@react-native/babel-preset": "0.81.5",
"**/@expo/image-utils": "0.8.12", "@react-native/normalize-colors": "0.81.5",
"**/multiformats": "9.9.0", "@expo/image-utils": "0.8.12",
"unicode-segmenter": "0.14.5", "multiformats": "9.9.0",
"@types/estree": "1.0.6", "unicode-segmenter": "0.14.5",
"metro": "0.83.3", "@types/estree": "1.0.6",
"metro-core": "0.83.3", "metro": "0.83.3",
"metro-config": "0.83.3", "metro-core": "0.83.3",
"metro-runtime": "0.83.3", "metro-config": "0.83.3",
"metro-source-map": "0.83.3" "metro-runtime": "0.83.3",
"metro-source-map": "0.83.3",
"react-native-compressor": "1.13.0",
"react-native-reanimated": "3.19.1",
"psl": "1.9.0",
"@types/psl": "1.1.1"
},
"onlyBuiltDependencies": [
"@sentry/cli",
"core-js-pure",
"esbuild",
"unrs-resolver"
]
}, },
"jest": { "jest": {
"preset": "jest-expo/ios", "preset": "jest-expo/ios",
@@ -372,7 +383,7 @@
] ]
}, },
"lockfile-lint": { "lockfile-lint": {
"path": "yarn.lock", "path": "pnpm-lock.yaml",
"allowedHosts": [ "allowedHosts": [
"npm", "npm",
"yarn" "yarn"
@@ -0,0 +1,5 @@
# `expo-image-picker` patch
Patches this issue: https://github.com/expo/expo/issues/39937
Source: https://github.com/expo/expo/issues/39937#issuecomment-3342082239
+19395
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -29,7 +29,7 @@ directly in Xcode.
1. Boot an iOS simulator and install the app: 1. Boot an iOS simulator and install the app:
``` ```
yarn ios pnpm ios
``` ```
2. Sign in to the account you'll be testing against. The `recipientDid` in 2. Sign in to the account you'll be testing against. The `recipientDid` in
each payload is substituted at send time and must match the signed-in DID, each payload is substituted at send time and must match the signed-in DID,
-16918
View File
File diff suppressed because it is too large Load Diff