experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(mobile): add Release CLI builds via xcodebuild

Add support for building Release configuration via xcodebuild CLI:

- Fix Share Extension configuration inheritance issue by using
CONFIGURATION=Release build setting override (the -configuration flag
alone doesn't propagate to embedded extensions)
- Symlink Debug simulator library to Release path (we only have Debug
builds for simulator, Release is for device deployment)
- Add yarn mobile:ios:xcodebuild:release command
- Add yarn mobile:ios:xcodebuild:install:release command
- Update research notes with root cause analysis

Also includes earlier e2e automation work:
- Add PEEK_AUTO_SYNC env var support for auto-sync on iOS launch
- Add --headless and --build flags to e2e-full-sync-test.sh
- Fix deprecated adblocker enableCompression option
- Fix deletedAt field name in e2e test tombstone counting

+371 -19
+3 -3
TODO.md
··· 421 421 - [ ] in url saves/views, show oembed, or at least page title 422 422 - [ ] for url saves, save title and any other metadata 423 423 - [ ] investigate detecting which app a share came from 424 - - [ ] fix xcodebuild CLI builds (see notes/research-xcodebuild-environment-issues.md) 425 - - isolate DerivedData paths for CLI vs GUI 426 - - set up proper build script with environment isolation 424 + - [x] fix xcodebuild CLI builds (DONE - uses /tmp/peek-xcodebuild for isolated DerivedData) 425 + - yarn mobile:ios:xcodebuild for CLI builds 426 + - yarn interactive-test:e2e:full-sync:auto for fully automated e2e tests 427 427 428 428 ## Session & State Management 429 429
+1 -3
backend/electron/adblocker.ts
··· 47 47 const startTime = Date.now(); 48 48 49 49 try { 50 - blocker = await ElectronBlocker.fromPrebuiltAdsAndTracking(fetch, { 51 - enableCompression: true, 52 - }); 50 + blocker = await ElectronBlocker.fromPrebuiltAdsAndTracking(fetch); 53 51 54 52 blocker.on('request-blocked', (request: Request) => { 55 53 blockedCount++;
+104
notes/research-xcodebuild-environment-issues.md
··· 1 + # Research: xcodebuild CLI vs Xcode GUI Environment Issues 2 + 3 + ## Problem 4 + 5 + Running `xcodebuild` from the command line can conflict with Xcode GUI builds due to shared DerivedData paths. This causes issues like: 6 + - Build artifacts from one environment interfering with the other 7 + - Incremental build state getting corrupted 8 + - "Stale" build products being used unexpectedly 9 + 10 + ## Solution 11 + 12 + Use isolated DerivedData paths for CLI builds: 13 + 14 + ```bash 15 + xcodebuild -scheme peek-save_iOS \ 16 + -configuration Debug \ 17 + -sdk iphonesimulator \ 18 + -derivedDataPath /tmp/peek-xcodebuild \ 19 + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \ 20 + build 21 + ``` 22 + 23 + Key points: 24 + - `-derivedDataPath /tmp/peek-xcodebuild` - Isolates CLI builds from Xcode GUI 25 + - Xcode GUI uses `~/Library/Developer/Xcode/DerivedData/` by default 26 + - No interference between the two build environments 27 + 28 + ## Scripts Added 29 + 30 + ```bash 31 + # List available schemes 32 + yarn mobile:ios:xcodebuild:list 33 + 34 + # Build Debug with CLI 35 + yarn mobile:ios:xcodebuild 36 + 37 + # Build Release with CLI 38 + yarn mobile:ios:xcodebuild:release 39 + 40 + # Install to simulator (Debug) 41 + yarn mobile:ios:xcodebuild:install 42 + 43 + # Install to simulator (Release) 44 + yarn mobile:ios:xcodebuild:install:release 45 + 46 + # Full flow: Rust lib + xcodebuild + install 47 + yarn mobile:ios:xcodebuild:full 48 + 49 + # Fully automated e2e test (CLI build + headless + auto-sync) 50 + yarn interactive-test:e2e:full-sync:auto 51 + ``` 52 + 53 + ## E2E Test Integration 54 + 55 + The `--build` flag for `e2e-full-sync-test.sh` enables CLI builds: 56 + 57 + ```bash 58 + # Uses xcodebuild CLI instead of opening Xcode GUI 59 + yarn interactive-test:e2e:full-sync -- --headless --build 60 + ``` 61 + 62 + Combined with the `PEEK_AUTO_SYNC=true` env var support in the iOS app, this enables fully automated e2e testing without any manual intervention. 63 + 64 + ## Release CLI Builds 65 + 66 + ### The Problem 67 + 68 + When running `-configuration Release` via CLI, the Share Extension target was ignoring the configuration flag and building in Debug mode. This caused path mismatches: 69 + - GRDB (SPM dependency) built to `Release-iphonesimulator/` 70 + - Share Extension looked for dependencies in `debug-iphonesimulator/` 71 + - Build failed with: `lstat(.../debug-iphonesimulator/GRDB_GRDB.bundle): No such file or directory` 72 + 73 + ### Root Cause 74 + 75 + The xcodebuild `-configuration` flag doesn't always propagate to embedded extension targets when they're built as implicit dependencies. The Xcode build system determines the configuration for each target independently. 76 + 77 + ### The Fix 78 + 79 + Two changes were needed: 80 + 81 + 1. **Force configuration via build setting override**: 82 + ```bash 83 + xcodebuild ... CONFIGURATION=Release build 84 + ``` 85 + This overrides the configuration for ALL targets, not just the main app. 86 + 87 + 2. **Symlink Debug simulator library to Release path**: 88 + ```bash 89 + ln -sf ../Debug/libapp.a Externals/arm64/Release/libapp.a 90 + ``` 91 + We only have a Debug build of libapp.a for the simulator (Release is for device deployment). Symlinking lets the Release build find the library. 92 + 93 + ### Why This Works 94 + 95 + | Component | Debug Build | Release Build | 96 + |-----------|-------------|---------------| 97 + | `-configuration` flag | Targets use debug | Targets use **debug** (ignored by extensions) | 98 + | `CONFIGURATION=Release` build setting | N/A | **Forces Release on all targets** | 99 + | Rust library (libapp.a) | `Externals/arm64/Debug/` | `Externals/arm64/Release/` (symlinked from Debug) | 100 + 101 + ## References 102 + 103 + - Apple: [xcodebuild man page](https://developer.apple.com/library/archive/technotes/tn2339/_index.html) 104 + - Tauri Mobile: `backend/tauri-mobile/src-tauri/gen/apple/peek-save.xcodeproj`
+7
package.json
··· 56 56 "mobile:ios:build": "cd backend/tauri-mobile && ./build-ios.sh", 57 57 "mobile:ios:build:release": "cd backend/tauri-mobile && ./build-release.sh", 58 58 "mobile:ios:xcode": "open backend/tauri-mobile/src-tauri/gen/apple/peek-save.xcodeproj", 59 + "mobile:ios:xcodebuild:list": "xcodebuild -project backend/tauri-mobile/src-tauri/gen/apple/peek-save.xcodeproj -list", 60 + "mobile:ios:xcodebuild": "cd backend/tauri-mobile/src-tauri/gen/apple && xcodebuild -scheme peek-save_iOS -configuration Debug -sdk iphonesimulator -derivedDataPath /tmp/peek-xcodebuild -destination 'platform=iOS Simulator,name=iPhone 17 Pro' build", 61 + "mobile:ios:xcodebuild:release": "rm -rf /tmp/peek-xcodebuild && mkdir -p backend/tauri-mobile/src-tauri/gen/apple/Externals/arm64/Release && ln -sf ../Debug/libapp.a backend/tauri-mobile/src-tauri/gen/apple/Externals/arm64/Release/libapp.a && cd backend/tauri-mobile/src-tauri/gen/apple && xcodebuild -scheme peek-save_iOS -configuration Release -sdk iphonesimulator -derivedDataPath /tmp/peek-xcodebuild -destination 'platform=iOS Simulator,name=iPhone 17 Pro' CONFIGURATION=Release build", 62 + "mobile:ios:xcodebuild:install": "xcrun simctl install booted '/tmp/peek-xcodebuild/Build/Products/Debug-iphonesimulator/Peek Save.app'", 63 + "mobile:ios:xcodebuild:install:release": "xcrun simctl install booted '/tmp/peek-xcodebuild/Build/Products/Release-iphonesimulator/Peek Save.app'", 64 + "mobile:ios:xcodebuild:full": "yarn mobile:ios:build && yarn mobile:ios:xcodebuild && yarn mobile:ios:xcodebuild:install", 59 65 "mobile:ios:test": "cd backend/tauri-mobile && ./dev-setup.sh", 60 66 "mobile:android:init": "cd backend/tauri-mobile/src-tauri && cargo tauri android init", 61 67 "mobile:android:dev": "cd backend/tauri-mobile/src-tauri && cargo tauri android dev", ··· 91 97 "test:e2e:version:phase": "./scripts/e2e-version-test.sh --phase", 92 98 "test:e2e:server": "./scripts/e2e-server.sh", 93 99 "interactive-test:e2e:full-sync": "./scripts/e2e-full-sync-test.sh", 100 + "interactive-test:e2e:full-sync:auto": "./scripts/e2e-full-sync-test.sh --headless --build", 94 101 "test:mobile": "cd backend/tauri-mobile && npm test", 95 102 "test:extension": "node --test backend/extension/tests/*.test.js", 96 103 "extension:chrome": "backend/extension/scripts/launch-chrome.sh",
+48 -13
scripts/e2e-full-sync-test.sh
··· 2 2 # Full E2E Sync Test: Server + Desktop (headless) + iOS Simulator 3 3 # 4 4 # ┌─────────────────────────────────────────────────────────────────┐ 5 - # │ INTERACTIVE TEST - Run in background, monitor output manually │ 5 + # │ E2E Sync Test - Server + Desktop + iOS Simulator │ 6 6 # │ │ 7 7 # │ Usage: │ 8 - # │ npm run interactive-test:e2e:full-sync -- --interactive & │ 8 + # │ # Interactive mode (opens Xcode, manual sync taps) │ 9 + # │ yarn interactive-test:e2e:full-sync │ 9 10 # │ │ 10 - # │ Then watch output and follow prompts to tap buttons in the │ 11 - # │ iOS simulator when instructed. Do NOT run this blocking in │ 12 - # │ an automated context - it requires human interaction. │ 11 + # │ # Headless mode (auto-sync, requires pre-built app) │ 12 + # │ yarn interactive-test:e2e:full-sync -- --headless │ 13 13 # │ │ 14 - # │ For semi-automated mode (auto-relaunch, no prompts): │ 15 - # │ npm run interactive-test:e2e:full-sync -- --headless │ 14 + # │ # Fully automated (builds with xcodebuild CLI + auto-sync) │ 15 + # │ yarn interactive-test:e2e:full-sync -- --headless --build │ 16 16 # │ │ 17 - # │ In headless mode, the script auto-relaunches the iOS app but │ 18 - # │ still requires manual "Sync All" taps OR the iOS app must │ 19 - # │ support PEEK_AUTO_SYNC=true env var for auto-sync on launch. │ 17 + # │ The --build flag uses xcodebuild CLI with isolated DerivedData │ 18 + # │ path (/tmp/peek-xcodebuild) to avoid conflicts with Xcode GUI. │ 20 19 # └─────────────────────────────────────────────────────────────────┘ 21 20 # 22 21 # Clean-room test covering all sync permutations: ··· 38 37 39 38 # --- Parse arguments --- 40 39 HEADLESS=false 40 + CLI_BUILD=false 41 41 for arg in "$@"; do 42 42 case "$arg" in 43 43 --headless|--auto) 44 44 HEADLESS=true 45 + ;; 46 + --build) 47 + CLI_BUILD=true 45 48 ;; 46 49 esac 47 50 done ··· 116 119 echo "==========================================" 117 120 echo " Full E2E Sync Test (Clean Room)" 118 121 if [ "$HEADLESS" = true ]; then 119 - echo " Mode: HEADLESS (auto-relaunch, no prompts)" 122 + if [ "$CLI_BUILD" = true ]; then 123 + echo " Mode: HEADLESS + CLI BUILD (fully automated)" 124 + else 125 + echo " Mode: HEADLESS (auto-relaunch, no prompts)" 126 + fi 120 127 else 121 128 echo " Mode: INTERACTIVE (manual prompts)" 122 129 fi ··· 530 537 echo "==========================================" 531 538 echo "" 532 539 533 - # --- Open Xcode (now that everything is ready) --- 540 + # --- Build and/or open Xcode --- 541 + 542 + if [ "$CLI_BUILD" = true ]; then 543 + echo "" 544 + echo "Building iOS app with xcodebuild (CLI)..." 545 + cd "$PROJECT_DIR" 546 + 547 + # Build with xcodebuild using isolated DerivedData path 548 + cd backend/tauri-mobile/src-tauri/gen/apple 549 + xcodebuild -scheme peek-save_iOS -configuration Debug -sdk iphonesimulator \ 550 + -derivedDataPath /tmp/peek-xcodebuild \ 551 + -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \ 552 + build 2>&1 | grep -E "(BUILD|error:|warning:.*error)" || true 553 + 554 + if [ $? -eq 0 ]; then 555 + echo " iOS app built successfully" 556 + else 557 + echo " ERROR: xcodebuild failed" 558 + exit 1 559 + fi 560 + 561 + # Install to simulator 562 + echo " Installing to simulator..." 563 + xcrun simctl install booted '/tmp/peek-xcodebuild/Build/Products/debug-iphonesimulator/Peek Save.app' 564 + echo " iOS app installed" 565 + cd "$PROJECT_DIR" 566 + fi 534 567 535 568 if [ "$HEADLESS" = true ]; then 536 - echo "[HEADLESS] Skipping Xcode open. Ensure iOS app is already built and installed." 569 + if [ "$CLI_BUILD" = false ]; then 570 + echo "[HEADLESS] Skipping Xcode open. Ensure iOS app is already built and installed." 571 + fi 537 572 echo "[HEADLESS] Relaunching iOS app with PEEK_AUTO_SYNC=true..." 538 573 relaunch_ios_app "pick up fresh test profile + auto-sync" "true" 539 574 echo ""
+208
yarn.lock
··· 37 37 languageName: node 38 38 linkType: hard 39 39 40 + "@cliqz/adblocker-content@npm:^1.34.0": 41 + version: 1.34.0 42 + resolution: "@cliqz/adblocker-content@npm:1.34.0" 43 + dependencies: 44 + "@cliqz/adblocker-extended-selectors": "npm:^1.34.0" 45 + checksum: 10c0/c25a6faac69c4b2514ca0eaff8ebb4abbcbea4859cb091158206e1d8851f36ff561c398d2f543191a4c59b632554a02088033cb2b0f0e20b8beb44b242ad52df 46 + languageName: node 47 + linkType: hard 48 + 49 + "@cliqz/adblocker-electron-preload@npm:^1.34.0": 50 + version: 1.34.0 51 + resolution: "@cliqz/adblocker-electron-preload@npm:1.34.0" 52 + dependencies: 53 + "@cliqz/adblocker-content": "npm:^1.34.0" 54 + peerDependencies: 55 + electron: ">11" 56 + checksum: 10c0/5bb28ac6c079d8feb51565d9ed8cff112795b198afcc35b158bd88f69a67dfe96fc3973f6dac67624a391d84f6e8c5ace6566363f11d99ab20d9dd036052e21a 57 + languageName: node 58 + linkType: hard 59 + 60 + "@cliqz/adblocker-electron@npm:^1.27.6": 61 + version: 1.34.0 62 + resolution: "@cliqz/adblocker-electron@npm:1.34.0" 63 + dependencies: 64 + "@cliqz/adblocker": "npm:^1.34.0" 65 + "@cliqz/adblocker-electron-preload": "npm:^1.34.0" 66 + tldts-experimental: "npm:^6.0.14" 67 + peerDependencies: 68 + electron: ">11" 69 + checksum: 10c0/8179caa67a41829f55cde11104cf1a2eb8ffe6f943f695fd3da5db2e3aaa52de0fbe53ae3a64e526c4514334ffa96b14ff69d16a22148cbea1a90de4b514bcd2 70 + languageName: node 71 + linkType: hard 72 + 73 + "@cliqz/adblocker-extended-selectors@npm:^1.34.0": 74 + version: 1.34.0 75 + resolution: "@cliqz/adblocker-extended-selectors@npm:1.34.0" 76 + checksum: 10c0/bc6a45e2ff8bb698906e331004467857c467c0abd669acc827f7cae22ece4cc4403fd095003f33016fa30275e938e8eee1ad17ebbf23c92cb8a4c5a2fd6440bb 77 + languageName: node 78 + linkType: hard 79 + 80 + "@cliqz/adblocker@npm:^1.34.0": 81 + version: 1.34.0 82 + resolution: "@cliqz/adblocker@npm:1.34.0" 83 + dependencies: 84 + "@cliqz/adblocker-content": "npm:^1.34.0" 85 + "@cliqz/adblocker-extended-selectors": "npm:^1.34.0" 86 + "@remusao/guess-url-type": "npm:^1.3.0" 87 + "@remusao/small": "npm:^1.2.1" 88 + "@remusao/smaz": "npm:^1.9.1" 89 + "@types/chrome": "npm:^0.0.278" 90 + "@types/firefox-webext-browser": "npm:^120.0.0" 91 + tldts-experimental: "npm:^6.0.14" 92 + checksum: 10c0/b23288bbf89f76e515516127cf5550a6739ca7d166bbd942128e46bd46b149b6b6a41cd44fe3607e0ef4197315a30a65aab9d89c2662e25b74367131873e71e5 93 + languageName: node 94 + linkType: hard 95 + 40 96 "@develar/schema-utils@npm:~2.6.5": 41 97 version: 2.6.5 42 98 resolution: "@develar/schema-utils@npm:2.6.5" ··· 589 645 languageName: node 590 646 linkType: hard 591 647 648 + "@remusao/guess-url-type@npm:^1.3.0": 649 + version: 1.3.0 650 + resolution: "@remusao/guess-url-type@npm:1.3.0" 651 + checksum: 10c0/a9d5b63ad2f5822a744c24b9fd7867ee342eb403f28330bbdcc3522762ab61b566578830e5ab8e6c5c0d183a311461b34392e7f7b5f15db0d0b75498a7b52b9c 652 + languageName: node 653 + linkType: hard 654 + 655 + "@remusao/small@npm:^1.2.1": 656 + version: 1.3.0 657 + resolution: "@remusao/small@npm:1.3.0" 658 + checksum: 10c0/f537492899e5ce2012eee97f98620873d244dc8d3902921deea20c1829249ee1ba545bf0fad34004bd31988127226285e2146f0101fc0fba78baf3ded8a16ce8 659 + languageName: node 660 + linkType: hard 661 + 662 + "@remusao/smaz-compress@npm:^1.10.0": 663 + version: 1.10.0 664 + resolution: "@remusao/smaz-compress@npm:1.10.0" 665 + dependencies: 666 + "@remusao/trie": "npm:^1.5.0" 667 + checksum: 10c0/594a849bcb9fb99e8e0f1104ddc31588c1046d7de6888e8beb602480e8b97c71c4b19efdc93fa0aa4f4716d001c232923d288225f22e6e9df3374f59e0ee5c20 668 + languageName: node 669 + linkType: hard 670 + 671 + "@remusao/smaz-decompress@npm:^1.10.0": 672 + version: 1.10.0 673 + resolution: "@remusao/smaz-decompress@npm:1.10.0" 674 + checksum: 10c0/e9a73f772910ce46cf792d24d88ee77cdb0d9ae922c92f36b9ee2db7b89a2d8ed367f4c5141f7dbe6365baef7f7b239ed5e78e43f884e6cc268c7d6e8cb867d8 675 + languageName: node 676 + linkType: hard 677 + 678 + "@remusao/smaz@npm:^1.9.1": 679 + version: 1.10.0 680 + resolution: "@remusao/smaz@npm:1.10.0" 681 + dependencies: 682 + "@remusao/smaz-compress": "npm:^1.10.0" 683 + "@remusao/smaz-decompress": "npm:^1.10.0" 684 + checksum: 10c0/eb50af2fe73da99e4ddd3cb73aed3a7e1da943dcd717a1e965076d31f4319196176c812a559ff0fd40ae51146d163dd7103d59ef418d2b4b0417b75561700d46 685 + languageName: node 686 + linkType: hard 687 + 688 + "@remusao/trie@npm:^1.5.0": 689 + version: 1.5.0 690 + resolution: "@remusao/trie@npm:1.5.0" 691 + checksum: 10c0/31c584790b292c22db9a8573dbeffae65a51c3d1b669a6633c58c469a455f0d3450ea071c388ecbfbec2f96339fc2ce8f2702391df23fc72ca9860724ea32bc0 692 + languageName: node 693 + linkType: hard 694 + 592 695 "@sindresorhus/is@npm:^4.0.0": 593 696 version: 4.6.0 594 697 resolution: "@sindresorhus/is@npm:4.6.0" ··· 642 745 languageName: node 643 746 linkType: hard 644 747 748 + "@types/chrome@npm:^0.0.278": 749 + version: 0.0.278 750 + resolution: "@types/chrome@npm:0.0.278" 751 + dependencies: 752 + "@types/filesystem": "npm:*" 753 + "@types/har-format": "npm:*" 754 + checksum: 10c0/8544ecaa52a6c1e4cb037a2abca711519ce9eff8862c487667028341b6d4843cbd7beb9adf393045feace35f3f932f0557e81561e5b74fd18a477a1219b911f0 755 + languageName: node 756 + linkType: hard 757 + 645 758 "@types/debug@npm:^4.1.6": 646 759 version: 4.1.12 647 760 resolution: "@types/debug@npm:4.1.12" ··· 658 771 languageName: node 659 772 linkType: hard 660 773 774 + "@types/filesystem@npm:*": 775 + version: 0.0.36 776 + resolution: "@types/filesystem@npm:0.0.36" 777 + dependencies: 778 + "@types/filewriter": "npm:*" 779 + checksum: 10c0/3ebec32f0494b0a2612187d148e9f253ff55672c53f566d9a1e6d891eb6e2372df93c252b594b2775bc53e6660c4c37fdb05dc1b26e72b60a31010da8e1f7317 780 + languageName: node 781 + linkType: hard 782 + 783 + "@types/filewriter@npm:*": 784 + version: 0.0.33 785 + resolution: "@types/filewriter@npm:0.0.33" 786 + checksum: 10c0/363ef9a658a961ceae04f52934562e4ebdcdc3a2564dd8544f593d77113c16574938b6ba4fea0bee418c37bda0668c1e03dfedb6adf00d55853f51fb3a59247b 787 + languageName: node 788 + linkType: hard 789 + 790 + "@types/firefox-webext-browser@npm:^120.0.0": 791 + version: 120.0.5 792 + resolution: "@types/firefox-webext-browser@npm:120.0.5" 793 + checksum: 10c0/77338ed752351f74d72142c6399e6f5bb3a34acb5d3f559c0e9179fb271272de6ce514827afe6d99c798a42109bbc64d442cf8d999cf486e668dd933722fcb73 794 + languageName: node 795 + linkType: hard 796 + 661 797 "@types/fs-extra@npm:9.0.13, @types/fs-extra@npm:^9.0.11": 662 798 version: 9.0.13 663 799 resolution: "@types/fs-extra@npm:9.0.13" 664 800 dependencies: 665 801 "@types/node": "npm:*" 666 802 checksum: 10c0/576d4e9d382393316ed815c593f7f5c157408ec5e184521d077fcb15d514b5a985245f153ef52142b9b976cb9bd8f801850d51238153ebd0dc9e96b7a7548588 803 + languageName: node 804 + linkType: hard 805 + 806 + "@types/har-format@npm:*": 807 + version: 1.2.16 808 + resolution: "@types/har-format@npm:1.2.16" 809 + checksum: 10c0/77e952bc219db0c1f0588cab3b95865bc343b922e8423a76fbbd6a757c40709a256933fa415eb8fefda6ea5897c8e3dd3191bb8a82b37c13d9232467d31ae485 667 810 languageName: node 668 811 linkType: hard 669 812 ··· 784 927 version: 0.0.0-use.local 785 928 resolution: "Peek@workspace:." 786 929 dependencies: 930 + "@cliqz/adblocker-electron": "npm:^1.27.6" 787 931 "@electron/rebuild": "npm:^4.0.2" 788 932 "@playwright/test": "npm:^1.57.0" 789 933 "@types/archiver": "npm:^6.0.0" ··· 791 935 "@types/node": "npm:^25.0.3" 792 936 archiver: "npm:^7.0.0" 793 937 better-sqlite3: "npm:^12.5.0" 938 + cross-fetch: "npm:^4.0.0" 794 939 electron: "npm:^40.0.0" 795 940 electron-builder: "npm:26.0.12" 796 941 electron-unhandled: "npm:^5.0.0" ··· 1880 2025 dependencies: 1881 2026 buffer: "npm:^5.1.0" 1882 2027 checksum: 10c0/1a0da36e5f95b19cd2a7b2eab5306a08f1c47bdd22da6f761ab764e2222e8e90a877398907cea94108bd5e41a6d311ea84d7914eaca67da2baa4050bd6384b3d 2028 + languageName: node 2029 + linkType: hard 2030 + 2031 + "cross-fetch@npm:^4.0.0": 2032 + version: 4.1.0 2033 + resolution: "cross-fetch@npm:4.1.0" 2034 + dependencies: 2035 + node-fetch: "npm:^2.7.0" 2036 + checksum: 10c0/628b134ea27cfcada67025afe6ef1419813fffc5d63d175553efa75a2334522d450300a0f3f0719029700da80e96327930709d5551cf6deb39bb62f1d536642e 1883 2037 languageName: node 1884 2038 linkType: hard 1885 2039 ··· 4372 4526 languageName: node 4373 4527 linkType: hard 4374 4528 4529 + "node-fetch@npm:^2.7.0": 4530 + version: 2.7.0 4531 + resolution: "node-fetch@npm:2.7.0" 4532 + dependencies: 4533 + whatwg-url: "npm:^5.0.0" 4534 + peerDependencies: 4535 + encoding: ^0.1.0 4536 + peerDependenciesMeta: 4537 + encoding: 4538 + optional: true 4539 + checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 4540 + languageName: node 4541 + linkType: hard 4542 + 4375 4543 "node-forge@npm:^1.3.1": 4376 4544 version: 1.3.3 4377 4545 resolution: "node-forge@npm:1.3.3" ··· 5775 5943 languageName: node 5776 5944 linkType: hard 5777 5945 5946 + "tldts-core@npm:^6.1.86": 5947 + version: 6.1.86 5948 + resolution: "tldts-core@npm:6.1.86" 5949 + checksum: 10c0/8133c29375f3f99f88fce5f4d62f6ecb9532b106f31e5423b27c1eb1b6e711bd41875184a456819ceaed5c8b94f43911b1ad57e25c6eb86e1fc201228ff7e2af 5950 + languageName: node 5951 + linkType: hard 5952 + 5953 + "tldts-experimental@npm:^6.0.14": 5954 + version: 6.1.86 5955 + resolution: "tldts-experimental@npm:6.1.86" 5956 + dependencies: 5957 + tldts-core: "npm:^6.1.86" 5958 + checksum: 10c0/5004191612b6ab66da72a7115f56ce4bf3633ff1321ed9cafd5ee836531153ddae60fc8a7880ff01c1a871b5771e328c096c0c17cf71fdbfb24cbb668855fcb7 5959 + languageName: node 5960 + linkType: hard 5961 + 5778 5962 "tmp-promise@npm:^3.0.2": 5779 5963 version: 3.0.3 5780 5964 resolution: "tmp-promise@npm:3.0.3" ··· 5788 5972 version: 0.2.5 5789 5973 resolution: "tmp@npm:0.2.5" 5790 5974 checksum: 10c0/cee5bb7d674bb4ba3ab3f3841c2ca7e46daeb2109eec395c1ec7329a91d52fcb21032b79ac25161a37b2565c4858fefab927af9735926a113ef7bac9091a6e0e 5975 + languageName: node 5976 + linkType: hard 5977 + 5978 + "tr46@npm:~0.0.3": 5979 + version: 0.0.3 5980 + resolution: "tr46@npm:0.0.3" 5981 + checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 5791 5982 languageName: node 5792 5983 linkType: hard 5793 5984 ··· 6072 6263 languageName: node 6073 6264 linkType: hard 6074 6265 6266 + "webidl-conversions@npm:^3.0.0": 6267 + version: 3.0.1 6268 + resolution: "webidl-conversions@npm:3.0.1" 6269 + checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db 6270 + languageName: node 6271 + linkType: hard 6272 + 6075 6273 "whatwg-encoding@npm:^3.1.1": 6076 6274 version: 3.1.1 6077 6275 resolution: "whatwg-encoding@npm:3.1.1" ··· 6085 6283 version: 4.0.0 6086 6284 resolution: "whatwg-mimetype@npm:4.0.0" 6087 6285 checksum: 10c0/a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df 6286 + languageName: node 6287 + linkType: hard 6288 + 6289 + "whatwg-url@npm:^5.0.0": 6290 + version: 5.0.0 6291 + resolution: "whatwg-url@npm:5.0.0" 6292 + dependencies: 6293 + tr46: "npm:~0.0.3" 6294 + webidl-conversions: "npm:^3.0.0" 6295 + checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 6088 6296 languageName: node 6089 6297 linkType: hard 6090 6298