mnfst 0.5.249 → 0.5.250

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  (function () {
4
4
 
5
- const MANIFEST_BUILD_VERSION = '0.5.249';
5
+ const MANIFEST_BUILD_VERSION = '0.5.250';
6
6
 
7
7
  /* Manifest Data Sources - Appwrite Integration */
8
8
 
package/lib/manifest.d.ts CHANGED
@@ -342,7 +342,14 @@ export interface ManifestHaptics {
342
342
  /** `$biometric` from the device plugin. */
343
343
  export interface ManifestBiometric {
344
344
  available(): Promise<boolean>;
345
- verify(opts?: Record<string, unknown>): Promise<unknown>;
345
+ verify(opts?: {
346
+ reason?: string;
347
+ title?: string;
348
+ subtitle?: string;
349
+ cancelTitle?: string;
350
+ fallbackTitle?: string;
351
+ allowDeviceCredential?: boolean;
352
+ }): Promise<{ verified: boolean; error?: string; code?: string }>;
346
353
  }
347
354
 
348
355
  /** `$camera` from the device plugin. */
@@ -2,7 +2,7 @@
2
2
 
3
3
  (function () {
4
4
 
5
- const MANIFEST_BUILD_VERSION = '0.5.249';
5
+ const MANIFEST_BUILD_VERSION = '0.5.250';
6
6
 
7
7
  /* Manifest Data Sources - Configuration */
8
8
 
@@ -15,6 +15,14 @@ function manifestNativePlugin(name) {
15
15
  const cap = window.Capacitor;
16
16
  return (cap && cap.Plugins && cap.Plugins[name]) || null;
17
17
  }
18
+ // Whether a plugin exposes a native method. Bundled apps get a registerPlugin
19
+ // Proxy where every property is a function, so prefer the native header.
20
+ function manifestNativeHas(name, plugin, method) {
21
+ const headers = window.Capacitor && window.Capacitor.PluginHeaders;
22
+ const h = Array.isArray(headers) && headers.find(x => x && x.name === name);
23
+ if (h && Array.isArray(h.methods)) return h.methods.some(m => m && m.name === method);
24
+ return !!plugin && typeof plugin[method] === 'function';
25
+ }
18
26
  function manifestNativePlatform() {
19
27
  const cap = window.Capacitor;
20
28
  if (cap && typeof cap.getPlatform === 'function') { try { return cap.getPlatform(); } catch (e) {} }
@@ -137,9 +145,8 @@ function initManifestNativeNetwork() {
137
145
 
138
146
  // $secure — Keychain/Keystore-backed key/value storage (native) with a
139
147
  // namespaced localStorage fallback on the web. Intended for session tokens etc.
140
- // Native: install a Capacitor secure-storage plugin registered as
141
- // window.Capacitor.Plugins.SecureStorage; if its method shape differs from the
142
- // adapters below, override with $secure.use(adapter). Verify on device.
148
+ // Native: a plugin registered as SecureStorage (@aparajita/capacitor-secure-storage,
149
+ // or any getItem/setItem or get/set shape); $secure.use(adapter) overrides.
143
150
  // The web fallback is NOT encrypted — it degrades honestly, not securely.
144
151
 
145
152
  const MANIFEST_SECURE_NS = 'mnfst:';
@@ -158,33 +165,63 @@ function manifestSecureWebBackend() {
158
165
  };
159
166
  }
160
167
 
161
- // Adapts the two common Capacitor secure-storage plugin shapes: localStorage-like
162
- // (getItem/setItem/removeItem) or object-arg (get/set/remove with {key,value}).
163
- function manifestSecureNativeBackend(plugin) {
164
- const itemApi = typeof plugin.getItem === 'function';
168
+ // aparajita's default prefix, so keys interop with its own getItem/setItem
169
+ const MANIFEST_SECURE_NATIVE_PREFIX = 'capacitor-storage_';
170
+
171
+ function manifestSecureFail(op, e) {
172
+ try { console.error('[Manifest] $secure.' + op + ' failed', e); } catch (_) {}
173
+ throw e instanceof Error ? e : new Error('$secure.' + op + ' failed: ' + ((e && (e.message || e.code)) || e));
174
+ }
175
+
176
+ // Adapts three native shapes: aparajita (internalGetItem…), localStorage-like
177
+ // (getItem/setItem/removeItem) and object-arg (get/set/remove with {key,value}).
178
+ function manifestSecureNativeBackend(plugin, name) {
179
+ const n = name || 'SecureStorage';
180
+ const has = (m) => manifestNativeHas(n, plugin, m);
181
+ const P = MANIFEST_SECURE_NATIVE_PREFIX;
182
+ const shape = has('internalGetItem') ? 'internal' : has('getItem') ? 'item' : has('get') ? 'object' : null;
183
+ const call = async (op, fn) => {
184
+ if (!shape) manifestSecureFail(op, new Error(n + ' plugin has no supported API; use $secure.use(adapter)'));
185
+ try { return await fn(); } catch (e) { manifestSecureFail(op, e); }
186
+ };
165
187
  return {
166
- async get(key) {
167
- try {
168
- if (itemApi) { const v = await plugin.getItem(key); return v == null ? null : v; }
169
- const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
170
- } catch (e) { return null; }
171
- },
172
- async set(key, value) {
173
- try { if (itemApi) await plugin.setItem(key, String(value)); else await plugin.set({ key, value: String(value) }); } catch (e) {}
174
- },
175
- async remove(key) {
176
- try { if (typeof plugin.removeItem === 'function') await plugin.removeItem(key); else await plugin.remove({ key }); } catch (e) {}
177
- },
178
- async keys() { try { const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || []; } catch (e) { return []; } },
179
- async clear() { try { await plugin.clear(); } catch (e) {} }
188
+ get: (key) => call('get', async () => {
189
+ if (key == null || key === '') return null;
190
+ if (shape === 'internal') { const r = await plugin.internalGetItem({ prefixedKey: P + key }); return r && r.data != null ? r.data : null; }
191
+ if (shape === 'item') { const v = await plugin.getItem(key); return v == null ? null : v; }
192
+ const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
193
+ }),
194
+ set: (key, value) => call('set', async () => {
195
+ if (key == null || key === '') throw new Error('No key provided');
196
+ if (shape === 'internal') await plugin.internalSetItem({ prefixedKey: P + key, data: String(value) });
197
+ else if (shape === 'item') await plugin.setItem(key, String(value));
198
+ else await plugin.set({ key, value: String(value) });
199
+ }),
200
+ remove: (key) => call('remove', async () => {
201
+ if (key == null || key === '') return;
202
+ if (shape === 'internal') await plugin.internalRemoveItem({ prefixedKey: P + key });
203
+ else if (shape === 'item') {
204
+ if (!has('removeItem')) throw new Error(n + ' plugin has no removeItem(); use $secure.use(adapter)');
205
+ await plugin.removeItem(key);
206
+ }
207
+ else await plugin.remove({ key });
208
+ }),
209
+ keys: () => call('keys', async () => {
210
+ if (shape === 'internal') { const r = await plugin.internalGetPrefixedKeys({ prefix: P }); return ((r && r.keys) || []).map(k => k.slice(P.length)); }
211
+ const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || [];
212
+ }),
213
+ clear: () => call('clear', async () => {
214
+ if (shape === 'internal') await plugin.internalClearItemsWithPrefix({ prefix: P });
215
+ else await plugin.clear();
216
+ })
180
217
  };
181
218
  }
182
219
 
183
220
  let _manifestSecureBackend = null;
184
221
  function manifestSecureBackend() {
185
222
  if (_manifestSecureBackend) return _manifestSecureBackend;
186
- const plugin = manifestNativePlugin('SecureStorage');
187
- _manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin) : manifestSecureWebBackend();
223
+ const plugin = manifestNativeIsNative() ? manifestNativePlugin('SecureStorage') : null;
224
+ _manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin, 'SecureStorage') : manifestSecureWebBackend();
188
225
  return _manifestSecureBackend;
189
226
  }
190
227
 
@@ -392,33 +429,57 @@ function initManifestHaptics() {
392
429
  }
393
430
 
394
431
 
395
- // $biometric — Face ID / Touch ID. Native: a Capacitor biometric plugin
396
- // (BiometricAuth or NativeBiometric; method shapes differ, adapted below). The web
397
- // has no equivalent one-shot verify (WebAuthn is a separate server ceremony), so
398
- // available() is false and verify() reports unsupported — a genuine native win.
432
+ // $biometric — Face ID / Touch ID. Native: @aparajita/capacitor-biometric-auth
433
+ // (BiometricAuthNative) or @capgo/capacitor-native-biometric (NativeBiometric).
434
+ // No web equivalent: available() is false and verify() reports unsupported.
399
435
 
436
+ const MANIFEST_BIOMETRIC_PLUGINS = ['BiometricAuthNative', 'BiometricAuth', 'NativeBiometric'];
437
+
438
+ // Native only: bundled web builds expose plugin web stubs that always "verify".
400
439
  function manifestBiometricPlugin() {
401
- return manifestNativePlugin('BiometricAuth') || manifestNativePlugin('NativeBiometric') || null;
440
+ if (!manifestNativeIsNative()) return null;
441
+ for (const name of MANIFEST_BIOMETRIC_PLUGINS) {
442
+ const plugin = manifestNativePlugin(name);
443
+ if (plugin) return { name, plugin };
444
+ }
445
+ return null;
446
+ }
447
+
448
+ function manifestBiometricWarn(msg, e) {
449
+ try { console.warn('[Manifest] $biometric: ' + msg, e || ''); } catch (_) {}
402
450
  }
403
451
 
404
452
  async function manifestBiometricAvailable() {
405
- const B = manifestBiometricPlugin();
406
- if (!B) return false;
453
+ const found = manifestBiometricPlugin();
454
+ if (!found) return false;
455
+ const { name, plugin: B } = found;
407
456
  try {
408
- if (typeof B.checkBiometry === 'function') { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
409
- if (typeof B.isAvailable === 'function') { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
410
- } catch (e) {}
457
+ if (manifestNativeHas(name, B, 'checkBiometry')) { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
458
+ if (manifestNativeHas(name, B, 'isAvailable')) { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
459
+ } catch (e) { manifestBiometricWarn('availability check failed', e); return false; }
460
+ manifestBiometricWarn(name + ' has no checkBiometry() or isAvailable()');
411
461
  return false;
412
462
  }
413
463
 
414
464
  async function manifestBiometricVerify(opts) {
415
465
  const o = opts || {};
416
- const B = manifestBiometricPlugin();
417
- if (!B) return { verified: false, error: 'unsupported' };
466
+ const found = manifestBiometricPlugin();
467
+ if (!found) return { verified: false, error: 'unsupported' };
468
+ const { name, plugin: B } = found;
418
469
  try {
419
- if (typeof B.authenticate === 'function') { await B.authenticate({ reason: o.reason, title: o.title, subtitle: o.subtitle, cancelTitle: o.cancelTitle }); return { verified: true }; }
420
- if (typeof B.verifyIdentity === 'function') { await B.verifyIdentity({ reason: o.reason, title: o.title, subtitle: o.subtitle }); return { verified: true }; }
421
- } catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed' }; }
470
+ // aparajita: native method + its own option names
471
+ if (manifestNativeHas(name, B, 'internalAuthenticate') || manifestNativeHas(name, B, 'authenticate')) {
472
+ const args = { reason: o.reason, cancelTitle: o.cancelTitle, iosFallbackTitle: o.fallbackTitle, androidTitle: o.title, androidSubtitle: o.subtitle, allowDeviceCredential: o.allowDeviceCredential };
473
+ if (manifestNativeHas(name, B, 'internalAuthenticate')) await B.internalAuthenticate(args);
474
+ else await B.authenticate(args);
475
+ return { verified: true };
476
+ }
477
+ if (manifestNativeHas(name, B, 'verifyIdentity')) {
478
+ await B.verifyIdentity({ reason: o.reason, description: o.reason, title: o.title, subtitle: o.subtitle, negativeButtonText: o.cancelTitle, useFallback: !!o.allowDeviceCredential, fallbackTitle: o.fallbackTitle });
479
+ return { verified: true };
480
+ }
481
+ } catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed', code: (e && e.code) || undefined }; }
482
+ manifestBiometricWarn(name + ' has no supported verify method');
422
483
  return { verified: false, error: 'unsupported' };
423
484
  }
424
485
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest.appwrite.auth.js": "sha384-dsIWnH0qCAGSzAXMGrd8fvOrVl4tOIE6j5tC35JPTrQXZ56qLD36ARyvhR7vi3Id",
3
- "manifest.appwrite.data.js": "sha384-DmpgWkBF02iuwOvFEq/0rpjHm5ts9F4Y961J8h6+gT2WhyGm3Ryp9Pgk0D/CWDki",
3
+ "manifest.appwrite.data.js": "sha384-7n9o9oibFpnpHDDJ8oYPtiIPddMZyKmmQfXVSwPvTQQw5kK4hz6QNxjmDqjPbbgU",
4
4
  "manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
5
5
  "manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
6
6
  "manifest.charts.js": "sha384-G+huD7UvjF9zDovdVVlh4I5X1Mq4oNnJfoFg4NnGdP3R/4Skq9hy5cGuHNYLxDYm",
@@ -11,24 +11,24 @@
11
11
  "manifest.combobox.js": "sha384-MILTkrgsTzsYUjGo4ZuADqV85Xs4GmfB4xexfe9vbJMIoQTZ42W4zs+DTaVSPEsx",
12
12
  "manifest.components.js": "sha384-BUFA8h+G5Plr82sV7bKzO42pPoiRZwRQcKj1lt2ROFiKjjlkayU/vmkAFqEsdBA+",
13
13
  "manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
14
- "manifest.data.js": "sha384-viViXTPQiJr7QNSx9Ln+uMXyNif1EK10JAmyPqeW4I6FrNtUu5MgKt04sa7LkABg",
14
+ "manifest.data.js": "sha384-E3eYfLsWJzw3OjoBBG/tcJPnvEq8guDOBCtnro7hMHA73LcCjlKIjMDFLzpnmUSn",
15
15
  "manifest.datepicker.js": "sha384-2XwFFnS4Bg5FDvG/v8x6KUvrjcBQEOYyTxynX2K/D/Qb3PI6+Y04lEwCnVDJLzwL",
16
16
  "manifest.defer.js": "sha384-pMRGqQKiEoJhpUcD40QeM4jEHau7sz9Xn/YCpiUamT1T4xJBZDSiYX+xnVrSWoq+",
17
- "manifest.device.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
17
+ "manifest.device.js": "sha384-LseLVXfne1wPR8xXM1jqSqylUxekRF3v26TIEaEICE3a4vxjdXoxOJ3wsLAU0zq+",
18
18
  "manifest.dropdowns.js": "sha384-acufUps7R9WjqB4XXW5JLACqniuHJGM4CNTb2rF4B2Q/jv7ZRmsAwfr2McanOz3s",
19
19
  "manifest.edit.js": "sha384-MOgQNdNLeHijhR0u2W6ntoOulKFglsATCFDqkinesOU15tHoILk/JNzHKkGi5dUG",
20
20
  "manifest.export.js": "sha384-Rx6XvqBZc4apzP/FwcDr6yIln4/zNa08Q4ZqBZcEqUz1aNZQfl4h0+Ae7mqCQyuG",
21
21
  "manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
22
22
  "manifest.localization.js": "sha384-EImsIw8Z3l13V5eH9ZJF/yfsOfIvR1oPRNSArANkPji7V8O3IRf6zMwsNiAGj3Hk",
23
23
  "manifest.markdown.js": "sha384-heyDR40LXHaAmAuA+fa381uFwShk1oAqpFFY6E2Qq4T3VN0TQfRqyc++MF40K5Hj",
24
- "manifest.native.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
24
+ "manifest.native.js": "sha384-LseLVXfne1wPR8xXM1jqSqylUxekRF3v26TIEaEICE3a4vxjdXoxOJ3wsLAU0zq+",
25
25
  "manifest.payments.js": "sha384-8pofk2zhxtapPMpwnFyTelPMrYhShNhDCE722uQh/EYFvZFuPLmSdgunqsarVQjv",
26
26
  "manifest.rich.text.js": "sha384-ZBV9jXmu2nmprEHicddRE/m7nR4RPZtVc969Jte0+EJYBcVph7itkjcgN/61PyeC",
27
27
  "manifest.router.js": "sha384-JcKnEb0E9azl6DVSN1DQMysyZOpGkskSQREjD947sMEs87nFEeZpCigB0iq8psz5",
28
28
  "manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
29
29
  "manifest.status.js": "sha384-MBO345ab7H6Uq1X2dZLt4Ge1Gcra+Z2qYApvlAeIV8CJhDDJrz2FPXpp+Kcp8zcM",
30
30
  "manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
31
- "manifest.sw.js": "sha384-XGf/EbAhHXR7BCSlP6QFnCWPNxuwxyHgU/I8DdxEYw0UPQaZEGDlUILxExqx+ae+",
31
+ "manifest.sw.js": "sha384-3uO0YGmWHY8tHYrkFf+yAVtEwzM+HIbtCZLKR5suOfKWOL7dd8Yul9+kiB2UM1X4",
32
32
  "manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
33
33
  "manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
34
34
  "manifest.toasts.js": "sha384-3zkWxzw693pxg3QDFsoYCA3CqYaLKmBaMArULXODD66Utolpewl0OAeTB92aWUVv",
@@ -15,6 +15,14 @@ function manifestNativePlugin(name) {
15
15
  const cap = window.Capacitor;
16
16
  return (cap && cap.Plugins && cap.Plugins[name]) || null;
17
17
  }
18
+ // Whether a plugin exposes a native method. Bundled apps get a registerPlugin
19
+ // Proxy where every property is a function, so prefer the native header.
20
+ function manifestNativeHas(name, plugin, method) {
21
+ const headers = window.Capacitor && window.Capacitor.PluginHeaders;
22
+ const h = Array.isArray(headers) && headers.find(x => x && x.name === name);
23
+ if (h && Array.isArray(h.methods)) return h.methods.some(m => m && m.name === method);
24
+ return !!plugin && typeof plugin[method] === 'function';
25
+ }
18
26
  function manifestNativePlatform() {
19
27
  const cap = window.Capacitor;
20
28
  if (cap && typeof cap.getPlatform === 'function') { try { return cap.getPlatform(); } catch (e) {} }
@@ -137,9 +145,8 @@ function initManifestNativeNetwork() {
137
145
 
138
146
  // $secure — Keychain/Keystore-backed key/value storage (native) with a
139
147
  // namespaced localStorage fallback on the web. Intended for session tokens etc.
140
- // Native: install a Capacitor secure-storage plugin registered as
141
- // window.Capacitor.Plugins.SecureStorage; if its method shape differs from the
142
- // adapters below, override with $secure.use(adapter). Verify on device.
148
+ // Native: a plugin registered as SecureStorage (@aparajita/capacitor-secure-storage,
149
+ // or any getItem/setItem or get/set shape); $secure.use(adapter) overrides.
143
150
  // The web fallback is NOT encrypted — it degrades honestly, not securely.
144
151
 
145
152
  const MANIFEST_SECURE_NS = 'mnfst:';
@@ -158,33 +165,63 @@ function manifestSecureWebBackend() {
158
165
  };
159
166
  }
160
167
 
161
- // Adapts the two common Capacitor secure-storage plugin shapes: localStorage-like
162
- // (getItem/setItem/removeItem) or object-arg (get/set/remove with {key,value}).
163
- function manifestSecureNativeBackend(plugin) {
164
- const itemApi = typeof plugin.getItem === 'function';
168
+ // aparajita's default prefix, so keys interop with its own getItem/setItem
169
+ const MANIFEST_SECURE_NATIVE_PREFIX = 'capacitor-storage_';
170
+
171
+ function manifestSecureFail(op, e) {
172
+ try { console.error('[Manifest] $secure.' + op + ' failed', e); } catch (_) {}
173
+ throw e instanceof Error ? e : new Error('$secure.' + op + ' failed: ' + ((e && (e.message || e.code)) || e));
174
+ }
175
+
176
+ // Adapts three native shapes: aparajita (internalGetItem…), localStorage-like
177
+ // (getItem/setItem/removeItem) and object-arg (get/set/remove with {key,value}).
178
+ function manifestSecureNativeBackend(plugin, name) {
179
+ const n = name || 'SecureStorage';
180
+ const has = (m) => manifestNativeHas(n, plugin, m);
181
+ const P = MANIFEST_SECURE_NATIVE_PREFIX;
182
+ const shape = has('internalGetItem') ? 'internal' : has('getItem') ? 'item' : has('get') ? 'object' : null;
183
+ const call = async (op, fn) => {
184
+ if (!shape) manifestSecureFail(op, new Error(n + ' plugin has no supported API; use $secure.use(adapter)'));
185
+ try { return await fn(); } catch (e) { manifestSecureFail(op, e); }
186
+ };
165
187
  return {
166
- async get(key) {
167
- try {
168
- if (itemApi) { const v = await plugin.getItem(key); return v == null ? null : v; }
169
- const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
170
- } catch (e) { return null; }
171
- },
172
- async set(key, value) {
173
- try { if (itemApi) await plugin.setItem(key, String(value)); else await plugin.set({ key, value: String(value) }); } catch (e) {}
174
- },
175
- async remove(key) {
176
- try { if (typeof plugin.removeItem === 'function') await plugin.removeItem(key); else await plugin.remove({ key }); } catch (e) {}
177
- },
178
- async keys() { try { const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || []; } catch (e) { return []; } },
179
- async clear() { try { await plugin.clear(); } catch (e) {} }
188
+ get: (key) => call('get', async () => {
189
+ if (key == null || key === '') return null;
190
+ if (shape === 'internal') { const r = await plugin.internalGetItem({ prefixedKey: P + key }); return r && r.data != null ? r.data : null; }
191
+ if (shape === 'item') { const v = await plugin.getItem(key); return v == null ? null : v; }
192
+ const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
193
+ }),
194
+ set: (key, value) => call('set', async () => {
195
+ if (key == null || key === '') throw new Error('No key provided');
196
+ if (shape === 'internal') await plugin.internalSetItem({ prefixedKey: P + key, data: String(value) });
197
+ else if (shape === 'item') await plugin.setItem(key, String(value));
198
+ else await plugin.set({ key, value: String(value) });
199
+ }),
200
+ remove: (key) => call('remove', async () => {
201
+ if (key == null || key === '') return;
202
+ if (shape === 'internal') await plugin.internalRemoveItem({ prefixedKey: P + key });
203
+ else if (shape === 'item') {
204
+ if (!has('removeItem')) throw new Error(n + ' plugin has no removeItem(); use $secure.use(adapter)');
205
+ await plugin.removeItem(key);
206
+ }
207
+ else await plugin.remove({ key });
208
+ }),
209
+ keys: () => call('keys', async () => {
210
+ if (shape === 'internal') { const r = await plugin.internalGetPrefixedKeys({ prefix: P }); return ((r && r.keys) || []).map(k => k.slice(P.length)); }
211
+ const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || [];
212
+ }),
213
+ clear: () => call('clear', async () => {
214
+ if (shape === 'internal') await plugin.internalClearItemsWithPrefix({ prefix: P });
215
+ else await plugin.clear();
216
+ })
180
217
  };
181
218
  }
182
219
 
183
220
  let _manifestSecureBackend = null;
184
221
  function manifestSecureBackend() {
185
222
  if (_manifestSecureBackend) return _manifestSecureBackend;
186
- const plugin = manifestNativePlugin('SecureStorage');
187
- _manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin) : manifestSecureWebBackend();
223
+ const plugin = manifestNativeIsNative() ? manifestNativePlugin('SecureStorage') : null;
224
+ _manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin, 'SecureStorage') : manifestSecureWebBackend();
188
225
  return _manifestSecureBackend;
189
226
  }
190
227
 
@@ -392,33 +429,57 @@ function initManifestHaptics() {
392
429
  }
393
430
 
394
431
 
395
- // $biometric — Face ID / Touch ID. Native: a Capacitor biometric plugin
396
- // (BiometricAuth or NativeBiometric; method shapes differ, adapted below). The web
397
- // has no equivalent one-shot verify (WebAuthn is a separate server ceremony), so
398
- // available() is false and verify() reports unsupported — a genuine native win.
432
+ // $biometric — Face ID / Touch ID. Native: @aparajita/capacitor-biometric-auth
433
+ // (BiometricAuthNative) or @capgo/capacitor-native-biometric (NativeBiometric).
434
+ // No web equivalent: available() is false and verify() reports unsupported.
399
435
 
436
+ const MANIFEST_BIOMETRIC_PLUGINS = ['BiometricAuthNative', 'BiometricAuth', 'NativeBiometric'];
437
+
438
+ // Native only: bundled web builds expose plugin web stubs that always "verify".
400
439
  function manifestBiometricPlugin() {
401
- return manifestNativePlugin('BiometricAuth') || manifestNativePlugin('NativeBiometric') || null;
440
+ if (!manifestNativeIsNative()) return null;
441
+ for (const name of MANIFEST_BIOMETRIC_PLUGINS) {
442
+ const plugin = manifestNativePlugin(name);
443
+ if (plugin) return { name, plugin };
444
+ }
445
+ return null;
446
+ }
447
+
448
+ function manifestBiometricWarn(msg, e) {
449
+ try { console.warn('[Manifest] $biometric: ' + msg, e || ''); } catch (_) {}
402
450
  }
403
451
 
404
452
  async function manifestBiometricAvailable() {
405
- const B = manifestBiometricPlugin();
406
- if (!B) return false;
453
+ const found = manifestBiometricPlugin();
454
+ if (!found) return false;
455
+ const { name, plugin: B } = found;
407
456
  try {
408
- if (typeof B.checkBiometry === 'function') { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
409
- if (typeof B.isAvailable === 'function') { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
410
- } catch (e) {}
457
+ if (manifestNativeHas(name, B, 'checkBiometry')) { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
458
+ if (manifestNativeHas(name, B, 'isAvailable')) { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
459
+ } catch (e) { manifestBiometricWarn('availability check failed', e); return false; }
460
+ manifestBiometricWarn(name + ' has no checkBiometry() or isAvailable()');
411
461
  return false;
412
462
  }
413
463
 
414
464
  async function manifestBiometricVerify(opts) {
415
465
  const o = opts || {};
416
- const B = manifestBiometricPlugin();
417
- if (!B) return { verified: false, error: 'unsupported' };
466
+ const found = manifestBiometricPlugin();
467
+ if (!found) return { verified: false, error: 'unsupported' };
468
+ const { name, plugin: B } = found;
418
469
  try {
419
- if (typeof B.authenticate === 'function') { await B.authenticate({ reason: o.reason, title: o.title, subtitle: o.subtitle, cancelTitle: o.cancelTitle }); return { verified: true }; }
420
- if (typeof B.verifyIdentity === 'function') { await B.verifyIdentity({ reason: o.reason, title: o.title, subtitle: o.subtitle }); return { verified: true }; }
421
- } catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed' }; }
470
+ // aparajita: native method + its own option names
471
+ if (manifestNativeHas(name, B, 'internalAuthenticate') || manifestNativeHas(name, B, 'authenticate')) {
472
+ const args = { reason: o.reason, cancelTitle: o.cancelTitle, iosFallbackTitle: o.fallbackTitle, androidTitle: o.title, androidSubtitle: o.subtitle, allowDeviceCredential: o.allowDeviceCredential };
473
+ if (manifestNativeHas(name, B, 'internalAuthenticate')) await B.internalAuthenticate(args);
474
+ else await B.authenticate(args);
475
+ return { verified: true };
476
+ }
477
+ if (manifestNativeHas(name, B, 'verifyIdentity')) {
478
+ await B.verifyIdentity({ reason: o.reason, description: o.reason, title: o.title, subtitle: o.subtitle, negativeButtonText: o.cancelTitle, useFallback: !!o.allowDeviceCredential, fallbackTitle: o.fallbackTitle });
479
+ return { verified: true };
480
+ }
481
+ } catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed', code: (e && e.code) || undefined }; }
482
+ manifestBiometricWarn(name + ' has no supported verify method');
422
483
  return { verified: false, error: 'unsupported' };
423
484
  }
424
485
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  // Build stamps the published version here; unstamped (dev) falls back to the
18
18
  // registration URL's `v`, then 'dev'.
19
- const BUILD_VERSION = '0.5.249';
19
+ const BUILD_VERSION = '0.5.250';
20
20
  const CACHE_PREFIX = 'mnfst-sw:';
21
21
  const META_CACHE = CACHE_PREFIX + 'meta';
22
22
  // Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mnfst",
3
- "version": "0.5.249",
3
+ "version": "0.5.250",
4
4
  "private": false,
5
5
  "workspaces": [
6
6
  "templates/starter",