@depup/react-native 0.87.0-depup.0 → 0.87.1-depup.0

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 (37) hide show
  1. package/Libraries/Animated/AnimatedEvent.js +1 -1
  2. package/Libraries/Animated/AnimatedImplementation.js +6 -2
  3. package/Libraries/Animated/nodes/AnimatedNode.js +1 -1
  4. package/Libraries/Animated/nodes/AnimatedValue.js +2 -2
  5. package/Libraries/Core/ReactNativeVersion.js +1 -1
  6. package/README.md +3 -3
  7. package/React/Base/RCTVersion.m +1 -1
  8. package/ReactAndroid/gradle.properties +1 -1
  9. package/ReactAndroid/src/main/java/com/facebook/react/modules/intent/IntentModule.kt +7 -3
  10. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  11. package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
  12. package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTFontUtils.mm +1 -1
  13. package/changes.json +2 -2
  14. package/package.json +12 -12
  15. package/scripts/cocoapods/rndependencies.rb +31 -25
  16. package/scripts/replace-rncore-version.js +18 -2
  17. package/scripts/setup-apple-spm.js +28 -12
  18. package/scripts/spm/autolinking-plugins.js +80 -0
  19. package/scripts/spm/download-spm-artifacts.js +64 -6
  20. package/scripts/spm/expand-spm-dependencies.js +249 -30
  21. package/scripts/spm/generate-spm-autolinking.js +157 -40
  22. package/scripts/spm/generate-spm-package.js +30 -18
  23. package/scripts/spm/generate-spm-xcodeproj.js +595 -71
  24. package/scripts/spm/scaffold-package-swift.js +65 -24
  25. package/scripts/spm/spm-pbxproj.js +158 -28
  26. package/scripts/spm/spm-types.js +29 -3
  27. package/scripts/spm/spm-utils.js +117 -2
  28. package/sdks/.hermesv1version +1 -1
  29. package/sdks/hermes-engine/version.properties +1 -1
  30. package/types_generated/Libraries/Animated/AnimatedImplementation.d.ts +2 -2
  31. package/types_generated/Libraries/Animated/nodes/AnimatedNode.d.ts +4 -1
  32. package/types_generated/Libraries/Animated/nodes/AnimatedValue.d.ts +3 -3
  33. package/scripts/spm/__doc__/rfc-spm-xcframework.md +0 -707
  34. package/scripts/spm/__doc__/spm-autolinking-plugins.md +0 -244
  35. package/scripts/spm/__doc__/spm-header-paths-contract.md +0 -97
  36. package/scripts/spm/__doc__/spm-plugins-assessment.md +0 -128
  37. package/scripts/spm/__doc__/spm-scripts.md +0 -486
@@ -19,6 +19,7 @@
19
19
  PluginFlavoredFramework,
20
20
  PluginPackageDep,
21
21
  PluginProductDep,
22
+ PluginScriptPhase,
22
23
  ReactDescriptor,
23
24
  RawAutolinkingJson,
24
25
  SpmModuleConfig,
@@ -58,17 +59,24 @@
58
59
 
59
60
  const {discoverPlugins, invokePlugins} = require('./autolinking-plugins');
60
61
  const {
62
+ SpmNameCollisionError,
63
+ assertSwiftNameNotReserved,
61
64
  defaultReadConfig,
62
65
  defaultResolveDep,
63
66
  expandSpmDependencies,
67
+ isValidSwiftName,
64
68
  } = require('./expand-spm-dependencies');
65
69
  const {readPodspec} = require('./read-podspec');
66
70
  const {
71
+ AUTOLINKED_PACKAGE_NAME,
72
+ REACT_CODEGEN_PACKAGE_NAME,
73
+ REACT_CODEGEN_PRODUCTS,
74
+ REACT_NATIVE_PACKAGE_NAME,
75
+ REACT_NATIVE_PRODUCTS,
67
76
  RemoteVersionError,
68
77
  findProjectRoot,
69
78
  makeLogger,
70
79
  remotePackageConfig,
71
- toSwiftName,
72
80
  } = require('./spm-utils');
73
81
  const fs = require('fs');
74
82
  const path = require('path');
