@smileid/usesmileid_vision_document 12.3.1-SNAPSHOT.52 → 12.3.1-SNAPSHOT.62

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.
@@ -136,11 +136,15 @@ final class UseSmileIDVisionDocumentSessionHolder {
136
136
  let nativeOutput = scanResult.output as? UseSmileIDBridge.DocumentDetectorOutput
137
137
  let state = scanResult.state
138
138
  let events = currentSession.drainCaptureReadyEvents()
139
- resultBox.value = [
139
+ var wire: [String: Any] = [
140
140
  "output": nativeOutput?.toWireMap() ?? (["documents": [], "brightness": 0.0] as [String: Any]),
141
141
  "state": state.toWireMap(),
142
142
  "capturedEvents": events.map { $0.toWireMap() }
143
143
  ]
144
+ if let waived = scanResult.qualityWaived {
145
+ wire["qualityWaived"] = waived
146
+ }
147
+ resultBox.value = wire
144
148
  semaphore.signal()
145
149
  }
146
150
  semaphore.wait()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smileid/usesmileid_vision_document",
3
- "version": "12.3.1-SNAPSHOT.52",
3
+ "version": "12.3.1-SNAPSHOT.62",
4
4
  "description": "Apple Vision document detection implementation for the UseSmileID React Native (Expo) SDK.",
5
5
  "homepage": "https://usesmileid.com",
6
6
  "repository": {
@@ -46,8 +46,8 @@
46
46
  "CHANGELOG.md"
47
47
  ],
48
48
  "dependencies": {
49
- "@smileid/usesmileid_bridge": "12.3.1-SNAPSHOT.52",
50
- "@smileid/usesmileid_platform_interface": "12.3.1-SNAPSHOT.52"
49
+ "@smileid/usesmileid_bridge": "12.3.1-SNAPSHOT.62",
50
+ "@smileid/usesmileid_platform_interface": "12.3.1-SNAPSHOT.62"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "expo": ">=56.0.0",
@@ -57,10 +57,9 @@
57
57
  "devDependencies": {
58
58
  "@types/node": "^26.6.4",
59
59
  "expo": "~57.0.26",
60
- "expo-modules-core": "^57.0.21",
60
+ "expo-modules-core": "^57.0.23",
61
61
  "react-native": "^0.86.3",
62
- "typescript": "^6.0.3",
63
- "xcode": "^3.0.1"
62
+ "typescript": "^6.0.3"
64
63
  },
65
64
  "publishConfig": {
66
65
  "access": "public"
@@ -1,12 +1,5 @@
1
- import { ConfigPlugin } from "expo/config-plugins";
2
- export interface VisionDocumentOptions {
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
- }
1
+ import { type SmileIDSpmOptions } from "@smileid/usesmileid_bridge/plugin";
2
+ export type VisionDocumentOptions = SmileIDSpmOptions;
10
3
  export declare const SPM_PRODUCTS: readonly ["UseSmileIDVisionDocument"];
11
- declare const withVisionDocumentSpm: ConfigPlugin<VisionDocumentOptions | void>;
12
- export default withVisionDocumentSpm;
4
+ declare const _default: import("@expo/config-plugins").ConfigPlugin<void | SmileIDSpmOptions>;
5
+ export default _default;
@@ -1 +1 @@
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.3.0"}},POD_TARGET="UseSmileIDVisionDocumentExpo";exports.SPM_PRODUCTS=["UseSmileIDVisionDocument"];const PODFILE_MARKER="usesmileid_vision_document",BRIDGE_POD_TARGET="UseSmileIDBridgeExpo",BRIDGE_SPM_PRODUCTS=["UseSmileIDBridge"],BRIDGE_PODFILE_MARKER="usesmileid_bridge",withVisionDocumentSpm=(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_document] 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.injectPodfileNjiaLinkBlock)(n),n=(0,podfile_1.injectPodfileSignatureDedupBlock)(n),n!==o&&fs.writeFileSync(e,n),t}]),i);exports.default=withVisionDocumentSpm;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SPM_PRODUCTS=void 0;const plugin_1=require("@smileid/usesmileid_bridge/plugin");exports.SPM_PRODUCTS=["UseSmileIDVisionDocument"],exports.default=(0,plugin_1.withSmileIDSpm)({packageName:"usesmileid_vision_document",podTarget:"UseSmileIDVisionDocumentExpo",products:exports.SPM_PRODUCTS});
@@ -1,5 +0,0 @@
1
- import { type ConfigPlugin } from "expo/config-plugins";
2
- /** Sets `ios.deploymentTarget` to `minimum` unless the project already asks for a higher one. */
3
- export declare const withIosDeploymentTargetFloor: ConfigPlugin<string>;
4
- /** Pure form of the edit the plugin makes to the Podfile properties. */
5
- export declare function raiseDeploymentTarget(properties: Readonly<Record<string, string>>, minimum: string): Record<string, string>;
@@ -1 +0,0 @@
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}
@@ -1,42 +0,0 @@
1
- import type { SpmPackage } from "./spm";
2
- export interface PodfileLinkOptions {
3
- /** Marker key — distinct per bridge so each plugin owns its own block. */
4
- marker: string;
5
- package: SpmPackage;
6
- /** Pod target name (e.g. `UseSmileIDVisionFaceExpo`). */
7
- podTarget: string;
8
- /** SPM library product names to link to the pod target. */
9
- products: string[];
10
- /** Fail `pod install` when the target is absent — a warning there reads as success. */
11
- required?: boolean;
12
- }
13
- /**
14
- * Idempotently injects an SPM-linking Ruby block into the Podfile's
15
- * top-level `post_install` block. Re-running on an already-injected
16
- * Podfile rewrites the same marker block in place (so version /
17
- * product changes flow through cleanly on the next prebuild).
18
- */
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
- * Links njia-spm's `Njia` product into the `njia-rn` pod target with the helper
31
- * `@smileid/njia` ships. The SDK's flows route through njia's native engine, which that
32
- * pod hosts. The helper pins njia-spm at the installed package's own version, lists the
33
- * package on the app's own project, and links Njia into its app targets, so Xcode
34
- * resolves the package and embeds the dynamic framework. Idempotent per marker.
35
- */
36
- export declare function injectPodfileNjiaLinkBlock(podfile: string): string;
37
- /**
38
- * Adds the archive signature-dedup phase to the app target of the user's own
39
- * project — the path for apps whose `ios/` is hand-maintained, where no config
40
- * plugin runs. Guarded by phase name, so an app on both paths gets one.
41
- */
42
- export declare function injectPodfileSignatureDedupBlock(podfile: string): string;
@@ -1,260 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.injectPodfileSpmBlock=injectPodfileSpmBlock,exports.injectPodfileKameraLinkBlock=injectPodfileKameraLinkBlock,exports.injectPodfileNjiaLinkBlock=injectPodfileNjiaLinkBlock,exports.injectPodfileSignatureDedupBlock=injectPodfileSignatureDedupBlock;const signature_dedup_1=require("./signature_dedup"),BEGIN_PREFIX="# === BEGIN smileid-spm:",END_PREFIX="# === END smileid-spm:",SIGNATURE_DEDUP_MARKER="usesmileid_signature_dedup",KAMERA_LINK_MARKER="kamera_spm",NJIA_LINK_MARKER="njia_spm";function injectPodfileSpmBlock(e,r){return validateRubySafe(r),injectMarkerBlock(e,r.marker,renderBlock(r))}function injectPodfileKameraLinkBlock(e){return injectMarkerBlock(e,KAMERA_LINK_MARKER,renderKameraLinkBlock())}function injectPodfileNjiaLinkBlock(e){return injectMarkerBlock(e,NJIA_LINK_MARKER,renderNjiaLinkBlock())}function injectPodfileSignatureDedupBlock(e){return injectMarkerBlock(e,SIGNATURE_DEDUP_MARKER,renderSignatureDedupBlock())}function injectMarkerBlock(e,r,a){const t=`${BEGIN_PREFIX} ${r} ===`,o=`${END_PREFIX} ${r} ===`,s=new RegExp(`([ \\t]*)${escapeRegExp(t)}[\\s\\S]*?${escapeRegExp(o)}`,"m"),i=e.match(s);if(i)return e.replace(s,()=>indentBlock(a,i[1]??""));const p=/(post_install\s+do\s*\|\s*installer\s*\|)\r?\n/,n=e.match(p);if(!n||n.index===void 0)throw new Error("[smileid-spm] Could not locate `post_install do |installer|` in Podfile. Refusing to append a top-level post_install hook because CocoaPods only honors one \u2014 adding a second would silently override the React Native post-install plumbing. Restore the Expo Podfile template or wire the SPM block in manually.");const d=n.index+n[0].length,c=`${indentBlock(a," ")}
2
- `;return e.slice(0,d)+c+e.slice(d)}function indentBlock(e,r){return e.split(`
3
- `).map(a=>a.length>0?`${r}${a}`:a).join(`
4
- `)}function validateRubySafe(e){const r=[["marker",e.marker],["package.url",e.package.url],["podTarget",e.podTarget]];for(const a of e.products)r.push(["products[*]",a]);switch(e.package.requirement.kind){case"upToNextMajorVersion":case"upToNextMinorVersion":r.push(["requirement.minimumVersion",e.package.requirement.minimumVersion]);break;case"exactVersion":r.push(["requirement.version",e.package.requirement.version]);break;case"branch":r.push(["requirement.branch",e.package.requirement.branch]);break}for(const[a,t]of r)if(/['"#\\\n\r\t]/.test(t))throw new Error(`[smileid-spm] Refusing to inject Podfile block: '${a}' contains an unsafe character (got: ${JSON.stringify(t)}).`)}function renderBlock(e){const r=`${BEGIN_PREFIX} ${e.marker} ===`,a=`${END_PREFIX} ${e.marker} ===`,t=renderRequirement(e.package.requirement),o=e.products.map(i=>`'${i}'`).join(", "),s=e.required?`raise "[smileid-spm] Pod target #{target_name} is missing from Pods.xcodeproj, so #{product_names.join(', ')} cannot be linked and the Smile ID bridge will not compile. Check that '@smileid/usesmileid_bridge' is installed and that its npm package ships its 'ios' directory."`:'Pod::UI.warn "[smileid-spm] Pod target #{target_name} not found; skipping SPM link."';return`${r}
5
- # Wires ${e.package.url} into Pods.xcodeproj and links its
6
- # products to the '${e.podTarget}' pod target so the Swift
7
- # bridge code can \`import\` them. Idempotent across pod installs.
8
- #
9
- # UUIDs are minted via SecureRandom rather than \`pods_project.new\`
10
- # because \`prepare_react_native_project!\` sets
11
- # \`:deterministic_uuids => false\`. With that flag off, CocoaPods
12
- # skips its predictabilize step and \`stabilize_target_uuids\` resets
13
- # \`@generated_uuids\` to a tiny leftover pool \u2014 so any post_install
14
- # call to \`pods_project.new\` restarts the sequential index near 0
15
- # and re-mints UUIDs already in use. The collision then runs through
16
- # \`add_referrer\`, which clobbers \`objects_by_uuid[uuid]\` and
17
- # leaves the rootObject (\`46EB2E00000000\`) unreachable, crashing
18
- # Xcode 26 with \`XCSwiftPackageProductDependency
19
- # _setSavedArchiveVersion:\` unrecognized selector. Random 24-char
20
- # hex IDs can't collide with the 14-char cocoapods scheme.
21
- begin
22
- pods_project = installer.pods_project
23
- spm_url = '${e.package.url}'
24
- spm_requirement = ${t}
25
- product_names = [${o}]
26
- target_name = '${e.podTarget}'
27
-
28
- smileid_spm_safe_uuid = lambda do |project|
29
- loop do
30
- candidate = SecureRandom.hex(12).upcase
31
- return candidate unless project.objects_by_uuid.key?(candidate)
32
- end
33
- end
34
-
35
- pkg = pods_project.root_object.package_references.find do |r|
36
- r.respond_to?(:repositoryURL) && r.repositoryURL == spm_url
37
- end
38
- unless pkg
39
- pkg_uuid = smileid_spm_safe_uuid.call(pods_project)
40
- pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new(pods_project, pkg_uuid)
41
- pkg.initialize_defaults
42
- pkg.repositoryURL = spm_url
43
- pkg.requirement = spm_requirement
44
- pods_project.root_object.package_references << pkg
45
- end
46
-
47
- target = pods_project.targets.find { |t| t.name == target_name }
48
- if target.nil?
49
- ${s}
50
- else
51
- product_names.each do |product_name|
52
- already = target.package_product_dependencies.any? do |d|
53
- d.package == pkg && d.product_name == product_name
54
- end
55
- next if already
56
-
57
- dep_uuid = smileid_spm_safe_uuid.call(pods_project)
58
- dep = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new(pods_project, dep_uuid)
59
- dep.initialize_defaults
60
- dep.package = pkg
61
- dep.product_name = product_name
62
- target.package_product_dependencies << dep
63
-
64
- bf_uuid = smileid_spm_safe_uuid.call(pods_project)
65
- bf = Xcodeproj::Project::Object::PBXBuildFile.new(pods_project, bf_uuid)
66
- bf.initialize_defaults
67
- bf.product_ref = dep
68
- target.frameworks_build_phase.files << bf
69
- end
70
-
71
- # Every linking static pod absorbs ios-spm's source-target objects and the
72
- # app's -ObjC link then sees duplicates \u2014 the app keeps the single copy.
73
- strip_name = '[smileid-spm] Strip absorbed SPM source objects'
74
- unless target.shell_script_build_phases.any? { |p| p.name == strip_name }
75
- # \`new_shell_script_build_phase\` mints through \`pods_project.new\`, whose
76
- # reset index (see above) hands out 46EB2E00000000 \u2014 the rootObject's own
77
- # UUID \u2014 and the overwrite makes Xcode reject the project as damaged.
78
- phase_uuid = smileid_spm_safe_uuid.call(pods_project)
79
- phase = Xcodeproj::Project::Object::PBXShellScriptBuildPhase.new(pods_project, phase_uuid)
80
- phase.initialize_defaults
81
- phase.name = strip_name
82
- target.build_phases << phase
83
- phase.shell_script = <<~'STRIPSH'
84
- set -u
85
- A="\${TARGET_BUILD_DIR}/\${EXECUTABLE_PATH}"
86
- [ -f "$A" ] || exit 0
87
- strip_obj() {
88
- ar -t "$1" 2>/dev/null | grep -q "^$2$" || return 0
89
- ar -d "$1" "$2" && ranlib "$1" 2>/dev/null || true
90
- }
91
- ARCHS_IN=$(lipo -archs "$A" 2>/dev/null || true)
92
- for OBJ in UseSmileIDSentrySupport.o UseSmileIDLottieSupport.o UseSmileIDKameraSupport.o; do
93
- if [ "$(echo "$ARCHS_IN" | wc -w)" -gt 1 ]; then
94
- THIN=""
95
- for ARCH in $ARCHS_IN; do
96
- lipo -thin "$ARCH" "$A" -output "$A.$ARCH"
97
- strip_obj "$A.$ARCH" "$OBJ"
98
- THIN="$THIN $A.$ARCH"
99
- done
100
- lipo -create $THIN -output "$A"
101
- rm -f $THIN
102
- else
103
- strip_obj "$A" "$OBJ"
104
- fi
105
- done
106
- STRIPSH
107
- end
108
- end
109
-
110
- pods_project.save
111
- rescue => e
112
- Pod::UI.warn "[smileid-spm] Failed to link SPM products for ${e.podTarget}: #{e.message}"
113
- raise
114
- end
115
- ${a}`}function renderKameraLinkBlock(){return`${BEGIN_PREFIX} ${KAMERA_LINK_MARKER} ===
116
- # Links kamera-spm's Kamera / KameraVision products into the kamera-rn pod target (and
117
- # KameraTesting into kamera-testing when present) with the helper @smileid/kamera ships,
118
- # pinned at the installed package's own version. The Smile ID SDK binaries link
119
- # Kamera.framework dynamically and ios-spm declares kamera-spm for the app, so the pod
120
- # must take Kamera from that same package rather than vendor a second copy.
121
- require 'json'
122
- require 'securerandom'
123
- begin
124
- kamera_package_json = \`node --print "const p=require('path');let d=[process.cwd()];try{d.unshift(p.dirname(require.resolve('@smileid/usesmileid')))}catch(e){}require.resolve('@smileid/kamera/package.json',{paths:d})"\`.strip
125
- if kamera_package_json.empty?
126
- raise "[smileid-spm] @smileid/kamera is not installed, so its kamera-rn pod cannot be linked to kamera-spm."
127
- end
128
- kamera_spm_helper = File.join(File.dirname(kamera_package_json), 'ios', 'kamera_spm_link.rb')
129
- if File.exist?(kamera_spm_helper)
130
- require kamera_spm_helper
131
- # The Smile ID provider pods import Kamera themselves. A SwiftPM product linked into the
132
- # kamera-rn target does not reach the pods that depend on it the way a vendored framework's
133
- # search path did, so those targets take the product directly (absent ones are skipped).
134
- kamera_spm_link!(installer, targets: KAMERA_SPM_TARGETS.merge(
135
- 'UseSmileIDVisionFaceExpo' => %w[Kamera],
136
- 'UseSmileIDVisionDocumentExpo' => %w[Kamera],
137
- ))
138
- # Two things only the app's own project can do, exactly as it does for ios-spm:
139
- # 1. CocoaPods rewrites the Pods project after post_install and drops the package
140
- # references the helper attaches to it (the product dependencies survive), so Xcode
141
- # resolves kamera-spm only if a project in the workspace still lists it \u2014 otherwise
142
- # the build stops at "Missing package product 'Kamera'".
143
- # 2. Kamera and KameraVision are dynamic frameworks. Linked into static pod targets they
144
- # are never embedded, and the app dies in dyld ("Library not loaded:
145
- # @rpath/Kamera.framework/Kamera"). Xcode embeds a binary product only for an app
146
- # target that depends on it, so the app target takes both products directly.
147
- kamera_spm_url = 'https://github.com/smileidentity/kamera-spm'
148
- kamera_spm_version = JSON.parse(File.read(kamera_package_json))['version'].sub(/-SNAPSHOT$/, '')
149
- kamera_spm_app_products = %w[Kamera KameraVision]
150
- # A reference an app added by hand may spell the same repository differently (.git suffix,
151
- # trailing slash, case); a second reference to one repository fails Xcode's resolution.
152
- normalize_url = ->(url) { url.to_s.downcase.chomp('/').sub(/\\.git\\z/, '') }
153
- installer.aggregate_targets.group_by(&:user_project).each do |user_project, aggregate_targets|
154
- next if user_project.nil? # integrate_targets: false \u2014 nothing to register on
155
- # SecureRandom, not user_project.new: React Native's prepare_react_native_project!
156
- # leaves Xcodeproj's UUID pool unusable for objects minted in post_install.
157
- new_uuid = lambda do
158
- loop do
159
- candidate = SecureRandom.hex(12).upcase
160
- break candidate unless user_project.objects_by_uuid.key?(candidate)
161
- end
162
- end
163
- changed = false
164
- ref = user_project.root_object.package_references.find do |r|
165
- r.respond_to?(:repositoryURL) && normalize_url.call(r.repositoryURL) == normalize_url.call(kamera_spm_url)
166
- end
167
- unless ref
168
- ref = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new(user_project, new_uuid.call)
169
- ref.initialize_defaults
170
- ref.repositoryURL = kamera_spm_url
171
- user_project.root_object.package_references << ref
172
- changed = true
173
- end
174
- requirement = { 'kind' => 'exactVersion', 'version' => kamera_spm_version }
175
- if ref.requirement != requirement
176
- ref.requirement = requirement
177
- changed = true
178
- end
179
- app_targets = aggregate_targets.flat_map(&:user_targets).uniq.select do |t|
180
- t.respond_to?(:product_type) && t.product_type == 'com.apple.product-type.application'
181
- end
182
- app_targets.each do |app_target|
183
- kamera_spm_app_products.each do |product_name|
184
- next if app_target.package_product_dependencies.any? { |d| d.package == ref && d.product_name == product_name }
185
- dep = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new(user_project, new_uuid.call)
186
- dep.initialize_defaults
187
- dep.package = ref
188
- dep.product_name = product_name
189
- app_target.package_product_dependencies << dep
190
- build_file = Xcodeproj::Project::Object::PBXBuildFile.new(user_project, new_uuid.call)
191
- build_file.initialize_defaults
192
- build_file.product_ref = dep
193
- app_target.frameworks_build_phase.files << build_file
194
- changed = true
195
- end
196
- end
197
- next unless changed
198
- user_project.save
199
- Pod::UI.puts "[smileid-spm] #{File.basename(user_project.path)}: #{app_targets.map(&:name).join(', ')} link kamera-spm #{kamera_spm_version} (#{kamera_spm_app_products.join(', ')}) so Xcode resolves and embeds it"
200
- end
201
- else
202
- # Releases before the helper vendor Kamera.xcframework themselves, so the pod still
203
- # compiles; but the app then embeds that copy next to the one ios-spm resolves.
204
- Pod::UI.warn "[smileid-spm] @smileid/kamera at #{File.dirname(kamera_package_json)} ships no ios/kamera_spm_link.rb " \\
205
- "(it still vendors Kamera.xcframework). Upgrade to a release that depends on kamera-spm so the app carries one Kamera.framework."
206
- end
207
- rescue => e
208
- Pod::UI.warn "[smileid-spm] Failed to link kamera-spm into the kamera pods: #{e.message}"
209
- raise
210
- end
211
- ${END_PREFIX} ${KAMERA_LINK_MARKER} ===`}function renderNjiaLinkBlock(){return`${BEGIN_PREFIX} ${NJIA_LINK_MARKER} ===
212
- # The SDK's flows route through njia's native engine. Links njia-spm's Njia product into the
213
- # njia-rn pod, and into the app so Xcode embeds the framework, with the helper @smileid/njia
214
- # ships, pinned at the installed package's own version.
215
- njia_package_json = \`node --print "const p=require('path');let d=[process.cwd()];try{d.unshift(p.dirname(require.resolve('@smileid/usesmileid')))}catch(e){}require.resolve('@smileid/njia/package.json',{paths:d})"\`.strip
216
- if njia_package_json.empty?
217
- raise "[smileid-spm] @smileid/njia is not installed, so the njia-rn pod cannot be linked to njia-spm."
218
- end
219
- require File.join(File.dirname(njia_package_json), 'ios', 'njia_spm_link.rb')
220
- njia_spm_link!(installer)
221
- ${END_PREFIX} ${NJIA_LINK_MARKER} ===`}function renderSignatureDedupBlock(){return`${BEGIN_PREFIX} ${SIGNATURE_DEDUP_MARKER} ===
222
- # For apps whose \`ios/\` is hand-maintained, so no config plugin ever runs.
223
- # UUIDs come from SecureRandom for the same reason as above.
224
- begin
225
- dedup_name = '${signature_dedup_1.SIGNATURE_DEDUP_PHASE_NAME}'
226
- smileid_dedup_safe_uuid = lambda do |project|
227
- loop do
228
- candidate = SecureRandom.hex(12).upcase
229
- return candidate unless project.objects_by_uuid.key?(candidate)
230
- end
231
- end
232
-
233
- installer.aggregate_targets.each do |aggregate_target|
234
- user_project = aggregate_target.user_project
235
- next unless user_project
236
-
237
- added = false
238
- aggregate_target.user_targets.each do |user_target|
239
- next if user_target.shell_script_build_phases.any? { |p| p.name == dedup_name }
240
-
241
- phase = Xcodeproj::Project::Object::PBXShellScriptBuildPhase.new(
242
- user_project, smileid_dedup_safe_uuid.call(user_project)
243
- )
244
- phase.initialize_defaults
245
- phase.name = dedup_name
246
- phase.always_out_of_date = '1'
247
- phase.shell_script = <<~'SMILEIDDEDUP'
248
- ${indentBlock(signature_dedup_1.SIGNATURE_DEDUP_SCRIPT," ")}
249
- SMILEIDDEDUP
250
- user_target.build_phases << phase
251
- added = true
252
- end
253
-
254
- user_project.save if added
255
- end
256
- rescue => e
257
- Pod::UI.warn "[smileid-spm] Failed to add the XCFramework signature dedup phase: #{e.message}"
258
- raise
259
- end
260
- ${END_PREFIX} ${SIGNATURE_DEDUP_MARKER} ===`}function renderRequirement(e){switch(e.kind){case"upToNextMajorVersion":return`{ kind: 'upToNextMajorVersion', minimumVersion: '${e.minimumVersion}' }`;case"upToNextMinorVersion":return`{ kind: 'upToNextMinorVersion', minimumVersion: '${e.minimumVersion}' }`;case"exactVersion":return`{ kind: 'exactVersion', version: '${e.version}' }`;case"branch":return`{ kind: 'branch', branch: '${e.branch}' }`}}function escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}
@@ -1,14 +0,0 @@
1
- import { XcodeProject } from "expo/config-plugins";
2
- export declare const SIGNATURE_DEDUP_PHASE_NAME = "[smileid-spm] Dedupe XCFramework signatures";
3
- export declare const SIGNATURE_DEDUP_SCRIPT: string;
4
- /**
5
- * Appends the dedup phase, idempotently by name so both vision plugins and
6
- * repeated prebuilds converge on one. It goes last because every pod target
7
- * must have staged its signatures before it runs.
8
- */
9
- export declare function ensureSignatureDedupPhase(project: XcodeProject, targetName: string): void;
10
- /**
11
- * Stops Xcode recording XCFramework signatures at all — the escape hatch behind
12
- * `iosSignatureAggregation: "disabled"`.
13
- */
14
- export declare function disableSignatureAggregation(project: XcodeProject, targetName: string): void;
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.SIGNATURE_DEDUP_SCRIPT=exports.SIGNATURE_DEDUP_PHASE_NAME=void 0,exports.ensureSignatureDedupPhase=ensureSignatureDedupPhase,exports.disableSignatureAggregation=disableSignatureAggregation;const spm_1=require("./spm");exports.SIGNATURE_DEDUP_PHASE_NAME="[smileid-spm] Dedupe XCFramework signatures",exports.SIGNATURE_DEDUP_SCRIPT=["# Archive assembly sweeps staged *.signature files into one filename-keyed","# folder and aborts on the first duplicate; keep exactly one per name.","set -u",'case "${BUILT_PRODUCTS_DIR:-}" in'," */ArchiveIntermediates/*) ;;"," *) exit 0 ;;","esac",'seen=" "','for sig in "${BUILT_PRODUCTS_DIR}"/*/*.xcframework-*.signature; do',' [ -e "$sig" ] || continue',' name=$(basename "$sig")',' if [ -e "${BUILT_PRODUCTS_DIR}/${name}" ]; then',' rm -rf "$sig"'," else",' case "$seen" in',' *" ${name} "*) rm -rf "$sig" ;;',' *) seen="${seen}${name} " ;;'," esac"," fi","done","exit 0"].join(`
2
- `);function ensureSignatureDedupPhase(e,i){const s=(0,spm_1.findNativeTarget)(e,i);if(!s)throw new Error(`[smileid-spm] Native target '${i}' not found in Xcode project.`);const t=(0,spm_1.section)(e,"PBXShellScriptBuildPhase");if(s.obj.buildPhases.some(n=>{const o=t[n.value];return o!==void 0&&typeof o=="object"&&o!==null&&o.name?.replace(/^"|"$/g,"")===exports.SIGNATURE_DEDUP_PHASE_NAME}))return;const r=(0,spm_1.generateUuid)(e);t[r]={isa:"PBXShellScriptBuildPhase",name:`"${exports.SIGNATURE_DEDUP_PHASE_NAME}"`,shellPath:"/bin/sh",shellScript:JSON.stringify(exports.SIGNATURE_DEDUP_SCRIPT),alwaysOutOfDate:"1",buildActionMask:"2147483647",files:[],inputPaths:[],outputPaths:[],runOnlyForDeploymentPostprocessing:"0"},t[`${r}_comment`]=exports.SIGNATURE_DEDUP_PHASE_NAME,s.obj.buildPhases.push({value:r,comment:exports.SIGNATURE_DEDUP_PHASE_NAME})}function disableSignatureAggregation(e,i){const s=(0,spm_1.findNativeTarget)(e,i);if(!s)throw new Error(`[smileid-spm] Native target '${i}' not found in Xcode project.`);const t=s.obj.buildConfigurationList;if(!t)throw new Error(`[smileid-spm] Native target '${i}' has no build configuration list.`);const u=(0,spm_1.section)(e,"XCConfigurationList"),r=(0,spm_1.section)(e,"XCBuildConfiguration"),n=u[t];if(!n||typeof n!="object"||!n.buildConfigurations)throw new Error(`[smileid-spm] Build configuration list for '${i}' is unreadable.`);for(const o of n.buildConfigurations){const a=r[o.value];!a||typeof a!="object"||(a.buildSettings??={},a.buildSettings.ENABLE_SIGNATURE_AGGREGATION="NO")}}
@@ -1,54 +0,0 @@
1
- import { XcodeProject } from "expo/config-plugins";
2
- export interface SpmPackage {
3
- /** Remote git URL of the Swift Package, e.g. `https://github.com/smileidentity/ios-spm`. */
4
- url: string;
5
- /** Version requirement; mirrors Xcode's package resolution UI. */
6
- requirement: SpmRequirement;
7
- }
8
- export type SpmRequirement = {
9
- kind: "upToNextMajorVersion";
10
- minimumVersion: string;
11
- } | {
12
- kind: "upToNextMinorVersion";
13
- minimumVersion: string;
14
- } | {
15
- kind: "exactVersion";
16
- version: string;
17
- } | {
18
- kind: "branch";
19
- branch: string;
20
- };
21
- export interface SpmTargetLink {
22
- /** Native target name in the project (app target or pod target). */
23
- targetName: string;
24
- /** SPM library product names to attach to the target. */
25
- products: string[];
26
- }
27
- /**
28
- * Adds (or reuses) a remote Swift Package reference on the given
29
- * Xcode project and links the requested products to the target.
30
- * Idempotent: existing package refs and product deps are reused so
31
- * multiple plugins can compose without conflict.
32
- */
33
- export declare function linkSpmPackage(project: XcodeProject, pkg: SpmPackage, link: SpmTargetLink): void;
34
- export interface NativeTarget {
35
- uuid: string;
36
- obj: PbxNativeTarget;
37
- }
38
- interface PbxNativeTarget {
39
- isa: "PBXNativeTarget";
40
- name: string;
41
- packageProductDependencies?: Array<{
42
- value: string;
43
- comment?: string;
44
- }>;
45
- buildPhases: Array<{
46
- value: string;
47
- comment?: string;
48
- }>;
49
- buildConfigurationList?: string;
50
- }
51
- export declare function section<T>(project: XcodeProject, isa: string): Record<string, T>;
52
- export declare function generateUuid(project: XcodeProject): string;
53
- export declare function findNativeTarget(project: XcodeProject, name: string): NativeTarget | undefined;
54
- export {};
@@ -1 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.linkSpmPackage=linkSpmPackage,exports.section=section,exports.generateUuid=generateUuid,exports.findNativeTarget=findNativeTarget;function linkSpmPackage(e,n,o){const t=upsertPackageReference(e,n),i=findNativeTarget(e,o.targetName);if(!i)throw new Error(`[smileid-spm] Native target '${o.targetName}' not found in Xcode project.`);for(const c of o.products)upsertProductDependency(e,i.uuid,t,c)}function objects(e){return e.hash.project.objects}function section(e,n){const o=objects(e);return o[n]||(o[n]={}),o[n]}function generateUuid(e){return e.generateUuid()}function upsertPackageReference(e,n){const o=section(e,"XCRemoteSwiftPackageReference");for(const[c,r]of Object.entries(o))if(!c.endsWith("_comment")&&!(typeof r!="object"||r===null)&&r.repositoryURL?.replace(/^"|"$/g,"")===n.url)return{uuid:c};const t=generateUuid(e);o[t]={isa:"XCRemoteSwiftPackageReference",repositoryURL:`"${n.url}"`,requirement:serializeRequirement(n.requirement)},o[`${t}_comment`]=`XCRemoteSwiftPackageReference "${repoName(n.url)}"`;const i=section(e,"PBXProject");for(const[c,r]of Object.entries(i))c.endsWith("_comment")||typeof r!="object"||r===null||r.isa==="PBXProject"&&(r.packageReferences??=[],r.packageReferences.some(s=>s.value===t)||r.packageReferences.push({value:t,comment:`XCRemoteSwiftPackageReference "${repoName(n.url)}"`}));return{uuid:t}}function upsertProductDependency(e,n,o,t){const c=section(e,"PBXNativeTarget")[n];if(!c||typeof c!="object")throw new Error(`[smileid-spm] Target ${n} disappeared between lookups.`);const r=section(e,"XCSwiftPackageProductDependency");c.packageProductDependencies??=[];let s=c.packageProductDependencies.find(a=>{const u=r[a.value];return u!==void 0&&typeof u=="object"&&u!==null&&u.package===o.uuid&&u.productName===t})?.value;s||(s=generateUuid(e),r[s]={isa:"XCSwiftPackageProductDependency",package:o.uuid,productName:t},r[`${s}_comment`]=t,c.packageProductDependencies.push({value:s,comment:t})),ensureFrameworkLink(e,c,s,t)}function ensureFrameworkLink(e,n,o,t){const i=findFrameworksBuildPhase(e,n);if(!i)throw new Error(`[smileid-spm] Target '${n.name}' has no PBXFrameworksBuildPhase; cannot link ${t}.`);const c=section(e,"PBXBuildFile");i.obj.files??=[];for(const s of i.obj.files){const a=c[s.value];if(a!==void 0&&typeof a=="object"&&a!==null&&a.productRef===o)return}const r=generateUuid(e);c[r]={isa:"PBXBuildFile",productRef:o},c[`${r}_comment`]=`${t} in Frameworks`,i.obj.files.push({value:r,comment:`${t} in Frameworks`})}function findFrameworksBuildPhase(e,n){const o=section(e,"PBXFrameworksBuildPhase");for(const t of n.buildPhases){const i=o[t.value];if(i&&typeof i=="object"&&i.isa==="PBXFrameworksBuildPhase")return{uuid:t.value,obj:i}}}function findNativeTarget(e,n){const o=section(e,"PBXNativeTarget");for(const[t,i]of Object.entries(o))if(!t.endsWith("_comment")&&!(typeof i!="object"||i===null)&&i.isa==="PBXNativeTarget"&&(i.name===n||i.name===`"${n}"`))return{uuid:t,obj:i}}function serializeRequirement(e){switch(e.kind){case"upToNextMajorVersion":return{kind:"upToNextMajorVersion",minimumVersion:e.minimumVersion};case"upToNextMinorVersion":return{kind:"upToNextMinorVersion",minimumVersion:e.minimumVersion};case"exactVersion":return{kind:"exactVersion",version:e.version};case"branch":return{kind:"branch",branch:e.branch}}}function repoName(e){return e.replace(/\.git$/,"").match(/\/([^/]+)$/)?.[1]??e}