@mcamdali/sdkbump 0.0.0-stage → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.de.md +251 -0
  3. package/README.es.md +252 -0
  4. package/README.fr.md +252 -0
  5. package/README.ja.md +250 -0
  6. package/README.ko.md +250 -0
  7. package/README.md +322 -2
  8. package/README.pt-BR.md +252 -0
  9. package/README.ru.md +252 -0
  10. package/README.tr.md +338 -0
  11. package/README.zh-CN.md +250 -0
  12. package/dist/cli/main.d.ts +2 -0
  13. package/dist/cli/main.js +11 -0
  14. package/dist/cli/run.d.ts +29 -0
  15. package/dist/cli/run.js +111 -0
  16. package/dist/collect/app.d.ts +48 -0
  17. package/dist/collect/app.js +117 -0
  18. package/dist/collect/blank.d.ts +6 -0
  19. package/dist/collect/blank.js +75 -0
  20. package/dist/collect/pbxproj.d.ts +45 -0
  21. package/dist/collect/pbxproj.js +260 -0
  22. package/dist/collect/plist-binary.d.ts +2 -0
  23. package/dist/collect/plist-binary.js +123 -0
  24. package/dist/collect/plist-value.d.ts +15 -0
  25. package/dist/collect/plist-value.js +14 -0
  26. package/dist/collect/plist-xml.d.ts +2 -0
  27. package/dist/collect/plist-xml.js +195 -0
  28. package/dist/collect/plist.d.ts +6 -0
  29. package/dist/collect/plist.js +19 -0
  30. package/dist/collect/regions.d.ts +9 -0
  31. package/dist/collect/regions.js +108 -0
  32. package/dist/collect/sources.d.ts +45 -0
  33. package/dist/collect/sources.js +99 -0
  34. package/dist/core/files.d.ts +22 -0
  35. package/dist/core/files.js +47 -0
  36. package/dist/core/lines.d.ts +2 -0
  37. package/dist/core/lines.js +21 -0
  38. package/dist/core/versions.d.ts +18 -0
  39. package/dist/core/versions.js +63 -0
  40. package/dist/detect/project.d.ts +46 -0
  41. package/dist/detect/project.js +220 -0
  42. package/dist/index.d.ts +26 -0
  43. package/dist/index.js +27 -0
  44. package/dist/model.d.ts +93 -0
  45. package/dist/model.js +2 -0
  46. package/dist/report/index.d.ts +12 -0
  47. package/dist/report/index.js +22 -0
  48. package/dist/report/markdown.d.ts +2 -0
  49. package/dist/report/markdown.js +113 -0
  50. package/dist/report/text.d.ts +27 -0
  51. package/dist/report/text.js +63 -0
  52. package/dist/report/tty.d.ts +7 -0
  53. package/dist/report/tty.js +112 -0
  54. package/dist/rules/check.d.ts +11 -0
  55. package/dist/rules/check.js +253 -0
  56. package/dist/rules/data.d.ts +217 -0
  57. package/dist/rules/data.js +141 -0
  58. package/dist/rules/fixes.d.ts +28 -0
  59. package/dist/rules/fixes.js +161 -0
  60. package/dist/rules/patterns.d.ts +29 -0
  61. package/dist/rules/patterns.js +109 -0
  62. package/dist/rules/query.d.ts +16 -0
  63. package/dist/rules/query.js +50 -0
  64. package/dist/scan.d.ts +10 -0
  65. package/dist/scan.js +115 -0
  66. package/dist/version.d.ts +2 -0
  67. package/dist/version.js +7 -0
  68. package/package.json +69 -4
  69. package/rules/ios27.json +613 -0
  70. package/rules/schema.json +449 -0
