expo 58.0.0-preview.6 → 58.0.0-preview.8
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.
- package/Package.swift +49 -0
- package/android/build.gradle +2 -2
- package/bundledNativeModules.json +45 -45
- package/package.json +17 -16
- package/scripts/spm/__tests__/app-target.test.js +370 -0
- package/scripts/spm/__tests__/cli.test.js +80 -0
- package/scripts/spm/__tests__/fixtures/target-paths/README.md +31 -0
- package/scripts/spm/__tests__/fixtures/target-paths/default-sources/Sources/Fixture/Fixture.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/default-sources/Sources/FixtureObjC/FixtureObjC.m +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/default-sources/Sources/FixtureObjC/include/FixtureObjC.h +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/default-sources/dump.json +68 -0
- package/scripts/spm/__tests__/fixtures/target-paths/default-sources/expected.json +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/explicit-path/dump.json +54 -0
- package/scripts/spm/__tests__/fixtures/target-paths/explicit-path/expected.json +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/explicit-path/ios/ExpoHaptics.podspec +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/explicit-path/ios/HapticsModule.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/missing-dir/Sources/Fixture/Fixture.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/missing-dir/dump.json +61 -0
- package/scripts/spm/__tests__/fixtures/target-paths/missing-dir/expected.json +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/other-predefined-dir/Source/Fixture/Fixture.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/other-predefined-dir/dump.json +68 -0
- package/scripts/spm/__tests__/fixtures/target-paths/other-predefined-dir/expected.json +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/other-predefined-dir/src/FixtureCore/FixtureCore.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/single-target-fallback/Sources/Fixture.swift +1 -0
- package/scripts/spm/__tests__/fixtures/target-paths/single-target-fallback/dump.json +51 -0
- package/scripts/spm/__tests__/fixtures/target-paths/single-target-fallback/expected.json +1 -0
- package/scripts/spm/__tests__/manifests.test.js +29 -0
- package/scripts/spm/__tests__/plugin.test.js +146 -1
- package/scripts/spm/__tests__/script-phases.test.js +69 -0
- package/scripts/spm/__tests__/target-paths.test.js +33 -0
- package/scripts/spm/__tests__/with-node.test.js +278 -0
- package/scripts/spm/app-target.js +208 -0
- package/scripts/spm/cli.js +20 -1
- package/scripts/spm/plugin.js +54 -17
- package/scripts/spm/script-phases.js +104 -0
- package/template.tgz +0 -0
package/Package.swift
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// swift-tools-version: 6.2
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "expo",
|
|
6
|
+
platforms: [
|
|
7
|
+
.iOS("16.4"),
|
|
8
|
+
.tvOS("16.4"),
|
|
9
|
+
.macOS("13.4"),
|
|
10
|
+
],
|
|
11
|
+
products: [
|
|
12
|
+
.library(name: "Expo", targets: ["Expo", "ExpoObjC", "ExpoLoader"])
|
|
13
|
+
],
|
|
14
|
+
dependencies: [],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "Expo",
|
|
18
|
+
dependencies: ["ExpoObjC"],
|
|
19
|
+
path: "ios/Expo",
|
|
20
|
+
),
|
|
21
|
+
.target(
|
|
22
|
+
name: "ExpoObjC",
|
|
23
|
+
dependencies: [],
|
|
24
|
+
path: "ios/ExpoObjC",
|
|
25
|
+
publicHeadersPath: "include",
|
|
26
|
+
// CocoaPods gets this from the build environment; under Swift Package Manager
|
|
27
|
+
// nothing sets it, and EXAppDefinesLoader would then report the old architecture.
|
|
28
|
+
cSettings: [.define("RCT_NEW_ARCH_ENABLED", to: "1")],
|
|
29
|
+
cxxSettings: [.define("RCT_NEW_ARCH_ENABLED", to: "1")],
|
|
30
|
+
),
|
|
31
|
+
// The ObjC `+load` bootstrap that registers app-delegate subscribers before any
|
|
32
|
+
// life-cycle event fires. It needs BOTH halves — `EXLegacyAppDelegateWrapper` from
|
|
33
|
+
// ExpoObjC and `AppDelegatesLoaderDelegate` from Expo's generated Swift interface —
|
|
34
|
+
// and Expo already depends on ExpoObjC, so it cannot live in either without a cycle.
|
|
35
|
+
// A third target depending on both keeps the graph acyclic. (CocoaPods compiles all
|
|
36
|
+
// of `ios/**` into one target, so this split is SwiftPM-only.)
|
|
37
|
+
.target(
|
|
38
|
+
name: "ExpoLoader",
|
|
39
|
+
dependencies: ["Expo", "ExpoObjC"],
|
|
40
|
+
path: "ios/ExpoLoader",
|
|
41
|
+
publicHeadersPath: "include",
|
|
42
|
+
),
|
|
43
|
+
.testTarget(
|
|
44
|
+
name: "ExpoTests",
|
|
45
|
+
dependencies: ["Expo"],
|
|
46
|
+
path: "ios/Tests",
|
|
47
|
+
),
|
|
48
|
+
]
|
|
49
|
+
)
|
package/android/build.gradle
CHANGED
|
@@ -10,7 +10,7 @@ buildscript {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
group = 'host.exp.exponent'
|
|
13
|
-
version = '58.0.0-preview.
|
|
13
|
+
version = '58.0.0-preview.8'
|
|
14
14
|
|
|
15
15
|
expoModule {
|
|
16
16
|
// We can't prebuild the module because it depends on the generated files.
|
|
@@ -21,7 +21,7 @@ android {
|
|
|
21
21
|
namespace "expo.core"
|
|
22
22
|
defaultConfig {
|
|
23
23
|
versionCode 1
|
|
24
|
-
versionName "58.0.0-preview.
|
|
24
|
+
versionName "58.0.0-preview.8"
|
|
25
25
|
consumerProguardFiles("proguard-rules.pro")
|
|
26
26
|
}
|
|
27
27
|
testOptions {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@expo/dom-webview": "~58.0.1",
|
|
3
3
|
"@expo/fingerprint": "~0.21.1",
|
|
4
|
-
"@expo/metro-runtime": "~58.0.
|
|
4
|
+
"@expo/metro-runtime": "~58.0.8",
|
|
5
5
|
"@expo/vector-icons": "^15.0.2",
|
|
6
|
-
"@expo/ui": "~58.0.
|
|
6
|
+
"@expo/ui": "~58.0.8",
|
|
7
7
|
"@react-native-async-storage/async-storage": "2.2.0",
|
|
8
8
|
"@react-native-community/datetimepicker": "9.2.1",
|
|
9
9
|
"@react-native-masked-view/masked-view": "0.3.2",
|
|
@@ -13,102 +13,102 @@
|
|
|
13
13
|
"@react-native-picker/picker": "2.11.4",
|
|
14
14
|
"@react-native-segmented-control/segmented-control": "2.5.7",
|
|
15
15
|
"@stripe/stripe-react-native": "0.76.0",
|
|
16
|
-
"eslint-config-expo": "~58.0.
|
|
16
|
+
"eslint-config-expo": "~58.0.3",
|
|
17
17
|
"expo-analytics-amplitude": "~11.3.0",
|
|
18
18
|
"expo-app-auth": "~11.1.0",
|
|
19
|
-
"expo-app-intents": "~0.4.
|
|
19
|
+
"expo-app-intents": "~0.4.6",
|
|
20
20
|
"expo-app-loader-provider": "~8.0.0",
|
|
21
|
-
"expo-app-metrics": "~58.0.
|
|
21
|
+
"expo-app-metrics": "~58.0.8",
|
|
22
22
|
"expo-apple-authentication": "~58.0.1",
|
|
23
23
|
"expo-application": "~58.0.1",
|
|
24
|
-
"expo-asset": "~58.0.
|
|
24
|
+
"expo-asset": "~58.0.8",
|
|
25
25
|
"expo-audio": "~58.0.2",
|
|
26
|
-
"expo-auth-session": "~58.0.
|
|
27
|
-
"expo-background-fetch": "~58.0.
|
|
28
|
-
"expo-background-task": "~58.0.
|
|
26
|
+
"expo-auth-session": "~58.0.5",
|
|
27
|
+
"expo-background-fetch": "~58.0.8",
|
|
28
|
+
"expo-background-task": "~58.0.8",
|
|
29
29
|
"expo-battery": "~58.0.1",
|
|
30
30
|
"expo-blur": "~58.0.1",
|
|
31
31
|
"expo-brightness": "~58.0.0",
|
|
32
|
-
"expo-brownfield": "~58.0.
|
|
33
|
-
"expo-build-properties": "~58.0.
|
|
34
|
-
"expo-calendar": "~58.0.
|
|
35
|
-
"expo-camera": "~58.0.
|
|
32
|
+
"expo-brownfield": "~58.0.8",
|
|
33
|
+
"expo-build-properties": "~58.0.8",
|
|
34
|
+
"expo-calendar": "~58.0.4",
|
|
35
|
+
"expo-camera": "~58.0.4",
|
|
36
36
|
"expo-cellular": "~58.0.0",
|
|
37
37
|
"expo-checkbox": "~58.0.1",
|
|
38
38
|
"expo-clipboard": "~58.0.1",
|
|
39
|
-
"expo-constants": "~58.0.
|
|
39
|
+
"expo-constants": "~58.0.8",
|
|
40
40
|
"expo-contacts": "~58.0.2",
|
|
41
41
|
"expo-crypto": "~58.0.2",
|
|
42
|
-
"expo-dev-client": "~58.0.
|
|
42
|
+
"expo-dev-client": "~58.0.8",
|
|
43
43
|
"expo-device": "~58.0.2",
|
|
44
|
-
"expo-document-picker": "~58.0.
|
|
44
|
+
"expo-document-picker": "~58.0.2",
|
|
45
45
|
"expo-eas-client": "~58.0.0",
|
|
46
|
-
"expo-file-system": "~58.0.
|
|
47
|
-
"expo-font": "~58.0.
|
|
46
|
+
"expo-file-system": "~58.0.3",
|
|
47
|
+
"expo-font": "~58.0.3",
|
|
48
48
|
"expo-gl": "~58.0.1",
|
|
49
49
|
"expo-glass-effect": "~58.0.2",
|
|
50
50
|
"expo-google-app-auth": "~8.3.0",
|
|
51
|
-
"expo-haptics": "~58.0.
|
|
52
|
-
"expo-image": "~58.0.
|
|
51
|
+
"expo-haptics": "~58.0.2",
|
|
52
|
+
"expo-image": "~58.0.7",
|
|
53
53
|
"expo-image-loader": "~58.0.1",
|
|
54
|
-
"expo-image-manipulator": "~58.0.
|
|
55
|
-
"expo-image-picker": "~58.0.
|
|
54
|
+
"expo-image-manipulator": "~58.0.9",
|
|
55
|
+
"expo-image-picker": "~58.0.8",
|
|
56
56
|
"expo-intent-launcher": "~58.0.0",
|
|
57
|
-
"expo-insights": "~58.0.
|
|
57
|
+
"expo-insights": "~58.0.8",
|
|
58
58
|
"expo-keep-awake": "~58.0.1",
|
|
59
59
|
"expo-linear-gradient": "~58.0.1",
|
|
60
|
-
"expo-linking": "~58.0.
|
|
60
|
+
"expo-linking": "~58.0.8",
|
|
61
61
|
"expo-local-authentication": "~58.0.0",
|
|
62
62
|
"expo-localization": "~58.0.1",
|
|
63
|
-
"expo-location": "~58.0.
|
|
63
|
+
"expo-location": "~58.0.8",
|
|
64
64
|
"expo-mail-composer": "~58.0.0",
|
|
65
65
|
"expo-manifests": "~58.0.0",
|
|
66
66
|
"expo-maps": "~58.0.2",
|
|
67
67
|
"expo-mcp": "~0.2.1",
|
|
68
|
-
"expo-media-library": "~58.0.
|
|
68
|
+
"expo-media-library": "~58.0.3",
|
|
69
69
|
"expo-mesh-gradient": "~58.0.1",
|
|
70
|
-
"expo-module-template": "~58.0.
|
|
71
|
-
"expo-modules-core": "~58.0.
|
|
72
|
-
"expo-navigation-bar": "~58.0.
|
|
70
|
+
"expo-module-template": "~58.0.4",
|
|
71
|
+
"expo-modules-core": "~58.0.8",
|
|
72
|
+
"expo-navigation-bar": "~58.0.2",
|
|
73
73
|
"expo-network": "~58.0.1",
|
|
74
|
-
"expo-notifications": "~58.0.
|
|
75
|
-
"expo-observe": "~58.0.
|
|
74
|
+
"expo-notifications": "~58.0.8",
|
|
75
|
+
"expo-observe": "~58.0.10",
|
|
76
76
|
"expo-print": "~58.0.2",
|
|
77
77
|
"expo-live-photo": "~58.0.1",
|
|
78
|
-
"expo-router": "~58.0.
|
|
79
|
-
"expo-screen-capture": "~58.0.
|
|
78
|
+
"expo-router": "~58.0.9",
|
|
79
|
+
"expo-screen-capture": "~58.0.3",
|
|
80
80
|
"expo-screen-orientation": "~58.0.0",
|
|
81
81
|
"expo-secure-store": "~58.0.0",
|
|
82
82
|
"expo-sensors": "~58.0.0",
|
|
83
83
|
"expo-server": "~58.0.1",
|
|
84
|
-
"expo-sharing": "~58.0.
|
|
84
|
+
"expo-sharing": "~58.0.11",
|
|
85
85
|
"expo-sms": "~58.0.0",
|
|
86
|
-
"expo-speech": "~58.0.
|
|
86
|
+
"expo-speech": "~58.0.1",
|
|
87
87
|
"expo-splash-screen": "~58.0.1",
|
|
88
|
-
"expo-sqlite": "~58.0.
|
|
88
|
+
"expo-sqlite": "~58.0.6",
|
|
89
89
|
"expo-status-bar": "~58.0.1",
|
|
90
90
|
"expo-store-review": "~58.0.0",
|
|
91
91
|
"expo-symbols": "~58.0.2",
|
|
92
|
-
"expo-system-ui": "~58.0.
|
|
93
|
-
"expo-task-manager": "~58.0.
|
|
92
|
+
"expo-system-ui": "~58.0.3",
|
|
93
|
+
"expo-task-manager": "~58.0.9",
|
|
94
94
|
"expo-tracking-transparency": "~58.0.0",
|
|
95
|
-
"expo-updates": "~58.0.
|
|
95
|
+
"expo-updates": "~58.0.10",
|
|
96
96
|
"expo-video-thumbnails": "~58.0.0",
|
|
97
|
-
"expo-video": "~58.0.
|
|
97
|
+
"expo-video": "~58.0.4",
|
|
98
98
|
"expo-web-browser": "~58.0.2",
|
|
99
|
-
"expo-widgets": "~58.0.
|
|
100
|
-
"jest-expo": "~58.0.
|
|
99
|
+
"expo-widgets": "~58.0.8",
|
|
100
|
+
"jest-expo": "~58.0.4",
|
|
101
101
|
"lottie-react-native": "~7.5.0",
|
|
102
102
|
"react": "19.3.0",
|
|
103
103
|
"react-dom": "19.3.0",
|
|
104
|
-
"react-native": "0.88.0-rc.
|
|
104
|
+
"react-native": "0.88.0-rc.2",
|
|
105
105
|
"react-native-web": "~0.21.0",
|
|
106
106
|
"react-native-gesture-handler": "~3.2.1",
|
|
107
107
|
"react-native-keyboard-controller": "1.22.4",
|
|
108
108
|
"react-native-maps": "1.29.0",
|
|
109
109
|
"react-native-pager-view": "9.0.4",
|
|
110
|
-
"react-native-worklets": "0.
|
|
111
|
-
"react-native-reanimated": "4.
|
|
110
|
+
"react-native-worklets": "0.13.0",
|
|
111
|
+
"react-native-reanimated": "4.7.0",
|
|
112
112
|
"react-native-screens": "~4.28.0",
|
|
113
113
|
"react-native-safe-area-context": "~5.9.1",
|
|
114
114
|
"react-native-svg": "15.15.5",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo",
|
|
3
|
-
"version": "58.0.0-preview.
|
|
3
|
+
"version": "58.0.0-preview.8",
|
|
4
4
|
"description": "The Expo SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"expo"
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"src",
|
|
34
34
|
"AppEntry.js",
|
|
35
35
|
"Expo.podspec",
|
|
36
|
+
"Package.swift",
|
|
36
37
|
"bundledNativeModules.json",
|
|
37
38
|
"expo-module.config.json",
|
|
38
39
|
"metro-config.js",
|
|
@@ -200,40 +201,40 @@
|
|
|
200
201
|
},
|
|
201
202
|
"dependencies": {
|
|
202
203
|
"@babel/runtime": "^7.20.0",
|
|
203
|
-
"@expo/cli": "^58.0.
|
|
204
|
+
"@expo/cli": "^58.0.8",
|
|
204
205
|
"@expo/config": "~58.0.0",
|
|
205
|
-
"@expo/config-plugins": "~58.0.
|
|
206
|
+
"@expo/config-plugins": "~58.0.3",
|
|
206
207
|
"@expo/devtools": "~58.0.1",
|
|
207
208
|
"@expo/dom-webview": "~58.0.1",
|
|
208
209
|
"@expo/fingerprint": "^0.21.1",
|
|
209
210
|
"@expo/local-build-cache-provider": "^58.0.0",
|
|
210
|
-
"@expo/log-box": "^58.0.
|
|
211
|
+
"@expo/log-box": "^58.0.6",
|
|
211
212
|
"@expo/log-box-utils": "^58.0.0",
|
|
212
213
|
"@expo/metro": "~58.0.0-rc.0",
|
|
213
|
-
"@expo/metro-config": "~58.0.
|
|
214
|
+
"@expo/metro-config": "~58.0.5",
|
|
214
215
|
"@ungap/structured-clone": "^1.3.0",
|
|
215
|
-
"babel-preset-expo": "~58.0.
|
|
216
|
-
"expo-asset": "~58.0.
|
|
217
|
-
"expo-constants": "~58.0.
|
|
218
|
-
"expo-file-system": "~58.0.
|
|
219
|
-
"expo-font": "~58.0.
|
|
216
|
+
"babel-preset-expo": "~58.0.5",
|
|
217
|
+
"expo-asset": "~58.0.8",
|
|
218
|
+
"expo-constants": "~58.0.8",
|
|
219
|
+
"expo-file-system": "~58.0.3",
|
|
220
|
+
"expo-font": "~58.0.3",
|
|
220
221
|
"expo-keep-awake": "~58.0.1",
|
|
221
|
-
"expo-modules-autolinking": "~58.0.
|
|
222
|
-
"expo-modules-core": "~58.0.
|
|
222
|
+
"expo-modules-autolinking": "~58.0.5",
|
|
223
|
+
"expo-modules-core": "~58.0.8",
|
|
223
224
|
"pretty-format": "^29.7.0",
|
|
224
225
|
"react-refresh": "^0.14.2",
|
|
225
226
|
"whatwg-url-minimum": "^0.2.0"
|
|
226
227
|
},
|
|
227
228
|
"devDependencies": {
|
|
228
229
|
"@expo/dom-webview": "58.0.1",
|
|
229
|
-
"@expo/metro-runtime": "58.0.
|
|
230
|
+
"@expo/metro-runtime": "58.0.8",
|
|
230
231
|
"@types/node": "^22.14.0",
|
|
231
232
|
"@types/react": "~19.3.0",
|
|
232
|
-
"expo-updates": "58.0.
|
|
233
|
+
"expo-updates": "58.0.10",
|
|
233
234
|
"npm-run-all2": "^8.0.4",
|
|
234
235
|
"react": "19.3.0",
|
|
235
236
|
"react-dom": "19.3.0",
|
|
236
|
-
"react-native": "0.88.0-rc.
|
|
237
|
+
"react-native": "0.88.0-rc.2",
|
|
237
238
|
"rimraf": "^6.1.2",
|
|
238
239
|
"web-streams-polyfill": "^3.3.2"
|
|
239
240
|
},
|
|
@@ -269,7 +270,7 @@
|
|
|
269
270
|
"engines": {
|
|
270
271
|
"node": "^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0"
|
|
271
272
|
},
|
|
272
|
-
"gitHead": "
|
|
273
|
+
"gitHead": "74f6d2b90bc50bd8df7b160d6e6b2204b37a8ce7",
|
|
273
274
|
"scripts": {
|
|
274
275
|
"build": "../expo-module-scripts/bin/expo-build src",
|
|
275
276
|
"clean": "rimraf build",
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const os = require('os');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const { resolveAppTarget } = require('../app-target');
|
|
8
|
+
|
|
9
|
+
// The real project of apps/minimal-swiftpm: the entitlements derivation reads an
|
|
10
|
+
// Xcode project, so mocking one out would only assert our own fixture back.
|
|
11
|
+
const TESTER_PBXPROJ = fs.readFileSync(
|
|
12
|
+
path.join(
|
|
13
|
+
__dirname,
|
|
14
|
+
'../../../../..',
|
|
15
|
+
'apps/minimal-swiftpm/ios/minimalswiftpm.xcodeproj/project.pbxproj'
|
|
16
|
+
),
|
|
17
|
+
'utf8'
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const ENTITLEMENTS_LINE = /^[ \t]*CODE_SIGN_ENTITLEMENTS = .*;\n/gm;
|
|
21
|
+
const DEBUG = 0;
|
|
22
|
+
const RELEASE = 1;
|
|
23
|
+
|
|
24
|
+
/** Rewrite the nth `CODE_SIGN_ENTITLEMENTS` line; the app target declares Debug first. */
|
|
25
|
+
function withEntitlementsSetting(pbxproj, index, replacement) {
|
|
26
|
+
let seen = 0;
|
|
27
|
+
return pbxproj.replace(ENTITLEMENTS_LINE, (line) =>
|
|
28
|
+
seen++ === index ? replacement.replace('$', line.match(/^[ \t]*/)[0]) : line
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function withoutEntitlementsSettings(pbxproj) {
|
|
33
|
+
return pbxproj.replace(ENTITLEMENTS_LINE, '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Append a unit-test target declaring its own entitlements. The tester project has a
|
|
38
|
+
* single application target, so without a second one no test can tell a lookup by name
|
|
39
|
+
* apart from `findFirstNativeTarget`.
|
|
40
|
+
*/
|
|
41
|
+
function withTestTarget(pbxproj, name = 'minimalswiftpmTests') {
|
|
42
|
+
return pbxproj
|
|
43
|
+
.replace(
|
|
44
|
+
'/* End PBXNativeTarget section */',
|
|
45
|
+
`\t\tAAAA0000000000000000001 /* ${name} */ = {
|
|
46
|
+
\t\t\tisa = PBXNativeTarget;
|
|
47
|
+
\t\t\tbuildConfigurationList = AAAA0000000000000000002 /* Build configuration list for PBXNativeTarget "${name}" */;
|
|
48
|
+
\t\t\tbuildPhases = (
|
|
49
|
+
\t\t\t);
|
|
50
|
+
\t\t\tdependencies = (
|
|
51
|
+
\t\t\t);
|
|
52
|
+
\t\t\tname = ${name};
|
|
53
|
+
\t\t\tproductName = ${name};
|
|
54
|
+
\t\t\tproductType = "com.apple.product-type.bundle.unit-test";
|
|
55
|
+
\t\t};
|
|
56
|
+
/* End PBXNativeTarget section */`
|
|
57
|
+
)
|
|
58
|
+
.replace(
|
|
59
|
+
'/* End XCConfigurationList section */',
|
|
60
|
+
`\t\tAAAA0000000000000000002 /* Build configuration list for PBXNativeTarget "${name}" */ = {
|
|
61
|
+
\t\t\tisa = XCConfigurationList;
|
|
62
|
+
\t\t\tbuildConfigurations = (
|
|
63
|
+
\t\t\t\tAAAA0000000000000000003 /* Debug */,
|
|
64
|
+
\t\t\t\tAAAA0000000000000000004 /* Release */,
|
|
65
|
+
\t\t\t);
|
|
66
|
+
\t\t\tdefaultConfigurationIsVisible = 0;
|
|
67
|
+
\t\t\tdefaultConfigurationName = Release;
|
|
68
|
+
\t\t};
|
|
69
|
+
/* End XCConfigurationList section */`
|
|
70
|
+
)
|
|
71
|
+
.replace(
|
|
72
|
+
'/* End XCBuildConfiguration section */',
|
|
73
|
+
['Debug', 'Release']
|
|
74
|
+
.map(
|
|
75
|
+
(
|
|
76
|
+
configuration,
|
|
77
|
+
index
|
|
78
|
+
) => `\t\tAAAA000000000000000000${index + 3} /* ${configuration} */ = {
|
|
79
|
+
\t\t\tisa = XCBuildConfiguration;
|
|
80
|
+
\t\t\tbuildSettings = {
|
|
81
|
+
\t\t\t\tCODE_SIGN_ENTITLEMENTS = ${name}/${name}.entitlements;
|
|
82
|
+
\t\t\t};
|
|
83
|
+
\t\t\tname = ${configuration};
|
|
84
|
+
\t\t};
|
|
85
|
+
`
|
|
86
|
+
)
|
|
87
|
+
.join('') + '/* End XCBuildConfiguration section */'
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function makeApp({
|
|
92
|
+
pbxproj = TESTER_PBXPROJ,
|
|
93
|
+
entitlements = ['minimalswiftpm/minimalswiftpm.entitlements'],
|
|
94
|
+
marker = { target: 'minimalswiftpm' },
|
|
95
|
+
projectDirName = 'ios',
|
|
96
|
+
} = {}) {
|
|
97
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'expo-spm-app-target-'));
|
|
98
|
+
const appRoot = path.join(tmp, projectDirName);
|
|
99
|
+
const project = path.join(appRoot, 'minimalswiftpm.xcodeproj');
|
|
100
|
+
fs.mkdirSync(project, { recursive: true });
|
|
101
|
+
if (pbxproj != null) fs.writeFileSync(path.join(project, 'project.pbxproj'), pbxproj);
|
|
102
|
+
if (marker != null) {
|
|
103
|
+
fs.writeFileSync(path.join(project, '.spm-injected.json'), JSON.stringify(marker));
|
|
104
|
+
}
|
|
105
|
+
for (const relative of entitlements) {
|
|
106
|
+
const file = path.join(appRoot, relative);
|
|
107
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
108
|
+
fs.writeFileSync(file, '<plist version="1.0"><dict/></plist>');
|
|
109
|
+
}
|
|
110
|
+
return appRoot;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
let warn;
|
|
114
|
+
beforeEach(() => {
|
|
115
|
+
warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
116
|
+
});
|
|
117
|
+
afterEach(() => warn.mockRestore());
|
|
118
|
+
|
|
119
|
+
const warnings = () => warn.mock.calls.map(([text]) => text).join('\n');
|
|
120
|
+
|
|
121
|
+
describe('the Xcode target name', () => {
|
|
122
|
+
it('comes from the injection marker of the Xcode project', () => {
|
|
123
|
+
expect(resolveAppTarget(makeApp()).targetName).toBe('minimalswiftpm');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('is omitted when no Xcode project carries a marker', () => {
|
|
127
|
+
expect(resolveAppTarget(makeApp({ marker: null })).targetName).toBeNull();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// RN's injector takes the first marker it finds; guessing the same one is not
|
|
131
|
+
// safe, but a silently dropped --target-name is undiagnosable, so say it.
|
|
132
|
+
it('is omitted with a warning when several Xcode projects carry a marker', () => {
|
|
133
|
+
const appRoot = makeApp();
|
|
134
|
+
const stale = path.join(appRoot, 'stale.xcodeproj');
|
|
135
|
+
fs.mkdirSync(stale, { recursive: true });
|
|
136
|
+
fs.writeFileSync(path.join(stale, 'project.pbxproj'), TESTER_PBXPROJ);
|
|
137
|
+
fs.writeFileSync(path.join(stale, '.spm-injected.json'), JSON.stringify({ target: 'stale' }));
|
|
138
|
+
|
|
139
|
+
expect(resolveAppTarget(appRoot).targetName).toBeNull();
|
|
140
|
+
expect(warnings()).toContain('minimalswiftpm.xcodeproj');
|
|
141
|
+
expect(warnings()).toContain('stale.xcodeproj');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// A leftover directory with no project in it is not a project RN can inject into.
|
|
145
|
+
it('ignores a marker in an .xcodeproj without a project.pbxproj', () => {
|
|
146
|
+
const appRoot = makeApp();
|
|
147
|
+
const stale = path.join(appRoot, 'Stale.xcodeproj');
|
|
148
|
+
fs.mkdirSync(stale);
|
|
149
|
+
fs.writeFileSync(path.join(stale, '.spm-injected.json'), JSON.stringify({ target: 'stale' }));
|
|
150
|
+
|
|
151
|
+
expect(resolveAppTarget(appRoot).targetName).toBe('minimalswiftpm');
|
|
152
|
+
expect(warn).not.toHaveBeenCalled();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('is omitted when the marker is unreadable or names no target', () => {
|
|
156
|
+
expect(resolveAppTarget(makeApp({ marker: { rootUuid: 'ABC' } })).targetName).toBeNull();
|
|
157
|
+
|
|
158
|
+
const appRoot = makeApp({ marker: null });
|
|
159
|
+
fs.writeFileSync(
|
|
160
|
+
path.join(appRoot, 'minimalswiftpm.xcodeproj', '.spm-injected.json'),
|
|
161
|
+
'{ not json'
|
|
162
|
+
);
|
|
163
|
+
expect(resolveAppTarget(appRoot).targetName).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('is omitted when the Xcode project directory does not exist', () => {
|
|
167
|
+
expect(
|
|
168
|
+
resolveAppTarget(path.join(os.tmpdir(), 'expo-spm-absent', 'ios')).targetName
|
|
169
|
+
).toBeNull();
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('the entitlements file', () => {
|
|
174
|
+
it('is the one the app target declares', () => {
|
|
175
|
+
const appRoot = makeApp();
|
|
176
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
177
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// CocoaPods scans every build configuration of the target. Reading only Release
|
|
182
|
+
// leaves an app that signs entitlements in Debug with empty app groups.
|
|
183
|
+
it('is found when only the Debug configuration declares it', () => {
|
|
184
|
+
const appRoot = makeApp({
|
|
185
|
+
pbxproj: withEntitlementsSetting(TESTER_PBXPROJ, RELEASE, ''),
|
|
186
|
+
});
|
|
187
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
188
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
189
|
+
);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('is resolved for the target the marker names, not the first application target', () => {
|
|
193
|
+
const appRoot = makeApp({
|
|
194
|
+
pbxproj: withTestTarget(TESTER_PBXPROJ),
|
|
195
|
+
marker: { target: 'minimalswiftpmTests' },
|
|
196
|
+
entitlements: [
|
|
197
|
+
'minimalswiftpm/minimalswiftpm.entitlements',
|
|
198
|
+
'minimalswiftpmTests/minimalswiftpmTests.entitlements',
|
|
199
|
+
],
|
|
200
|
+
});
|
|
201
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
202
|
+
path.join(appRoot, 'minimalswiftpmTests/minimalswiftpmTests.entitlements')
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('is omitted when the marker names a target the project does not have', () => {
|
|
207
|
+
const appRoot = makeApp({ marker: { target: 'renamed' } });
|
|
208
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBeNull();
|
|
209
|
+
expect(warnings()).toContain('"renamed"');
|
|
210
|
+
expect(warnings()).toContain('react-native spm update');
|
|
211
|
+
// The project parsed fine; only the target was missing.
|
|
212
|
+
expect(warnings()).not.toContain('could not be read');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// An empty setting resolves to the project directory, which exists — so without a
|
|
216
|
+
// file check it wins and suppresses the file another configuration declares.
|
|
217
|
+
it('ignores a configuration whose entitlements setting is empty', () => {
|
|
218
|
+
const appRoot = makeApp({
|
|
219
|
+
pbxproj: withEntitlementsSetting(TESTER_PBXPROJ, DEBUG, '$CODE_SIGN_ENTITLEMENTS = "";\n'),
|
|
220
|
+
});
|
|
221
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
222
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
223
|
+
);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it.each([['$(SRCROOT)'], ['${SRCROOT}']])(
|
|
227
|
+
'warns and skips a setting built from the %s build variable',
|
|
228
|
+
(variable) => {
|
|
229
|
+
const appRoot = makeApp({
|
|
230
|
+
pbxproj: withEntitlementsSetting(
|
|
231
|
+
TESTER_PBXPROJ,
|
|
232
|
+
DEBUG,
|
|
233
|
+
`$CODE_SIGN_ENTITLEMENTS = "${variable}/minimalswiftpm/minimalswiftpm.entitlements";\n`
|
|
234
|
+
),
|
|
235
|
+
});
|
|
236
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
237
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
238
|
+
);
|
|
239
|
+
expect(warnings()).toContain(variable);
|
|
240
|
+
// Skipped outright, so it is not one of two "different entitlements files".
|
|
241
|
+
expect(warnings()).not.toContain('declare different entitlements files');
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
// An app that signs no entitlements at all is the common case, not a problem.
|
|
246
|
+
it('is omitted silently when no build configuration declares one', () => {
|
|
247
|
+
const pbxproj = withoutEntitlementsSettings(TESTER_PBXPROJ);
|
|
248
|
+
expect(resolveAppTarget(makeApp({ pbxproj })).entitlementPath).toBeNull();
|
|
249
|
+
expect(warn).not.toHaveBeenCalled();
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('is omitted with a warning when the declared file is not on disk', () => {
|
|
253
|
+
const appRoot = makeApp({ entitlements: [] });
|
|
254
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBeNull();
|
|
255
|
+
expect(warnings()).toContain(path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements'));
|
|
256
|
+
expect(warnings()).toContain('app groups');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('is omitted with a warning when the Xcode project cannot be read', () => {
|
|
260
|
+
const appRoot = makeApp({ pbxproj: 'not a pbxproj' });
|
|
261
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBeNull();
|
|
262
|
+
expect(warnings()).toContain(path.join(appRoot, 'minimalswiftpm.xcodeproj'));
|
|
263
|
+
expect(warnings()).toContain('app groups');
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('is omitted with a warning when there is no Xcode project', () => {
|
|
267
|
+
const appRoot = makeApp({ pbxproj: null });
|
|
268
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBeNull();
|
|
269
|
+
expect(warnings()).toContain(appRoot);
|
|
270
|
+
expect(warnings()).toContain('no .xcodeproj');
|
|
271
|
+
expect(warnings()).toContain('app groups');
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('is read from a marked Xcode project only when it has a project.pbxproj', () => {
|
|
275
|
+
const appRoot = makeApp({ marker: null });
|
|
276
|
+
const stale = path.join(appRoot, 'Stale.xcodeproj');
|
|
277
|
+
fs.mkdirSync(stale);
|
|
278
|
+
fs.writeFileSync(
|
|
279
|
+
path.join(stale, '.spm-injected.json'),
|
|
280
|
+
JSON.stringify({ target: 'minimalswiftpm' })
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
284
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Matches IOSConfig.Paths.getAllPBXProjectPaths, which `expo prebuild` writes through.
|
|
289
|
+
it('is read from the Xcode project config-plugins would pick when none carries a marker', () => {
|
|
290
|
+
const appRoot = makeApp({ pbxproj: null, marker: null });
|
|
291
|
+
fs.mkdirSync(path.join(appRoot, 'Aardvark.xcodeproj'));
|
|
292
|
+
for (const [name, pbxproj] of [
|
|
293
|
+
['alpha', TESTER_PBXPROJ],
|
|
294
|
+
['Zebra', withoutEntitlementsSettings(TESTER_PBXPROJ)],
|
|
295
|
+
]) {
|
|
296
|
+
fs.mkdirSync(path.join(appRoot, `${name}.xcodeproj`));
|
|
297
|
+
fs.writeFileSync(path.join(appRoot, `${name}.xcodeproj`, 'project.pbxproj'), pbxproj);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
301
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
302
|
+
);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('is found when the Xcode project directory is not named ios', () => {
|
|
306
|
+
const appRoot = makeApp({ projectDirName: 'App' });
|
|
307
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
308
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
309
|
+
);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Reading whichever project sorts first would miss the target and blame a rename.
|
|
313
|
+
it('is read from the Xcode project that carries the marker, not the first one', () => {
|
|
314
|
+
const appRoot = makeApp({
|
|
315
|
+
pbxproj: withTestTarget(TESTER_PBXPROJ),
|
|
316
|
+
marker: { target: 'minimalswiftpmTests' },
|
|
317
|
+
entitlements: ['minimalswiftpmTests/minimalswiftpmTests.entitlements'],
|
|
318
|
+
});
|
|
319
|
+
const unmarked = path.join(appRoot, 'Archived.xcodeproj');
|
|
320
|
+
fs.mkdirSync(unmarked);
|
|
321
|
+
fs.writeFileSync(path.join(unmarked, 'project.pbxproj'), TESTER_PBXPROJ);
|
|
322
|
+
|
|
323
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
324
|
+
path.join(appRoot, 'minimalswiftpmTests/minimalswiftpmTests.entitlements')
|
|
325
|
+
);
|
|
326
|
+
expect(warnings()).not.toContain('renamed');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it('is read from the first application target when no Xcode project carries a marker', () => {
|
|
330
|
+
const appRoot = makeApp({ marker: null });
|
|
331
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
332
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
333
|
+
);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Both configurations normally declare the same file; warning about that would
|
|
337
|
+
// put a spurious line in every sync.
|
|
338
|
+
it('says nothing when every build configuration declares the same file', () => {
|
|
339
|
+
expect(resolveAppTarget(makeApp()).entitlementPath).not.toBeNull();
|
|
340
|
+
expect(warn).not.toHaveBeenCalled();
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('warns when the build configurations declare different files', () => {
|
|
344
|
+
const appRoot = makeApp({
|
|
345
|
+
pbxproj: withEntitlementsSetting(
|
|
346
|
+
TESTER_PBXPROJ,
|
|
347
|
+
DEBUG,
|
|
348
|
+
'$CODE_SIGN_ENTITLEMENTS = minimalswiftpm/debug.entitlements;\n'
|
|
349
|
+
),
|
|
350
|
+
});
|
|
351
|
+
expect(resolveAppTarget(appRoot).entitlementPath).toBe(
|
|
352
|
+
path.join(appRoot, 'minimalswiftpm/minimalswiftpm.entitlements')
|
|
353
|
+
);
|
|
354
|
+
expect(warnings()).toContain('debug.entitlements');
|
|
355
|
+
expect(warnings()).toContain('minimalswiftpm.entitlements');
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
describe('the Podfile properties file', () => {
|
|
360
|
+
it('is taken from the Xcode project directory when it exists', () => {
|
|
361
|
+
const appRoot = makeApp();
|
|
362
|
+
const properties = path.join(appRoot, 'Podfile.properties.json');
|
|
363
|
+
fs.writeFileSync(properties, '{}');
|
|
364
|
+
expect(resolveAppTarget(appRoot).podfilePropertiesPath).toBe(properties);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('is omitted when the app has none', () => {
|
|
368
|
+
expect(resolveAppTarget(makeApp()).podfilePropertiesPath).toBeNull();
|
|
369
|
+
});
|
|
370
|
+
});
|