@smileid/usesmileid_vision_face 12.0.2 → 12.1.1

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 (34) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +33 -1
  3. package/dist/index.d.ts +4 -4
  4. package/dist/index.js +1 -36
  5. package/ios/UseSmileIDVisionFaceExpo.podspec +2 -5
  6. package/ios/UseSmileIDVisionFaceModule/ResizingFrameStorage.swift +1 -1
  7. package/ios/UseSmileIDVisionFaceModule/UseSmileIDVisionFaceKameraAnalysisTick.swift +61 -0
  8. package/ios/UseSmileIDVisionFaceModule/UseSmileIDVisionFaceModule.swift +6 -13
  9. package/package.json +13 -14
  10. package/plugin/build/index.d.ts +10 -1
  11. package/plugin/build/index.js +1 -132
  12. package/plugin/build/lib/deployment_target.js +1 -39
  13. package/plugin/build/lib/podfile.d.ts +15 -0
  14. package/plugin/build/lib/podfile.js +159 -130
  15. package/plugin/build/lib/signature_dedup.d.ts +14 -0
  16. package/plugin/build/lib/signature_dedup.js +2 -0
  17. package/plugin/build/lib/spm.d.ts +21 -0
  18. package/plugin/build/lib/spm.js +1 -196
  19. package/dist/index.d.ts.map +0 -1
  20. package/dist/index.js.map +0 -1
  21. package/ios/UseSmileIDVisionFaceModule/UseSmileIDVisionFaceFrameProcessorPlugin.swift +0 -96
  22. package/plugin/build/index.js.map +0 -1
  23. package/plugin/build/lib/deployment_target.js.map +0 -1
  24. package/plugin/build/lib/podfile.js.map +0 -1
  25. package/plugin/build/lib/spm.js.map +0 -1
  26. package/plugin/src/__tests__/deployment_target.test.ts +0 -41
  27. package/plugin/src/__tests__/podfile.test.ts +0 -136
  28. package/plugin/src/index.ts +0 -116
  29. package/plugin/src/lib/deployment_target.ts +0 -46
  30. package/plugin/src/lib/podfile.ts +0 -254
  31. package/plugin/src/lib/spm.ts +0 -314
  32. package/plugin/tsconfig.json +0 -24
  33. package/src/__tests__/use_smile_id_vision_face.test.ts +0 -79
  34. package/src/index.ts +0 -41
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ Full release notes: [Smile ID docs](https://docs.usesmileid.com/developer-resources/sdks/mobile/release-notes/react-native-expo).
2
+
3
+ ## 12.1.1
4
+
5
+ See the repository CHANGELOG for the 12.1.1 release notes.
6
+
7
+
8
+ ## 12.1.0
9
+
10
+ See the repository CHANGELOG for the 12.1.0 release notes.
11
+
12
+
1
13
  ## 12.0.2
2
14
 
3
15
  See the repository CHANGELOG for the 12.0.2 release notes.
package/README.md CHANGED
@@ -17,13 +17,45 @@ No ML logic is reimplemented in this package — it's a pure passthrough.
17
17
  ## Installation
18
18
 
19
19
  ```sh
20
- pnpm add @smileid/usesmileid_vision_face
20
+ pnpm add @smileid/usesmileid_vision_face react-native-vision-camera@^4
21
21
  ```
22
22
 
23
+ This package's pod depends on VisionCamera: without it `pod install` fails
24
+ with `Unable to find a specification for VisionCamera depended upon by
25
+ UseSmileIDVisionFaceExpo`. Pin v4 — the SDK is built against the v4
26
+ API, and a bare `expo install react-native-vision-camera` resolves a v5.
27
+
23
28
  Run `npx pod-install` (or let Expo's prebuild handle it) so the iOS
24
29
  project picks up the SPM dependency declared in
25
30
  `UseSmileIDVisionFace.podspec`.
26
31
 
32
+ ## Config plugin options
33
+
34
+ | Option | Values | Default |
35
+ | ------------------------- | ------------------------ | -------- |
36
+ | `iosSignatureAggregation` | `"keep"` \| `"disabled"` | `"keep"` |
37
+
38
+ Several targets have to reference the same signed Smile ID XCFramework, and an
39
+ iOS release archive collects framework signatures into one directory keyed by
40
+ filename — so `"keep"` adds a build phase that leaves exactly one staged copy of
41
+ each signature while the archive is assembled.
42
+
43
+ `"disabled"` instead turns off Xcode's signature aggregation for the app target.
44
+ Reach for it only if an Xcode version we have not seen still fails to archive:
45
+ it drops the recorded signatures of every framework in the archive, including
46
+ your own and other vendors'.
47
+
48
+ ```json
49
+ {
50
+ "plugins": [
51
+ [
52
+ "@smileid/usesmileid_vision_face",
53
+ { "iosSignatureAggregation": "disabled" }
54
+ ]
55
+ ]
56
+ }
57
+ ```
58
+
27
59
  ## Usage
28
60
 
29
61
  ```ts
package/dist/index.d.ts CHANGED
@@ -18,9 +18,10 @@ import type { FaceConfig, FaceScanResult } from "@smileid/usesmileid_bridge";
18
18
  * contract.
19
19
  */
20
20
  /**
21
- * Must match the Swift Expo Module's `Name("UseSmileIDVisionFace")` and its
22
- * VisionCamera frame-processor-plugin registration — drift is a runtime
23
- * "module/plugin not found" error, not a compile error.
21
+ * Must match the Swift Expo Module's `Name("UseSmileIDVisionFace")` — drift is a runtime
22
+ * "module not found" error, not a compile error.
23
+ *
24
+ * `frameProcessorPluginName` is inert; kept only for API compatibility.
24
25
  */
25
26
  export declare const UseSmileIDVisionFaceIdentifiers: {
26
27
  readonly nativeModuleName: "UseSmileIDVisionFace";
@@ -28,4 +29,3 @@ export declare const UseSmileIDVisionFaceIdentifiers: {
28
29
  };
29
30
  export declare const useSmileIDVisionFace: import("@smileid/usesmileid_platform_interface").FaceAnalyzer;
30
31
  export type { FaceConfig, FaceScanResult };
31
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,36 +1 @@
1
- import { AnalyzerFactoryKey } from "@smileid/usesmileid_bridge";
2
- import { useSmileIDAnalyzerExecutor } from "@smileid/usesmileid_platform_interface";
3
- /**
4
- * Apple Vision face analyzer (iOS-only).
5
- *
6
- * Thin shim around the existing native session
7
- * `UseSmileID.UseSmileIDFaceSession(FaceDetectorAnalyzer())` shipped in
8
- * the `UseSmileIDVisionFace` Swift Package. The native side runs the
9
- * entire pipeline (analyzer + validator + transitioner + state
10
- * machine); this TS layer routes calls and validates wire payloads at
11
- * the channel boundary.
12
- *
13
- * The canonical wiring lives in [useSmileIDAnalyzerExecutor] in
14
- * `usesmileid_platform_interface`.
15
- *
16
- * Lifecycle: `configure()` → per-frame analysis via the native frame
17
- * processor plugin → `reset()`? → `close()`. See
18
- * `usesmileid_platform_interface` `FaceAnalyzer` for the canonical
19
- * contract.
20
- */
21
- /**
22
- * Must match the Swift Expo Module's `Name("UseSmileIDVisionFace")` and its
23
- * VisionCamera frame-processor-plugin registration — drift is a runtime
24
- * "module/plugin not found" error, not a compile error.
25
- */
26
- export const UseSmileIDVisionFaceIdentifiers = {
27
- nativeModuleName: "UseSmileIDVisionFace",
28
- frameProcessorPluginName: "UseSmileIDVisionFaceFrameProcessor",
29
- };
30
- export const useSmileIDVisionFace = useSmileIDAnalyzerExecutor({
31
- nativeModuleName: UseSmileIDVisionFaceIdentifiers.nativeModuleName,
32
- frameProcessorPluginName: UseSmileIDVisionFaceIdentifiers.frameProcessorPluginName,
33
- kind: "face",
34
- key: AnalyzerFactoryKey.VisionFace,
35
- });
36
- //# sourceMappingURL=index.js.map
1
+ "use strict";import{AnalyzerFactoryKey as e}from"@smileid/usesmileid_bridge";import{useSmileIDAnalyzerExecutor as i}from"@smileid/usesmileid_platform_interface";export const UseSmileIDVisionFaceIdentifiers={nativeModuleName:"UseSmileIDVisionFace",frameProcessorPluginName:"UseSmileIDVisionFaceFrameProcessor"},useSmileIDVisionFace=i({nativeModuleName:UseSmileIDVisionFaceIdentifiers.nativeModuleName,frameProcessorPluginName:UseSmileIDVisionFaceIdentifiers.frameProcessorPluginName,kind:"face",key:e.VisionFace});
@@ -23,11 +23,8 @@ Pod::Spec.new do |s|
23
23
  s.static_framework = true
24
24
 
25
25
  s.dependency 'ExpoModulesCore'
26
- # VisionCamera provides the FrameProcessorPlugin base class and
27
- # FrameProcessorPluginRegistry used by UseSmileIDVisionFaceFrameProcessorPlugin.
28
- # Frame processors additionally require react-native-worklets-core in the
29
- # consuming app (already declared as an SDK peer dependency).
30
- s.dependency 'VisionCamera'
26
+ # kamera native core (pre-release pod); analyzeKameraFrame takes frames from its KameraFrameHub.
27
+ s.dependency 'kamera-rn'
31
28
 
32
29
  # The Smile ID native deps (`UseSmileIDVisionFace` / `UseSmileIDBridge`)
33
30
  # are SPM-only — declared in `expo-module.config.json` under
@@ -34,7 +34,7 @@ final class ResizingFrameStorage: FrameStorage {
34
34
  private let livenessQuality: CGFloat
35
35
  private let documentQuality: CGFloat
36
36
  private let writer: Writer
37
- // The frame-processor plugin calls `setCropRegion` on the VisionCamera FP
37
+ // The analysis tick calls `setCropRegion` on the module's async-function
38
38
  // thread; `persist` reads the value on that same serialised scan path before
39
39
  // handing it (by value) to the background encode task. The Swift value is a
40
40
  // `Sendable` struct captured by value into `Writer.enqueue`, so no background
@@ -0,0 +1,61 @@
1
+ import CoreMedia
2
+ import Kamera
3
+ import CoreImage
4
+ import UIKit
5
+
6
+
7
+ private extension CGImagePropertyOrientation {
8
+ /// Kamera rotation + mirror metadata → the preview's selfie-mirrored view. The mirror
9
+ /// applies after the rotation, so the quarter-turn cases swap (`.right` ↔ `.leftMirrored`).
10
+ init(rotationDegrees: Int, isMirrored: Bool) {
11
+ let normalised = ((rotationDegrees % 360) + 360) % 360
12
+ switch (normalised, isMirrored) {
13
+ case (90, false): self = .right
14
+ case (90, true): self = .leftMirrored
15
+ case (180, false): self = .down
16
+ case (180, true): self = .downMirrored
17
+ case (270, false): self = .left
18
+ case (270, true): self = .rightMirrored
19
+ case (_, true): self = .upMirrored
20
+ default: self = .up
21
+ }
22
+ }
23
+ }
24
+
25
+ /// Scans the latest `KameraFrameHub` frame; no pending frame returns the `no_frame` wire error.
26
+ enum UseSmileIDVisionFaceKameraTick {
27
+ /// Reused across ticks — per-tick creation recompiles the GPU pipeline.
28
+ private static let ciContext = CIContext(options: [.useSoftwareRenderer: false])
29
+
30
+ static func analyze(arguments: [String: Any?]?) -> Any {
31
+ guard let frame = KameraFrameHub.take() else {
32
+ return ["error": "no_frame"]
33
+ }
34
+ guard let concrete = frame as? CVPixelBufferKameraFrame else {
35
+ frame.close()
36
+ return ["error": "frame_conversion_failed"]
37
+ }
38
+
39
+ let orientedImage = CIImage(cvPixelBuffer: concrete.pixelBuffer)
40
+ .oriented(CGImagePropertyOrientation(
41
+ rotationDegrees: frame.rotationDegrees,
42
+ isMirrored: frame.isMirrored
43
+ ))
44
+ let cgImage = ciContext.createCGImage(orientedImage, from: orientedImage.extent)
45
+ frame.close()
46
+ guard let cgImage else {
47
+ return ["error": "frame_conversion_failed"]
48
+ }
49
+
50
+ // Device-tilt context (0 = upright portrait) for head-pose math.
51
+ let rotation = (arguments?["rotation"] as? NSNumber)?.intValue ?? 0
52
+
53
+ guard let result = UseSmileIDVisionFaceSessionHolder.shared.scanAndDrain(
54
+ image: UIImage(cgImage: cgImage),
55
+ rotation: rotation
56
+ ) else {
57
+ return ["error": "session_not_configured"]
58
+ }
59
+ return result
60
+ }
61
+ }
@@ -1,8 +1,6 @@
1
1
  import ExpoModulesCore
2
- import UIKit
3
2
  import UseSmileIDBridge
4
3
  import UseSmileIDVisionFace
5
- import VisionCamera
6
4
 
7
5
  /// Expo Module bridging `UseSmileIDFaceSession` to the JS side.
8
6
  /// No ML logic lives here — the native session owns the full pipeline.
@@ -12,10 +10,6 @@ public class UseSmileIDVisionFaceModule: Module {
12
10
  /// Wire-format key partners pass via `FaceConfig.analyzerFactoryKey`.
13
11
  static let KEY = "vision-face"
14
12
 
15
- /// Prevents double-registration of the frame processor plugin when
16
- /// Expo Go / dev-client fast-refreshes the JS bundle and `OnCreate`
17
- /// runs again in the same native process.
18
- private static var isFrameProcessorRegistered = false
19
13
 
20
14
  private var session: UseSmileIDFaceSession?
21
15
 
@@ -45,13 +39,6 @@ public class UseSmileIDVisionFaceModule: Module {
45
39
  return { @Sendable input, state in await analyzer.analyze(data: input, state: state) }
46
40
  }
47
41
 
48
- // Guard prevents double-registration on dev-client fast-refresh reloads.
49
- if !Self.isFrameProcessorRegistered {
50
- FrameProcessorPluginRegistry.addFrameProcessorPlugin("UseSmileIDVisionFaceFrameProcessor") { proxy, options in
51
- UseSmileIDVisionFaceFrameProcessorPlugin(proxy: proxy, options: options)
52
- }
53
- Self.isFrameProcessorRegistered = true
54
- }
55
42
  }
56
43
 
57
44
  AsyncFunction("configure") { (config: [String: Any?]) in
@@ -69,6 +56,11 @@ public class UseSmileIDVisionFaceModule: Module {
69
56
  UseSmileIDVisionFaceSessionHolder.shared.setSession(newSession)
70
57
  }
71
58
 
59
+ AsyncFunction("analyzeKameraFrame") { (arguments: [String: Any?]?) -> Any in
60
+ // Runs on this module's async queue, so only one scan is in flight at a time.
61
+ UseSmileIDVisionFaceKameraTick.analyze(arguments: arguments)
62
+ }
63
+
72
64
  AsyncFunction("reset") {
73
65
  UseSmileIDVisionFaceSessionHolder.shared.reset()
74
66
  }
@@ -279,3 +271,4 @@ extension UseSmileIDBridge.UseSmileIDScanState {
279
271
  return map
280
272
  }
281
273
  }
274
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smileid/usesmileid_vision_face",
3
- "version": "12.0.2",
3
+ "version": "12.1.1",
4
4
  "description": "Apple Vision face detection implementation for the UseSmileID React Native (Expo) SDK.",
5
5
  "homepage": "https://usesmileid.com",
6
6
  "repository": {
@@ -36,11 +36,9 @@
36
36
  },
37
37
  "files": [
38
38
  "dist",
39
- "src",
40
- "ios",
39
+ "ios/UseSmileIDVisionFaceExpo.podspec",
40
+ "ios/UseSmileIDVisionFaceModule",
41
41
  "plugin/build",
42
- "plugin/src",
43
- "plugin/tsconfig.json",
44
42
  "app.plugin.js",
45
43
  "expo-module.config.json",
46
44
  "README.md",
@@ -48,8 +46,8 @@
48
46
  "CHANGELOG.md"
49
47
  ],
50
48
  "dependencies": {
51
- "@smileid/usesmileid_bridge": "12.0.2",
52
- "@smileid/usesmileid_platform_interface": "12.0.2"
49
+ "@smileid/usesmileid_bridge": "12.1.1",
50
+ "@smileid/usesmileid_platform_interface": "12.1.1"
53
51
  },
54
52
  "peerDependencies": {
55
53
  "expo": ">=56.0.0",
@@ -57,22 +55,23 @@
57
55
  "react-native": ">=0.83.0"
58
56
  },
59
57
  "devDependencies": {
60
- "@types/node": "^25.9.1",
61
- "expo": "^56.0.9",
62
- "expo-modules-core": "^56.0.15",
63
- "react-native": "^0.85.3",
64
- "typescript": "^6.0.3"
58
+ "@types/node": "^26.4.1",
59
+ "expo": "~57.0.20",
60
+ "expo-modules-core": "^57.0.16",
61
+ "react-native": "^0.86.3",
62
+ "typescript": "^6.0.3",
63
+ "xcode": "^3.0.1"
65
64
  },
66
65
  "publishConfig": {
67
66
  "access": "public"
68
67
  },
69
68
  "scripts": {
70
- "build": "pnpm run build:lib && pnpm run build:plugin",
69
+ "build": "pnpm run build:lib && pnpm run build:plugin && node ../Scripts/copy-assets.mjs",
71
70
  "build:lib": "tsc -p tsconfig.json",
72
71
  "build:plugin": "tsc -p plugin/tsconfig.json",
73
72
  "typecheck": "tsc -b && tsc -p plugin/tsconfig.json --noEmit",
74
73
  "test": "vitest run",
75
74
  "test:watch": "vitest",
76
- "clean": "rm -rf dist plugin/build .turbo coverage"
75
+ "clean": "rm -rf dist plugin/build .turbo coverage tsconfig.tsbuildinfo"
77
76
  }
78
77
  }
@@ -1,3 +1,12 @@
1
1
  import { ConfigPlugin } from "expo/config-plugins";
2
- declare const withVisionFaceSpm: ConfigPlugin;
2
+ export interface VisionFaceOptions {
3
+ /**
4
+ * `"disabled"` stops Xcode recording XCFramework signatures in iOS archives
5
+ * instead of keeping one staged copy per framework — an escape hatch that
6
+ * drops the records for every framework, Smile ID's and yours alike.
7
+ */
8
+ iosSignatureAggregation?: "keep" | "disabled";
9
+ }
10
+ export declare const SPM_PRODUCTS: readonly ["UseSmileIDVisionFace"];
11
+ declare const withVisionFaceSpm: ConfigPlugin<VisionFaceOptions | void>;
3
12
  export default withVisionFaceSpm;
@@ -1,132 +1 @@
1
- "use strict";
2
- // Expo config plugin that wires the Smile Identity Swift Package
3
- // (`https://github.com/smileidentity/ios-spm`) into both:
4
- // 1. The consuming app's Xcode project — so the .xcframeworks ship
5
- // and embed in the final .app bundle.
6
- // 2. The autogenerated Pods.xcodeproj at `pod install` time — so
7
- // the Expo Module bridge (`UseSmileIDVisionFaceExpo`) compiles
8
- // with `import UseSmileIDVisionFace` / `import UseSmileIDBridge`.
9
- //
10
- // Why a plugin: `expo-modules-autolinking@55.0.x`'s
11
- // `RawModuleConfigApple` schema has no `dependencies` field, so the
12
- // `apple.dependencies` block in `expo-module.config.json` is silently
13
- // ignored. Without this plugin, neither the bridge nor the host app
14
- // know about the SPM package.
15
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
- if (k2 === undefined) k2 = k;
17
- var desc = Object.getOwnPropertyDescriptor(m, k);
18
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
- desc = { enumerable: true, get: function() { return m[k]; } };
20
- }
21
- Object.defineProperty(o, k2, desc);
22
- }) : (function(o, m, k, k2) {
23
- if (k2 === undefined) k2 = k;
24
- o[k2] = m[k];
25
- }));
26
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
- Object.defineProperty(o, "default", { enumerable: true, value: v });
28
- }) : function(o, v) {
29
- o["default"] = v;
30
- });
31
- var __importStar = (this && this.__importStar) || (function () {
32
- var ownKeys = function(o) {
33
- ownKeys = Object.getOwnPropertyNames || function (o) {
34
- var ar = [];
35
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
- return ar;
37
- };
38
- return ownKeys(o);
39
- };
40
- return function (mod) {
41
- if (mod && mod.__esModule) return mod;
42
- var result = {};
43
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
- __setModuleDefault(result, mod);
45
- return result;
46
- };
47
- })();
48
- Object.defineProperty(exports, "__esModule", { value: true });
49
- const config_plugins_1 = require("expo/config-plugins");
50
- const fs = __importStar(require("fs"));
51
- const path = __importStar(require("path"));
52
- const deployment_target_1 = require("./lib/deployment_target");
53
- const podfile_1 = require("./lib/podfile");
54
- const spm_1 = require("./lib/spm");
55
- // The lowest the Expo iOS template and the pods alongside it still compile at.
56
- const IOS_DEPLOYMENT_TARGET = "16.4";
57
- // Pinned to the exact `12.0.0` release tag — `from: 12.0.0`
58
- // would not resolve because `ios-spm` publishes pre-release tags (e.g.
59
- // `12.0.0`), and SPM excludes pre-release tags from open-ended
60
- // major-version requirements.
61
- const SMILE_ID_PACKAGE = {
62
- url: "https://github.com/smileidentity/ios-spm",
63
- requirement: {
64
- kind: "exactVersion",
65
- version: "12.0.2",
66
- },
67
- };
68
- const POD_TARGET = "UseSmileIDVisionFaceExpo";
69
- // `UseSmileIDBridge` is also listed explicitly even though the Vision
70
- // library product wraps it as a transitive target — empirically this
71
- // is what makes `import UseSmileIDBridge` resolve in the bridge under
72
- // SPM-via-CocoaPods. A cleaner config that drops the redundant
73
- // listing is plausible (the SPM Package.swift declares
74
- // `targets: ["UseSmileIDVisionFace", "UseSmileIDBridge"]` for the Vision
75
- // library product) but unverified, and the duplicate produces only a
76
- // benign "Conflicting parseable interfaces" warning at link time.
77
- const SPM_PRODUCTS = ["UseSmileIDVisionFace", "UseSmileIDBridge"];
78
- const PODFILE_MARKER = "usesmileid_vision_face";
79
- // Nothing else links the bridge's own pod target, so without this block its
80
- // `import UseSmileIDBridge` fails. Both vision plugins emit it; the injection is
81
- // idempotent per marker, so installing both is harmless.
82
- const BRIDGE_POD_TARGET = "UseSmileIDBridgeExpo";
83
- const BRIDGE_SPM_PRODUCTS = ["UseSmileIDBridge"];
84
- const BRIDGE_PODFILE_MARKER = "usesmileid_bridge";
85
- const withVisionFaceSpm = (config) => {
86
- config = (0, deployment_target_1.withIosDeploymentTargetFloor)(config, IOS_DEPLOYMENT_TARGET);
87
- // 1. Add the package + products to the host app's Xcode project so
88
- // Xcode resolves the binary xcframeworks and embeds them in the
89
- // .app at link time.
90
- config = (0, config_plugins_1.withXcodeProject)(config, (config) => {
91
- const appTarget = config.modRequest.projectName;
92
- if (!appTarget) {
93
- throw new Error("[usesmileid_vision_face] Unable to resolve host app native target name from Expo config.");
94
- }
95
- (0, spm_1.linkSpmPackage)(config.modResults, SMILE_ID_PACKAGE, {
96
- targetName: appTarget,
97
- products: [...SPM_PRODUCTS],
98
- });
99
- return config;
100
- });
101
- // 2. Inject a Ruby block into the Podfile's post_install hook that
102
- // re-applies the same wiring to Pods.xcodeproj when CocoaPods
103
- // materializes it. The bridge pod target needs the products
104
- // visible at compile time; the host-app step alone isn't enough.
105
- config = (0, config_plugins_1.withDangerousMod)(config, [
106
- "ios",
107
- (config) => {
108
- const podfilePath = path.join(config.modRequest.platformProjectRoot, "Podfile");
109
- const original = fs.readFileSync(podfilePath, "utf-8");
110
- let next = (0, podfile_1.injectPodfileSpmBlock)(original, {
111
- marker: PODFILE_MARKER,
112
- package: SMILE_ID_PACKAGE,
113
- podTarget: POD_TARGET,
114
- products: [...SPM_PRODUCTS],
115
- });
116
- next = (0, podfile_1.injectPodfileSpmBlock)(next, {
117
- marker: BRIDGE_PODFILE_MARKER,
118
- package: SMILE_ID_PACKAGE,
119
- podTarget: BRIDGE_POD_TARGET,
120
- products: [...BRIDGE_SPM_PRODUCTS],
121
- required: true,
122
- });
123
- if (next !== original) {
124
- fs.writeFileSync(podfilePath, next);
125
- }
126
- return config;
127
- },
128
- ]);
129
- return config;
130
- };
131
- exports.default = withVisionFaceSpm;
132
- //# sourceMappingURL=index.js.map
1
+ "use strict";var __createBinding=this&&this.__createBinding||(Object.create?(function(i,r,t,e){e===void 0&&(e=t);var o=Object.getOwnPropertyDescriptor(r,t);(!o||("get"in o?!r.__esModule:o.writable||o.configurable))&&(o={enumerable:!0,get:function(){return r[t]}}),Object.defineProperty(i,e,o)}):(function(i,r,t,e){e===void 0&&(e=t),i[e]=r[t]})),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?(function(i,r){Object.defineProperty(i,"default",{enumerable:!0,value:r})}):function(i,r){i.default=r}),__importStar=this&&this.__importStar||(function(){var i=function(r){return i=Object.getOwnPropertyNames||function(t){var e=[];for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&(e[e.length]=o);return e},i(r)};return function(r){if(r&&r.__esModule)return r;var t={};if(r!=null)for(var e=i(r),o=0;o<e.length;o++)e[o]!=="default"&&__createBinding(t,r,e[o]);return __setModuleDefault(t,r),t}})();Object.defineProperty(exports,"__esModule",{value:!0}),exports.SPM_PRODUCTS=void 0;const config_plugins_1=require("expo/config-plugins"),fs=__importStar(require("fs")),path=__importStar(require("path")),deployment_target_1=require("./lib/deployment_target"),podfile_1=require("./lib/podfile"),signature_dedup_1=require("./lib/signature_dedup"),spm_1=require("./lib/spm"),IOS_DEPLOYMENT_TARGET="16.4",SMILE_ID_PACKAGE={url:"https://github.com/smileidentity/ios-spm",requirement:{kind:"exactVersion",version:"12.1.1"}},POD_TARGET="UseSmileIDVisionFaceExpo";exports.SPM_PRODUCTS=["UseSmileIDVisionFace"];const PODFILE_MARKER="usesmileid_vision_face",BRIDGE_POD_TARGET="UseSmileIDBridgeExpo",BRIDGE_SPM_PRODUCTS=["UseSmileIDBridge"],BRIDGE_PODFILE_MARKER="usesmileid_bridge",withVisionFaceSpm=(i,r)=>(i=(0,deployment_target_1.withIosDeploymentTargetFloor)(i,IOS_DEPLOYMENT_TARGET),i=(0,config_plugins_1.withXcodeProject)(i,t=>{const e=t.modRequest.projectName;if(!e)throw new Error("[usesmileid_vision_face] Unable to resolve host app native target name from Expo config.");return(0,spm_1.linkSpmPackage)(t.modResults,SMILE_ID_PACKAGE,{targetName:e,products:[...exports.SPM_PRODUCTS]}),r?.iosSignatureAggregation==="disabled"?(0,signature_dedup_1.disableSignatureAggregation)(t.modResults,e):(0,signature_dedup_1.ensureSignatureDedupPhase)(t.modResults,e),t}),i=(0,config_plugins_1.withDangerousMod)(i,["ios",t=>{const e=path.join(t.modRequest.platformProjectRoot,"Podfile"),o=fs.readFileSync(e,"utf-8");let n=(0,podfile_1.injectPodfileSpmBlock)(o,{marker:PODFILE_MARKER,package:SMILE_ID_PACKAGE,podTarget:POD_TARGET,products:[...exports.SPM_PRODUCTS]});return n=(0,podfile_1.injectPodfileSpmBlock)(n,{marker:BRIDGE_PODFILE_MARKER,package:SMILE_ID_PACKAGE,podTarget:BRIDGE_POD_TARGET,products:[...BRIDGE_SPM_PRODUCTS],required:!0}),n=(0,podfile_1.injectPodfileKameraLinkBlock)(n),n=(0,podfile_1.injectPodfileSignatureDedupBlock)(n),n!==o&&fs.writeFileSync(e,n),t}]),i);exports.default=withVisionFaceSpm;
@@ -1,39 +1 @@
1
- "use strict";
2
- // The Podfile prebuild generates reads `ios.deploymentTarget` from
3
- // `ios/Podfile.properties.json`, which nothing the SDK publishes used to set.
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.withIosDeploymentTargetFloor = void 0;
6
- exports.raiseDeploymentTarget = raiseDeploymentTarget;
7
- const config_plugins_1 = require("expo/config-plugins");
8
- /** Sets `ios.deploymentTarget` to `minimum` unless the project already asks for a higher one. */
9
- const withIosDeploymentTargetFloor = (config, minimum) => (0, config_plugins_1.withPodfileProperties)(config, (config) => {
10
- config.modResults = raiseDeploymentTarget(config.modResults, minimum);
11
- return config;
12
- });
13
- exports.withIosDeploymentTargetFloor = withIosDeploymentTargetFloor;
14
- /** Pure form of the edit the plugin makes to the Podfile properties. */
15
- function raiseDeploymentTarget(properties, minimum) {
16
- const current = properties["ios.deploymentTarget"];
17
- if (current !== undefined && compareVersions(current, minimum) >= 0) {
18
- return { ...properties };
19
- }
20
- return { ...properties, "ios.deploymentTarget": minimum };
21
- }
22
- // An unparseable component sorts as 0 so a bad value in a partner's project is
23
- // overwritten rather than crashing prebuild.
24
- function compareVersions(left, right) {
25
- const leftParts = left.split(".");
26
- const rightParts = right.split(".");
27
- for (let i = 0; i < Math.max(leftParts.length, rightParts.length); i++) {
28
- const difference = toNumber(leftParts[i] ?? "0") - toNumber(rightParts[i] ?? "0");
29
- if (difference !== 0) {
30
- return difference;
31
- }
32
- }
33
- return 0;
34
- }
35
- function toNumber(part) {
36
- const parsed = Number.parseInt(part, 10);
37
- return Number.isNaN(parsed) ? 0 : parsed;
38
- }
39
- //# sourceMappingURL=deployment_target.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.withIosDeploymentTargetFloor=void 0,exports.raiseDeploymentTarget=raiseDeploymentTarget;const config_plugins_1=require("expo/config-plugins"),withIosDeploymentTargetFloor=(e,t)=>(0,config_plugins_1.withPodfileProperties)(e,r=>(r.modResults=raiseDeploymentTarget(r.modResults,t),r));exports.withIosDeploymentTargetFloor=withIosDeploymentTargetFloor;function raiseDeploymentTarget(e,t){const r=e["ios.deploymentTarget"];return r!==void 0&&compareVersions(r,t)>=0?{...e}:{...e,"ios.deploymentTarget":t}}function compareVersions(e,t){const r=e.split("."),n=t.split(".");for(let o=0;o<Math.max(r.length,n.length);o++){const s=toNumber(r[o]??"0")-toNumber(n[o]??"0");if(s!==0)return s}return 0}function toNumber(e){const t=Number.parseInt(e,10);return Number.isNaN(t)?0:t}
@@ -17,3 +17,18 @@ export interface PodfileLinkOptions {
17
17
  * product changes flow through cleanly on the next prebuild).
18
18
  */
19
19
  export declare function injectPodfileSpmBlock(podfile: string, options: PodfileLinkOptions): string;
20
+ /**
21
+ * Links kamera-spm's products into the `kamera-rn` (and `kamera-testing`) pod
22
+ * targets with the helper `@smileid/kamera` ships. The SDK's own binaries link
23
+ * `Kamera.framework` dynamically and ios-spm declares kamera-spm for the app, so
24
+ * the kamera pod must take Kamera from that same package instead of vendoring a
25
+ * second copy; the helper pins kamera-spm at the installed `@smileid/kamera`
26
+ * version, so the pin can never drift from the JS side. Idempotent per marker.
27
+ */
28
+ export declare function injectPodfileKameraLinkBlock(podfile: string): string;
29
+ /**
30
+ * Adds the archive signature-dedup phase to the app target of the user's own
31
+ * project — the path for apps whose `ios/` is hand-maintained, where no config
32
+ * plugin runs. Guarded by phase name, so an app on both paths gets one.
33
+ */
34
+ export declare function injectPodfileSignatureDedupBlock(podfile: string): string;