mnfst 0.5.249 → 0.5.251
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/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.d.ts +8 -1
- package/lib/manifest.data.js +1 -1
- package/lib/manifest.device.js +122 -50
- package/lib/manifest.integrity.json +5 -5
- package/lib/manifest.native.js +122 -50
- package/lib/manifest.sw.js +1 -1
- package/package.json +1 -1
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?:
|
|
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. */
|
package/lib/manifest.data.js
CHANGED
package/lib/manifest.device.js
CHANGED
|
@@ -15,6 +15,25 @@ 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; a
|
|
20
|
+
// header list without this plugin means it isn't installed natively.
|
|
21
|
+
function manifestNativeHas(name, plugin, method) {
|
|
22
|
+
const headers = window.Capacitor && window.Capacitor.PluginHeaders;
|
|
23
|
+
if (Array.isArray(headers)) {
|
|
24
|
+
const h = headers.find(x => x && x.name === name);
|
|
25
|
+
if (!h) return false;
|
|
26
|
+
if (Array.isArray(h.methods)) return h.methods.some(m => m && m.name === method);
|
|
27
|
+
}
|
|
28
|
+
return !!plugin && typeof plugin[method] === 'function';
|
|
29
|
+
}
|
|
30
|
+
// A plugin with a native method, or null. Web builds use Manifest's own fallbacks,
|
|
31
|
+
// not plugin web stubs, so bundled and plain web builds behave the same.
|
|
32
|
+
function manifestNativeUse(name, method) {
|
|
33
|
+
if (!manifestNativeIsNative()) return null;
|
|
34
|
+
const plugin = manifestNativePlugin(name);
|
|
35
|
+
return plugin && manifestNativeHas(name, plugin, method) ? plugin : null;
|
|
36
|
+
}
|
|
18
37
|
function manifestNativePlatform() {
|
|
19
38
|
const cap = window.Capacitor;
|
|
20
39
|
if (cap && typeof cap.getPlatform === 'function') { try { return cap.getPlatform(); } catch (e) {} }
|
|
@@ -96,7 +115,7 @@ function manifestShareWeb(payload) {
|
|
|
96
115
|
}
|
|
97
116
|
function manifestShare(opts) {
|
|
98
117
|
const payload = opts || {};
|
|
99
|
-
const Share =
|
|
118
|
+
const Share = manifestNativeUse('Share', 'share');
|
|
100
119
|
if (Share) {
|
|
101
120
|
// When the native sheet is present, never fall through to the web sheet
|
|
102
121
|
// (that would double-prompt); report the native outcome instead.
|
|
@@ -128,7 +147,7 @@ function manifestNativeApplyOnline(connected) {
|
|
|
128
147
|
} catch (e) {}
|
|
129
148
|
}
|
|
130
149
|
function initManifestNativeNetwork() {
|
|
131
|
-
const Network =
|
|
150
|
+
const Network = manifestNativeUse('Network', 'getStatus');
|
|
132
151
|
if (!Network) return;
|
|
133
152
|
try { Network.getStatus().then(s => manifestNativeApplyOnline(s && s.connected)).catch(() => {}); } catch (e) {}
|
|
134
153
|
try { Network.addListener('networkStatusChange', s => manifestNativeApplyOnline(s && s.connected)); } catch (e) {}
|
|
@@ -137,9 +156,8 @@ function initManifestNativeNetwork() {
|
|
|
137
156
|
|
|
138
157
|
// $secure — Keychain/Keystore-backed key/value storage (native) with a
|
|
139
158
|
// namespaced localStorage fallback on the web. Intended for session tokens etc.
|
|
140
|
-
// Native:
|
|
141
|
-
//
|
|
142
|
-
// adapters below, override with $secure.use(adapter). Verify on device.
|
|
159
|
+
// Native: a plugin registered as SecureStorage (@aparajita/capacitor-secure-storage,
|
|
160
|
+
// or any getItem/setItem or get/set shape); $secure.use(adapter) overrides.
|
|
143
161
|
// The web fallback is NOT encrypted — it degrades honestly, not securely.
|
|
144
162
|
|
|
145
163
|
const MANIFEST_SECURE_NS = 'mnfst:';
|
|
@@ -158,33 +176,63 @@ function manifestSecureWebBackend() {
|
|
|
158
176
|
};
|
|
159
177
|
}
|
|
160
178
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
// aparajita's default prefix, so keys interop with its own getItem/setItem
|
|
180
|
+
const MANIFEST_SECURE_NATIVE_PREFIX = 'capacitor-storage_';
|
|
181
|
+
|
|
182
|
+
function manifestSecureFail(op, e) {
|
|
183
|
+
try { console.error('[Manifest] $secure.' + op + ' failed', e); } catch (_) {}
|
|
184
|
+
throw e instanceof Error ? e : new Error('$secure.' + op + ' failed: ' + ((e && (e.message || e.code)) || e));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Adapts three native shapes: aparajita (internalGetItem…), localStorage-like
|
|
188
|
+
// (getItem/setItem/removeItem) and object-arg (get/set/remove with {key,value}).
|
|
189
|
+
function manifestSecureNativeBackend(plugin, name) {
|
|
190
|
+
const n = name || 'SecureStorage';
|
|
191
|
+
const has = (m) => manifestNativeHas(n, plugin, m);
|
|
192
|
+
const P = MANIFEST_SECURE_NATIVE_PREFIX;
|
|
193
|
+
const shape = has('internalGetItem') ? 'internal' : has('getItem') ? 'item' : has('get') ? 'object' : null;
|
|
194
|
+
const call = async (op, fn) => {
|
|
195
|
+
if (!shape) manifestSecureFail(op, new Error(n + ' plugin has no supported API; use $secure.use(adapter)'));
|
|
196
|
+
try { return await fn(); } catch (e) { manifestSecureFail(op, e); }
|
|
197
|
+
};
|
|
165
198
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
|
|
199
|
+
get: (key) => call('get', async () => {
|
|
200
|
+
if (key == null || key === '') return null;
|
|
201
|
+
if (shape === 'internal') { const r = await plugin.internalGetItem({ prefixedKey: P + key }); return r && r.data != null ? r.data : null; }
|
|
202
|
+
if (shape === 'item') { const v = await plugin.getItem(key); return v == null ? null : v; }
|
|
203
|
+
const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
|
|
204
|
+
}),
|
|
205
|
+
set: (key, value) => call('set', async () => {
|
|
206
|
+
if (key == null || key === '') throw new Error('No key provided');
|
|
207
|
+
if (shape === 'internal') await plugin.internalSetItem({ prefixedKey: P + key, data: String(value) });
|
|
208
|
+
else if (shape === 'item') await plugin.setItem(key, String(value));
|
|
209
|
+
else await plugin.set({ key, value: String(value) });
|
|
210
|
+
}),
|
|
211
|
+
remove: (key) => call('remove', async () => {
|
|
212
|
+
if (key == null || key === '') return;
|
|
213
|
+
if (shape === 'internal') await plugin.internalRemoveItem({ prefixedKey: P + key });
|
|
214
|
+
else if (shape === 'item') {
|
|
215
|
+
if (!has('removeItem')) throw new Error(n + ' plugin has no removeItem(); use $secure.use(adapter)');
|
|
216
|
+
await plugin.removeItem(key);
|
|
217
|
+
}
|
|
218
|
+
else await plugin.remove({ key });
|
|
219
|
+
}),
|
|
220
|
+
keys: () => call('keys', async () => {
|
|
221
|
+
if (shape === 'internal') { const r = await plugin.internalGetPrefixedKeys({ prefix: P }); return ((r && r.keys) || []).map(k => k.slice(P.length)); }
|
|
222
|
+
const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || [];
|
|
223
|
+
}),
|
|
224
|
+
clear: () => call('clear', async () => {
|
|
225
|
+
if (shape === 'internal') await plugin.internalClearItemsWithPrefix({ prefix: P });
|
|
226
|
+
else await plugin.clear();
|
|
227
|
+
})
|
|
180
228
|
};
|
|
181
229
|
}
|
|
182
230
|
|
|
183
231
|
let _manifestSecureBackend = null;
|
|
184
232
|
function manifestSecureBackend() {
|
|
185
233
|
if (_manifestSecureBackend) return _manifestSecureBackend;
|
|
186
|
-
const plugin = manifestNativePlugin('SecureStorage');
|
|
187
|
-
_manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin) : manifestSecureWebBackend();
|
|
234
|
+
const plugin = manifestNativeIsNative() ? manifestNativePlugin('SecureStorage') : null;
|
|
235
|
+
_manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin, 'SecureStorage') : manifestSecureWebBackend();
|
|
188
236
|
return _manifestSecureBackend;
|
|
189
237
|
}
|
|
190
238
|
|
|
@@ -251,7 +299,7 @@ function initManifestLinks() {
|
|
|
251
299
|
get last() { const s = window.Alpine.store('links'); return s ? s.last : null; }
|
|
252
300
|
}));
|
|
253
301
|
|
|
254
|
-
const App =
|
|
302
|
+
const App = manifestNativeUse('App', 'getLaunchUrl');
|
|
255
303
|
if (App) {
|
|
256
304
|
try { App.addListener('appUrlOpen', (data) => { if (data && data.url) manifestHandleUrl(data.url); }); } catch (e) {}
|
|
257
305
|
try { App.getLaunchUrl().then(r => { if (r && r.url) manifestHandleUrl(r.url); }).catch(() => {}); } catch (e) {}
|
|
@@ -298,7 +346,7 @@ function initManifestPush() {
|
|
|
298
346
|
window.Alpine.store('push', store);
|
|
299
347
|
}
|
|
300
348
|
|
|
301
|
-
const Push =
|
|
349
|
+
const Push = manifestNativeUse('PushNotifications', 'register');
|
|
302
350
|
if (Push) {
|
|
303
351
|
try { Push.addListener('registration', t => { store.token = t && t.value; _manifestPushTokenHandlers.forEach(fn => { try { fn(store.token); } catch (e) {} }); }); } catch (e) {}
|
|
304
352
|
try { Push.addListener('pushNotificationReceived', n => { _manifestPushReceiveHandlers.forEach(fn => { try { fn(n); } catch (e) {} }); }); } catch (e) {}
|
|
@@ -307,13 +355,13 @@ function initManifestPush() {
|
|
|
307
355
|
|
|
308
356
|
window.Alpine.magic('push', () => ({
|
|
309
357
|
async request() {
|
|
310
|
-
const P =
|
|
358
|
+
const P = manifestNativeUse('PushNotifications', 'requestPermissions');
|
|
311
359
|
if (P) { try { const r = await P.requestPermissions(); const p = manifestPushMapPermission(r && r.receive); window.Alpine.store('push').permission = p; return p; } catch (e) { return 'denied'; } }
|
|
312
360
|
if (typeof Notification !== 'undefined' && Notification.requestPermission) { try { const p = manifestPushMapPermission(await Notification.requestPermission()); window.Alpine.store('push').permission = p; return p; } catch (e) { return 'denied'; } }
|
|
313
361
|
return 'unsupported';
|
|
314
362
|
},
|
|
315
363
|
async register() {
|
|
316
|
-
const P =
|
|
364
|
+
const P = manifestNativeUse('PushNotifications', 'register');
|
|
317
365
|
if (P) { try { await P.register(); } catch (e) {} }
|
|
318
366
|
},
|
|
319
367
|
onToken(fn) { if (typeof fn === 'function') _manifestPushTokenHandlers.push(fn); },
|
|
@@ -341,7 +389,7 @@ function initManifestApp() {
|
|
|
341
389
|
const visible = (typeof document !== 'undefined') ? document.visibilityState !== 'hidden' : true;
|
|
342
390
|
if (!window.Alpine.store('app')) window.Alpine.store('app', { active: visible });
|
|
343
391
|
|
|
344
|
-
const App =
|
|
392
|
+
const App = manifestNativeUse('App', 'getState');
|
|
345
393
|
if (App) {
|
|
346
394
|
try { App.addListener('appStateChange', s => manifestAppSetActive(s && s.isActive)); } catch (e) {}
|
|
347
395
|
} else if (typeof document !== 'undefined') {
|
|
@@ -369,22 +417,22 @@ function manifestVibrate(pattern) {
|
|
|
369
417
|
function initManifestHaptics() {
|
|
370
418
|
window.Alpine.magic('haptics', () => ({
|
|
371
419
|
impact(style) {
|
|
372
|
-
const H =
|
|
420
|
+
const H = manifestNativeUse('Haptics', 'impact');
|
|
373
421
|
if (H) { try { return H.impact({ style: style || 'MEDIUM' }); } catch (e) {} }
|
|
374
422
|
manifestVibrate(10); return Promise.resolve();
|
|
375
423
|
},
|
|
376
424
|
notification(type) {
|
|
377
|
-
const H =
|
|
425
|
+
const H = manifestNativeUse('Haptics', 'notification');
|
|
378
426
|
if (H) { try { return H.notification({ type: type || 'SUCCESS' }); } catch (e) {} }
|
|
379
427
|
manifestVibrate([10, 40, 10]); return Promise.resolve();
|
|
380
428
|
},
|
|
381
429
|
selection() {
|
|
382
|
-
const H =
|
|
430
|
+
const H = manifestNativeUse('Haptics', 'selectionChanged');
|
|
383
431
|
if (H) { try { return H.selectionChanged(); } catch (e) {} }
|
|
384
432
|
manifestVibrate(5); return Promise.resolve();
|
|
385
433
|
},
|
|
386
434
|
vibrate(ms) {
|
|
387
|
-
const H =
|
|
435
|
+
const H = manifestNativeUse('Haptics', 'vibrate');
|
|
388
436
|
if (H) { try { return H.vibrate({ duration: ms || 300 }); } catch (e) {} }
|
|
389
437
|
manifestVibrate(ms || 300); return Promise.resolve();
|
|
390
438
|
}
|
|
@@ -392,33 +440,57 @@ function initManifestHaptics() {
|
|
|
392
440
|
}
|
|
393
441
|
|
|
394
442
|
|
|
395
|
-
// $biometric — Face ID / Touch ID. Native:
|
|
396
|
-
// (
|
|
397
|
-
//
|
|
398
|
-
|
|
443
|
+
// $biometric — Face ID / Touch ID. Native: @aparajita/capacitor-biometric-auth
|
|
444
|
+
// (BiometricAuthNative) or @capgo/capacitor-native-biometric (NativeBiometric).
|
|
445
|
+
// No web equivalent: available() is false and verify() reports unsupported.
|
|
446
|
+
|
|
447
|
+
const MANIFEST_BIOMETRIC_PLUGINS = ['BiometricAuthNative', 'BiometricAuth', 'NativeBiometric'];
|
|
399
448
|
|
|
449
|
+
// Native only: bundled web builds expose plugin web stubs that always "verify".
|
|
400
450
|
function manifestBiometricPlugin() {
|
|
401
|
-
|
|
451
|
+
if (!manifestNativeIsNative()) return null;
|
|
452
|
+
for (const name of MANIFEST_BIOMETRIC_PLUGINS) {
|
|
453
|
+
const plugin = manifestNativePlugin(name);
|
|
454
|
+
if (plugin) return { name, plugin };
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function manifestBiometricWarn(msg, e) {
|
|
460
|
+
try { console.warn('[Manifest] $biometric: ' + msg, e || ''); } catch (_) {}
|
|
402
461
|
}
|
|
403
462
|
|
|
404
463
|
async function manifestBiometricAvailable() {
|
|
405
|
-
const
|
|
406
|
-
if (!
|
|
464
|
+
const found = manifestBiometricPlugin();
|
|
465
|
+
if (!found) return false;
|
|
466
|
+
const { name, plugin: B } = found;
|
|
407
467
|
try {
|
|
408
|
-
if (
|
|
409
|
-
if (
|
|
410
|
-
} catch (e) {}
|
|
468
|
+
if (manifestNativeHas(name, B, 'checkBiometry')) { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
|
|
469
|
+
if (manifestNativeHas(name, B, 'isAvailable')) { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
|
|
470
|
+
} catch (e) { manifestBiometricWarn('availability check failed', e); return false; }
|
|
471
|
+
manifestBiometricWarn(name + ' has no checkBiometry() or isAvailable()');
|
|
411
472
|
return false;
|
|
412
473
|
}
|
|
413
474
|
|
|
414
475
|
async function manifestBiometricVerify(opts) {
|
|
415
476
|
const o = opts || {};
|
|
416
|
-
const
|
|
417
|
-
if (!
|
|
477
|
+
const found = manifestBiometricPlugin();
|
|
478
|
+
if (!found) return { verified: false, error: 'unsupported' };
|
|
479
|
+
const { name, plugin: B } = found;
|
|
418
480
|
try {
|
|
419
|
-
|
|
420
|
-
if (
|
|
421
|
-
|
|
481
|
+
// aparajita: native method + its own option names
|
|
482
|
+
if (manifestNativeHas(name, B, 'internalAuthenticate') || manifestNativeHas(name, B, 'authenticate')) {
|
|
483
|
+
const args = { reason: o.reason, cancelTitle: o.cancelTitle, iosFallbackTitle: o.fallbackTitle, androidTitle: o.title, androidSubtitle: o.subtitle, allowDeviceCredential: o.allowDeviceCredential };
|
|
484
|
+
if (manifestNativeHas(name, B, 'internalAuthenticate')) await B.internalAuthenticate(args);
|
|
485
|
+
else await B.authenticate(args);
|
|
486
|
+
return { verified: true };
|
|
487
|
+
}
|
|
488
|
+
if (manifestNativeHas(name, B, 'verifyIdentity')) {
|
|
489
|
+
await B.verifyIdentity({ reason: o.reason, description: o.reason, title: o.title, subtitle: o.subtitle, negativeButtonText: o.cancelTitle, useFallback: !!o.allowDeviceCredential, fallbackTitle: o.fallbackTitle });
|
|
490
|
+
return { verified: true };
|
|
491
|
+
}
|
|
492
|
+
} catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed', code: (e && e.code) || undefined }; }
|
|
493
|
+
manifestBiometricWarn(name + ' has no supported verify method');
|
|
422
494
|
return { verified: false, error: 'unsupported' };
|
|
423
495
|
}
|
|
424
496
|
|
|
@@ -471,7 +543,7 @@ function manifestCameraWeb(opts) {
|
|
|
471
543
|
|
|
472
544
|
function manifestCameraPhoto(opts) {
|
|
473
545
|
const o = opts || {};
|
|
474
|
-
const Cam =
|
|
546
|
+
const Cam = manifestNativeUse('Camera', 'getPhoto');
|
|
475
547
|
if (Cam) {
|
|
476
548
|
return Cam.getPhoto({ resultType: 'dataUrl', source: o.source === 'photos' ? 'PHOTOS' : 'CAMERA', quality: o.quality || 90 })
|
|
477
549
|
.then(r => ({ dataUrl: r && (r.dataUrl || r.webPath), format: r && r.format }))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-dsIWnH0qCAGSzAXMGrd8fvOrVl4tOIE6j5tC35JPTrQXZ56qLD36ARyvhR7vi3Id",
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-ctnqsfCC4EDugNArRonGeZMTQn2iwksugU0309QM6l0uh6JJZOaU/Gsvvp8JrmZ3",
|
|
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-
|
|
14
|
+
"manifest.data.js": "sha384-ryR3dpYNybgJ8GONlEhkB0myOYz7fhGdnjEpXvKXcCQJUjZQaZbX7J8caPWv7UsN",
|
|
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-
|
|
17
|
+
"manifest.device.js": "sha384-cm59lFxLFOu+DzQGkTUax0lfjZIeEz21vnk26c6nN0+/7irQwzVGt9u545BQjgzM",
|
|
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-
|
|
24
|
+
"manifest.native.js": "sha384-cm59lFxLFOu+DzQGkTUax0lfjZIeEz21vnk26c6nN0+/7irQwzVGt9u545BQjgzM",
|
|
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-
|
|
31
|
+
"manifest.sw.js": "sha384-9+0Y6SDUeQcjS5w5yr2OjMbyuM2uc3U4htcj+f+GUHBFL4X7zxm4u7fekQwAzyxI",
|
|
32
32
|
"manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
|
|
33
33
|
"manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
|
|
34
34
|
"manifest.toasts.js": "sha384-3zkWxzw693pxg3QDFsoYCA3CqYaLKmBaMArULXODD66Utolpewl0OAeTB92aWUVv",
|
package/lib/manifest.native.js
CHANGED
|
@@ -15,6 +15,25 @@ 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; a
|
|
20
|
+
// header list without this plugin means it isn't installed natively.
|
|
21
|
+
function manifestNativeHas(name, plugin, method) {
|
|
22
|
+
const headers = window.Capacitor && window.Capacitor.PluginHeaders;
|
|
23
|
+
if (Array.isArray(headers)) {
|
|
24
|
+
const h = headers.find(x => x && x.name === name);
|
|
25
|
+
if (!h) return false;
|
|
26
|
+
if (Array.isArray(h.methods)) return h.methods.some(m => m && m.name === method);
|
|
27
|
+
}
|
|
28
|
+
return !!plugin && typeof plugin[method] === 'function';
|
|
29
|
+
}
|
|
30
|
+
// A plugin with a native method, or null. Web builds use Manifest's own fallbacks,
|
|
31
|
+
// not plugin web stubs, so bundled and plain web builds behave the same.
|
|
32
|
+
function manifestNativeUse(name, method) {
|
|
33
|
+
if (!manifestNativeIsNative()) return null;
|
|
34
|
+
const plugin = manifestNativePlugin(name);
|
|
35
|
+
return plugin && manifestNativeHas(name, plugin, method) ? plugin : null;
|
|
36
|
+
}
|
|
18
37
|
function manifestNativePlatform() {
|
|
19
38
|
const cap = window.Capacitor;
|
|
20
39
|
if (cap && typeof cap.getPlatform === 'function') { try { return cap.getPlatform(); } catch (e) {} }
|
|
@@ -96,7 +115,7 @@ function manifestShareWeb(payload) {
|
|
|
96
115
|
}
|
|
97
116
|
function manifestShare(opts) {
|
|
98
117
|
const payload = opts || {};
|
|
99
|
-
const Share =
|
|
118
|
+
const Share = manifestNativeUse('Share', 'share');
|
|
100
119
|
if (Share) {
|
|
101
120
|
// When the native sheet is present, never fall through to the web sheet
|
|
102
121
|
// (that would double-prompt); report the native outcome instead.
|
|
@@ -128,7 +147,7 @@ function manifestNativeApplyOnline(connected) {
|
|
|
128
147
|
} catch (e) {}
|
|
129
148
|
}
|
|
130
149
|
function initManifestNativeNetwork() {
|
|
131
|
-
const Network =
|
|
150
|
+
const Network = manifestNativeUse('Network', 'getStatus');
|
|
132
151
|
if (!Network) return;
|
|
133
152
|
try { Network.getStatus().then(s => manifestNativeApplyOnline(s && s.connected)).catch(() => {}); } catch (e) {}
|
|
134
153
|
try { Network.addListener('networkStatusChange', s => manifestNativeApplyOnline(s && s.connected)); } catch (e) {}
|
|
@@ -137,9 +156,8 @@ function initManifestNativeNetwork() {
|
|
|
137
156
|
|
|
138
157
|
// $secure — Keychain/Keystore-backed key/value storage (native) with a
|
|
139
158
|
// namespaced localStorage fallback on the web. Intended for session tokens etc.
|
|
140
|
-
// Native:
|
|
141
|
-
//
|
|
142
|
-
// adapters below, override with $secure.use(adapter). Verify on device.
|
|
159
|
+
// Native: a plugin registered as SecureStorage (@aparajita/capacitor-secure-storage,
|
|
160
|
+
// or any getItem/setItem or get/set shape); $secure.use(adapter) overrides.
|
|
143
161
|
// The web fallback is NOT encrypted — it degrades honestly, not securely.
|
|
144
162
|
|
|
145
163
|
const MANIFEST_SECURE_NS = 'mnfst:';
|
|
@@ -158,33 +176,63 @@ function manifestSecureWebBackend() {
|
|
|
158
176
|
};
|
|
159
177
|
}
|
|
160
178
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
// aparajita's default prefix, so keys interop with its own getItem/setItem
|
|
180
|
+
const MANIFEST_SECURE_NATIVE_PREFIX = 'capacitor-storage_';
|
|
181
|
+
|
|
182
|
+
function manifestSecureFail(op, e) {
|
|
183
|
+
try { console.error('[Manifest] $secure.' + op + ' failed', e); } catch (_) {}
|
|
184
|
+
throw e instanceof Error ? e : new Error('$secure.' + op + ' failed: ' + ((e && (e.message || e.code)) || e));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Adapts three native shapes: aparajita (internalGetItem…), localStorage-like
|
|
188
|
+
// (getItem/setItem/removeItem) and object-arg (get/set/remove with {key,value}).
|
|
189
|
+
function manifestSecureNativeBackend(plugin, name) {
|
|
190
|
+
const n = name || 'SecureStorage';
|
|
191
|
+
const has = (m) => manifestNativeHas(n, plugin, m);
|
|
192
|
+
const P = MANIFEST_SECURE_NATIVE_PREFIX;
|
|
193
|
+
const shape = has('internalGetItem') ? 'internal' : has('getItem') ? 'item' : has('get') ? 'object' : null;
|
|
194
|
+
const call = async (op, fn) => {
|
|
195
|
+
if (!shape) manifestSecureFail(op, new Error(n + ' plugin has no supported API; use $secure.use(adapter)'));
|
|
196
|
+
try { return await fn(); } catch (e) { manifestSecureFail(op, e); }
|
|
197
|
+
};
|
|
165
198
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
},
|
|
178
|
-
|
|
179
|
-
|
|
199
|
+
get: (key) => call('get', async () => {
|
|
200
|
+
if (key == null || key === '') return null;
|
|
201
|
+
if (shape === 'internal') { const r = await plugin.internalGetItem({ prefixedKey: P + key }); return r && r.data != null ? r.data : null; }
|
|
202
|
+
if (shape === 'item') { const v = await plugin.getItem(key); return v == null ? null : v; }
|
|
203
|
+
const r = await plugin.get({ key }); return r && typeof r.value !== 'undefined' ? r.value : (r == null ? null : r);
|
|
204
|
+
}),
|
|
205
|
+
set: (key, value) => call('set', async () => {
|
|
206
|
+
if (key == null || key === '') throw new Error('No key provided');
|
|
207
|
+
if (shape === 'internal') await plugin.internalSetItem({ prefixedKey: P + key, data: String(value) });
|
|
208
|
+
else if (shape === 'item') await plugin.setItem(key, String(value));
|
|
209
|
+
else await plugin.set({ key, value: String(value) });
|
|
210
|
+
}),
|
|
211
|
+
remove: (key) => call('remove', async () => {
|
|
212
|
+
if (key == null || key === '') return;
|
|
213
|
+
if (shape === 'internal') await plugin.internalRemoveItem({ prefixedKey: P + key });
|
|
214
|
+
else if (shape === 'item') {
|
|
215
|
+
if (!has('removeItem')) throw new Error(n + ' plugin has no removeItem(); use $secure.use(adapter)');
|
|
216
|
+
await plugin.removeItem(key);
|
|
217
|
+
}
|
|
218
|
+
else await plugin.remove({ key });
|
|
219
|
+
}),
|
|
220
|
+
keys: () => call('keys', async () => {
|
|
221
|
+
if (shape === 'internal') { const r = await plugin.internalGetPrefixedKeys({ prefix: P }); return ((r && r.keys) || []).map(k => k.slice(P.length)); }
|
|
222
|
+
const r = await plugin.keys(); return Array.isArray(r) ? r : (r && (r.keys || r.value)) || [];
|
|
223
|
+
}),
|
|
224
|
+
clear: () => call('clear', async () => {
|
|
225
|
+
if (shape === 'internal') await plugin.internalClearItemsWithPrefix({ prefix: P });
|
|
226
|
+
else await plugin.clear();
|
|
227
|
+
})
|
|
180
228
|
};
|
|
181
229
|
}
|
|
182
230
|
|
|
183
231
|
let _manifestSecureBackend = null;
|
|
184
232
|
function manifestSecureBackend() {
|
|
185
233
|
if (_manifestSecureBackend) return _manifestSecureBackend;
|
|
186
|
-
const plugin = manifestNativePlugin('SecureStorage');
|
|
187
|
-
_manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin) : manifestSecureWebBackend();
|
|
234
|
+
const plugin = manifestNativeIsNative() ? manifestNativePlugin('SecureStorage') : null;
|
|
235
|
+
_manifestSecureBackend = plugin ? manifestSecureNativeBackend(plugin, 'SecureStorage') : manifestSecureWebBackend();
|
|
188
236
|
return _manifestSecureBackend;
|
|
189
237
|
}
|
|
190
238
|
|
|
@@ -251,7 +299,7 @@ function initManifestLinks() {
|
|
|
251
299
|
get last() { const s = window.Alpine.store('links'); return s ? s.last : null; }
|
|
252
300
|
}));
|
|
253
301
|
|
|
254
|
-
const App =
|
|
302
|
+
const App = manifestNativeUse('App', 'getLaunchUrl');
|
|
255
303
|
if (App) {
|
|
256
304
|
try { App.addListener('appUrlOpen', (data) => { if (data && data.url) manifestHandleUrl(data.url); }); } catch (e) {}
|
|
257
305
|
try { App.getLaunchUrl().then(r => { if (r && r.url) manifestHandleUrl(r.url); }).catch(() => {}); } catch (e) {}
|
|
@@ -298,7 +346,7 @@ function initManifestPush() {
|
|
|
298
346
|
window.Alpine.store('push', store);
|
|
299
347
|
}
|
|
300
348
|
|
|
301
|
-
const Push =
|
|
349
|
+
const Push = manifestNativeUse('PushNotifications', 'register');
|
|
302
350
|
if (Push) {
|
|
303
351
|
try { Push.addListener('registration', t => { store.token = t && t.value; _manifestPushTokenHandlers.forEach(fn => { try { fn(store.token); } catch (e) {} }); }); } catch (e) {}
|
|
304
352
|
try { Push.addListener('pushNotificationReceived', n => { _manifestPushReceiveHandlers.forEach(fn => { try { fn(n); } catch (e) {} }); }); } catch (e) {}
|
|
@@ -307,13 +355,13 @@ function initManifestPush() {
|
|
|
307
355
|
|
|
308
356
|
window.Alpine.magic('push', () => ({
|
|
309
357
|
async request() {
|
|
310
|
-
const P =
|
|
358
|
+
const P = manifestNativeUse('PushNotifications', 'requestPermissions');
|
|
311
359
|
if (P) { try { const r = await P.requestPermissions(); const p = manifestPushMapPermission(r && r.receive); window.Alpine.store('push').permission = p; return p; } catch (e) { return 'denied'; } }
|
|
312
360
|
if (typeof Notification !== 'undefined' && Notification.requestPermission) { try { const p = manifestPushMapPermission(await Notification.requestPermission()); window.Alpine.store('push').permission = p; return p; } catch (e) { return 'denied'; } }
|
|
313
361
|
return 'unsupported';
|
|
314
362
|
},
|
|
315
363
|
async register() {
|
|
316
|
-
const P =
|
|
364
|
+
const P = manifestNativeUse('PushNotifications', 'register');
|
|
317
365
|
if (P) { try { await P.register(); } catch (e) {} }
|
|
318
366
|
},
|
|
319
367
|
onToken(fn) { if (typeof fn === 'function') _manifestPushTokenHandlers.push(fn); },
|
|
@@ -341,7 +389,7 @@ function initManifestApp() {
|
|
|
341
389
|
const visible = (typeof document !== 'undefined') ? document.visibilityState !== 'hidden' : true;
|
|
342
390
|
if (!window.Alpine.store('app')) window.Alpine.store('app', { active: visible });
|
|
343
391
|
|
|
344
|
-
const App =
|
|
392
|
+
const App = manifestNativeUse('App', 'getState');
|
|
345
393
|
if (App) {
|
|
346
394
|
try { App.addListener('appStateChange', s => manifestAppSetActive(s && s.isActive)); } catch (e) {}
|
|
347
395
|
} else if (typeof document !== 'undefined') {
|
|
@@ -369,22 +417,22 @@ function manifestVibrate(pattern) {
|
|
|
369
417
|
function initManifestHaptics() {
|
|
370
418
|
window.Alpine.magic('haptics', () => ({
|
|
371
419
|
impact(style) {
|
|
372
|
-
const H =
|
|
420
|
+
const H = manifestNativeUse('Haptics', 'impact');
|
|
373
421
|
if (H) { try { return H.impact({ style: style || 'MEDIUM' }); } catch (e) {} }
|
|
374
422
|
manifestVibrate(10); return Promise.resolve();
|
|
375
423
|
},
|
|
376
424
|
notification(type) {
|
|
377
|
-
const H =
|
|
425
|
+
const H = manifestNativeUse('Haptics', 'notification');
|
|
378
426
|
if (H) { try { return H.notification({ type: type || 'SUCCESS' }); } catch (e) {} }
|
|
379
427
|
manifestVibrate([10, 40, 10]); return Promise.resolve();
|
|
380
428
|
},
|
|
381
429
|
selection() {
|
|
382
|
-
const H =
|
|
430
|
+
const H = manifestNativeUse('Haptics', 'selectionChanged');
|
|
383
431
|
if (H) { try { return H.selectionChanged(); } catch (e) {} }
|
|
384
432
|
manifestVibrate(5); return Promise.resolve();
|
|
385
433
|
},
|
|
386
434
|
vibrate(ms) {
|
|
387
|
-
const H =
|
|
435
|
+
const H = manifestNativeUse('Haptics', 'vibrate');
|
|
388
436
|
if (H) { try { return H.vibrate({ duration: ms || 300 }); } catch (e) {} }
|
|
389
437
|
manifestVibrate(ms || 300); return Promise.resolve();
|
|
390
438
|
}
|
|
@@ -392,33 +440,57 @@ function initManifestHaptics() {
|
|
|
392
440
|
}
|
|
393
441
|
|
|
394
442
|
|
|
395
|
-
// $biometric — Face ID / Touch ID. Native:
|
|
396
|
-
// (
|
|
397
|
-
//
|
|
398
|
-
|
|
443
|
+
// $biometric — Face ID / Touch ID. Native: @aparajita/capacitor-biometric-auth
|
|
444
|
+
// (BiometricAuthNative) or @capgo/capacitor-native-biometric (NativeBiometric).
|
|
445
|
+
// No web equivalent: available() is false and verify() reports unsupported.
|
|
446
|
+
|
|
447
|
+
const MANIFEST_BIOMETRIC_PLUGINS = ['BiometricAuthNative', 'BiometricAuth', 'NativeBiometric'];
|
|
399
448
|
|
|
449
|
+
// Native only: bundled web builds expose plugin web stubs that always "verify".
|
|
400
450
|
function manifestBiometricPlugin() {
|
|
401
|
-
|
|
451
|
+
if (!manifestNativeIsNative()) return null;
|
|
452
|
+
for (const name of MANIFEST_BIOMETRIC_PLUGINS) {
|
|
453
|
+
const plugin = manifestNativePlugin(name);
|
|
454
|
+
if (plugin) return { name, plugin };
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function manifestBiometricWarn(msg, e) {
|
|
460
|
+
try { console.warn('[Manifest] $biometric: ' + msg, e || ''); } catch (_) {}
|
|
402
461
|
}
|
|
403
462
|
|
|
404
463
|
async function manifestBiometricAvailable() {
|
|
405
|
-
const
|
|
406
|
-
if (!
|
|
464
|
+
const found = manifestBiometricPlugin();
|
|
465
|
+
if (!found) return false;
|
|
466
|
+
const { name, plugin: B } = found;
|
|
407
467
|
try {
|
|
408
|
-
if (
|
|
409
|
-
if (
|
|
410
|
-
} catch (e) {}
|
|
468
|
+
if (manifestNativeHas(name, B, 'checkBiometry')) { const r = await B.checkBiometry(); return !!(r && r.isAvailable); }
|
|
469
|
+
if (manifestNativeHas(name, B, 'isAvailable')) { const r = await B.isAvailable(); return !!(r && r.isAvailable !== false); }
|
|
470
|
+
} catch (e) { manifestBiometricWarn('availability check failed', e); return false; }
|
|
471
|
+
manifestBiometricWarn(name + ' has no checkBiometry() or isAvailable()');
|
|
411
472
|
return false;
|
|
412
473
|
}
|
|
413
474
|
|
|
414
475
|
async function manifestBiometricVerify(opts) {
|
|
415
476
|
const o = opts || {};
|
|
416
|
-
const
|
|
417
|
-
if (!
|
|
477
|
+
const found = manifestBiometricPlugin();
|
|
478
|
+
if (!found) return { verified: false, error: 'unsupported' };
|
|
479
|
+
const { name, plugin: B } = found;
|
|
418
480
|
try {
|
|
419
|
-
|
|
420
|
-
if (
|
|
421
|
-
|
|
481
|
+
// aparajita: native method + its own option names
|
|
482
|
+
if (manifestNativeHas(name, B, 'internalAuthenticate') || manifestNativeHas(name, B, 'authenticate')) {
|
|
483
|
+
const args = { reason: o.reason, cancelTitle: o.cancelTitle, iosFallbackTitle: o.fallbackTitle, androidTitle: o.title, androidSubtitle: o.subtitle, allowDeviceCredential: o.allowDeviceCredential };
|
|
484
|
+
if (manifestNativeHas(name, B, 'internalAuthenticate')) await B.internalAuthenticate(args);
|
|
485
|
+
else await B.authenticate(args);
|
|
486
|
+
return { verified: true };
|
|
487
|
+
}
|
|
488
|
+
if (manifestNativeHas(name, B, 'verifyIdentity')) {
|
|
489
|
+
await B.verifyIdentity({ reason: o.reason, description: o.reason, title: o.title, subtitle: o.subtitle, negativeButtonText: o.cancelTitle, useFallback: !!o.allowDeviceCredential, fallbackTitle: o.fallbackTitle });
|
|
490
|
+
return { verified: true };
|
|
491
|
+
}
|
|
492
|
+
} catch (e) { return { verified: false, error: (e && (e.message || e.code)) || 'failed', code: (e && e.code) || undefined }; }
|
|
493
|
+
manifestBiometricWarn(name + ' has no supported verify method');
|
|
422
494
|
return { verified: false, error: 'unsupported' };
|
|
423
495
|
}
|
|
424
496
|
|
|
@@ -471,7 +543,7 @@ function manifestCameraWeb(opts) {
|
|
|
471
543
|
|
|
472
544
|
function manifestCameraPhoto(opts) {
|
|
473
545
|
const o = opts || {};
|
|
474
|
-
const Cam =
|
|
546
|
+
const Cam = manifestNativeUse('Camera', 'getPhoto');
|
|
475
547
|
if (Cam) {
|
|
476
548
|
return Cam.getPhoto({ resultType: 'dataUrl', source: o.source === 'photos' ? 'PHOTOS' : 'CAMERA', quality: o.quality || 90 })
|
|
477
549
|
.then(r => ({ dataUrl: r && (r.dataUrl || r.webPath), format: r && r.format }))
|
package/lib/manifest.sw.js
CHANGED
|
@@ -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.
|
|
19
|
+
const BUILD_VERSION = '0.5.251';
|
|
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)
|