package/README.tr.md ADDED
@@ -0,0 +1,338 @@
1
+ <!-- i18n-source: README.md@49073c524eb2b7aad433b6794961ec40869c1170 status=reviewed -->
2
+ <!-- brand:start -->
3
+
4
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg" alt="sdkbump: Checks native iOS, Flutter and React Native apps for the iOS 27 SDK changes and names the fix for each."></picture></p>
5
+
6
+ <!-- lang-selector:start -->
7
+ <p align="center"><a href="README.md">English</a> · <a href="README.tr.md">Türkçe</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a> · <a href="README.es.md">Español</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.ru.md">Русский</a></p>
8
+ <!-- lang-selector:end -->
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml"><img src="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml/badge.svg" alt="CI durumu"></a>
12
+ <a href="https://github.com/muhittincamdali/sdkbump/releases"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg" alt="Son sürüm: v0.1.2"></picture></a>
13
+ <a href="https://github.com/muhittincamdali/sdkbump/blob/main/package.json"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg" alt="Dil sürümü: Node.js 22.12+"></picture></a>
14
+ <a href="https://github.com/muhittincamdali/sdkbump/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg" alt="Lisans: MIT"></picture></a>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="#hızlı-başlangıç"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-tr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-tr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-tr-light.svg" alt="Başlayın"></picture></a>
19
+ <a href="https://muhittincamdali.github.io/sdkbump/"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-tr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-tr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-tr-light.svg" alt="Dokümantasyon"></picture></a>
20
+ <a href="https://github.com/muhittincamdali/sdkbump/tree/main/docs/guides"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-tr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-tr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-tr-light.svg" alt="Rehberler"></picture></a>
21
+ <a href="https://github.com/muhittincamdali/sdkbump/tree/main/examples"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-tr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-tr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-tr-light.svg" alt="Örnekler"></picture></a>
22
+ </p>
23
+
24
+ > Bu belge İngilizce README'nin çevirisidir. İkisi arasında fark varsa güncel olan İngilizce sürümdür.
25
+
26
+ <!-- brand:end -->
27
+
28
+ Xcode 27 ile derlenmiş bir sürümü yayınlamadan önce: sdkbump, yerel iOS, Flutter veya React
29
+ Native/Expo projesini iOS 27 SDK'sının getirdiği değişiklikler (başta UIScene yaşam döngüsü) için
30
+ denetler ve her bulgu için hangi çözümün geçerli olduğunu söyler. Projenizin dosyalarını okur;
31
+ hiçbir şeyi derlemez, çalıştırmaz veya değiştirmez.
32
+
33
+ <picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-rn-087-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-rn-087-light.svg"><img src="docs/media/demo-rn-087-light.svg" alt="React Native 0.87 uygulamasında çalıştırılan sdkbump: iOS 27 SDK'sıyla derlendiğinde açılmıyor; SCN001 sahne yapılandırması yok ve SCN002 pencere uygulama delegesinde oluşturuluyor, üç çözüm yoluyla"></picture>
34
+
35
+ <sub>Gerçek CLI'dan kaydedildi; <a href="fixtures/rn-087">rn-087 fixture</a>'ında, yani
36
+ <code>@react-native-community/cli init</code> ile oluşturulmuş bir React Native 0.87.1
37
+ uygulamasında (<code>npm run demo</code>).</sub>
38
+
39
+ ## Öne çıkanlar
40
+
41
+ - **"Açılacak mı?" sorusunu yanıtlar.** Hiçbir sahne tanımlamayan bir uygulama Xcode 27 ile derlenir,
42
+ ama açılışta durur. sdkbump bunu bir test cihazında fark etmenizden önce söyler ve değiştirmeniz
43
+ gereken dosyaları belirtir.
44
+ - **Yerel, Flutter, React Native ve Expo** tek raporda, aynı kural kimlikleriyle; metin, Markdown
45
+ veya JSON olarak ve CI için bir çıkış koduyla.
46
+ - **Projenize uyan çözüm**: React Native 0.88 veya elle yazılmış bir sahne delegesi, Expo SDK 57'nin
47
+ isteğe bağlı desteği veya SDK 58, Flutter'ın otomatik geçişi veya elle yapılacak adımlar (sdkbump,
48
+ Flutter'ın geçiş aracıyla aynı koşulları denetler) ya da SwiftUI uygulaması için SwiftUI API'si.
49
+ - **Sessiz bozulmalar da**: uygulamada bir sahne olduğunda UIKit'in artık kullanmadığı uygulama
50
+ delegesi metotları ve başlatma seçenekleri (bağlantılar, Handoff, hızlı eylemler, ön plan ve arka
51
+ plan geçişleri) ile doğru pencereyi artık bulamayan pencere sorguları.
52
+ - **Her ifadenin bir kaynağı var.** Kurallar veridir ([rules/ios27.json](rules/ios27.json)) ve her
53
+ biri Apple'ın, Flutter'ın, React Native'in veya Expo'nun kendi sayfalarına atıfta bulunur; birinin
54
+ kaynağı yoksa testler başarısız olur.
55
+ - **iOS 27 simülatöründe denendi**: SCN001 ve SCN002'nin arkasındaki açılış hatası ve siyah ekran
56
+ Xcode 27.0 ile yeniden üretildi; kayıtlar depodadır.
57
+
58
+ ## Hızlı başlangıç
59
+
60
+ [Node.js](https://nodejs.org/) 22.12 veya üstü gerekir (`node --version` sürümü gösterir; Mac'te
61
+ `brew install node` ile kurulur). Başka bir şey gerekmez.
62
+
63
+ **1. Uygulamanızın klasöründe bir terminal açın**; `.xcodeproj`, `pubspec.yaml` veya
64
+ `package.json` dosyasının bulunduğu klasör:
65
+
66
+ ```sh
67
+ cd path/to/YourApp
68
+ ```
69
+
70
+ **2. sdkbump'ı çalıştırın:**
71
+
72
+ ```sh
73
+ npx @mcamdali/sdkbump
74
+ ```
75
+
76
+ npm paketinin adı `@mcamdali/sdkbump`; kurduğu komut `sdkbump`. Scope'suz bir `npx sdkbump` bu
77
+ paketi çalıştırmaz.
78
+
79
+ **3. Projenizin adının altındaki ilk satırı okuyun.** "Fails to launch when built with the iOS 27
80
+ SDK" (iOS 27 SDK'sıyla derlendiğinde açılmıyor), **ERROR** bulgularını düzeltene kadar uygulamanın
81
+ açılışta duracağı anlamına gelir; her bulgu, "How to fix" listesindeki hangi çözümün geçerli
82
+ olduğunu söyler. **WARNING** bulguları açılışı engellemez, ancak uygulamada bir sahne olunca
83
+ çalışmayı bırakır. "Launch not determined" (açılıp açılmayacağı belirlenemedi), sdkbump'ın bir
84
+ Info.plist'i okuyamadığı anlamına gelir; raporun sonundaki notlar hangisi olduğunu ve nedenini
85
+ söyler (aşağıdaki Sınırlar bölümüne bakın).
86
+
87
+ ## iOS 27 SDK'sıyla derleyince ne değişiyor
88
+
89
+ Apple'ın
90
+ [Transitioning to the UIKit scene-based life cycle](https://developer.apple.com/documentation/uikit/transitioning-to-the-uikit-scene-based-life-cycle)
91
+ sayfasından (çeviri):
92
+
93
+ > iOS 27, iPadOS 27, Mac Catalyst 27, tvOS 27 ve visionOS 27'den itibaren, en son SDK ile derlenen
94
+ > uygulamaların sahne tabanlı yaşam döngüsünü benimsemesi gerekir; aksi halde açılmazlar.
95
+
96
+ 1. **Uygulama hiçbir sahne tanımlamıyorsa açılışta durur.** Info.plist'te yapılandırması olan bir
97
+ `UIApplicationSceneManifest` yok ve `application(_:configurationForConnecting:options:)` yok:
98
+ UIKit süreci "UIScene life cycle is required for apps built with this SDK" iletisiyle sonlandırır.
99
+ Derleyici uyarı vermez, çünkü denetim uygulama başlarken yapılır. React Native 0.87 ve öncesi,
100
+ isteğe bağlı desteği açılmamış Expo SDK 57 ve Expo SDK 56 ve öncesi böyle uygulamalar oluşturur;
101
+ Flutter aracının geçiremediği Flutter uygulamaları da öyle.
102
+ 2. **Bir sahne varsa uygulama delegesi artık arayüz olaylarını almaz.** Bağlantılar, kullanıcı
103
+ etkinlikleri, hızlı eylemler ve etkin/arka plan geçişleri sahne delegesine gider; uygulama
104
+ delegesinin oluşturduğu pencere ise hiç gösterilmez.
105
+
106
+ [Neden derleniyor ama yine de çöküyor](docs/guides/why-it-crashes.md), iOS 27.0 simülatöründe
107
+ çalıştırdığımız [açılış matrisini](examples/launch-matrix/README.md) gösterir.
108
+
109
+ ## sdkbump neleri denetler
110
+
111
+ | Kural | Önem derecesi | Bulgu | iOS 27.0 simülatöründe gözlenen |
112
+ | ------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
113
+ | SCN001 | error | Sahne yapılandırması yok: yapılandırılmış `UIApplicationSceneManifest` yok, `configurationForConnecting` yok, SwiftUI `App` değil; `ios/` klasörü olmayan Expo için SDK sürümü ve `enableSceneSupport` | açılışta duruyor |
114
+ | SCN002 | error | Uygulama delegesi pencereyi `UIWindow(frame:)` ile oluşturuyor | uygulamada bir sahne olunca siyah ekran |
115
+ | SCN003 | warning | UIKit'in sahnelerle artık kullanmadığı uygulama delegesi metotları ve başlatma seçeneği anahtarları (13 tane), sahne delegesi zaten işlemiyorsa | bir SwiftUI uygulamasında `applicationDidEnterBackground(_:)` çağrılmıyor |
116
+ | SCN004 | warning | `UIApplication.shared.keyWindow`, `.windows` veya uygulama delegesinin `window` özelliği üzerinden pencere sorguları | yalnızca derleyicinin kullanımdan kaldırma uyarıları |
117
+
118
+ Kural verisi `ios27@2026.10.15`, Xcode 27.0 (27A266a) ile denetlendi. React Native veya Expo
119
+ projesinde `react-native-uiscene-bridge` ya da `react-native-xcode27` kuruluysa, bunların çalışma
120
+ zamanında ele aldığı bulgular README'lerindeki sınırlarla birlikte "ele alınmış" olarak gösterilir
121
+ ve çalıştırmayı başarısız saymaz.
122
+
123
+ ## Kurulum
124
+
125
+ `sdkbump` komutunu npm'den kurun (paket `@mcamdali/sdkbump`):
126
+
127
+ ```sh
128
+ npm i -g @mcamdali/sdkbump
129
+ sdkbump
130
+ ```
131
+
132
+ Bir projede `npm install --save-dev @mcamdali/sdkbump` bir sürümü sabitler; ardından
133
+ `npx sdkbump` o kopyayı çalıştırır. Her [GitHub sürümü](https://github.com/muhittincamdali/sdkbump/releases) aynı paketi
134
+ `sdkbump-<sürüm>.tgz` olarak bir `SHA256SUMS` dosyasıyla birlikte taşır; `npx` onu npm olmadan
135
+ URL'sinden çalıştırır. `muhittincamdali/tap` için bir Homebrew
136
+ formülü release workflow'u tarafından hazırlanır (tap'in ilk sürümüyle birlikte planlanıyor).
137
+
138
+ ## Kullanım
139
+
140
+ ```text
141
+ sdkbump [path] [options]
142
+ ```
143
+
144
+ | Seçenek | Ne yapar |
145
+ | ----------------------- | ------------------------------------------------------------------------------------- |
146
+ | `path` | Proje klasörü veya `.xcodeproj`; varsayılan geçerli klasördür |
147
+ | `-f, --format <format>` | `tty` (varsayılan), `markdown` veya `json` |
148
+ | `-o, --output <file>` | Raporu terminal yerine bir dosyaya yazar |
149
+ | `--fail-on <severity>` | `error` (varsayılan), `warning`, `info` veya `none`: çıkış kodunun ne zaman 1 olacağı |
150
+ | `--no-color` | Terminalde bile düz metin (`NO_COLOR` ve `FORCE_COLOR` dikkate alınır) |
151
+
152
+ Çıkış kodları: `0` `--fail-on` düzeyinde veya üstünde ele alınmamış bulgu yok, `1` bu düzeyde veya
153
+ üstünde bulgu var, `2` hatalı argüman, iOS projesi bulunamadı veya beklenmeyen bir hata.
154
+
155
+ sdkbump iOS uygulamasını kendisi bulur: yerel uygulamalar için kökteki veya bir klasör altındaki bir
156
+ `.xcodeproj`, Flutter, React Native ve Expo uygulamaları için `ios/` (Flutter eklentisi için
157
+ `example/ios/`). Proje dosyasındaki her iOS uygulama hedefini, her birinin adını verdiği Info.plist
158
+ dosyasını (XML veya ikili) ve uygulamanın Swift ile Objective-C dosyalarını okur; Pods,
159
+ `node_modules`, derleme çıktıları ve testleri atlar. `ios/` klasörü olmayan Expo uygulamaları
160
+ package.json ve app.json üzerinden denetlenir.
161
+
162
+ ### Markdown raporunu kodla birlikte saklayın
163
+
164
+ ```sh
165
+ npx @mcamdali/sdkbump --format markdown --output sdkbump.md
166
+ ```
167
+
168
+ ### JSON raporunu betiklerde kullanın
169
+
170
+ ```sh
171
+ npx @mcamdali/sdkbump --format json > sdkbump.json
172
+ ```
173
+
174
+ Her bulguda `rule`, `severity`, `file`, `line`, `message`, adımları ve rehberiyle `fix`,
175
+ `alternatives`, `mitigation` (bir geçici çözüm paketi ele alıyorsa dolu olur) ve `sources` bulunur.
176
+ Yapı `schemaVersion` 0'dır ve 1.0'dan önce değişebilir.
177
+ [examples/shell/launch-blockers.sh](examples/shell/launch-blockers.sh) bunu `jq` ile süzer.
178
+
179
+ ### CI'da çalıştırın
180
+
181
+ [examples/github-actions/sdkbump.yml](examples/github-actions/sdkbump.yml), iOS uygulamasına dokunan
182
+ her pull request'in iş özetine raporu ekler ve hata varsa işi başarısız kılar.
183
+
184
+ ### JavaScript'ten
185
+
186
+ ```js
187
+ import { render, scan } from 'sdkbump';
188
+
189
+ const report = await scan('path/to/app');
190
+ console.log(report.verdict.text);
191
+ console.log(render(report, 'markdown'));
192
+ ```
193
+
194
+ Çalıştırılabilir bir sürümü [examples/api/verdicts.mjs](examples/api/verdicts.mjs) dosyasındadır.
195
+
196
+ ## Demo
197
+
198
+ Terminal kayıtları, her araç zinciriyle oluşturulmuş gerçek projeler olan
199
+ [fixture'lar](fixtures/README.md) üzerinde CLI'dan alınmıştır:
200
+
201
+ | Proje | Kayıt |
202
+ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
203
+ | React Native 0.87.1 uygulaması | bu sayfanın başında |
204
+ | Özelleştirilmiş AppDelegate'li Flutter uygulaması (Flutter 3.24) | [açık](docs/media/demo-flutter-light.svg) · [koyu](docs/media/demo-flutter-dark.svg) |
205
+ | Adaptör uygulama delegeli SwiftUI uygulaması | [açık](docs/media/demo-swiftui-light.svg) · [koyu](docs/media/demo-swiftui-dark.svg) |
206
+
207
+ iOS 27.0 simülatöründe (iPhone 17, Xcode 27.0 ile derlendi) yerel UIKit fixture'ı açılışta durur;
208
+ aynı uygulama bir sahne delegesine taşındığında açılır:
209
+
210
+ <picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-simulator-native-uikit-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-simulator-native-uikit-light.svg"><img src="docs/media/demo-simulator-native-uikit-light.svg" alt="iOS 27.0 simülatöründe scripts/simulator-check.sh native-uikit: açılıştan 4 saniye sonra çalışmıyor; UIKit'in satırı: Application failed to launch: UIScene life cycle is required for apps built with this SDK"></picture>
211
+
212
+ <p align="center"><img src="docs/media/simulator/launched.png" width="480" alt="native-uikit-scenes ve native-swiftui fixture'ları, Xcode 27.0 ile derlenmiş, iOS 27.0 yüklü bir iPhone 17 simülatöründe çalışıyor"></p>
213
+
214
+ 15 Ekim 2026'da, Node.js 26.11 yüklü bir Mac'te (Apple silicon, M5 Max), makinede başka işler
215
+ çalışırken ölçüldü: on fixture üzerinde `node dist/cli/main.js` 100'er çalıştırmalık üç seri,
216
+ Node.js'in açılışı dahil. Serilerin medyanları 0,11, 0,12 ve 0,19 saniye; en yavaş çalıştırma 0,33
217
+ saniye sürdü. Makine daha yüklüyken süreler uzar.
218
+
219
+ ## Durum
220
+
221
+ | Özellik | Durum |
222
+ | -------------------------------------------------------------------------------------------------------------------- | ----------------- |
223
+ | Yerel, Flutter (uygulama ve eklenti örneği), React Native ve Expo projesi algılama | çalışıyor |
224
+ | Uygulamanın kendi Info.plist'i ve Swift/Objective-C kaynaklarında SCN001 ile SCN004 | çalışıyor |
225
+ | Ekosisteme ve sürüme göre çözüm seçimi; Flutter otomatik geçiş denetimi; geçici çözüm paketleri | çalışıyor |
226
+ | Terminal, Markdown ve JSON raporları; `--fail-on` çıkış kodları | çalışıyor |
227
+ | Bağımlılıklar: Pods, `node_modules` ve Flutter eklenti kaynakları, paketin adıyla | planlanıyor (0.2) |
228
+ | SCN005 geçici çözüm bildirimi ayrı bir kural olarak; 15.0 altındaki dağıtım hedefleri için DPT001 | planlanıyor (0.2) |
229
+ | `--verify`: CLI'dan iOS 27 simülatöründe derleme ve açma | planlanıyor (0.3) |
230
+ | Kalıplar yerine Swift/Objective-C sözdizimi ağaçları; derlenmiş `.app` denetimleri; SiriKit kullanımdan kaldırmaları | planlanıyor (0.5) |
231
+ | Yerel uygulamalar için `fix --dry-run`, SARIF çıktısı, GitHub Action | planlanıyor (0.8) |
232
+ | Kararlı kural şeması ve JSON yapısı | planlanıyor (1.0) |
233
+
234
+ ## Sınırlar
235
+
236
+ - **Derleyici değil, kalıp.** Kurallar, yorumları ve dizgeleri boşaltılmış Swift ve Objective-C
237
+ metni üzerinde çalışan düzenli ifadelerdir. Üretilmiş kod, makroların arkasındaki kod veya
238
+ alışılmadık biçimde yazılmış kod gözden kaçabilir ya da yanlışlıkla eşleşebilir. Sözdizimi
239
+ ağaçları planlanıyor (0.5).
240
+ - **Yalnızca uygulamanın kendi kaynakları.** Pods, `node_modules`, Flutter eklentileri ve diğer
241
+ bağımlılıklar okunmaz; bu yüzden UIKit'in artık çağırmadığı app delegate yöntemlerine dayanan bir
242
+ eklenti raporlanmaz. Bağımlılık denetimi planlanıyor (0.2).
243
+ - **Derleme ayarları yalnızca project.pbxproj'den.** sdkbump, `INFOPLIST_FILE` ve
244
+ `GENERATE_INFOPLIST_FILE` ayarlarını proje dosyasından okur ve `$(SRCROOT)`, `$(PROJECT_DIR)`,
245
+ `$(TARGET_NAME)` ile `$(PRODUCT_NAME)` değerlerini yerine koyar. `.xcconfig` dosyalarını okumaz,
246
+ diğer derleme ayarlarını yerine koymaz ve proje klasörünün dışındaki bir Info.plist'i okumaz. Bir
247
+ hedefin Info.plist'ini okuyamadığında tahmin yürütmek yerine SCN001'i info düzeyinde bir bulgu
248
+ yapar ve sonucu "Launch not determined" olarak verir.
249
+ - **Bastırma dosyası yok.** Bir bulgu incelendi olarak işaretlenemez; hangi önem düzeylerinin
250
+ çalıştırmayı başarısız yapacağına `--fail-on` karar verir.
251
+ - **Yalnızca dosyalar.** sdkbump uygulamayı derlemez ve açmaz; `--verify` planlanıyor (0.3).
252
+
253
+ ## Dokümantasyon
254
+
255
+ API başvurusu ve rehberler: [muhittincamdali.github.io/sdkbump](https://muhittincamdali.github.io/sdkbump/).
256
+
257
+ ## Rehberler
258
+
259
+ - [Neden derleniyor ama yine de çöküyor](docs/guides/why-it-crashes.md)
260
+ - [Yerel UIKit ve SwiftUI uygulamaları](docs/guides/native-ios.md)
261
+ - [Flutter: özelleştirilmiş AppDelegate ve eklentiler](docs/guides/flutter.md)
262
+ - [0.88 öncesi React Native ve SDK 58 öncesi Expo](docs/guides/react-native-expo.md)
263
+ - [Yerel modül yazarları: soğuk başlangıçta bağlantılar ve bildirimler](docs/guides/native-module-authors.md)
264
+
265
+ ## İlgili araçlar
266
+
267
+ Başka projeler de aynı değişiklik üzerinde çalışıyor; hangisinin uygun olduğu neye ihtiyacınız
268
+ olduğuna bağlıdır:
269
+
270
+ - [react-native-uiscene-bridge](https://github.com/Atomics-hub/react-native-uiscene-bridge) ve
271
+ [react-native-xcode27](https://github.com/Atomics-hub/react-native-xcode27), bir React Native
272
+ veya Expo uygulamasını kod değişikliği olmadan, çalışma zamanında açılır hale getirir. Henüz
273
+ yükseltemediğinizde işe yararlar; sdkbump bunları tanır.
274
+ - [auditor-uiscene](https://github.com/Anzell/auditor-uiscene), Flutter uygulamalarını ve
275
+ eklentilerini bir kabuk betiğiyle denetler.
276
+ - Flutter'ın kendi geçiş aracı (3.41'den itibaren `flutter build ios`), değiştirilmemiş bir Flutter
277
+ uygulamasını geçirir.
278
+ - [flutter_spm_doctor](https://pub.dev/packages/flutter_spm_doctor) Flutter eklentilerini denetler.
279
+
280
+ ## Gereksinimler
281
+
282
+ | Araç zinciri | En düşük sürüm |
283
+ | ------------ | -------------- |
284
+ | Node.js | 22.12 |
285
+
286
+ sdkbump'ın Xcode'a ihtiyacı yoktur: dosyaları okur, bu yüzden Linux'ta da çalışır. CI testleri
287
+ Node.js 22 ve 24'te (Linux) çalıştırır; yerelde 280 testin tamamı bir Mac'te (Apple silicon)
288
+ Node.js 22.23, 24.22 ve 26.11 ile geçer. Simülatör kayıtları Xcode 27 yüklü bir Mac gerektirir ve
289
+ CI'ın parçası değildir.
290
+
291
+ ## Mimari
292
+
293
+ ```text
294
+ path ─► detectProject native | flutter | react-native | expo; iOS folder; versions
295
+ ─► collectApp iOS app targets from project.pbxproj, their Info.plist (XML or binary),
296
+ Swift and Objective-C sources with comments and strings blanked
297
+ ─► checkApp SCN001…SCN004, fix per ecosystem and version, workaround packages
298
+ rules/ios27.json what each rule says, fixes, sources (validated with zod)
299
+ ─► render tty | markdown | json
300
+ ```
301
+
302
+ - Algılama kalıpları, yorumları ve dizgeleri boşaltılmış kaynak metin üzerindeki düzenli ifadelerdir
303
+ ve gereken yerde yalnızca bir uygulama delegesinin veya sahne delegesinin içinde sayılır.
304
+ - Kural verisi koddan ayrıdır ve sürümlüdür (`ios27@2026.10.15`); bir kuralın, çözümün veya geçici
305
+ çözümün kaynağı yoksa bir test başarısız olur.
306
+ - CLI (`src/cli/`) yalnızca argümanları ayrıştırır, renkleri ve genişlikleri seçer ve çıkış kodunu
307
+ belirler.
308
+
309
+ ## Yol haritası
310
+
311
+ [Durum](#durum) tablosuna bakın: 0.2 bağımlılıkları ve dağıtım hedeflerini ekler, 0.3 CLI'dan
312
+ simülatörde açmayı, 0.5 sözdizimi ağaçlarını ve derlenmiş uygulama denetimlerini, 0.8 çözümleri ve
313
+ SARIF'i, 1.0 kararlı bir şemayı. [CHANGELOG.md](CHANGELOG.md) her sürümde nelerin değiştiğini listeler.
314
+
315
+ ## SSS
316
+
317
+ **Uygulamam bugün iOS 27'de çalışıyor. Etkilenir mi?** Xcode 26 veya öncesiyle derlendiyse bu denetim
318
+ o derleme için geçerli değildir: bizim denememizde, iOS 26 SDK'sına bağlanan aynı kod iOS 27
319
+ simülatöründe açıldı. Xcode 27 ile yapacağınız bir sonraki derleme için geçerlidir.
320
+
321
+ **sdkbump bir cihazda test etmenin yerini tutar mı?** Hayır. Dosyaları okur. Bu depodaki simülatör
322
+ kayıtları iOS 27.0 simülatöründendir; burada hiçbir şey bir cihazda çalıştırılmadı.
323
+
324
+ **Bir bulgu neden "ele alınmış" görünüyor?** package.json'daki bir geçici çözüm paketi
325
+ (react-native-uiscene-bridge veya react-native-xcode27) çalışma zamanında bir sahne tanımlar.
326
+ Uygulama açılır, ama kendi başına hâlâ sahne desteği yoktur; rapor paketin sınırlarını ve gerçek
327
+ çözümü listeler.
328
+
329
+ **sdkbump projemi değiştirir mi?** Hayır. Projeyi okur ve yalnızca istediğiniz raporu yazar.
330
+
331
+
332
+ ## Katkıda bulunma
333
+
334
+ Katkılarınızı bekliyoruz. Pull request açmadan önce [katkı rehberini](CONTRIBUTING.md) ve [davranış kurallarını](https://github.com/muhittincamdali/.github/blob/main/CODE_OF_CONDUCT.md) okuyun. Güvenlik açıklarını [güvenlik politikasında](SECURITY.md) anlatıldığı gibi gizli olarak bildirin.
335
+
336
+ ## Lisans
337
+
338
+ MIT lisansıyla yayımlanmıştır. Ayrıntılar için [LICENSE](LICENSE) dosyasına bakın.
@@ -0,0 +1,250 @@
1
+ <!-- i18n-source: README.md@49073c524eb2b7aad433b6794961ec40869c1170 status=reviewed -->
2
+ <!-- brand:start -->
3
+
4
+ <p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg" alt="sdkbump: Checks native iOS, Flutter and React Native apps for the iOS 27 SDK changes and names the fix for each."></picture></p>
5
+
6
+ <!-- lang-selector:start -->
7
+ <p align="center"><a href="README.md">English</a> · <a href="README.tr.md">Türkçe</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a> · <a href="README.es.md">Español</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.ru.md">Русский</a></p>
8
+ <!-- lang-selector:end -->
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml"><img src="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml/badge.svg" alt="CI 状态"></a>
12
+ <a href="https://github.com/muhittincamdali/sdkbump/releases"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg" alt="最新版本: v0.1.2"></picture></a>
13
+ <a href="https://github.com/muhittincamdali/sdkbump/blob/main/package.json"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg" alt="语言版本: Node.js 22.12+"></picture></a>
14
+ <a href="https://github.com/muhittincamdali/sdkbump/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg" alt="许可证: MIT"></picture></a>
15
+ </p>
16
+
17
+ <p align="center">
18
+ <a href="#快速开始"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-zh-CN-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-zh-CN-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-zh-CN-light.svg" alt="开始使用"></picture></a>
19
+ <a href="https://muhittincamdali.github.io/sdkbump/"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-zh-CN-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-zh-CN-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-zh-CN-light.svg" alt="文档"></picture></a>
20
+ <a href="https://github.com/muhittincamdali/sdkbump/tree/main/docs/guides"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-zh-CN-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-zh-CN-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-zh-CN-light.svg" alt="指南"></picture></a>
21
+ <a href="https://github.com/muhittincamdali/sdkbump/tree/main/examples"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-zh-CN-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-zh-CN-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-zh-CN-light.svg" alt="示例"></picture></a>
22
+ </p>
23
+
24
+ > 本文是英文 README 的译文。如两者内容不一致,以英文版为准。
25
+
26
+ <!-- brand:end -->
27
+
28
+ 在发布使用 Xcode 27 构建的版本之前:sdkbump 会检查原生 iOS、Flutter 或 React Native/Expo 项目是否受 iOS 27 SDK 变更的影响(首先是 UIScene 生命周期),并针对每一项发现告诉你适用的修复方式。它只读取项目文件,不会构建、运行或修改任何内容。
29
+
30
+ <picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-rn-087-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-rn-087-light.svg"><img src="docs/media/demo-rn-087-light.svg" alt="在 React Native 0.87 应用上运行 sdkbump:使用 iOS 27 SDK 构建后无法启动;SCN001 没有场景配置,SCN002 在 app delegate 中创建窗口,并给出三种修复方式"></picture>
31
+
32
+ <sub>录制自真实的 CLI,运行对象是 <a href="fixtures/rn-087">rn-087 fixture</a>,即由 <code>@react-native-community/cli init</code> 创建的 React Native 0.87.1 应用(<code>npm run demo</code>)。</sub>
33
+
34
+ ## 亮点
35
+
36
+ - **回答“能启动吗?”** 没有声明任何 scene 的应用可以用 Xcode 27 构建,但会在启动时停止。sdkbump 会在你在测试设备上才发现之前就告诉你,并指出需要修改的文件。
37
+ - **原生、Flutter、React Native 和 Expo** 在同一份报告中使用相同的规则 ID,输出格式为文本、Markdown 或 JSON,并提供供 CI 使用的退出码。
38
+ - **适用于你的项目的修复方式**:React Native 0.88 或手写的 scene delegate,Expo SDK 57 的可选开关或 SDK 58,Flutter 的自动迁移或手动步骤(sdkbump 检查的条件与 Flutter 的迁移工具相同),或者针对 SwiftUI 应用的 SwiftUI API。
39
+ - **也包括悄无声息的故障**:应用有了 scene 之后,UIKit 不再使用的 app delegate 方法和启动选项(链接、Handoff、快捷操作、前台与后台切换),以及再也找不到正确窗口的窗口查找方式。
40
+ - **每一条说明都有出处。** 规则以数据形式存放([rules/ios27.json](rules/ios27.json)),每条规则都引用 Apple、Flutter、React Native 或 Expo 自己的页面;缺少出处时测试会失败。
41
+ - **已在 iOS 27 模拟器中验证**:SCN001 和 SCN002 背后的启动失败与黑屏已用 Xcode 27.0 复现,录像保存在仓库中。
42
+
43
+ ## 快速开始
44
+
45
+ 你需要 [Node.js](https://nodejs.org/) 22.12 或更高版本(`node --version` 可查看版本;在 Mac 上,`brew install node` 即可安装)。不需要其他任何东西。
46
+
47
+ **1. 在应用所在的文件夹中打开终端**,也就是包含 `.xcodeproj`、`pubspec.yaml` 或 `package.json` 的那个文件夹:
48
+
49
+ ```sh
50
+ cd path/to/YourApp
51
+ ```
52
+
53
+ **2. 运行 sdkbump:**
54
+
55
+ ```sh
56
+ npx @mcamdali/sdkbump
57
+ ```
58
+
59
+ npm 包名是 `@mcamdali/sdkbump`,它安装的命令是 `sdkbump`。不带 scope 的 `npx sdkbump` 不会运行它。
60
+
61
+ **3. 阅读项目名称下方的第一行。** “Fails to launch when built with the iOS 27 SDK”(使用 iOS 27 SDK 构建后无法启动)表示在你修复 **ERROR** 级别的发现之前,应用会在启动时停止;每一项发现都会说明适用“How to fix”列表中的哪种修复方式。**WARNING** 级别的发现不会阻止启动,但应用有了 scene 之后就会失效。 “Launch not determined”(无法判断能否启动)表示 sdkbump 没能读取某个 Info.plist;报告末尾的注释会说明是哪一个以及原因(见下方“限制”)。
62
+
63
+ ## 使用 iOS 27 SDK 构建时有哪些变化
64
+
65
+ 引自 Apple 的 [Transitioning to the UIKit scene-based life cycle](https://developer.apple.com/documentation/uikit/transitioning-to-the-uikit-scene-based-life-cycle)(译文):
66
+
67
+ > 从 iOS 27、iPadOS 27、Mac Catalyst 27、tvOS 27 和 visionOS 27 开始,使用最新 SDK 构建的应用必须采用基于 scene 的生命周期,否则将无法启动。
68
+
69
+ 1. **如果应用没有声明 scene,它会在启动时停止。** Info.plist 中没有带配置的 `UIApplicationSceneManifest`,也没有 `application(_:configurationForConnecting:options:)`:UIKit 会以 “UIScene life cycle is required for apps built with this SDK” 为提示结束进程。编译器不会给出警告,因为这项检查发生在应用启动时。React Native 0.87 及更早版本、未启用可选开关的 Expo SDK 57,以及 Expo SDK 56 及更早版本创建的应用都属于这种情况;Flutter 工具无法迁移的 Flutter 应用也是如此。
70
+ 2. **有了 scene,app delegate 就不再接收界面事件。** 链接、user activity、快捷操作以及活跃/后台切换都会转到 scene delegate,而由 app delegate 创建的窗口永远不会显示。
71
+
72
+ [为什么能编译却仍然崩溃](docs/guides/why-it-crashes.md)介绍了我们在 iOS 27.0 模拟器中运行的[启动矩阵](examples/launch-matrix/README.md)。
73
+
74
+ ## sdkbump 检查什么
75
+
76
+ | 规则 | 严重程度 | 发现 | 在 iOS 27.0 模拟器中观察到的现象 |
77
+ | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
78
+ | SCN001 | error | 没有 scene 配置:没有已配置的 `UIApplicationSceneManifest`,没有 `configurationForConnecting`,也不是 SwiftUI `App`;对于没有 `ios/` 的 Expo,则检查 SDK 版本和 `enableSceneSupport` | 启动时停止 |
79
+ | SCN002 | error | app delegate 使用 `UIWindow(frame:)` 创建窗口 | 应用有了 scene 之后出现黑屏 |
80
+ | SCN003 | warning | UIKit 在使用 scene 时不再使用的 app delegate 方法和启动选项键(共 13 个),除非 scene delegate 已经处理了它们 | SwiftUI 应用中 `applicationDidEnterBackground(_:)` 不会被调用 |
81
+ | SCN004 | warning | 通过 `UIApplication.shared.keyWindow`、`.windows` 或 app delegate 的 `window` 查找窗口 | 仅有编译器的弃用警告 |
82
+
83
+ 规则数据 `ios27@2026.10.15`,已对照 Xcode 27.0(27A266a)检查。当 React Native 或 Expo 项目安装了 `react-native-uiscene-bridge` 或 `react-native-xcode27` 时,它们在运行时处理的发现会显示为“已处理”,并附上其 README 中说明的限制,不会导致运行失败。
84
+
85
+ ## 安装
86
+
87
+ 从 npm 安装 `sdkbump` 命令(包名 `@mcamdali/sdkbump`):
88
+
89
+ ```sh
90
+ npm i -g @mcamdali/sdkbump
91
+ sdkbump
92
+ ```
93
+
94
+ 在项目中,`npm install --save-dev @mcamdali/sdkbump` 会锁定一个版本,之后 `npx sdkbump` 运行的就是这个副本。每个 [GitHub 发布版本](https://github.com/muhittincamdali/sdkbump/releases)也以 `sdkbump-<版本>.tgz` 的形式附带同一个包和 `SHA256SUMS` 文件,`npx` 可以不经 npm 直接从其 URL 运行。适用于 `muhittincamdali/tap` 的 Homebrew formula 由发布工作流准备(计划随 tap 的首个版本提供)。
95
+
96
+ ## 使用方法
97
+
98
+ ```text
99
+ sdkbump [path] [options]
100
+ ```
101
+
102
+ | 选项 | 作用 |
103
+ | ----------------------- | -------------------------------------------------------------- |
104
+ | `path` | 项目文件夹或 `.xcodeproj`;默认为当前文件夹 |
105
+ | `-f, --format <format>` | `tty`(默认)、`markdown` 或 `json` |
106
+ | `-o, --output <file>` | 将报告写入文件,而不是输出到终端 |
107
+ | `--fail-on <severity>` | `error`(默认)、`warning`、`info` 或 `none`:退出码何时为 1 |
108
+ | `--no-color` | 即使在终端中也输出纯文本(会遵循 `NO_COLOR` 和 `FORCE_COLOR`) |
109
+
110
+ 退出码:`0` 表示没有达到或超过 `--fail-on` 级别的未处理发现,`1` 表示有达到或超过该级别的发现,`2` 表示参数错误、未找到 iOS 项目或发生意外错误。
111
+
112
+ sdkbump 会自行找到 iOS 应用:原生应用是根目录或下一级文件夹中的 `.xcodeproj`,Flutter、React Native 和 Expo 应用是 `ios/`(Flutter 插件是 `example/ios/`)。它会读取项目文件中的每个 iOS 应用 target、每个 target 指定的 Info.plist(XML 或二进制),以及应用的 Swift 和 Objective-C 文件,并跳过 Pods、`node_modules`、构建产物和测试。没有 `ios/` 的 Expo 应用则根据 package.json 和 app.json 检查。
113
+
114
+ ### 将 Markdown 报告与代码一起保存
115
+
116
+ ```sh
117
+ npx @mcamdali/sdkbump --format markdown --output sdkbump.md
118
+ ```
119
+
120
+ ### 在脚本中使用 JSON 报告
121
+
122
+ ```sh
123
+ npx @mcamdali/sdkbump --format json > sdkbump.json
124
+ ```
125
+
126
+ 每项发现都包含 `rule`、`severity`、`file`、`line`、`message`、带有步骤和指南的 `fix`、`alternatives`、`mitigation`(当有变通方案包处理该问题时会设置)以及 `sources`。其结构为 `schemaVersion` 0,在 1.0 之前可能会变化。[examples/shell/launch-blockers.sh](examples/shell/launch-blockers.sh) 用 `jq` 对其进行过滤。
127
+
128
+ ### 在 CI 中运行
129
+
130
+ [examples/github-actions/sdkbump.yml](examples/github-actions/sdkbump.yml) 会把报告添加到每个涉及 iOS 应用的 pull request 的作业摘要中,并在出现 error 时使作业失败。
131
+
132
+ ### 在 JavaScript 中使用
133
+
134
+ ```js
135
+ import { render, scan } from 'sdkbump';
136
+
137
+ const report = await scan('path/to/app');
138
+ console.log(report.verdict.text);
139
+ console.log(render(report, 'markdown'));
140
+ ```
141
+
142
+ 可运行的版本见 [examples/api/verdicts.mjs](examples/api/verdicts.mjs)。
143
+
144
+ ## 演示
145
+
146
+ 终端录像来自 CLI 在 [fixtures](fixtures/README.md) 上的运行,这些 fixture 是用各个工具链创建的真实项目:
147
+
148
+ | 项目 | 录像 |
149
+ | ---------------------------------------------------- | ------------------------------------------------------------------------------------ |
150
+ | React Native 0.87.1 应用 | 本页顶部 |
151
+ | 自定义了 AppDelegate 的 Flutter 应用(Flutter 3.24) | [浅色](docs/media/demo-flutter-light.svg) · [深色](docs/media/demo-flutter-dark.svg) |
152
+ | 使用适配器 app delegate 的 SwiftUI 应用 | [浅色](docs/media/demo-swiftui-light.svg) · [深色](docs/media/demo-swiftui-dark.svg) |
153
+
154
+ 在 iOS 27.0 模拟器(iPhone 17,使用 Xcode 27.0 构建)中,原生 UIKit fixture 会在启动时停止,而改用 scene delegate 的同一个应用可以正常启动:
155
+
156
+ <picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-simulator-native-uikit-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-simulator-native-uikit-light.svg"><img src="docs/media/demo-simulator-native-uikit-light.svg" alt="在 iOS 27.0 模拟器上运行 scripts/simulator-check.sh native-uikit:启动 4 秒后未在运行,UIKit 的输出为:Application failed to launch: UIScene life cycle is required for apps built with this SDK"></picture>
157
+
158
+ <p align="center"><img src="docs/media/simulator/launched.png" width="480" alt="native-uikit-scenes 和 native-swiftui fixture 运行在安装了 iOS 27.0 的 iPhone 17 模拟器上,使用 Xcode 27.0 构建"></p>
159
+
160
+ 2026 年 10 月 15 日在一台 Mac(Apple silicon,M5 Max)上使用 Node.js 26.11 测得,测量时机器上还在运行其他任务:在十个 fixture 上运行 `node dist/cli/main.js`,每组 100 次,共三组(包含 Node.js 启动时间)。三组的中位数分别为 0.11、0.12 和 0.19 秒,最慢的一次为 0.33 秒。机器负载越高,耗时越长。
161
+
162
+ ## 状态
163
+
164
+ | 功能 | 状态 |
165
+ | ----------------------------------------------------------------------------- | ------------- |
166
+ | 原生、Flutter(应用和插件示例)、React Native 和 Expo 项目检测 | 可用 |
167
+ | 针对应用自身 Info.plist 和 Swift/Objective-C 源码的 SCN001 到 SCN004 | 可用 |
168
+ | 按生态系统和版本选择修复方式;Flutter 自动迁移检查;变通方案包 | 可用 |
169
+ | 终端、Markdown 和 JSON 报告;`--fail-on` 退出码 | 可用 |
170
+ | 依赖项:Pods、`node_modules` 和 Flutter 插件源码,并指出包名 | 计划中(0.2) |
171
+ | 将 SCN005 变通方案提示作为独立规则;针对低于 15.0 的部署目标的 DPT001 | 计划中(0.2) |
172
+ | `--verify`:通过 CLI 在 iOS 27 模拟器中构建并启动 | 计划中(0.3) |
173
+ | 用 Swift/Objective-C 语法树取代模式匹配;已构建的 `.app` 检查;SiriKit 弃用项 | 计划中(0.5) |
174
+ | 面向原生应用的 `fix --dry-run`、SARIF 输出、GitHub Action | 计划中(0.8) |
175
+ | 稳定的规则 schema 和 JSON 结构 | 计划中(1.0) |
176
+
177
+ ## 限制
178
+
179
+ - **基于模式,而不是编译器。** 规则是作用于 Swift 和 Objective-C 文本的正则表达式,文本中的注释和字符串已被清空。生成的代码、藏在宏里的代码或写法不常见的代码可能被漏掉或误判。语法树计划中(0.5)。
180
+ - **只读取应用自身的源码。** 不读取 Pods、`node_modules`、Flutter 插件和其他依赖,因此依赖 UIKit 已不再调用的 app delegate 方法的插件不会被报告。依赖检查计划中(0.2)。
181
+ - **构建设置只来自 project.pbxproj。** sdkbump 从项目文件读取 `INFOPLIST_FILE` 和 `GENERATE_INFOPLIST_FILE`,并展开 `$(SRCROOT)`、`$(PROJECT_DIR)`、`$(TARGET_NAME)` 和 `$(PRODUCT_NAME)`。它不读取 `.xcconfig` 文件,不展开其他构建设置,也不读取项目文件夹之外的 Info.plist。无法读取某个 target 的 Info.plist 时,SCN001 会作为 info 级别的发现报告,结论为“Launch not determined”,而不是猜测。
182
+ - **没有屏蔽文件。** 无法把某项发现标记为已审查;由 `--fail-on` 决定哪些严重级别会让运行失败。
183
+ - **只读取文件。** sdkbump 不会构建或启动应用;`--verify` 计划中(0.3)。
184
+
185
+ ## 文档
186
+
187
+ API 参考与指南:[muhittincamdali.github.io/sdkbump](https://muhittincamdali.github.io/sdkbump/)。
188
+
189
+ ## 指南
190
+
191
+ - [为什么能编译却仍然崩溃](docs/guides/why-it-crashes.md)
192
+ - [原生 UIKit 和 SwiftUI 应用](docs/guides/native-ios.md)
193
+ - [Flutter:自定义 AppDelegate 和插件](docs/guides/flutter.md)
194
+ - [0.88 之前的 React Native 和 SDK 58 之前的 Expo](docs/guides/react-native-expo.md)
195
+ - [原生模块作者:冷启动时的链接与通知](docs/guides/native-module-authors.md)
196
+
197
+ ## 相关工具
198
+
199
+ 还有其他项目也在处理同一项变更;哪一个合适,取决于你的需求:
200
+
201
+ - [react-native-uiscene-bridge](https://github.com/Atomics-hub/react-native-uiscene-bridge) 和 [react-native-xcode27](https://github.com/Atomics-hub/react-native-xcode27) 可以在运行时让 React Native 或 Expo 应用无需修改代码即可启动。它们适用于暂时无法升级的情况;sdkbump 能够识别它们。
202
+ - [auditor-uiscene](https://github.com/Anzell/auditor-uiscene) 用 shell 脚本审计 Flutter 应用及其插件。
203
+ - Flutter 自带的迁移工具(从 3.41 起的 `flutter build ios`)可以迁移未经修改的 Flutter 应用。
204
+ - [flutter_spm_doctor](https://pub.dev/packages/flutter_spm_doctor) 检查 Flutter 插件。
205
+
206
+ ## 系统要求
207
+
208
+ | 工具链 | 最低版本 |
209
+ | ------- | -------- |
210
+ | Node.js | 22.12 |
211
+
212
+ sdkbump 不需要 Xcode:它只读取文件,因此也可以在 Linux 上运行。CI 在 Node.js 22 和 24(Linux)上运行测试;在本地的 Mac(Apple silicon)上,全部 280 个测试在 Node.js 22.23、24.22 和 26.11 上均通过。模拟器录像需要安装了 Xcode 27 的 Mac,不属于 CI 的一部分。
213
+
214
+ ## 架构
215
+
216
+ ```text
217
+ path ─► detectProject native | flutter | react-native | expo; iOS folder; versions
218
+ ─► collectApp iOS app targets from project.pbxproj, their Info.plist (XML or binary),
219
+ Swift and Objective-C sources with comments and strings blanked
220
+ ─► checkApp SCN001…SCN004, fix per ecosystem and version, workaround packages
221
+ rules/ios27.json what each rule says, fixes, sources (validated with zod)
222
+ ─► render tty | markdown | json
223
+ ```
224
+
225
+ - 检测模式是针对源码文本的正则表达式,其中的注释和字符串已被清空;在需要的地方,只有位于 app delegate 或 scene delegate 内部的匹配才会计入。
226
+ - 规则数据与代码分离并带有版本(`ios27@2026.10.15`);如果某条规则、修复方式或变通方案没有出处,测试就会失败。
227
+ - CLI(`src/cli/`)只负责解析参数、选择颜色和宽度,以及设置退出码。
228
+
229
+ ## 路线图
230
+
231
+ 参见[状态](#状态)表:0.2 增加依赖项和部署目标,0.3 支持通过 CLI 在模拟器中启动,0.5 增加语法树和已构建应用的检查,0.8 增加修复和 SARIF,1.0 提供稳定的 schema。[CHANGELOG.md](CHANGELOG.md) 列出了每个版本的变更。
232
+
233
+ ## 常见问题
234
+
235
+ **我的应用今天在 iOS 27 上能运行,会受到影响吗?** 如果它是用 Xcode 26 或更早版本构建的,这项检查不适用于那次构建:在我们的测试中,链接到 iOS 26 SDK 的同一份代码可以在 iOS 27 模拟器上启动。它适用于你下一次使用 Xcode 27 的构建。
236
+
237
+ **sdkbump 能取代真机测试吗?** 不能。它只读取文件。本仓库中的模拟器录像来自 iOS 27.0 模拟器;这里没有任何内容是在真机上运行的。
238
+
239
+ **为什么某项发现显示为“已处理”?** package.json 中的某个变通方案包(react-native-uiscene-bridge 或 react-native-xcode27)会在运行时声明一个 scene。应用可以启动,但它自身仍然没有 scene 支持;报告会列出该包的限制以及真正的修复方式。
240
+
241
+ **sdkbump 会修改我的项目吗?** 不会。它只读取项目,只写入你要求的报告。
242
+
243
+
244
+ ## 参与贡献
245
+
246
+ 欢迎参与贡献。提交 pull request 之前,请先阅读[贡献指南](CONTRIBUTING.md)和[行为准则](https://github.com/muhittincamdali/.github/blob/main/CODE_OF_CONDUCT.md)。如发现安全问题,请按照[安全策略](SECURITY.md)私下报告。
247
+
248
+ ## 许可证
249
+
250
+ 基于 MIT 许可证发布。详见 [LICENSE](LICENSE)。
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import { run } from './run.js';
3
+ process.exitCode = await run(process.argv.slice(2), {
4
+ cwd: process.cwd(),
5
+ env: process.env,
6
+ stdout: (text) => process.stdout.write(text),
7
+ stderr: (text) => process.stderr.write(text),
8
+ stdoutIsTty: process.stdout.isTTY === true,
9
+ columns: process.stdout.columns,
10
+ });
11
+ //# sourceMappingURL=main.js.map