@smileid/usesmileid_vision_document 12.0.1 → 12.1.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.
- package/CHANGELOG.md +11 -0
- package/README.md +33 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -34
- package/ios/UseSmileIDVisionDocumentExpo.podspec +2 -5
- package/ios/UseSmileIDVisionDocumentModule/ResizingFrameStorage.swift +1 -1
- package/ios/UseSmileIDVisionDocumentModule/UseSmileIDVisionDocumentKameraAnalysisTick.swift +80 -0
- package/ios/UseSmileIDVisionDocumentModule/UseSmileIDVisionDocumentModule.swift +9 -14
- package/package.json +13 -14
- package/plugin/build/index.d.ts +11 -2
- package/plugin/build/index.js +1 -107
- package/plugin/build/lib/deployment_target.d.ts +5 -0
- package/plugin/build/lib/deployment_target.js +1 -0
- package/plugin/build/lib/podfile.d.ts +17 -0
- package/plugin/build/lib/podfile.js +187 -117
- package/plugin/build/lib/signature_dedup.d.ts +14 -0
- package/plugin/build/lib/signature_dedup.js +2 -0
- package/plugin/build/lib/spm.d.ts +22 -1
- package/plugin/build/lib/spm.js +1 -196
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/ios/UseSmileIDVisionDocumentModule/UseSmileIDVisionDocumentFrameProcessorPlugin.swift +0 -149
- package/plugin/build/index.js.map +0 -1
- package/plugin/build/lib/podfile.js.map +0 -1
- package/plugin/build/lib/spm.js.map +0 -1
- package/plugin/src/index.ts +0 -88
- package/plugin/src/lib/podfile.ts +0 -209
- package/plugin/src/lib/spm.ts +0 -314
- package/plugin/tsconfig.json +0 -19
- package/src/__tests__/use_smile_id_vision_document.test.ts +0 -79
- package/src/index.ts +0 -42
package/ios/UseSmileIDVisionDocumentModule/UseSmileIDVisionDocumentFrameProcessorPlugin.swift
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import CoreMedia
|
|
2
|
-
import CoreImage
|
|
3
|
-
import UIKit
|
|
4
|
-
import UseSmileIDBridge
|
|
5
|
-
import VisionCamera
|
|
6
|
-
|
|
7
|
-
/// VisionCamera frame processor that feeds camera frames into the active
|
|
8
|
-
/// `UseSmileIDDocumentSession` without crossing the JS thread. Session ops
|
|
9
|
-
/// serialise through `UseSmileIDVisionDocumentSessionHolder.operationQueue`;
|
|
10
|
-
/// the `CIContext` is reused across frames (per-frame creation re-compiles the
|
|
11
|
-
/// GPU pipeline).
|
|
12
|
-
@objc(UseSmileIDVisionDocumentFrameProcessorPlugin)
|
|
13
|
-
public class UseSmileIDVisionDocumentFrameProcessorPlugin: FrameProcessorPlugin {
|
|
14
|
-
|
|
15
|
-
/// GPU-backed context reused across frames (CPU fallback if Metal unavailable).
|
|
16
|
-
private let ciContext = CIContext(options: [.useSoftwareRenderer: false])
|
|
17
|
-
|
|
18
|
-
@objc public override init(proxy: VisionCameraProxyHolder, options: [AnyHashable: Any]? = nil) {
|
|
19
|
-
super.init(proxy: proxy, options: options)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public override func callback(_ frame: Frame, withArguments arguments: [AnyHashable: Any]?) -> Any? {
|
|
23
|
-
guard frame.isValid else {
|
|
24
|
-
return ["error": "frame_conversion_failed"]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
guard let pixelBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
|
|
28
|
-
return ["error": "frame_conversion_failed"]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Bake rotation + mirror into the pixels (CIImage.oriented) rather than an
|
|
32
|
-
// EXIF flag — some consumers ignore the flag. `frame.orientation` only
|
|
33
|
-
// uprights to the sensor-natural (portrait) axis; the document screen
|
|
34
|
-
// force-locks the interface, so we additionally rotate onto that LOCKED
|
|
35
|
-
// INTERFACE axis so the saved JPEG matches the preview and the guide-rect
|
|
36
|
-
// crop. `viewportOrientation` is the interface orientation in degrees
|
|
37
|
-
// (0/90/270); each maps to a device-verified rotation in
|
|
38
|
-
// `rotatedOntoViewportAxis` — including the portrait (0°) half-turn.
|
|
39
|
-
let orientationFlag = frame.isMirrored
|
|
40
|
-
? frame.orientation.composedWithHorizontalMirror()
|
|
41
|
-
: frame.orientation
|
|
42
|
-
let viewportOrientation = (arguments?["viewportOrientation"] as? NSNumber)?.intValue ?? 0
|
|
43
|
-
let orientedImage = CIImage(cvPixelBuffer: pixelBuffer)
|
|
44
|
-
.oriented(CGImagePropertyOrientation(orientationFlag))
|
|
45
|
-
.rotatedOntoViewportAxis(degrees: viewportOrientation)
|
|
46
|
-
|
|
47
|
-
guard let cgImage = ciContext.createCGImage(orientedImage, from: orientedImage.extent) else {
|
|
48
|
-
return ["error": "frame_conversion_failed"]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let rotation = (arguments?["rotation"] as? NSNumber)?.intValue ?? 0
|
|
52
|
-
let uiImage = UIImage(cgImage: cgImage)
|
|
53
|
-
|
|
54
|
-
// Forward the on-screen document guide rectangle (if JS supplied it) so the
|
|
55
|
-
// saved capture is cropped to exactly what the user framed. Set before the
|
|
56
|
-
// scan so the storage holds the region when this frame's `persist` runs.
|
|
57
|
-
// Both calls serialise through the holder's operation queue, so the region
|
|
58
|
-
// is stable for the duration of this frame's scan.
|
|
59
|
-
UseSmileIDVisionDocumentSessionHolder.shared.setCropRegion(cropRegionFrom(arguments))
|
|
60
|
-
|
|
61
|
-
guard let result = UseSmileIDVisionDocumentSessionHolder.shared.scanAndDrain(
|
|
62
|
-
image: uiImage,
|
|
63
|
-
rotation: rotation
|
|
64
|
-
) else {
|
|
65
|
-
return ["error": "session_not_configured"]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return result
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/// Build the `ViewportCropRegion` from the flat numeric crop args the JS
|
|
72
|
-
/// worklet supplies. Returns `nil` when `cropWidth <= 0` (the "no region"
|
|
73
|
-
/// signal for selfie / before the viewport is measured). Flat primitives
|
|
74
|
-
/// because frame-processor arguments don't reliably accept nested objects.
|
|
75
|
-
private func cropRegionFrom(_ arguments: [AnyHashable: Any]?) -> ViewportCropRegion? {
|
|
76
|
-
guard let width = (arguments?["cropWidth"] as? NSNumber)?.floatValue, width > 0 else {
|
|
77
|
-
return nil
|
|
78
|
-
}
|
|
79
|
-
return ViewportCropRegion(
|
|
80
|
-
left: (arguments?["cropLeft"] as? NSNumber)?.floatValue ?? 0,
|
|
81
|
-
top: (arguments?["cropTop"] as? NSNumber)?.floatValue ?? 0,
|
|
82
|
-
width: width,
|
|
83
|
-
height: (arguments?["cropHeight"] as? NSNumber)?.floatValue ?? 0,
|
|
84
|
-
viewportWidthPx: (arguments?["cropViewportWidth"] as? NSNumber)?.intValue ?? 0,
|
|
85
|
-
viewportHeightPx: (arguments?["cropViewportHeight"] as? NSNumber)?.intValue ?? 0,
|
|
86
|
-
contentScale: .crop
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
private extension UIImage.Orientation {
|
|
93
|
-
/// Fold the buffer's horizontal mirror into this orientation so rendering
|
|
94
|
-
/// undoes the flip with the rotation (.left ↔ .leftMirrored, etc.).
|
|
95
|
-
func composedWithHorizontalMirror() -> UIImage.Orientation {
|
|
96
|
-
switch self {
|
|
97
|
-
case .up: return .upMirrored
|
|
98
|
-
case .upMirrored: return .up
|
|
99
|
-
case .down: return .downMirrored
|
|
100
|
-
case .downMirrored: return .down
|
|
101
|
-
case .left: return .leftMirrored
|
|
102
|
-
case .leftMirrored: return .left
|
|
103
|
-
case .right: return .rightMirrored
|
|
104
|
-
case .rightMirrored: return .right
|
|
105
|
-
@unknown default: return self
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
private extension CIImage {
|
|
112
|
-
/// Rotate the sensor-natural (portrait) image onto the locked interface
|
|
113
|
-
/// (viewport) axis so the guide-rect crop lands on the right pixels and the
|
|
114
|
-
/// preview matches the capture. `degrees` is the interface orientation
|
|
115
|
-
/// (0/90/270). Directions are device-verified on iPhone — the opposite
|
|
116
|
-
/// assignment lands the document upside down.
|
|
117
|
-
func rotatedOntoViewportAxis(degrees: Int) -> CIImage {
|
|
118
|
-
let normalized = ((degrees % 360) + 360) % 360
|
|
119
|
-
switch normalized {
|
|
120
|
-
// Portrait document (0° interface): the rear camera's sensor-natural upright
|
|
121
|
-
// sits 180° from the portrait interface — the phone is held flat over the
|
|
122
|
-
// document — so the saved portrait document needs a half-turn. The guide
|
|
123
|
-
// rect is centred, so the half-turn leaves the crop aligned.
|
|
124
|
-
case 0: return oriented(.down)
|
|
125
|
-
case 90: return oriented(.left)
|
|
126
|
-
case 270: return oriented(.right)
|
|
127
|
-
default: return self
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private extension CGImagePropertyOrientation {
|
|
133
|
-
/// Case-for-case translation from `UIImage.Orientation` — the two
|
|
134
|
-
/// enums share semantics but not raw values, so a direct cast would
|
|
135
|
-
/// silently produce the wrong transform.
|
|
136
|
-
init(_ uiOrientation: UIImage.Orientation) {
|
|
137
|
-
switch uiOrientation {
|
|
138
|
-
case .up: self = .up
|
|
139
|
-
case .upMirrored: self = .upMirrored
|
|
140
|
-
case .down: self = .down
|
|
141
|
-
case .downMirrored: self = .downMirrored
|
|
142
|
-
case .left: self = .left
|
|
143
|
-
case .leftMirrored: self = .leftMirrored
|
|
144
|
-
case .right: self = .right
|
|
145
|
-
case .rightMirrored: self = .rightMirrored
|
|
146
|
-
@unknown default: self = .up
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,iEAAiE;AACjE,0DAA0D;AAC1D,qEAAqE;AACrE,2CAA2C;AAC3C,mEAAmE;AACnE,wEAAwE;AACxE,2EAA2E;AAC3E,EAAE;AACF,oDAAoD;AACpD,oEAAoE;AACpE,sEAAsE;AACtE,oEAAoE;AACpE,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE9B,yDAI8B;AAC9B,uCAAyB;AACzB,2CAA6B;AAE7B,2CAAsD;AACtD,mCAAuD;AAEvD,4DAA4D;AAC5D,uEAAuE;AACvE,+DAA+D;AAC/D,8BAA8B;AAC9B,MAAM,gBAAgB,GAAe;IACnC,GAAG,EAAE,0CAA0C;IAC/C,WAAW,EAAE;QACX,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,4CAA4C;KACtD;CACF,CAAC;AAEF,MAAM,UAAU,GAAG,8BAA8B,CAAC;AAClD,MAAM,YAAY,GAAG,CAAC,0BAA0B,EAAE,kBAAkB,CAAU,CAAC;AAC/E,MAAM,cAAc,GAAG,4BAA4B,CAAC;AAEpD,MAAM,qBAAqB,GAAiB,CAAC,MAAM,EAAE,EAAE;IACrD,mEAAmE;IACnE,mEAAmE;IACnE,wBAAwB;IACxB,MAAM,GAAG,IAAA,iCAAgB,EAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;QACJ,CAAC;QACD,IAAA,oBAAc,EAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,EAAE;YAClD,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,CAAC,GAAG,YAAY,CAAC;SAC5B,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,mEAAmE;IACnE,iEAAiE;IACjE,+DAA+D;IAC/D,oEAAoE;IACpE,MAAM,GAAG,IAAA,iCAAgB,EAAC,MAAM,EAAE;QAChC,KAAK;QACL,CAAC,MAAM,EAAE,EAAE;YACT,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAC3B,MAAM,CAAC,UAAU,CAAC,mBAAmB,EACrC,SAAS,CACV,CAAC;YACF,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM,IAAI,GAAG,IAAA,+BAAqB,EAAC,QAAQ,EAAE;gBAC3C,MAAM,EAAE,cAAc;gBACtB,OAAO,EAAE,gBAAgB;gBACzB,SAAS,EAAE,UAAU;gBACrB,QAAQ,EAAE,CAAC,GAAG,YAAY,CAAC;aAC5B,CAAC,CAAC;YACH,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACtC,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,kBAAe,qBAAqB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"podfile.js","sourceRoot":"","sources":["../../src/lib/podfile.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spm.js","sourceRoot":"","sources":["../../src/lib/spm.ts"],"names":[],"mappings":"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"}
|
package/plugin/src/index.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
// Expo config plugin that wires the Smile Identity Swift Package
|
|
2
|
-
// (`https://github.com/smileidentity/ios-spm`) into both:
|
|
3
|
-
// 1. The consuming app's Xcode project — so the .xcframeworks ship
|
|
4
|
-
// and embed in the final .app bundle.
|
|
5
|
-
// 2. The autogenerated Pods.xcodeproj at `pod install` time — so
|
|
6
|
-
// the Expo Module bridge (`UseSmileIDVisionDocumentExpo`) compiles
|
|
7
|
-
// with `import UseSmileIDVisionDocument` / `import UseSmileIDBridge`.
|
|
8
|
-
//
|
|
9
|
-
// Why a plugin: `expo-modules-autolinking@55.0.x`'s
|
|
10
|
-
// `RawModuleConfigApple` schema has no `dependencies` field, so the
|
|
11
|
-
// `apple.dependencies` block in `expo-module.config.json` is silently
|
|
12
|
-
// ignored. Without this plugin, neither the bridge nor the host app
|
|
13
|
-
// know about the SPM package.
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
ConfigPlugin,
|
|
17
|
-
withDangerousMod,
|
|
18
|
-
withXcodeProject,
|
|
19
|
-
} from "@expo/config-plugins";
|
|
20
|
-
import * as fs from "fs";
|
|
21
|
-
import * as path from "path";
|
|
22
|
-
|
|
23
|
-
import { injectPodfileSpmBlock } from "./lib/podfile";
|
|
24
|
-
import { linkSpmPackage, SpmPackage } from "./lib/spm";
|
|
25
|
-
|
|
26
|
-
// Pinned to the exact `12.0.0` release tag — `from: 12.0.0`
|
|
27
|
-
// would not resolve because `ios-spm` publishes pre-release tags (e.g.
|
|
28
|
-
// `12.0.0`), and SPM excludes pre-release tags from open-ended
|
|
29
|
-
// major-version requirements.
|
|
30
|
-
const SMILE_ID_PACKAGE: SpmPackage = {
|
|
31
|
-
url: "https://github.com/smileidentity/ios-spm",
|
|
32
|
-
requirement: {
|
|
33
|
-
kind: "exactVersion",
|
|
34
|
-
version: "12.0.1-SNAPSHOT.20260729180601.30478033861",
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const POD_TARGET = "UseSmileIDVisionDocumentExpo";
|
|
39
|
-
const SPM_PRODUCTS = ["UseSmileIDVisionDocument", "UseSmileIDBridge"] as const;
|
|
40
|
-
const PODFILE_MARKER = "usesmileid_vision_document";
|
|
41
|
-
|
|
42
|
-
const withVisionDocumentSpm: ConfigPlugin = (config) => {
|
|
43
|
-
// 1. Add the package + products to the host app's Xcode project so
|
|
44
|
-
// Xcode resolves the binary xcframeworks and embeds them in the
|
|
45
|
-
// .app at link time.
|
|
46
|
-
config = withXcodeProject(config, (config) => {
|
|
47
|
-
const appTarget = config.modRequest.projectName;
|
|
48
|
-
if (!appTarget) {
|
|
49
|
-
throw new Error(
|
|
50
|
-
"[usesmileid_vision_document] Unable to resolve host app native target name from Expo config.",
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
linkSpmPackage(config.modResults, SMILE_ID_PACKAGE, {
|
|
54
|
-
targetName: appTarget,
|
|
55
|
-
products: [...SPM_PRODUCTS],
|
|
56
|
-
});
|
|
57
|
-
return config;
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
// 2. Inject a Ruby block into the Podfile's post_install hook that
|
|
61
|
-
// re-applies the same wiring to Pods.xcodeproj when CocoaPods
|
|
62
|
-
// materializes it. The bridge pod target needs the products
|
|
63
|
-
// visible at compile time; the host-app step alone isn't enough.
|
|
64
|
-
config = withDangerousMod(config, [
|
|
65
|
-
"ios",
|
|
66
|
-
(config) => {
|
|
67
|
-
const podfilePath = path.join(
|
|
68
|
-
config.modRequest.platformProjectRoot,
|
|
69
|
-
"Podfile",
|
|
70
|
-
);
|
|
71
|
-
const original = fs.readFileSync(podfilePath, "utf-8");
|
|
72
|
-
const next = injectPodfileSpmBlock(original, {
|
|
73
|
-
marker: PODFILE_MARKER,
|
|
74
|
-
package: SMILE_ID_PACKAGE,
|
|
75
|
-
podTarget: POD_TARGET,
|
|
76
|
-
products: [...SPM_PRODUCTS],
|
|
77
|
-
});
|
|
78
|
-
if (next !== original) {
|
|
79
|
-
fs.writeFileSync(podfilePath, next);
|
|
80
|
-
}
|
|
81
|
-
return config;
|
|
82
|
-
},
|
|
83
|
-
]);
|
|
84
|
-
|
|
85
|
-
return config;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export default withVisionDocumentSpm;
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
// Injects an idempotent Ruby block into the Expo-generated Podfile's
|
|
2
|
-
// `post_install` hook. The block runs at `pod install` time and wires
|
|
3
|
-
// the Smile ID Swift Package into the autogenerated Pods.xcodeproj
|
|
4
|
-
// for a specific bridge pod target — Pods.xcodeproj only exists at
|
|
5
|
-
// pod-install time, so this is the only hook that can mutate it.
|
|
6
|
-
|
|
7
|
-
import type { SpmPackage, SpmRequirement } from "./spm";
|
|
8
|
-
|
|
9
|
-
const BEGIN_PREFIX = "# === BEGIN smileid-spm:";
|
|
10
|
-
const END_PREFIX = "# === END smileid-spm:";
|
|
11
|
-
|
|
12
|
-
export interface PodfileLinkOptions {
|
|
13
|
-
/** Marker key — distinct per bridge so each plugin owns its own block. */
|
|
14
|
-
marker: string;
|
|
15
|
-
package: SpmPackage;
|
|
16
|
-
/** Pod target name (e.g. `UseSmileIDVisionFaceExpo`). */
|
|
17
|
-
podTarget: string;
|
|
18
|
-
/** SPM library product names to link to the pod target. */
|
|
19
|
-
products: string[];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Idempotently injects an SPM-linking Ruby block into the Podfile's
|
|
24
|
-
* top-level `post_install` block. Re-running on an already-injected
|
|
25
|
-
* Podfile rewrites the same marker block in place (so version /
|
|
26
|
-
* product changes flow through cleanly on the next prebuild).
|
|
27
|
-
*/
|
|
28
|
-
export function injectPodfileSpmBlock(
|
|
29
|
-
podfile: string,
|
|
30
|
-
options: PodfileLinkOptions,
|
|
31
|
-
): string {
|
|
32
|
-
validateRubySafe(options);
|
|
33
|
-
|
|
34
|
-
const block = renderBlock(options);
|
|
35
|
-
const beginMarker = `${BEGIN_PREFIX} ${options.marker} ===`;
|
|
36
|
-
const endMarker = `${END_PREFIX} ${options.marker} ===`;
|
|
37
|
-
|
|
38
|
-
const blockRegex = new RegExp(
|
|
39
|
-
`${escapeRegExp(beginMarker)}[\\s\\S]*?${escapeRegExp(endMarker)}`,
|
|
40
|
-
"m",
|
|
41
|
-
);
|
|
42
|
-
if (blockRegex.test(podfile)) {
|
|
43
|
-
return podfile.replace(blockRegex, block);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Inject at the *start* of the post_install body — right after
|
|
47
|
-
// `post_install do |installer|`. We tried matching the closing
|
|
48
|
-
// `end` pair instead, but a second plugin running on a Podfile
|
|
49
|
-
// already mutated by the first sees a non-flat body and the
|
|
50
|
-
// non-greedy `end…end` match latches onto inner block ends,
|
|
51
|
-
// nesting the second injection inside the first. Anchoring on
|
|
52
|
-
// the opening line removes that failure mode entirely. Order
|
|
53
|
-
// relative to `react_native_post_install` doesn't matter because
|
|
54
|
-
// CocoaPods persists the Pods project at the end of pod install
|
|
55
|
-
// regardless of what we explicitly save mid-block.
|
|
56
|
-
const headerRegex = /(post_install\s+do\s*\|\s*installer\s*\|)\r?\n/;
|
|
57
|
-
const headerMatch = podfile.match(headerRegex);
|
|
58
|
-
if (!headerMatch || headerMatch.index === undefined) {
|
|
59
|
-
throw new Error(
|
|
60
|
-
"[smileid-spm] Could not locate `post_install do |installer|` in Podfile. " +
|
|
61
|
-
"Refusing to append a top-level post_install hook because CocoaPods only honors one — adding a second " +
|
|
62
|
-
"would silently override the React Native post-install plumbing. Restore the Expo Podfile template " +
|
|
63
|
-
"or wire the SPM block in manually.",
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
const insertAt = headerMatch.index + headerMatch[0].length;
|
|
67
|
-
const indented =
|
|
68
|
-
block
|
|
69
|
-
.split("\n")
|
|
70
|
-
.map((line) => (line.length > 0 ? ` ${line}` : line))
|
|
71
|
-
.join("\n") + "\n";
|
|
72
|
-
return podfile.slice(0, insertAt) + indented + podfile.slice(insertAt);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// All injected strings flow into single-quoted Ruby literals. We
|
|
76
|
-
// reject characters that could break out of those literals so a
|
|
77
|
-
// typo in the bridge plugin can't produce code that runs during
|
|
78
|
-
// `pod install`. Rejected: single-quote, backslash, control chars.
|
|
79
|
-
function validateRubySafe(options: PodfileLinkOptions): void {
|
|
80
|
-
const fields: Array<[string, string]> = [
|
|
81
|
-
["marker", options.marker],
|
|
82
|
-
["package.url", options.package.url],
|
|
83
|
-
["podTarget", options.podTarget],
|
|
84
|
-
];
|
|
85
|
-
for (const product of options.products) {
|
|
86
|
-
fields.push(["products[*]", product]);
|
|
87
|
-
}
|
|
88
|
-
switch (options.package.requirement.kind) {
|
|
89
|
-
case "upToNextMajorVersion":
|
|
90
|
-
case "upToNextMinorVersion":
|
|
91
|
-
fields.push([
|
|
92
|
-
"requirement.minimumVersion",
|
|
93
|
-
options.package.requirement.minimumVersion,
|
|
94
|
-
]);
|
|
95
|
-
break;
|
|
96
|
-
case "exactVersion":
|
|
97
|
-
fields.push(["requirement.version", options.package.requirement.version]);
|
|
98
|
-
break;
|
|
99
|
-
case "branch":
|
|
100
|
-
fields.push(["requirement.branch", options.package.requirement.branch]);
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
for (const [name, value] of fields) {
|
|
104
|
-
if (/['\\\n\r\t]/.test(value)) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
`[smileid-spm] Refusing to inject Podfile block: '${name}' contains an unsafe character (got: ${JSON.stringify(value)}).`,
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function renderBlock(options: PodfileLinkOptions): string {
|
|
113
|
-
const beginMarker = `${BEGIN_PREFIX} ${options.marker} ===`;
|
|
114
|
-
const endMarker = `${END_PREFIX} ${options.marker} ===`;
|
|
115
|
-
const requirement = renderRequirement(options.package.requirement);
|
|
116
|
-
const productList = options.products.map((p) => `'${p}'`).join(", ");
|
|
117
|
-
|
|
118
|
-
return `${beginMarker}
|
|
119
|
-
# Wires ${options.package.url} into Pods.xcodeproj and links its
|
|
120
|
-
# products to the '${options.podTarget}' pod target so the Swift
|
|
121
|
-
# bridge code can \`import\` them. Idempotent across pod installs.
|
|
122
|
-
#
|
|
123
|
-
# UUIDs are minted via SecureRandom rather than \`pods_project.new\`
|
|
124
|
-
# because \`prepare_react_native_project!\` sets
|
|
125
|
-
# \`:deterministic_uuids => false\`. With that flag off, CocoaPods
|
|
126
|
-
# skips its predictabilize step and \`stabilize_target_uuids\` resets
|
|
127
|
-
# \`@generated_uuids\` to a tiny leftover pool — so any post_install
|
|
128
|
-
# call to \`pods_project.new\` restarts the sequential index near 0
|
|
129
|
-
# and re-mints UUIDs already in use. The collision then runs through
|
|
130
|
-
# \`add_referrer\`, which clobbers \`objects_by_uuid[uuid]\` and
|
|
131
|
-
# leaves the rootObject (\`46EB2E00000000\`) unreachable, crashing
|
|
132
|
-
# Xcode 26 with \`XCSwiftPackageProductDependency
|
|
133
|
-
# _setSavedArchiveVersion:\` unrecognized selector. Random 24-char
|
|
134
|
-
# hex IDs can't collide with the 14-char cocoapods scheme.
|
|
135
|
-
begin
|
|
136
|
-
pods_project = installer.pods_project
|
|
137
|
-
spm_url = '${options.package.url}'
|
|
138
|
-
spm_requirement = ${requirement}
|
|
139
|
-
product_names = [${productList}]
|
|
140
|
-
target_name = '${options.podTarget}'
|
|
141
|
-
|
|
142
|
-
smileid_spm_safe_uuid = lambda do |project|
|
|
143
|
-
loop do
|
|
144
|
-
candidate = SecureRandom.hex(12).upcase
|
|
145
|
-
return candidate unless project.objects_by_uuid.key?(candidate)
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
pkg = pods_project.root_object.package_references.find do |r|
|
|
150
|
-
r.respond_to?(:repositoryURL) && r.repositoryURL == spm_url
|
|
151
|
-
end
|
|
152
|
-
unless pkg
|
|
153
|
-
pkg_uuid = smileid_spm_safe_uuid.call(pods_project)
|
|
154
|
-
pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new(pods_project, pkg_uuid)
|
|
155
|
-
pkg.initialize_defaults
|
|
156
|
-
pkg.repositoryURL = spm_url
|
|
157
|
-
pkg.requirement = spm_requirement
|
|
158
|
-
pods_project.root_object.package_references << pkg
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
target = pods_project.targets.find { |t| t.name == target_name }
|
|
162
|
-
if target.nil?
|
|
163
|
-
Pod::UI.warn "[smileid-spm] Pod target #{target_name} not found; skipping SPM link."
|
|
164
|
-
else
|
|
165
|
-
product_names.each do |product_name|
|
|
166
|
-
already = target.package_product_dependencies.any? do |d|
|
|
167
|
-
d.package == pkg && d.product_name == product_name
|
|
168
|
-
end
|
|
169
|
-
next if already
|
|
170
|
-
|
|
171
|
-
dep_uuid = smileid_spm_safe_uuid.call(pods_project)
|
|
172
|
-
dep = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new(pods_project, dep_uuid)
|
|
173
|
-
dep.initialize_defaults
|
|
174
|
-
dep.package = pkg
|
|
175
|
-
dep.product_name = product_name
|
|
176
|
-
target.package_product_dependencies << dep
|
|
177
|
-
|
|
178
|
-
bf_uuid = smileid_spm_safe_uuid.call(pods_project)
|
|
179
|
-
bf = Xcodeproj::Project::Object::PBXBuildFile.new(pods_project, bf_uuid)
|
|
180
|
-
bf.initialize_defaults
|
|
181
|
-
bf.product_ref = dep
|
|
182
|
-
target.frameworks_build_phase.files << bf
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
pods_project.save
|
|
187
|
-
rescue => e
|
|
188
|
-
Pod::UI.warn "[smileid-spm] Failed to link SPM products for ${options.podTarget}: #{e.message}"
|
|
189
|
-
raise
|
|
190
|
-
end
|
|
191
|
-
${endMarker}`;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function renderRequirement(req: SpmRequirement): string {
|
|
195
|
-
switch (req.kind) {
|
|
196
|
-
case "upToNextMajorVersion":
|
|
197
|
-
return `{ kind: 'upToNextMajorVersion', minimumVersion: '${req.minimumVersion}' }`;
|
|
198
|
-
case "upToNextMinorVersion":
|
|
199
|
-
return `{ kind: 'upToNextMinorVersion', minimumVersion: '${req.minimumVersion}' }`;
|
|
200
|
-
case "exactVersion":
|
|
201
|
-
return `{ kind: 'exactVersion', version: '${req.version}' }`;
|
|
202
|
-
case "branch":
|
|
203
|
-
return `{ kind: 'branch', branch: '${req.branch}' }`;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function escapeRegExp(s: string): string {
|
|
208
|
-
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
209
|
-
}
|