@@ -89,7 +97,12 @@ const {log, warn} = makeLogger('generate-spm-autolinking');
89
97
  let remoteCfg /*: ?{url: string, version: string, identity: string} */ = null;
90
98
 
91
99
  function reactNativePackageLabel() /*: string */ {
92
- return remoteCfg != null ? remoteCfg.identity : 'ReactNative';
100
+ return remoteCfg != null ? remoteCfg.identity : REACT_NATIVE_PACKAGE_NAME;
101
+ }
102
+ // In remote mode the RN package is labelled with the remote identity, so that
103
+ // name is reserved for this run too.
104
+ function reservedNamesForRun() /*: ?Array<string> */ {
105
+ return remoteCfg != null ? [remoteCfg.identity] : undefined;
93
106
  }
94
107
  function reactNativePackageDecl(localDecl /*: string */) /*: string */ {
95
108
  return remoteCfg != null
@@ -104,10 +117,11 @@ function reactNativePackageDecl(localDecl /*: string */) /*: string */ {
104
117
  function reactProducts() /*: Array<{name: string, package: string}> */ {
105
118
  const rn = reactNativePackageLabel();
106
119
  return [
107
- {name: 'ReactHeaders', package: rn},
108
- {name: 'ReactNativeHeaders', package: rn},
109
- {name: 'ReactNativeDependenciesHeaders', package: rn},
110
- {name: 'ReactAppHeaders', package: 'React-GeneratedCode'},
120
+ ...REACT_NATIVE_PRODUCTS.map(name => ({name, package: rn})),
121
+ ...REACT_CODEGEN_PRODUCTS.map(name => ({
122
+ name,
123
+ package: REACT_CODEGEN_PACKAGE_NAME,
124
+ })),
111
125
  ];
112
126
  }
113
127
  function reactProductDeps() /*: string */ {
@@ -146,7 +160,7 @@ function reactDescriptor(
146
160
  };
147
161
  } else if (absXcframeworks != null) {
148
162
  packageRef = {
149
- name: 'ReactNative',
163
+ name: REACT_NATIVE_PACKAGE_NAME,
150
164
  path: toPosix(absXcframeworks),
151
165
  relPath:
152
166
  xcframeworksRelPath != null ? toPosix(xcframeworksRelPath) : undefined,
@@ -155,7 +169,7 @@ function reactDescriptor(
155
169
  return null;
156
170
  }
157
171
  const products = reactProducts().filter(
158
- p => p.package !== 'React-GeneratedCode' || codegenPackageExists,
172
+ p => p.package !== REACT_CODEGEN_PACKAGE_NAME || codegenPackageExists,
159
173
  );
160
174
  return {packageRef, products};
161
175
  }
@@ -231,7 +245,6 @@ function readAutolinkingJson(
231
245
  * name: "MyNativeModule",
232
246
  * path: "ios/MyNativeModule", // relative to appRoot
233
247
  * exclude: ["*.js", "*.podspec"], // optional
234
- * publicHeadersPath: ".", // optional
235
248
  * }
236
249
  * ]
237
250
  * }
@@ -254,6 +267,41 @@ function readSpmModulesFromConfig(
254
267
  }
255
268
  }
256
269
 
