@capgo/capacitor-passkey 8.2.0 → 8.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-passkey",
3
- "version": "8.2.0",
3
+ "version": "8.2.1",
4
4
  "description": "Capacitor passkey plugin with a WebAuthn-style shim for Capacitor apps.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -165,24 +165,6 @@ function createEntitlementsPlist() {
165
165
  return `<?xml version="1.0" encoding="UTF-8"?>\n<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n<plist version="1.0">\n<dict>\n</dict>\n</plist>\n`;
166
166
  }
167
167
 
168
- function replaceEntitlementArray(content, key, values) {
169
- const keyPattern = new RegExp(`\\s*<key>${key}</key>\\s*<array>[\\s\\S]*?<\\/array>\\s*`, 'm');
170
- const replacement =
171
- values.length > 0
172
- ? `\n\t<key>${key}</key>\n\t<array>\n${values.map((value) => `\t\t<string>${value}</string>`).join('\n')}\n\t</array>\n`
173
- : '\n';
174
-
175
- if (keyPattern.test(content)) {
176
- return content.replace(keyPattern, replacement);
177
- }
178
-
179
- if (values.length === 0) {
180
- return content;
181
- }
182
-
183
- return content.replace('</dict>', `${replacement}</dict>`);
184
- }
185
-
186
168
  function ensureIosEntitlementsReference(projectContent, entitlementsRelativePath) {
187
169
  if (projectContent.includes('CODE_SIGN_ENTITLEMENTS =')) {
188
170
  return projectContent;
@@ -199,6 +181,59 @@ function findExistingEntitlementsPath(projectContent) {
199
181
  return match?.[1]?.trim();
200
182
  }
201
183
 
184
+ function parseAssociatedDomains(content) {
185
+ const match = content.match(
186
+ /^(\s*)<key>com\.apple\.developer\.associated-domains<\/key>\s*<array>([\s\S]*?)<\/array>/m,
187
+ );
188
+
189
+ if (!match) {
190
+ return undefined;
191
+ }
192
+
193
+ const [fullMatch, indent, body] = match;
194
+ const items = [];
195
+ const itemRegex = /<string>([^<]+)<\/string>/g;
196
+ let itemMatch;
197
+ while ((itemMatch = itemRegex.exec(body))) {
198
+ items.push(itemMatch[1].trim());
199
+ }
200
+
201
+ return { fullMatch, indent: indent ?? '\t', items };
202
+ }
203
+
204
+ function buildAssociatedDomainsBlock(indent, items) {
205
+ const childIndent = indent.includes('\t') || indent === '' ? '\t' : ' ';
206
+ const arrayIndent = `${indent}${childIndent}`;
207
+ const lines = [
208
+ `${indent}<key>com.apple.developer.associated-domains</key>`,
209
+ `${indent}<array>`,
210
+ ...items.map((item) => `${arrayIndent}<string>${item}</string>`),
211
+ `${indent}</array>`,
212
+ ];
213
+
214
+ return `${lines.join('\n')}\n`;
215
+ }
216
+
217
+ function upsertAssociatedDomains(content, webCredentialEntries) {
218
+ const parsed = parseAssociatedDomains(content);
219
+ const webCredentialSet = new Set(webCredentialEntries);
220
+
221
+ if (parsed) {
222
+ const preserved = parsed.items.filter((item) => !item.startsWith('webcredentials:'));
223
+ const merged = [...preserved, ...webCredentialSet];
224
+ const nextBlock = buildAssociatedDomainsBlock(parsed.indent, merged);
225
+ return content.replace(parsed.fullMatch, nextBlock);
226
+ }
227
+
228
+ if (webCredentialEntries.length === 0) {
229
+ return content;
230
+ }
231
+
232
+ const indent = '\t';
233
+ const nextBlock = buildAssociatedDomainsBlock(indent, [...webCredentialSet]);
234
+ return content.replace('</dict>', `${nextBlock}</dict>`);
235
+ }
236
+
202
237
  function configureIOS(rootDir, domains) {
203
238
  const iosProjectRoot = path.join(rootDir, 'ios', 'App');
204
239
  const pbxprojPath = path.join(iosProjectRoot, 'App.xcodeproj', 'project.pbxproj');
@@ -216,9 +251,8 @@ function configureIOS(rootDir, domains) {
216
251
  const originalEntitlements = fs.existsSync(entitlementsPath)
217
252
  ? fs.readFileSync(entitlementsPath, 'utf8')
218
253
  : createEntitlementsPlist();
219
- const nextEntitlements = replaceEntitlementArray(
254
+ const nextEntitlements = upsertAssociatedDomains(
220
255
  originalEntitlements.includes('<dict>') ? originalEntitlements : createEntitlementsPlist(),
221
- 'com.apple.developer.associated-domains',
222
256
  associatedDomains,
223
257
  );
224
258
  const entitlementsChanged = writeFileIfChanged(entitlementsPath, nextEntitlements);
@@ -242,6 +276,17 @@ function run() {
242
276
  }
243
277
 
244
278
  const config = parseConfig();
279
+ if (config.autoShim === false) {
280
+ log('Native auto-configuration disabled via plugins.CapacitorPasskey.autoShim = false.');
281
+ return;
282
+ }
283
+
284
+ if (config.domains.length === 0) {
285
+ log(
286
+ 'No passkey domains configured. Add plugins.CapacitorPasskey.origin or domains in capacitor.config.* to enable automatic native wiring.',
287
+ );
288
+ return;
289
+ }
245
290
  const shouldConfigureAndroid = !PLATFORM || PLATFORM === 'android';
246
291
  const shouldConfigureIOS = !PLATFORM || PLATFORM === 'ios';
247
292
 
@@ -252,12 +297,6 @@ function run() {
252
297
  if (shouldConfigureIOS) {
253
298
  configureIOS(ROOT_DIR, config.domains);
254
299
  }
255
-
256
- if (config.domains.length === 0) {
257
- log(
258
- 'No passkey domains configured. Add plugins.CapacitorPasskey.origin or domains in capacitor.config.* to enable automatic native wiring.',
259
- );
260
- }
261
300
  }
262
301
 
263
302
  run();