@smileid/usesmileid_vision_document 12.0.0-beta01

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.
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ // Injects an idempotent Ruby block into the Expo-generated Podfile's
3
+ // `post_install` hook. The block runs at `pod install` time and wires
4
+ // the Smile ID Swift Package into the autogenerated Pods.xcodeproj
5
+ // for a specific bridge pod target — Pods.xcodeproj only exists at
6
+ // pod-install time, so this is the only hook that can mutate it.
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.injectPodfileSpmBlock = injectPodfileSpmBlock;
9
+ const BEGIN_PREFIX = "# === BEGIN smileid-spm:";
10
+ const END_PREFIX = "# === END smileid-spm:";
11
+ /**
12
+ * Idempotently injects an SPM-linking Ruby block into the Podfile's
13
+ * top-level `post_install` block. Re-running on an already-injected
14
+ * Podfile rewrites the same marker block in place (so version /
15
+ * product changes flow through cleanly on the next prebuild).
16
+ */
17
+ function injectPodfileSpmBlock(podfile, options) {
18
+ validateRubySafe(options);
19
+ const block = renderBlock(options);
20
+ const beginMarker = `${BEGIN_PREFIX} ${options.marker} ===`;
21
+ const endMarker = `${END_PREFIX} ${options.marker} ===`;
22
+ const blockRegex = new RegExp(`${escapeRegExp(beginMarker)}[\\s\\S]*?${escapeRegExp(endMarker)}`, "m");
23
+ if (blockRegex.test(podfile)) {
24
+ return podfile.replace(blockRegex, block);
25
+ }
26
+ // Inject at the *start* of the post_install body — right after
27
+ // `post_install do |installer|`. We tried matching the closing
28
+ // `end` pair instead, but a second plugin running on a Podfile
29
+ // already mutated by the first sees a non-flat body and the
30
+ // non-greedy `end…end` match latches onto inner block ends,
31
+ // nesting the second injection inside the first. Anchoring on
32
+ // the opening line removes that failure mode entirely. Order
33
+ // relative to `react_native_post_install` doesn't matter because
34
+ // CocoaPods persists the Pods project at the end of pod install
35
+ // regardless of what we explicitly save mid-block.
36
+ const headerRegex = /(post_install\s+do\s*\|\s*installer\s*\|)\r?\n/;
37
+ const headerMatch = podfile.match(headerRegex);
38
+ if (!headerMatch || headerMatch.index === undefined) {
39
+ throw new Error("[smileid-spm] Could not locate `post_install do |installer|` in Podfile. " +
40
+ "Refusing to append a top-level post_install hook because CocoaPods only honors one — adding a second " +
41
+ "would silently override the React Native post-install plumbing. Restore the Expo Podfile template " +
42
+ "or wire the SPM block in manually.");
43
+ }
44
+ const insertAt = headerMatch.index + headerMatch[0].length;
45
+ const indented = block
46
+ .split("\n")
47
+ .map((line) => (line.length > 0 ? ` ${line}` : line))
48
+ .join("\n") + "\n";
49
+ return podfile.slice(0, insertAt) + indented + podfile.slice(insertAt);
50
+ }
51
+ // All injected strings flow into single-quoted Ruby literals. We
52
+ // reject characters that could break out of those literals so a
53
+ // typo in the bridge plugin can't produce code that runs during
54
+ // `pod install`. Rejected: single-quote, backslash, control chars.
55
+ function validateRubySafe(options) {
56
+ const fields = [
57
+ ["marker", options.marker],
58
+ ["package.url", options.package.url],
59
+ ["podTarget", options.podTarget],
60
+ ];
61
+ for (const product of options.products) {
62
+ fields.push(["products[*]", product]);
63
+ }
64
+ switch (options.package.requirement.kind) {
65
+ case "upToNextMajorVersion":
66
+ case "upToNextMinorVersion":
67
+ fields.push([
68
+ "requirement.minimumVersion",
69
+ options.package.requirement.minimumVersion,
70
+ ]);
71
+ break;
72
+ case "exactVersion":
73
+ fields.push(["requirement.version", options.package.requirement.version]);
74
+ break;
75
+ case "branch":
76
+ fields.push(["requirement.branch", options.package.requirement.branch]);
77
+ break;
78
+ }
79
+ for (const [name, value] of fields) {
80
+ if (/['\\\n\r\t]/.test(value)) {
81
+ throw new Error(`[smileid-spm] Refusing to inject Podfile block: '${name}' contains an unsafe character (got: ${JSON.stringify(value)}).`);
82
+ }
83
+ }
84
+ }
85
+ function renderBlock(options) {
86
+ const beginMarker = `${BEGIN_PREFIX} ${options.marker} ===`;
87
+ const endMarker = `${END_PREFIX} ${options.marker} ===`;
88
+ const requirement = renderRequirement(options.package.requirement);
89
+ const productList = options.products.map((p) => `'${p}'`).join(", ");
90
+ return `${beginMarker}
91
+ # Wires ${options.package.url} into Pods.xcodeproj and links its
92
+ # products to the '${options.podTarget}' pod target so the Swift
93
+ # bridge code can \`import\` them. Idempotent across pod installs.
94
+ #
95
+ # UUIDs are minted via SecureRandom rather than \`pods_project.new\`
96
+ # because \`prepare_react_native_project!\` sets
97
+ # \`:deterministic_uuids => false\`. With that flag off, CocoaPods
98
+ # skips its predictabilize step and \`stabilize_target_uuids\` resets
99
+ # \`@generated_uuids\` to a tiny leftover pool — so any post_install
100
+ # call to \`pods_project.new\` restarts the sequential index near 0
101
+ # and re-mints UUIDs already in use. The collision then runs through
102
+ # \`add_referrer\`, which clobbers \`objects_by_uuid[uuid]\` and
103
+ # leaves the rootObject (\`46EB2E00000000\`) unreachable, crashing
104
+ # Xcode 26 with \`XCSwiftPackageProductDependency
105
+ # _setSavedArchiveVersion:\` unrecognized selector. Random 24-char
106
+ # hex IDs can't collide with the 14-char cocoapods scheme.
107
+ begin
108
+ pods_project = installer.pods_project
109
+ spm_url = '${options.package.url}'
110
+ spm_requirement = ${requirement}
111
+ product_names = [${productList}]
112
+ target_name = '${options.podTarget}'
113
+
114
+ smileid_spm_safe_uuid = lambda do |project|
115
+ loop do
116
+ candidate = SecureRandom.hex(12).upcase
117
+ return candidate unless project.objects_by_uuid.key?(candidate)
118
+ end
119
+ end
120
+
121
+ pkg = pods_project.root_object.package_references.find do |r|
122
+ r.respond_to?(:repositoryURL) && r.repositoryURL == spm_url
123
+ end
124
+ unless pkg
125
+ pkg_uuid = smileid_spm_safe_uuid.call(pods_project)
126
+ pkg = Xcodeproj::Project::Object::XCRemoteSwiftPackageReference.new(pods_project, pkg_uuid)
127
+ pkg.initialize_defaults
128
+ pkg.repositoryURL = spm_url
129
+ pkg.requirement = spm_requirement
130
+ pods_project.root_object.package_references << pkg
131
+ end
132
+
133
+ target = pods_project.targets.find { |t| t.name == target_name }
134
+ if target.nil?
135
+ Pod::UI.warn "[smileid-spm] Pod target #{target_name} not found; skipping SPM link."
136
+ else
137
+ product_names.each do |product_name|
138
+ already = target.package_product_dependencies.any? do |d|
139
+ d.package == pkg && d.product_name == product_name
140
+ end
141
+ next if already
142
+
143
+ dep_uuid = smileid_spm_safe_uuid.call(pods_project)
144
+ dep = Xcodeproj::Project::Object::XCSwiftPackageProductDependency.new(pods_project, dep_uuid)
145
+ dep.initialize_defaults
146
+ dep.package = pkg
147
+ dep.product_name = product_name
148
+ target.package_product_dependencies << dep
149
+
150
+ bf_uuid = smileid_spm_safe_uuid.call(pods_project)
151
+ bf = Xcodeproj::Project::Object::PBXBuildFile.new(pods_project, bf_uuid)
152
+ bf.initialize_defaults
153
+ bf.product_ref = dep
154
+ target.frameworks_build_phase.files << bf
155
+ end
156
+ end
157
+
158
+ pods_project.save
159
+ rescue => e
160
+ Pod::UI.warn "[smileid-spm] Failed to link SPM products for ${options.podTarget}: #{e.message}"
161
+ raise
162
+ end
163
+ ${endMarker}`;
164
+ }
165
+ function renderRequirement(req) {
166
+ switch (req.kind) {
167
+ case "upToNextMajorVersion":
168
+ return `{ kind: 'upToNextMajorVersion', minimumVersion: '${req.minimumVersion}' }`;
169
+ case "upToNextMinorVersion":
170
+ return `{ kind: 'upToNextMinorVersion', minimumVersion: '${req.minimumVersion}' }`;
171
+ case "exactVersion":
172
+ return `{ kind: 'exactVersion', version: '${req.version}' }`;
173
+ case "branch":
174
+ return `{ kind: 'branch', branch: '${req.branch}' }`;
175
+ }
176
+ }
177
+ function escapeRegExp(s) {
178
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
179
+ }
180
+ //# sourceMappingURL=podfile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"podfile.js","sourceRoot":"","sources":["../../src/lib/podfile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
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;
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ // Shared plumbing for wiring a remote Swift Package into both the
3
+ // consuming Expo app's Xcode project and the autogenerated CocoaPods
4
+ // project for a specific bridge pod target.
5
+ //
6
+ // Why this exists: `expo-modules-autolinking@55.0.x`'s
7
+ // `RawModuleConfigApple` schema does not surface a `dependencies`
8
+ // field, so listing SPM products in `expo-module.config.json` is a
9
+ // silent no-op. This module fills that gap.
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.linkSpmPackage = linkSpmPackage;
12
+ /**
13
+ * Adds (or reuses) a remote Swift Package reference on the given
14
+ * Xcode project and links the requested products to the target.
15
+ * Idempotent: existing package refs and product deps are reused so
16
+ * multiple plugins can compose without conflict.
17
+ */
18
+ function linkSpmPackage(project, pkg, link) {
19
+ const pkgRef = upsertPackageReference(project, pkg);
20
+ const target = findNativeTarget(project, link.targetName);
21
+ if (!target) {
22
+ throw new Error(`[smileid-spm] Native target '${link.targetName}' not found in Xcode project.`);
23
+ }
24
+ for (const product of link.products) {
25
+ upsertProductDependency(project, target.uuid, pkgRef, product);
26
+ }
27
+ }
28
+ function objects(project) {
29
+ const hash = project.hash.project.objects;
30
+ return hash;
31
+ }
32
+ function section(project, isa) {
33
+ const objs = objects(project);
34
+ if (!objs[isa]) {
35
+ objs[isa] = {};
36
+ }
37
+ return objs[isa];
38
+ }
39
+ function generateUuid(project) {
40
+ return project.generateUuid();
41
+ }
42
+ function upsertPackageReference(project, pkg) {
43
+ const refs = section(project, "XCRemoteSwiftPackageReference");
44
+ for (const [uuid, ref] of Object.entries(refs)) {
45
+ if (uuid.endsWith("_comment"))
46
+ continue;
47
+ if (typeof ref !== "object" || ref === null)
48
+ continue;
49
+ if (ref.repositoryURL?.replace(/^"|"$/g, "") === pkg.url) {
50
+ return { uuid };
51
+ }
52
+ }
53
+ const uuid = generateUuid(project);
54
+ refs[uuid] = {
55
+ isa: "XCRemoteSwiftPackageReference",
56
+ repositoryURL: `"${pkg.url}"`,
57
+ requirement: serializeRequirement(pkg.requirement),
58
+ };
59
+ refs[`${uuid}_comment`] =
60
+ `XCRemoteSwiftPackageReference "${repoName(pkg.url)}"`;
61
+ // Attach to the PBXProject's packageReferences list.
62
+ const projectSection = section(project, "PBXProject");
63
+ for (const [projUuid, proj] of Object.entries(projectSection)) {
64
+ if (projUuid.endsWith("_comment"))
65
+ continue;
66
+ if (typeof proj !== "object" || proj === null)
67
+ continue;
68
+ if (proj.isa !== "PBXProject")
69
+ continue;
70
+ proj.packageReferences ??= [];
71
+ if (!proj.packageReferences.some((r) => r.value === uuid)) {
72
+ proj.packageReferences.push({
73
+ value: uuid,
74
+ comment: `XCRemoteSwiftPackageReference "${repoName(pkg.url)}"`,
75
+ });
76
+ }
77
+ }
78
+ return { uuid };
79
+ }
80
+ function upsertProductDependency(project, targetUuid, pkgRef, productName) {
81
+ const targetSection = section(project, "PBXNativeTarget");
82
+ const target = targetSection[targetUuid];
83
+ if (!target || typeof target !== "object") {
84
+ throw new Error(`[smileid-spm] Target ${targetUuid} disappeared between lookups.`);
85
+ }
86
+ const productDeps = section(project, "XCSwiftPackageProductDependency");
87
+ // Each target owns its own XCSwiftPackageProductDependency entry —
88
+ // sharing one across targets is not how Xcode writes pbxproj and
89
+ // would cause downstream tools (and re-runs of this plugin) to
90
+ // silently drop the second target's binding. Look up the dep
91
+ // *within this target's* packageProductDependencies, never globally.
92
+ target.packageProductDependencies ??= [];
93
+ let depUuid = target.packageProductDependencies.find((d) => {
94
+ const entry = productDeps[d.value];
95
+ return (entry !== undefined &&
96
+ typeof entry === "object" &&
97
+ entry !== null &&
98
+ entry.package === pkgRef.uuid &&
99
+ entry.productName === productName);
100
+ })?.value;
101
+ if (!depUuid) {
102
+ depUuid = generateUuid(project);
103
+ productDeps[depUuid] = {
104
+ isa: "XCSwiftPackageProductDependency",
105
+ package: pkgRef.uuid,
106
+ productName,
107
+ };
108
+ productDeps[`${depUuid}_comment`] = productName;
109
+ target.packageProductDependencies.push({
110
+ value: depUuid,
111
+ comment: productName,
112
+ });
113
+ }
114
+ ensureFrameworkLink(project, target, depUuid, productName);
115
+ }
116
+ function ensureFrameworkLink(project, target, productDepUuid, productName) {
117
+ const frameworksPhase = findFrameworksBuildPhase(project, target);
118
+ if (!frameworksPhase) {
119
+ throw new Error(`[smileid-spm] Target '${target.name}' has no PBXFrameworksBuildPhase; cannot link ${productName}.`);
120
+ }
121
+ const buildFiles = section(project, "PBXBuildFile");
122
+ // Scope the existence check to *this target's* frameworks phase.
123
+ // A globally-scoped check would early-return when a sibling target
124
+ // already linked the same product, leaving this target unlinked.
125
+ frameworksPhase.obj.files ??= [];
126
+ for (const fileRef of frameworksPhase.obj.files) {
127
+ const bf = buildFiles[fileRef.value];
128
+ if (bf !== undefined &&
129
+ typeof bf === "object" &&
130
+ bf !== null &&
131
+ bf.productRef === productDepUuid) {
132
+ return;
133
+ }
134
+ }
135
+ const buildFileUuid = generateUuid(project);
136
+ buildFiles[buildFileUuid] = {
137
+ isa: "PBXBuildFile",
138
+ productRef: productDepUuid,
139
+ };
140
+ buildFiles[`${buildFileUuid}_comment`] =
141
+ `${productName} in Frameworks`;
142
+ frameworksPhase.obj.files.push({
143
+ value: buildFileUuid,
144
+ comment: `${productName} in Frameworks`,
145
+ });
146
+ }
147
+ function findFrameworksBuildPhase(project, target) {
148
+ const phaseSection = section(project, "PBXFrameworksBuildPhase");
149
+ for (const phaseRef of target.buildPhases) {
150
+ const phase = phaseSection[phaseRef.value];
151
+ if (phase &&
152
+ typeof phase === "object" &&
153
+ phase.isa === "PBXFrameworksBuildPhase") {
154
+ return { uuid: phaseRef.value, obj: phase };
155
+ }
156
+ }
157
+ return undefined;
158
+ }
159
+ function findNativeTarget(project, name) {
160
+ const targets = section(project, "PBXNativeTarget");
161
+ for (const [uuid, t] of Object.entries(targets)) {
162
+ if (uuid.endsWith("_comment"))
163
+ continue;
164
+ if (typeof t !== "object" || t === null)
165
+ continue;
166
+ if (t.isa !== "PBXNativeTarget")
167
+ continue;
168
+ if (t.name === name || t.name === `"${name}"`) {
169
+ return { uuid, obj: t };
170
+ }
171
+ }
172
+ return undefined;
173
+ }
174
+ function serializeRequirement(req) {
175
+ switch (req.kind) {
176
+ case "upToNextMajorVersion":
177
+ return {
178
+ kind: "upToNextMajorVersion",
179
+ minimumVersion: req.minimumVersion,
180
+ };
181
+ case "upToNextMinorVersion":
182
+ return {
183
+ kind: "upToNextMinorVersion",
184
+ minimumVersion: req.minimumVersion,
185
+ };
186
+ case "exactVersion":
187
+ return { kind: "exactVersion", version: req.version };
188
+ case "branch":
189
+ return { kind: "branch", branch: req.branch };
190
+ }
191
+ }
192
+ function repoName(url) {
193
+ const match = url.replace(/\.git$/, "").match(/\/([^/]+)$/);
194
+ return match?.[1] ?? url;
195
+ }
196
+ //# sourceMappingURL=spm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spm.js","sourceRoot":"","sources":["../../src/lib/spm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
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-beta01` release tag — `from: 12.0.0`
27
+ // would not resolve because `ios-spm` publishes pre-release tags (e.g.
28
+ // `12.0.0-beta01`), 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.0-beta01",
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;