270
+ /**
271
+ * Validates one app-local `spm.modules` name against the same rules a library's
272
+ * `spm.name` gets: a usable Swift identifier, not a name React Native reserves,
273
+ * and not one already taken by another module or an autolinked dep.
274
+ * `taken` maps lower-cased name → the name as written.
275
+ */
276
+ function assertSpmModuleName(
277
+ name /*: unknown */,
278
+ taken /*: Map<string, string> */,
279
+ ) /*: void */ {
280
+ const remedy =
281
+ "Rename it in this app's react-native.config.js 'spm.modules'.";
282
+ if (typeof name !== 'string' || !isValidSwiftName(name)) {
283
+ throw new Error(
284
+ `react-native autolinking: invalid 'spm.modules' name ${JSON.stringify(name) ?? 'undefined'}: must start with a letter or underscore and contain only letters, digits, underscores, or hyphens.`,
285
+ );
286
+ }
287
+ const moduleName = name;
288
+ assertSwiftNameNotReserved(moduleName, {
289
+ label: `the 'spm.modules' entry '${moduleName}'`,
290
+ remedy,
291
+ extraReservedNames: reservedNamesForRun(),
292
+ });
293
+ const clash = taken.get(moduleName.toLowerCase());
294
+ if (clash != null) {
295
+ throw new SpmNameCollisionError(
296
+ `react-native autolinking: SPM Swift name collision: the 'spm.modules' entry '${moduleName}' ` +
297
+ (clash === moduleName
298
+ ? `is already the name of another autolinked target.`
299
+ : `differs from the existing target '${clash}' only in case, which collides on case-insensitive filesystems.`) +
300
+ ` ${remedy}`,
301
+ );
302
+ }
303
+ }
304
+
257
305
  /**
258
306
  * Reads the app's `spm.denyPlugins` — npm names of autolinking plugins to
259
307
  * skip. The escape hatch for the transitive plugin discovery (an app opts a
@@ -730,9 +778,9 @@ function expandSpmSourceGlobs(
730
778
  * Returns null if the dependency doesn't have iOS support.
731
779
  *
732
780
  * `swiftNameByNpm` maps each autolinked dep's npm name to its resolved Swift
733
- * name (populated by expandSpmDependencies, possibly overridden via the dep's
734
- * `spm.name` config). Optional for backwards compatibility with callers that
735
- * don't have the map; falls back to `toSwiftName(name)` per entry.
781
+ * name (populated by expandSpmDependencies, honoring the dep's `spm.name`
782
+ * config and scope disambiguation). Every name this function emits comes from
783
+ * there see requireSwiftName.
736
784
  */
737
785
  /**
738
786
  * Read the dep's podspec (if any) and extract its declared
@@ -789,11 +837,27 @@ function extractPodspecHeaderSearchPaths(
789
837
  return out;
790
838
  }
791
839
 
840
+ /**
841
+ * The Swift name expandSpmDependencies resolved for `npmName`, or a hard error:
842
+ * re-deriving one here would emit a reference nothing in the graph matches.
843
+ */
844
+ function requireSwiftName(
845
+ npmName /*: string */,
846
+ resolved /*: ?string */,
847
+ ) /*: string */ {
848
+ if (resolved == null) {
849
+ throw new Error(
850
+ `react-native autolinking: no resolved Swift name for '${npmName}'. expandSpmDependencies must resolve every autolinked dep's name before SPM targets are generated.`,
851
+ );
852
+ }
853
+ return resolved;
854
+ }
855
+
792
856
  function autolinkingDepToSpmTarget(
793
857
  depName /*: string */,
794
858
  dep /*: AutolinkedDep */,
795
859
  outputDir /*: string */,
796
- swiftNameByNpm /*: ?Map<string, string> */,
860
+ swiftNameByNpm /*: Map<string, string> */,
797
861
  ) /*: SpmTarget | null */ {
798
862
  const iosPlatform = dep.platforms.ios;
799
863
  const sourceDir = iosPlatform.sourceDir ?? dep.root;
@@ -806,10 +870,7 @@ function autolinkingDepToSpmTarget(
806
870
  // same convention the spmModule branch in main() follows.
807
871
  const relSourcePath = path.relative(outputDir, sourceDir);
808
872
 
809
- // Prefer the resolved Swift name (which honors `spm.name` overrides set in
810
- // the dep's react-native.config.js). Fall back to toSwiftName(depName) when
811
- // the caller didn't run expandSpmDependencies.
812
- const targetName = dep.swiftName ?? toSwiftName(depName);
873
+ const targetName = requireSwiftName(depName, dep.swiftName);
813
874
 
814
875
  // No exclude inference — main()'s emission loop emits `sources:` (an
815
876
  // explicit allowlist). User-supplied excludes still work.
@@ -819,13 +880,11 @@ function autolinkingDepToSpmTarget(
819
880
  const resources = privacyManifest != null ? [privacyManifest] : undefined;
820
881
 
821
882
  // Map declared spm.dependencies (npm names) to Swift target names so the
822
- // synth's .product(...) deps list reaches the consuming target. Each
823
- // transitive npm name's Swift name comes from the map (honoring overrides);
824
- // toSwiftName fallback handles entries the map doesn't know about.
883
+ // synth's .product(...) deps list reaches the consuming target.
825
884
  const spmDeps /*: Array<string> */ = dep.spmDependencies ?? [];
826
885
  const spmTargetDependencies =
827
886
  spmDeps.length > 0
828
- ? spmDeps.map(n => swiftNameByNpm?.get(n) ?? toSwiftName(n))
887
+ ? spmDeps.map(n => requireSwiftName(n, swiftNameByNpm.get(n)))
829
888
  : undefined;
830
889
 
831
890
  const headerSearchPaths = extractPodspecHeaderSearchPaths(sourceDir);
@@ -899,12 +958,14 @@ function generateAutolinkedPackageSwift(
899
958
  ) {
900
959
  packageDeps.push(
901
960
  reactNativePackageDecl(
902
- `.package(name: "ReactNative", path: "${xcframeworksRelPath}")`,
961
+ `.package(name: "${REACT_NATIVE_PACKAGE_NAME}", path: "${xcframeworksRelPath}")`,
903
962
  ),
904
963
  );
905
964
  // Per-app generated headers come from the ReactAppHeaders product in
906
965
  // the codegen package (sibling of the autolinking dir).
907
- packageDeps.push(`.package(name: "React-GeneratedCode", path: "../ios")`);
966
+ packageDeps.push(
967
+ `.package(name: "${REACT_CODEGEN_PACKAGE_NAME}", path: "../ios")`,
968
+ );
908
969
  }
909
970
 
910
971
  // AutolinkedAggregate's target dependencies: .product(...) for npm sub-package
@@ -1007,10 +1068,10 @@ import PackageDescription
1007
1068
  import Foundation
1008
1069
 
1009
1070
  ${guardBlock}let package = Package(
1010
- name: "Autolinked",
1071
+ name: "${AUTOLINKED_PACKAGE_NAME}",
1011
1072
  platforms: [.iOS(.v15)],
1012
1073
  products: [
1013
- .library(name: "Autolinked", targets: ["AutolinkedAggregate"]),
1074
+ .library(name: "${AUTOLINKED_PACKAGE_NAME}", targets: ["AutolinkedAggregate"]),
1014
1075
  ],
1015
1076
  ${packageDepsBlock} targets: [
1016
1077
  .target(
@@ -1074,13 +1135,13 @@ function generateSynthPackageSwift(spec /*: SynthPackageSpec */) /*: string */ {
1074
1135
  spec.codegenPackagePath ?? '../../../ios';
1075
1136
  packageDeps.push(
1076
1137
  reactNativePackageDecl(
1077
- `.package(name: "ReactNative", path: "${reactNativePackagePath}")`,
1138
+ `.package(name: "${REACT_NATIVE_PACKAGE_NAME}", path: "${reactNativePackagePath}")`,
1078
1139
  ),
1079
1140
  );
1080
1141
  // Per-app generated headers come from the ReactAppHeaders product in
1081
1142
  // the codegen package.
1082
1143
  packageDeps.push(
1083
- `.package(name: "React-GeneratedCode", path: "${codegenPackagePath}")`,
1144
+ `.package(name: "${REACT_CODEGEN_PACKAGE_NAME}", path: "${codegenPackagePath}")`,
1084
1145
  );
1085
1146
  }
1086
1147
  for (const dep of spmDependencies) {
@@ -1251,11 +1312,13 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1251
1312
  const allDeps = expandSpmDependencies(directDeps, {
1252
1313
  readConfig: defaultReadConfig,
1253
1314
  resolveDep: defaultResolveDep,
1315
+ extraReservedNames: reservedNamesForRun(),
1316
+ log,
1254
1317
  });
1255
1318
 
1256
- // Map every autolinked npm name to its resolved Swift name (post-override)
1257
- // so transitive references inside autolinkingDepToSpmTarget find the right
1258
- // target identifier — not just the auto-derived toSwiftName.
1319
+ // Map every autolinked npm name to its resolved Swift name so transitive
1320
+ // references inside autolinkingDepToSpmTarget find the right target
1321
+ // identifier.
1259
1322
  const swiftNameByNpm /*: Map<string, string> */ = new Map();
1260
1323
  for (const dep of allDeps) {
1261
1324
  if (dep.swiftName != null) {
@@ -1287,8 +1350,39 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1287
1350
  discoveredPlugins.map(p => p.depName),
1288
1351
  );
1289
1352
 
1353
+ // Skipped means no sibling package is created for the host either, so a
1354
+ // dep declaring it in `spm.dependencies` gets a package reference to a
1355
+ // path this run never writes — SPM then reports only the missing path.
1356
+ // Only manifests React Native emits can carry that reference: a dep
1357
+ // shipping its own Package.swift declares its package references itself,
1358
+ // and the classification loop below would treat it as self-managed.
1359
+ const pluginHostDependents /*: Map<string, Array<string>> */ = new Map();
1360
+ for (const dep of allDeps) {
1361
+ const declaredHosts = (dep.spmDependencies ?? []).filter(name =>
1362
+ pluginHostDeps.has(name),
1363
+ );
1364
+ if (declaredHosts.length === 0) {
1365
+ continue;
1366
+ }
1367
+ const sourceDir = dep.platforms.ios.sourceDir ?? dep.root;
1368
+ if (sourceDir == null || findSelfManagedPackageDir(sourceDir) != null) {
1369
+ continue;
1370
+ }
1371
+ for (const host of declaredHosts) {
1372
+ const dependents = pluginHostDependents.get(host) ?? [];
1373
+ dependents.push(dep.name);
1374
+ pluginHostDependents.set(host, dependents);
1375
+ }
1376
+ }
1377
+
1290
1378
  for (const dep of allDeps) {
1291
1379
  if (pluginHostDeps.has(dep.name)) {
1380
+ const dependents = pluginHostDependents.get(dep.name);
1381
+ if (dependents != null) {
1382
+ throw new Error(
1383
+ `react-native autolinking: '${dep.name}' ships an SPM autolinking plugin, which owns its native contribution — so React Native does not build it as a sibling target for anything to depend on. It is declared in 'spm.dependencies' by ${dependents.map(name => `'${name}'`).join(', ')}. Remove it there; nothing is lost. Its plugin links its products into the app and resolves its own ecosystem's dependencies, so a library that builds against it does not declare it here.`,
1384
+ );
1385
+ }
1292
1386
  log(
1293
1387
  `Skipping ${dep.name} target generation — provided by its SPM autolinking plugin`,
1294
1388
  );
@@ -1321,7 +1415,15 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1321
1415
  // the globs now relative to its dir and attach the file list to the target
1322
1416
  // so the emission loop below renders `sources: [...]` literally.
1323
1417
  const configModules = readSpmModulesFromConfig(appRoot);
1418
+ // Module names land in the manifest exactly as written, so they get the same
1419
+ // checks a dep's Swift name gets. Seeded with the dep target names already
1420
+ // emitted so a module can't shadow an autolinked library either.
1421
+ const takenSwiftNames /*: Map<string, string> */ = new Map(
1422
+ entries.map(entry => [entry.target.name.toLowerCase(), entry.target.name]),
1423
+ );
1324
1424
  for (const mod of configModules) {
1425
+ assertSpmModuleName(mod.name, takenSwiftNames);
1426
+ takenSwiftNames.set(mod.name.toLowerCase(), mod.name);
1325
1427
  const absPath = path.resolve(appRoot, mod.path);
1326
1428
  const relPath = path.relative(outputDir, absPath);
1327
1429
  const userSources =
@@ -1333,7 +1435,9 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1333
1435
  name: mod.name,
1334
1436
  path: relPath,
1335
1437
  exclude: mod.exclude ?? [],
1336
- publicHeadersPath: mod.publicHeadersPath ?? null,
1438
+ // The synth wrapper owns the module's public interface: it declares
1439
+ // publicHeadersPath: "include", a symlink to the module's header tree.
1440
+ publicHeadersPath: null,
1337
1441
  sources: userSources,
1338
1442
  },
1339
1443
  origin: 'spmModule',
@@ -1402,8 +1506,9 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1402
1506
  // longer silently synthesize one for them (that duplicated the scaffolder and
1403
1507
  // hid the gap from the developer and the library author) — collect them and
1404
1508
  // fail with an actionable message after the classification pass. spmModules
1405
- // (app-local, podspec-less, explicitly declared in react-native.config.js)
1406
- // keep their synth wrappers: there is nothing to scaffold for them.
1509
+ // (app-local, explicitly declared in react-native.config.js) keep their synth
1510
+ // wrappers: an app-local dir has no npm identity, so there is no package for
1511
+ // the aggregator to reference until one is written for it.
1407
1512
  const missingManifests /*: Array<{name: string, npmName: string, hasPodspec: boolean, mixed?: boolean}> */ =
1408
1513
  [];
1409
1514
 
@@ -1455,11 +1560,14 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1455
1560
  }
1456
1561
  continue;
1457
1562
  }
1458
- // spmModule: synth wrapper is the legitimate mechanism (no podspec exists
1459
- // to scaffold from, and the app developer declared it explicitly). But a
1460
- // mixed-language module can't be wrapped either SPM can't compile Swift +
1461
- // C-family sources in one target, and a synth wrapper would fail with a
1462
- // cryptic SPM resolve error. Surface the same friendly diagnostic the
1563
+ // spmModule: the synth wrapper is the mechanism, not a fallback — an
1564
+ // app-local dir has no npm identity, so the wrapper is the only package the
1565
+ // aggregator can reference. No podspec is read on this route by design:
1566
+ // app-local native code isn't required to carry one. (A hand-written
1567
+ // Package.swift still wins the self-managed check above claims it first.)
1568
+ // But a mixed-language module can't be wrapped either — SPM can't compile
1569
+ // Swift + C-family sources in one target, and a synth wrapper would fail
1570
+ // with a cryptic SPM resolve error. Surface the same friendly diagnostic the
1463
1571
  // community-dep path uses instead of letting SPM emit the cryptic one.
1464
1572
  if (hasMixedLanguageSources(absSource)) {
1465
1573
  throw new Error(
@@ -1686,6 +1794,7 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1686
1794
  let pluginGeneratedSources /*: Array<{path: string}> */ = [];
1687
1795
  let pluginFlavoredFrameworks /*: Array<PluginFlavoredFramework> */ = [];
1688
1796
  let pluginWatchPaths /*: Array<string> */ = [];
1797
+ let pluginScriptPhases /*: Array<PluginScriptPhase> */ = [];
1689
1798
  if (discoveredPlugins.length > 0) {
1690
1799
  // React-GeneratedCode is the per-app codegen package (referenced as
1691
1800
  // `../ios` from outputDir). It may be absent (no codegen this run), so the
@@ -1714,15 +1823,17 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1714
1823
  pluginGeneratedSources = result.generatedSources;
1715
1824
  pluginFlavoredFrameworks = result.flavoredFrameworks;
1716
1825
  pluginWatchPaths = result.watchPaths;
1826
+ pluginScriptPhases = result.scriptPhases;
1717
1827
  log(
1718
1828
  `SPM plugins contributed ${pluginPackageDeps.length} package(s), ` +
1719
1829
  `${pluginProductDeps.length} product(s), ` +
1720
1830
  `${pluginGeneratedSources.length} generated source(s), ` +
1721
- `${pluginFlavoredFrameworks.length} flavored framework(s)`,
1831
+ `${pluginFlavoredFrameworks.length} flavored framework(s), ` +
1832
+ `${pluginScriptPhases.length} script phase(s)`,
1722
1833
  );
1723
1834
  }
1724
1835
 
1725
- // Plugin sidecars. Both are ALWAYS written — even `[]` — so removing a
1836
+ // Plugin sidecars. All are ALWAYS written — even `[]` — so removing a
1726
1837
  // plugin (or dropping its declaration) clears stale entries. Machine-local
1727
1838
  // absolute paths; gitignored + regenerated every sync.
1728
1839
  fs.mkdirSync(outputDir, {recursive: true});
@@ -1741,6 +1852,11 @@ function main(argv /*:: ?: Array<string> */) /*: void */ {
1741
1852
  JSON.stringify(pluginFlavoredFrameworks, null, 2) + '\n',
1742
1853
  'utf8',
1743
1854
  );
1855
+ fs.writeFileSync(
1856
+ path.join(outputDir, '.spm-plugin-script-phases.json'),
1857
+ JSON.stringify(pluginScriptPhases, null, 2) + '\n',
1858
+ 'utf8',
1859
+ );
1744
1860
 
1745
1861
  // Top-level aggregator: references every entry as .package(path:) and
1746
1862
  // depends on each via .product(...). No more inline targets — every
@@ -1873,6 +1989,7 @@ if (require.main === module) {
1873
1989
 
1874
1990
  module.exports = {
1875
1991
  main,
1992
+ autolinkingDepToSpmTarget,
1876
1993
  generateAutolinkedPackageSwift,
1877
1994
  generateSynthPackageSwift,
1878
1995
  reactDescriptor,
@@ -37,6 +37,12 @@
37
37
 
38
38
  const {prepareFlavoredFrameworks} = require('./flavored-frameworks');
39
39
  const {
40
+ REACT_HEADERS_TARGET_DIR,
41
+ REACT_NATIVE_HEADERS_PRODUCT,
42
+ REACT_NATIVE_PACKAGE_NAME,
43
+ REACT_NATIVE_PRODUCTS,
44
+ REACT_NATIVE_UMBRELLA_PRODUCT,
45
+ REACT_NATIVE_XCFRAMEWORK_PRODUCTS,
40
46
  deriveAppName,
41
47
  displayPath,
42
48
  findProjectRoot,
@@ -166,32 +172,38 @@ function findSourcePath(
166
172
  * Package.swift also imports it as a named package dependency.
167
173
  */
168
174
  function generateXCFrameworksPackageSwift() /*: string */ {
175
+ // Each product's target follows from its KIND, not from its position in the
176
+ // list: the umbrella is a Clang target over the staged headers, and every
177
+ // xcframework-backed product gets a binaryTarget of the same name.
178
+ const products = REACT_NATIVE_PRODUCTS.map(
179
+ product => ` .library(name: "${product}", targets: ["${product}"]),`,
180
+ );
181
+ const targets = [
182
+ ` .target(
183
+ name: "${REACT_NATIVE_UMBRELLA_PRODUCT}",
184
+ dependencies: ["${REACT_NATIVE_HEADERS_PRODUCT}"],
185
+ path: "${REACT_HEADERS_TARGET_DIR}",
186
+ publicHeadersPath: "include"
187
+ ),`,
188
+ ...REACT_NATIVE_XCFRAMEWORK_PRODUCTS.map(
189
+ product => ` .binaryTarget(
190
+ name: "${product}",
191
+ path: "${product}.xcframework"
192
+ ),`,
193
+ ),
194
+ ];
195
+
169
196
  return `// swift-tools-version: 6.0
170
197
  // AUTO-GENERATED by scripts/generate-spm-package.js – do not edit manually.
171
198
  import PackageDescription
172
199
 
173
200
  let package = Package(
174
- name: "ReactNative",
201
+ name: "${REACT_NATIVE_PACKAGE_NAME}",
175
202
  products: [
176
- .library(name: "ReactHeaders", targets: ["ReactHeaders"]),
177
- .library(name: "ReactNativeHeaders", targets: ["ReactNativeHeaders"]),
178
- .library(name: "ReactNativeDependenciesHeaders", targets: ["ReactNativeDependenciesHeaders"]),
203
+ ${products.join('\n')}
179
204
  ],
180
205
  targets: [
181
- .target(
182
- name: "ReactHeaders",
183
- dependencies: ["ReactNativeHeaders"],
184
- path: "ReactHeadersTarget",
185
- publicHeadersPath: "include"
186
- ),
187
- .binaryTarget(
188
- name: "ReactNativeHeaders",
189
- path: "ReactNativeHeaders.xcframework"
190
- ),
191
- .binaryTarget(
192
- name: "ReactNativeDependenciesHeaders",
193
- path: "ReactNativeDependenciesHeaders.xcframework"
194
- ),
206
+ ${targets.join('\n')}
195
207
  ]
196
208
  )
197
209
  `;