akanjs 3.0.0-beta.20 → 3.0.0-beta.21
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/README.ko.md +0 -1
- package/README.md +0 -1
- package/base/baseEnv.ts +40 -3
- package/client/cookie.ts +56 -20
- package/client/device.ts +47 -95
- package/client/frameConfig.ts +2 -2
- package/client/native.ts +44 -0
- package/client/router.ts +11 -1
- package/client/rscNavigation.ts +5 -0
- package/client/storage.ts +68 -39
- package/fetch/client/fetchClient.ts +13 -4
- package/index.ts +47 -46
- package/package.json +6 -87
- package/server/devtools/signalSerializer.ts +1 -2
- package/server/hmr/devHmrController.ts +29 -11
- package/server/resolver/signal.resolver.ts +1 -10
- package/server/routeTreeBuilder.ts +8 -11
- package/server/routing/apiRouter.ts +15 -2
- package/server/rscClient.tsx +1 -2
- package/server/ssrFromRscRenderer.tsx +2 -0
- package/server/webRouter.ts +1 -0
- package/signal/CrossSiteGuard.ts +34 -2
- package/signal/endpoint.ts +12 -7
- package/signal/endpointInfo.ts +13 -0
- package/signal/internal.ts +9 -5
- package/signal/serializer/fetch.serializer.ts +6 -3
- package/signal/slice.ts +34 -24
- package/store/baseSt.ts +0 -1
- package/store/storeInstance.ts +29 -17
- package/types/client/cookie.d.ts +6 -4
- package/types/client/device.d.ts +7 -10
- package/types/client/native.d.ts +26 -0
- package/types/client/rscNavigation.d.ts +4 -0
- package/types/client/storage.d.ts +8 -1
- package/types/index.d.ts +48 -44
- package/types/server/hmr/devHmrController.d.ts +2 -1
- package/types/server/resolver/signal.resolver.d.ts +0 -1
- package/types/server/rscClient.d.ts +0 -3
- package/types/signal/CrossSiteGuard.d.ts +7 -2
- package/types/signal/endpoint.d.ts +1 -1
- package/types/signal/endpointInfo.d.ts +3 -0
- package/types/signal/slice.d.ts +3 -2
- package/types/store/baseSt.d.ts +0 -13
- package/types/vendor/@akanjs/native/packages/cli/src/api.d.ts +182 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/build.d.ts +28 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/compat.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/dev.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/doctor.d.ts +37 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/plugin.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/signing.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/test.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/toolchain.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/commands/update.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/config.d.ts +278 -0
- package/types/vendor/@akanjs/native/packages/cli/src/index.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/acl.d.ts +21 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/apilevel.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/apk.d.ts +36 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/args.d.ts +9 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/boot.d.ts +32 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/chrome.d.ts +6 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/codegen.d.ts +94 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/compat.d.ts +49 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/configkeys.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/csp.d.ts +51 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/env.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/exec.d.ts +31 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/googleservices.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/hmr.d.ts +120 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/html.d.ts +20 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/icons.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/image.d.ts +21 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/iossigning.d.ts +81 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/launch.d.ts +51 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/log.d.ts +42 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.d.ts +18 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/maven.d.ts +97 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/names.d.ts +45 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.d.ts +67 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/permissions.d.ts +10 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/plist.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/png.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/prepare.d.ts +138 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/privacy.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/project.d.ts +208 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/root.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/routes.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/serve.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/signing.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/spec.d.ts +96 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/toolchains.d.ts +150 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/updates.d.ts +77 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/vectors.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/lib/xml.d.ts +13 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/android.d.ts +57 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/desktop.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/index.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/ios.d.ts +44 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/linux.d.ts +6 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/macos.d.ts +7 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/targets.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/web-run.d.ts +15 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms/windows.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/cli/src/platforms.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/cli/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/core/src/acl.d.ts +97 -0
- package/types/vendor/@akanjs/native/packages/core/src/boot.d.ts +66 -0
- package/types/vendor/@akanjs/native/packages/core/src/contract.d.ts +35 -0
- package/types/vendor/@akanjs/native/packages/core/src/errors.d.ts +27 -0
- package/types/vendor/@akanjs/native/packages/core/src/files.d.ts +23 -0
- package/types/vendor/@akanjs/native/packages/core/src/index.d.ts +14 -0
- package/types/vendor/@akanjs/native/packages/core/src/kernel.d.ts +112 -0
- package/types/vendor/@akanjs/native/packages/core/src/live.d.ts +12 -0
- package/types/vendor/@akanjs/native/packages/core/src/mime.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/core/src/plugin.d.ts +71 -0
- package/types/vendor/@akanjs/native/packages/core/src/protocol.d.ts +109 -0
- package/types/vendor/@akanjs/native/packages/core/src/runtime.d.ts +66 -0
- package/types/vendor/@akanjs/native/packages/core/src/state.d.ts +28 -0
- package/types/vendor/@akanjs/native/packages/core/src/testing.d.ts +41 -0
- package/types/vendor/@akanjs/native/packages/core/src/version.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/core/src/veto.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/core/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/deeplinks.d.ts +24 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/delta.d.ts +2 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/dispatcher.d.ts +95 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/ffi.d.ts +144 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/host.d.ts +11 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/lifecycle.d.ts +40 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/main.d.ts +4 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/page-veto.d.ts +17 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/paths.d.ts +25 -0
- package/types/vendor/@akanjs/native/packages/desktop/src/plugin.d.ts +179 -0
- package/types/vendor/@akanjs/native/packages/react/src/index.d.ts +8 -0
- package/types/vendor/@akanjs/native/packages/react/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/announce.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/index.d.ts +47 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/accessibility/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/app/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/app/src/index.d.ts +66 -0
- package/types/vendor/@akanjs/native/plugins/app/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/app/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src/index.d.ts +19 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/app-state/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/index.d.ts +32 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/setting.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/appearance/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/args.d.ts +18 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/desktop.d.ts +17 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src/index.d.ts +41 -0
- package/types/vendor/@akanjs/native/plugins/auth-session/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src/desktop.d.ts +44 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src/index.d.ts +44 -0
- package/types/vendor/@akanjs/native/plugins/autostart/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/count.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/index.d.ts +37 -0
- package/types/vendor/@akanjs/native/plugins/badge/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/badge/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/biometric/src/index.d.ts +53 -0
- package/types/vendor/@akanjs/native/plugins/biometric/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/args.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/index.d.ts +36 -0
- package/types/vendor/@akanjs/native/plugins/browser/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/browser/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/desktop.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/camera/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/camera/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/index.d.ts +40 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/clipboard/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/device/src/desktop.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/device/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/device/src/web.d.ts +22 -0
- package/types/vendor/@akanjs/native/plugins/device/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/index.d.ts +60 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/options.d.ts +29 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/dialog/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/dock/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/dock/src/index.d.ts +46 -0
- package/types/vendor/@akanjs/native/plugins/dock/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/common.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/desktop.d.ts +9 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/index.d.ts +84 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src/web.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/file-picker/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/common.d.ts +49 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/index.d.ts +123 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/filesystem/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src/index.d.ts +93 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src/web.d.ts +11 -0
- package/types/vendor/@akanjs/native/plugins/geolocation/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src/index.d.ts +52 -0
- package/types/vendor/@akanjs/native/plugins/global-shortcut/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src/index.d.ts +31 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/haptics/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/http/src/common.d.ts +71 -0
- package/types/vendor/@akanjs/native/plugins/http/src/desktop.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/http/src/index.d.ts +104 -0
- package/types/vendor/@akanjs/native/plugins/http/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/http/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/iap/src/index.d.ts +171 -0
- package/types/vendor/@akanjs/native/plugins/iap/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/desktop.d.ts +15 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/keep-awake/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src/index.d.ts +42 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/keyboard/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/desktop.d.ts +29 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/index.d.ts +126 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/schedule.d.ts +38 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/timers.d.ts +25 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/local-notifications/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/menu/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/menu/src/index.d.ts +85 -0
- package/types/vendor/@akanjs/native/plugins/menu/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/network/src/index.d.ts +22 -0
- package/types/vendor/@akanjs/native/plugins/network/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/network/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/desktop.d.ts +14 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/url.d.ts +16 -0
- package/types/vendor/@akanjs/native/plugins/opener/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/opener/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/index.d.ts +26 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/preferences/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/push/src/index.d.ts +57 -0
- package/types/vendor/@akanjs/native/plugins/push/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/index.d.ts +70 -0
- package/types/vendor/@akanjs/native/plugins/screen/src/web.d.ts +18 -0
- package/types/vendor/@akanjs/native/plugins/screen/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/index.d.ts +32 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/types.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src/web.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/screen-orientation/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/desktop.d.ts +16 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src/index.d.ts +39 -0
- package/types/vendor/@akanjs/native/plugins/secure-storage/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/share/src/index.d.ts +55 -0
- package/types/vendor/@akanjs/native/plugins/share/src/options.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/share/src/web.d.ts +5 -0
- package/types/vendor/@akanjs/native/plugins/share/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/desktop.d.ts +8 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/index.d.ts +25 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src/socket.d.ts +46 -0
- package/types/vendor/@akanjs/native/plugins/single-instance/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/index.d.ts +19 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src/web.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/splash-screen/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/common.d.ts +34 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/desktop.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src/index.d.ts +115 -0
- package/types/vendor/@akanjs/native/plugins/sqlite/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/index.d.ts +30 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/queue.d.ts +23 -0
- package/types/vendor/@akanjs/native/plugins/toast/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/toast/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/tray/src/desktop.d.ts +3 -0
- package/types/vendor/@akanjs/native/plugins/tray/src/index.d.ts +113 -0
- package/types/vendor/@akanjs/native/plugins/tray/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/desktop.d.ts +4 -0
- package/types/vendor/@akanjs/native/plugins/updates/src/index.d.ts +68 -0
- package/types/vendor/@akanjs/native/plugins/updates/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/window/src/desktop.d.ts +6 -0
- package/types/vendor/@akanjs/native/plugins/window/src/index.d.ts +185 -0
- package/types/vendor/@akanjs/native/plugins/window/src/web.d.ts +2 -0
- package/types/vendor/@akanjs/native/plugins/window/src.d.ts +1 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/desktop.d.ts +7 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/index.d.ts +33 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src/state.d.ts +39 -0
- package/types/vendor/@akanjs/native/plugins/window-state/src.d.ts +1 -0
- package/types/webkit/index.d.ts +0 -2
- package/types/webkit/nativeNavigation.d.ts +25 -0
- package/types/webkit/nativePurchase.d.ts +37 -0
- package/types/webkit/useCamera.d.ts +13 -15
- package/types/webkit/useGeoLocation.d.ts +4 -5
- package/types/webkit/usePurchase.d.ts +12 -16
- package/ui/Link/Anchor.tsx +2 -5
- package/ui/System/Client.tsx +2 -6
- package/vendor/@akanjs/native/LICENSE +21 -0
- package/vendor/@akanjs/native/README.ko.md +88 -0
- package/vendor/@akanjs/native/README.md +93 -0
- package/vendor/@akanjs/native/THIRD_PARTY_NOTICES.md +237 -0
- package/vendor/@akanjs/native/native/android/maven.lock.json +1751 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAcl.kt +243 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeActivity.kt +936 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeApplication.kt +189 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeAssetServer.kt +225 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeBridge.kt +444 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeCompat.kt +55 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeContract.kt +99 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeEd25519.kt +100 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeFileProvider.kt +71 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeKernel.kt +324 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativePlugin.kt +361 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeSpec.kt +100 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeUpdates.kt +305 -0
- package/vendor/@akanjs/native/native/android/src/com/akanjs/runtime/AkanNativeVectors.kt +132 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.lock +2565 -0
- package/vendor/@akanjs/native/native/desktop/Cargo.toml +49 -0
- package/vendor/@akanjs/native/native/desktop/build.rs +19 -0
- package/vendor/@akanjs/native/native/desktop/rust-toolchain.toml +7 -0
- package/vendor/@akanjs/native/native/desktop/src/accelerator.rs +466 -0
- package/vendor/@akanjs/native/native/desktop/src/autostart.rs +158 -0
- package/vendor/@akanjs/native/native/desktop/src/camera.rs +53 -0
- package/vendor/@akanjs/native/native/desktop/src/chrome.rs +710 -0
- package/vendor/@akanjs/native/native/desktop/src/contract.rs +105 -0
- package/vendor/@akanjs/native/native/desktop/src/devproxy.rs +234 -0
- package/vendor/@akanjs/native/native/desktop/src/dialog_args.rs +189 -0
- package/vendor/@akanjs/native/native/desktop/src/dock.rs +209 -0
- package/vendor/@akanjs/native/native/desktop/src/hotkey.rs +209 -0
- package/vendor/@akanjs/native/native/desktop/src/js_panels.rs +125 -0
- package/vendor/@akanjs/native/native/desktop/src/json.rs +272 -0
- package/vendor/@akanjs/native/native/desktop/src/keychain.rs +151 -0
- package/vendor/@akanjs/native/native/desktop/src/lib.rs +2185 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/appearance.rs +177 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/camera.rs +11 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/clipboard.rs +48 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/device.rs +9 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/dialogs.rs +348 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/dock.rs +146 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/hotkey.rs +228 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/keychain.rs +243 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/menu.rs +445 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/mod.rs +116 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/notify.rs +211 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/open.rs +79 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/power.rs +155 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/screen.rs +158 -0
- package/vendor/@akanjs/native/native/desktop/src/linux/tray.rs +604 -0
- package/vendor/@akanjs/native/native/desktop/src/menu.rs +517 -0
- package/vendor/@akanjs/native/native/desktop/src/navigation.rs +381 -0
- package/vendor/@akanjs/native/native/desktop/src/notify.rs +411 -0
- package/vendor/@akanjs/native/native/desktop/src/notify_schedule.rs +382 -0
- package/vendor/@akanjs/native/native/desktop/src/page_menu.rs +287 -0
- package/vendor/@akanjs/native/native/desktop/src/panels.rs +333 -0
- package/vendor/@akanjs/native/native/desktop/src/placement.rs +92 -0
- package/vendor/@akanjs/native/native/desktop/src/routes.rs +153 -0
- package/vendor/@akanjs/native/native/desktop/src/screen.rs +190 -0
- package/vendor/@akanjs/native/native/desktop/src/tray.rs +279 -0
- package/vendor/@akanjs/native/native/desktop/src/vectors.rs +126 -0
- package/vendor/@akanjs/native/native/desktop/src/win/appearance.rs +51 -0
- package/vendor/@akanjs/native/native/desktop/src/win/autostart.rs +77 -0
- package/vendor/@akanjs/native/native/desktop/src/win/camera.rs +34 -0
- package/vendor/@akanjs/native/native/desktop/src/win/clipboard.rs +106 -0
- package/vendor/@akanjs/native/native/desktop/src/win/device.rs +80 -0
- package/vendor/@akanjs/native/native/desktop/src/win/dialogs.rs +917 -0
- package/vendor/@akanjs/native/native/desktop/src/win/dock.rs +228 -0
- package/vendor/@akanjs/native/native/desktop/src/win/hotkey.rs +110 -0
- package/vendor/@akanjs/native/native/desktop/src/win/keychain.rs +103 -0
- package/vendor/@akanjs/native/native/desktop/src/win/menu.rs +500 -0
- package/vendor/@akanjs/native/native/desktop/src/win/mod.rs +100 -0
- package/vendor/@akanjs/native/native/desktop/src/win/msgwin.rs +86 -0
- package/vendor/@akanjs/native/native/desktop/src/win/notify.rs +334 -0
- package/vendor/@akanjs/native/native/desktop/src/win/open.rs +127 -0
- package/vendor/@akanjs/native/native/desktop/src/win/power.rs +64 -0
- package/vendor/@akanjs/native/native/desktop/src/win/registry.rs +87 -0
- package/vendor/@akanjs/native/native/desktop/src/win/screen.rs +127 -0
- package/vendor/@akanjs/native/native/desktop/src/win/tray.rs +280 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeAcl.swift +241 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeApp.swift +285 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeBridge.swift +407 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeContract.swift +106 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeKernel.swift +317 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativePlugin.swift +250 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSchemeHandler.swift +209 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeShell.swift +161 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeSpec.swift +143 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeUpdates.swift +270 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeVectors.swift +155 -0
- package/vendor/@akanjs/native/native/ios/Sources/AkanNativeViewController.swift +371 -0
- package/vendor/@akanjs/native/packages/cli/src/api.ts +600 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/build.ts +101 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/compat.ts +53 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/dev.ts +249 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/doctor.ts +536 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/plugin.ts +164 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/signing.ts +32 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/test.ts +130 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/toolchain.ts +143 -0
- package/vendor/@akanjs/native/packages/cli/src/commands/update.ts +168 -0
- package/vendor/@akanjs/native/packages/cli/src/config.ts +257 -0
- package/vendor/@akanjs/native/packages/cli/src/index.ts +77 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/acl.ts +420 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/apilevel.ts +245 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/apk.ts +203 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/args.ts +44 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/boot.ts +73 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/chrome.ts +89 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/codegen.ts +1128 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/compat.ts +185 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/configkeys.ts +91 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/csp.ts +198 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/env.ts +257 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/exec.ts +104 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/googleservices.ts +53 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/hmr.ts +534 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/html.ts +63 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/icons.ts +316 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/image.ts +175 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/iossigning.ts +295 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/launch.ts +98 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/log.ts +105 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/manifestmerge.ts +107 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/maven.ts +244 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/names.ts +202 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/native-plugins.ts +326 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/nativeconfig.ts +68 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/permissions.ts +80 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/plist.ts +139 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/png.ts +240 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/prepare.ts +290 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/privacy.ts +64 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/project.ts +710 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/root.ts +18 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/routes.ts +3 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/serve.ts +83 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/signing.ts +117 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/spec.ts +521 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/toolchains.ts +579 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/updates.ts +160 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/vectors.ts +121 -0
- package/vendor/@akanjs/native/packages/cli/src/lib/xml.ts +72 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/android.ts +1320 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop-update.ts +78 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/desktop.ts +279 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/index.ts +31 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/ios.ts +801 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/linux.ts +52 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/macos.ts +97 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/targets.ts +12 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/web-run.ts +69 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/web.ts +28 -0
- package/vendor/@akanjs/native/packages/cli/src/platforms/windows.ts +82 -0
- package/vendor/@akanjs/native/packages/core/contract.json +96 -0
- package/vendor/@akanjs/native/packages/core/src/acl.ts +272 -0
- package/vendor/@akanjs/native/packages/core/src/boot.ts +97 -0
- package/vendor/@akanjs/native/packages/core/src/contract.ts +100 -0
- package/vendor/@akanjs/native/packages/core/src/errors.ts +95 -0
- package/vendor/@akanjs/native/packages/core/src/files.ts +105 -0
- package/vendor/@akanjs/native/packages/core/src/index.ts +35 -0
- package/vendor/@akanjs/native/packages/core/src/kernel.ts +281 -0
- package/vendor/@akanjs/native/packages/core/src/live.ts +62 -0
- package/vendor/@akanjs/native/packages/core/src/mime.ts +8 -0
- package/vendor/@akanjs/native/packages/core/src/plugin.ts +358 -0
- package/vendor/@akanjs/native/packages/core/src/protocol.ts +194 -0
- package/vendor/@akanjs/native/packages/core/src/runtime.ts +520 -0
- package/vendor/@akanjs/native/packages/core/src/state.ts +46 -0
- package/vendor/@akanjs/native/packages/core/src/testing.ts +176 -0
- package/vendor/@akanjs/native/packages/core/src/version.ts +2 -0
- package/vendor/@akanjs/native/packages/core/src/veto.ts +55 -0
- package/vendor/@akanjs/native/packages/core/vectors/acl.json +57 -0
- package/vendor/@akanjs/native/packages/core/vectors/bridge.json +76 -0
- package/vendor/@akanjs/native/packages/core/vectors/ed25519.json +29 -0
- package/vendor/@akanjs/native/packages/core/vectors/ids.json +73 -0
- package/vendor/@akanjs/native/packages/core/vectors/navigation.json +75 -0
- package/vendor/@akanjs/native/packages/core/vectors/ranges.json +39 -0
- package/vendor/@akanjs/native/packages/core/vectors/retained.json +17 -0
- package/vendor/@akanjs/native/packages/core/vectors/routes.json +66 -0
- package/vendor/@akanjs/native/packages/core/vectors/scope.json +143 -0
- package/vendor/@akanjs/native/packages/desktop/src/deeplinks.ts +143 -0
- package/vendor/@akanjs/native/packages/desktop/src/delta.ts +174 -0
- package/vendor/@akanjs/native/packages/desktop/src/dispatcher.ts +679 -0
- package/vendor/@akanjs/native/packages/desktop/src/ffi.ts +76 -0
- package/vendor/@akanjs/native/packages/desktop/src/host.ts +355 -0
- package/vendor/@akanjs/native/packages/desktop/src/lifecycle.ts +142 -0
- package/vendor/@akanjs/native/packages/desktop/src/main.ts +133 -0
- package/vendor/@akanjs/native/packages/desktop/src/page-veto.ts +103 -0
- package/vendor/@akanjs/native/packages/desktop/src/paths.ts +59 -0
- package/vendor/@akanjs/native/packages/desktop/src/plugin.ts +232 -0
- package/vendor/@akanjs/native/packages/react/src/index.ts +23 -0
- package/vendor/@akanjs/native/plugins/accessibility/android/AccessibilityPlugin.kt +96 -0
- package/vendor/@akanjs/native/plugins/accessibility/ios/AccessibilityPlugin.swift +92 -0
- package/vendor/@akanjs/native/plugins/accessibility/native-plugin.json +21 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/announce.ts +71 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/index.ts +77 -0
- package/vendor/@akanjs/native/plugins/accessibility/src/web.ts +52 -0
- package/vendor/@akanjs/native/plugins/app/android/AppPlugin.kt +72 -0
- package/vendor/@akanjs/native/plugins/app/ios/AppPlugin.swift +52 -0
- package/vendor/@akanjs/native/plugins/app/native-plugin.json +21 -0
- package/vendor/@akanjs/native/plugins/app/src/desktop.ts +64 -0
- package/vendor/@akanjs/native/plugins/app/src/index.ts +77 -0
- package/vendor/@akanjs/native/plugins/app/src/web.ts +12 -0
- package/vendor/@akanjs/native/plugins/app-state/android/AppStatePlugin.kt +54 -0
- package/vendor/@akanjs/native/plugins/app-state/ios/AppStatePlugin.swift +58 -0
- package/vendor/@akanjs/native/plugins/app-state/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/app-state/src/index.ts +42 -0
- package/vendor/@akanjs/native/plugins/app-state/src/web.ts +33 -0
- package/vendor/@akanjs/native/plugins/appearance/android/AppearancePlugin.kt +133 -0
- package/vendor/@akanjs/native/plugins/appearance/ios/AppearancePlugin.swift +109 -0
- package/vendor/@akanjs/native/plugins/appearance/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/appearance/src/desktop.ts +133 -0
- package/vendor/@akanjs/native/plugins/appearance/src/index.ts +62 -0
- package/vendor/@akanjs/native/plugins/appearance/src/setting.ts +18 -0
- package/vendor/@akanjs/native/plugins/appearance/src/web.ts +25 -0
- package/vendor/@akanjs/native/plugins/auth-session/android/AuthSessionPlugin.kt +171 -0
- package/vendor/@akanjs/native/plugins/auth-session/ios/AuthSessionPlugin.swift +112 -0
- package/vendor/@akanjs/native/plugins/auth-session/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/args.ts +62 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/desktop.ts +133 -0
- package/vendor/@akanjs/native/plugins/auth-session/src/index.ts +39 -0
- package/vendor/@akanjs/native/plugins/autostart/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/autostart/src/desktop.ts +189 -0
- package/vendor/@akanjs/native/plugins/autostart/src/index.ts +51 -0
- package/vendor/@akanjs/native/plugins/badge/ios/BadgePlugin.swift +92 -0
- package/vendor/@akanjs/native/plugins/badge/native-plugin.json +15 -0
- package/vendor/@akanjs/native/plugins/badge/src/count.ts +12 -0
- package/vendor/@akanjs/native/plugins/badge/src/desktop.ts +24 -0
- package/vendor/@akanjs/native/plugins/badge/src/index.ts +40 -0
- package/vendor/@akanjs/native/plugins/badge/src/web.ts +37 -0
- package/vendor/@akanjs/native/plugins/biometric/android/BiometricPlugin.kt +179 -0
- package/vendor/@akanjs/native/plugins/biometric/ios/BiometricPlugin.swift +129 -0
- package/vendor/@akanjs/native/plugins/biometric/native-plugin.json +22 -0
- package/vendor/@akanjs/native/plugins/biometric/src/index.ts +100 -0
- package/vendor/@akanjs/native/plugins/browser/android/BrowserPlugin.kt +178 -0
- package/vendor/@akanjs/native/plugins/browser/ios/BrowserPlugin.swift +63 -0
- package/vendor/@akanjs/native/plugins/browser/native-plugin.json +22 -0
- package/vendor/@akanjs/native/plugins/browser/src/args.ts +34 -0
- package/vendor/@akanjs/native/plugins/browser/src/desktop.ts +40 -0
- package/vendor/@akanjs/native/plugins/browser/src/index.ts +47 -0
- package/vendor/@akanjs/native/plugins/browser/src/web.ts +60 -0
- package/vendor/@akanjs/native/plugins/camera/android/CameraPlugin.kt +365 -0
- package/vendor/@akanjs/native/plugins/camera/ios/CameraPlugin.swift +296 -0
- package/vendor/@akanjs/native/plugins/camera/native-plugin.json +32 -0
- package/vendor/@akanjs/native/plugins/camera/src/desktop.ts +27 -0
- package/vendor/@akanjs/native/plugins/camera/src/index.ts +85 -0
- package/vendor/@akanjs/native/plugins/camera/src/web.ts +267 -0
- package/vendor/@akanjs/native/plugins/clipboard/android/ClipboardPlugin.kt +51 -0
- package/vendor/@akanjs/native/plugins/clipboard/ios/ClipboardPlugin.swift +35 -0
- package/vendor/@akanjs/native/plugins/clipboard/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/desktop.ts +66 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/index.ts +72 -0
- package/vendor/@akanjs/native/plugins/clipboard/src/web.ts +69 -0
- package/vendor/@akanjs/native/plugins/device/android/DevicePlugin.kt +70 -0
- package/vendor/@akanjs/native/plugins/device/ios/DevicePlugin.swift +80 -0
- package/vendor/@akanjs/native/plugins/device/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/device/src/desktop.ts +276 -0
- package/vendor/@akanjs/native/plugins/device/src/index.ts +72 -0
- package/vendor/@akanjs/native/plugins/device/src/web.ts +162 -0
- package/vendor/@akanjs/native/plugins/dialog/android/DialogPlugin.kt +260 -0
- package/vendor/@akanjs/native/plugins/dialog/ios/DialogPlugin.swift +198 -0
- package/vendor/@akanjs/native/plugins/dialog/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/dialog/src/desktop.ts +80 -0
- package/vendor/@akanjs/native/plugins/dialog/src/index.ts +87 -0
- package/vendor/@akanjs/native/plugins/dialog/src/options.ts +111 -0
- package/vendor/@akanjs/native/plugins/dialog/src/web.ts +296 -0
- package/vendor/@akanjs/native/plugins/dock/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/dock/src/desktop.ts +34 -0
- package/vendor/@akanjs/native/plugins/dock/src/index.ts +46 -0
- package/vendor/@akanjs/native/plugins/file-picker/android/FilePickerPlugin.kt +316 -0
- package/vendor/@akanjs/native/plugins/file-picker/ios/FilePickerPlugin.swift +366 -0
- package/vendor/@akanjs/native/plugins/file-picker/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/common.ts +125 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/desktop.ts +164 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/index.ts +187 -0
- package/vendor/@akanjs/native/plugins/file-picker/src/web.ts +158 -0
- package/vendor/@akanjs/native/plugins/filesystem/android/FilesystemPlugin.kt +561 -0
- package/vendor/@akanjs/native/plugins/filesystem/ios/FilesystemPlugin.swift +596 -0
- package/vendor/@akanjs/native/plugins/filesystem/native-plugin.json +45 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/common.ts +150 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/desktop.ts +438 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/index.ts +179 -0
- package/vendor/@akanjs/native/plugins/filesystem/src/web.ts +334 -0
- package/vendor/@akanjs/native/plugins/geolocation/android/GeolocationPlugin.kt +360 -0
- package/vendor/@akanjs/native/plugins/geolocation/ios/GeolocationPlugin.swift +284 -0
- package/vendor/@akanjs/native/plugins/geolocation/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/geolocation/src/index.ts +155 -0
- package/vendor/@akanjs/native/plugins/geolocation/src/web.ts +132 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/src/desktop.ts +36 -0
- package/vendor/@akanjs/native/plugins/global-shortcut/src/index.ts +55 -0
- package/vendor/@akanjs/native/plugins/haptics/android/HapticsPlugin.kt +127 -0
- package/vendor/@akanjs/native/plugins/haptics/ios/HapticsPlugin.swift +127 -0
- package/vendor/@akanjs/native/plugins/haptics/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/haptics/src/index.ts +34 -0
- package/vendor/@akanjs/native/plugins/haptics/src/web.ts +53 -0
- package/vendor/@akanjs/native/plugins/http/android/HttpPlugin.kt +234 -0
- package/vendor/@akanjs/native/plugins/http/android/HttpUrl.kt +182 -0
- package/vendor/@akanjs/native/plugins/http/ios/HttpPlugin.swift +228 -0
- package/vendor/@akanjs/native/plugins/http/ios/HttpUrl.swift +166 -0
- package/vendor/@akanjs/native/plugins/http/native-plugin.json +27 -0
- package/vendor/@akanjs/native/plugins/http/src/common.ts +294 -0
- package/vendor/@akanjs/native/plugins/http/src/desktop.ts +69 -0
- package/vendor/@akanjs/native/plugins/http/src/index.ts +181 -0
- package/vendor/@akanjs/native/plugins/http/src/web.ts +40 -0
- package/vendor/@akanjs/native/plugins/iap/android/IapPlugin.kt +358 -0
- package/vendor/@akanjs/native/plugins/iap/ios/IapPlugin.swift +306 -0
- package/vendor/@akanjs/native/plugins/iap/native-plugin.json +28 -0
- package/vendor/@akanjs/native/plugins/iap/src/index.ts +206 -0
- package/vendor/@akanjs/native/plugins/keep-awake/android/KeepAwakePlugin.kt +48 -0
- package/vendor/@akanjs/native/plugins/keep-awake/ios/KeepAwakePlugin.swift +36 -0
- package/vendor/@akanjs/native/plugins/keep-awake/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/desktop.ts +127 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/index.ts +79 -0
- package/vendor/@akanjs/native/plugins/keep-awake/src/web.ts +78 -0
- package/vendor/@akanjs/native/plugins/keyboard/android/KeyboardPlugin.kt +77 -0
- package/vendor/@akanjs/native/plugins/keyboard/ios/KeyboardPlugin.swift +93 -0
- package/vendor/@akanjs/native/plugins/keyboard/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/keyboard/src/index.ts +78 -0
- package/vendor/@akanjs/native/plugins/keyboard/src/web.ts +57 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationReceiver.kt +38 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotifications.kt +284 -0
- package/vendor/@akanjs/native/plugins/local-notifications/android/LocalNotificationsPlugin.kt +248 -0
- package/vendor/@akanjs/native/plugins/local-notifications/ios/LocalNotificationsPlugin.swift +279 -0
- package/vendor/@akanjs/native/plugins/local-notifications/native-plugin.json +35 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/desktop.ts +196 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/index.ts +174 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/schedule.ts +164 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/timers.ts +72 -0
- package/vendor/@akanjs/native/plugins/local-notifications/src/web.ts +158 -0
- package/vendor/@akanjs/native/plugins/menu/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/menu/src/desktop.ts +52 -0
- package/vendor/@akanjs/native/plugins/menu/src/index.ts +107 -0
- package/vendor/@akanjs/native/plugins/network/android/NetworkPlugin.kt +124 -0
- package/vendor/@akanjs/native/plugins/network/ios/NetworkPlugin.swift +82 -0
- package/vendor/@akanjs/native/plugins/network/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/network/src/index.ts +59 -0
- package/vendor/@akanjs/native/plugins/network/src/web.ts +43 -0
- package/vendor/@akanjs/native/plugins/opener/android/OpenerPlugin.kt +81 -0
- package/vendor/@akanjs/native/plugins/opener/ios/OpenerPlugin.swift +83 -0
- package/vendor/@akanjs/native/plugins/opener/native-plugin.json +25 -0
- package/vendor/@akanjs/native/plugins/opener/src/desktop.ts +88 -0
- package/vendor/@akanjs/native/plugins/opener/src/index.ts +35 -0
- package/vendor/@akanjs/native/plugins/opener/src/url.ts +39 -0
- package/vendor/@akanjs/native/plugins/opener/src/web.ts +33 -0
- package/vendor/@akanjs/native/plugins/preferences/android/PreferencesPlugin.kt +44 -0
- package/vendor/@akanjs/native/plugins/preferences/ios/PreferencesPlugin.swift +47 -0
- package/vendor/@akanjs/native/plugins/preferences/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/preferences/src/desktop.ts +59 -0
- package/vendor/@akanjs/native/plugins/preferences/src/index.ts +75 -0
- package/vendor/@akanjs/native/plugins/preferences/src/web.ts +55 -0
- package/vendor/@akanjs/native/plugins/push/android/AkanNativeMessagingService.kt +17 -0
- package/vendor/@akanjs/native/plugins/push/android/PushPlugin.kt +257 -0
- package/vendor/@akanjs/native/plugins/push/ios/PushPlugin.swift +169 -0
- package/vendor/@akanjs/native/plugins/push/native-plugin.json +23 -0
- package/vendor/@akanjs/native/plugins/push/src/index.ts +73 -0
- package/vendor/@akanjs/native/plugins/screen/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/screen/src/desktop.ts +50 -0
- package/vendor/@akanjs/native/plugins/screen/src/index.ts +107 -0
- package/vendor/@akanjs/native/plugins/screen/src/web.ts +92 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/android/ScreenOrientationPlugin.kt +113 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/ios/ScreenOrientationPlugin.swift +150 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/index.ts +69 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/types.ts +26 -0
- package/vendor/@akanjs/native/plugins/screen-orientation/src/web.ts +67 -0
- package/vendor/@akanjs/native/plugins/secure-storage/android/SecureStoragePlugin.kt +184 -0
- package/vendor/@akanjs/native/plugins/secure-storage/ios/SecureStoragePlugin.swift +145 -0
- package/vendor/@akanjs/native/plugins/secure-storage/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/secure-storage/src/desktop.ts +332 -0
- package/vendor/@akanjs/native/plugins/secure-storage/src/index.ts +33 -0
- package/vendor/@akanjs/native/plugins/share/android/SharePlugin.kt +218 -0
- package/vendor/@akanjs/native/plugins/share/ios/SharePlugin.swift +142 -0
- package/vendor/@akanjs/native/plugins/share/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/share/src/index.ts +87 -0
- package/vendor/@akanjs/native/plugins/share/src/options.ts +43 -0
- package/vendor/@akanjs/native/plugins/share/src/web.ts +116 -0
- package/vendor/@akanjs/native/plugins/single-instance/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/desktop.ts +63 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/index.ts +32 -0
- package/vendor/@akanjs/native/plugins/single-instance/src/socket.ts +248 -0
- package/vendor/@akanjs/native/plugins/splash-screen/android/SplashScreenPlugin.kt +19 -0
- package/vendor/@akanjs/native/plugins/splash-screen/ios/SplashScreenPlugin.swift +20 -0
- package/vendor/@akanjs/native/plugins/splash-screen/native-plugin.json +17 -0
- package/vendor/@akanjs/native/plugins/splash-screen/src/index.ts +24 -0
- package/vendor/@akanjs/native/plugins/splash-screen/src/web.ts +17 -0
- package/vendor/@akanjs/native/plugins/sqlite/android/SqlStatements.kt +121 -0
- package/vendor/@akanjs/native/plugins/sqlite/android/SqlitePlugin.kt +327 -0
- package/vendor/@akanjs/native/plugins/sqlite/ios/SqlitePlugin.swift +361 -0
- package/vendor/@akanjs/native/plugins/sqlite/native-plugin.json +18 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/common.ts +221 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/desktop.ts +140 -0
- package/vendor/@akanjs/native/plugins/sqlite/src/index.ts +114 -0
- package/vendor/@akanjs/native/plugins/toast/android/ToastPlugin.kt +27 -0
- package/vendor/@akanjs/native/plugins/toast/native-plugin.json +14 -0
- package/vendor/@akanjs/native/plugins/toast/src/index.ts +41 -0
- package/vendor/@akanjs/native/plugins/toast/src/queue.ts +77 -0
- package/vendor/@akanjs/native/plugins/toast/src/web.ts +130 -0
- package/vendor/@akanjs/native/plugins/tray/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/tray/src/desktop.ts +73 -0
- package/vendor/@akanjs/native/plugins/tray/src/index.ts +111 -0
- package/vendor/@akanjs/native/plugins/updates/android/UpdatesPlugin.kt +290 -0
- package/vendor/@akanjs/native/plugins/updates/ios/UpdatesPlugin.swift +292 -0
- package/vendor/@akanjs/native/plugins/updates/native-plugin.json +19 -0
- package/vendor/@akanjs/native/plugins/updates/src/desktop.ts +558 -0
- package/vendor/@akanjs/native/plugins/updates/src/index.ts +95 -0
- package/vendor/@akanjs/native/plugins/window/native-plugin.json +32 -0
- package/vendor/@akanjs/native/plugins/window/src/desktop.ts +170 -0
- package/vendor/@akanjs/native/plugins/window/src/index.ts +342 -0
- package/vendor/@akanjs/native/plugins/window/src/web.ts +43 -0
- package/vendor/@akanjs/native/plugins/window-state/native-plugin.json +10 -0
- package/vendor/@akanjs/native/plugins/window-state/src/desktop.ts +73 -0
- package/vendor/@akanjs/native/plugins/window-state/src/index.ts +35 -0
- package/vendor/@akanjs/native/plugins/window-state/src/state.ts +146 -0
- package/webkit/bootCsr.tsx +26 -14
- package/webkit/index.ts +0 -2
- package/webkit/nativeNavigation.ts +116 -0
- package/webkit/nativePurchase.ts +93 -0
- package/webkit/useCamera.tsx +76 -71
- package/webkit/useCsrValues.ts +10 -124
- package/webkit/useGeoLocation.tsx +11 -13
- package/webkit/usePurchase.tsx +68 -123
- package/capacitor.base.config.ts +0 -140
- package/client/capacitor.ts +0 -252
- package/types/capacitor.base.config.d.ts +0 -3
- package/types/client/capacitor.d.ts +0 -290
- package/types/webkit/useCodepush.d.ts +0 -16
- package/types/webkit/useContact.d.ts +0 -11
- package/webkit/useCodepush.tsx +0 -76
- package/webkit/useContact.tsx +0 -45
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
package com.akanjs.plugins.securestorage
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.security.keystore.KeyGenParameterSpec
|
|
5
|
+
import android.security.keystore.KeyPermanentlyInvalidatedException
|
|
6
|
+
import android.security.keystore.KeyProperties
|
|
7
|
+
import android.util.Base64
|
|
8
|
+
import android.util.Log
|
|
9
|
+
import com.akanjs.runtime.AkanNativeErrorCode
|
|
10
|
+
import com.akanjs.runtime.AkanNativePluginContext
|
|
11
|
+
import com.akanjs.runtime.AkanNativeReply
|
|
12
|
+
import com.akanjs.runtime.AkanNativeVoidReply
|
|
13
|
+
import java.security.KeyStore
|
|
14
|
+
import java.util.concurrent.ExecutorService
|
|
15
|
+
import java.util.concurrent.Executors
|
|
16
|
+
import javax.crypto.AEADBadTagException
|
|
17
|
+
import javax.crypto.Cipher
|
|
18
|
+
import javax.crypto.KeyGenerator
|
|
19
|
+
import javax.crypto.SecretKey
|
|
20
|
+
import javax.crypto.spec.GCMParameterSpec
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* What androidx.security EncryptedSharedPreferences does, with framework APIs only (plugins.md §4.3):
|
|
24
|
+
* - One AES-256-GCM key in AndroidKeyStore (hardware-backed where the device has a TEE). It never
|
|
25
|
+
* leaves the keystore and needs no user authentication, so background work can read values.
|
|
26
|
+
* - Values are stored as "1:" + Base64(IV ‖ ciphertext ‖ tag) in their own SharedPreferences file.
|
|
27
|
+
* The keystore picks a fresh random IV per encryption (setRandomizedEncryptionRequired, default),
|
|
28
|
+
* and the key name is authenticated data, so values swapped between keys fail to decrypt.
|
|
29
|
+
* - Key names are stored in plain text (EncryptedSharedPreferences also encrypts them); they are
|
|
30
|
+
* identifiers, not secrets.
|
|
31
|
+
* - Keystore keys are not part of backups or device-to-device transfers. The shell sets
|
|
32
|
+
* allowBackup="false", but Android 12+ still copies app data in a device-to-device transfer, so a
|
|
33
|
+
* file can arrive without its key: without the key every entry is dropped, and an entry that fails
|
|
34
|
+
* to decrypt reads as null and is removed (expo-secure-store behaves the same way).
|
|
35
|
+
* - Keystore calls are IPC to keystore2 and first-use key generation takes ~100 ms, so everything
|
|
36
|
+
* runs on one worker thread, which also keeps set/get ordered. Writes use commit() on that thread
|
|
37
|
+
* so a resolved set() is on disk.
|
|
38
|
+
* StrongBox (setIsStrongBoxBacked) is not requested: it is much slower and missing on many devices.
|
|
39
|
+
* Arguments arrive decoded and type-checked by the generated SecureStoragePluginSpec (PL-10).
|
|
40
|
+
*/
|
|
41
|
+
class SecureStoragePlugin(context: AkanNativePluginContext) : SecureStoragePluginSpec {
|
|
42
|
+
private val prefs = context.activity.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
|
43
|
+
private val worker: ExecutorService = Executors.newSingleThreadExecutor { r -> Thread(r, "akan-native-secure-storage") }
|
|
44
|
+
private var key: SecretKey? = null // worker thread only
|
|
45
|
+
|
|
46
|
+
override fun get(args: SecureStorageGetArgs, reply: AkanNativeReply<SecureStorageGetResult>) {
|
|
47
|
+
if (!valid(args.key, reply)) return
|
|
48
|
+
val name = args.key
|
|
49
|
+
run(reply) { SecureStorageGetResult(value = read(name)) }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override fun set(args: SecureStorageSetArgs, reply: AkanNativeVoidReply) {
|
|
53
|
+
if (!valid(args.key, reply)) return
|
|
54
|
+
val name = args.key
|
|
55
|
+
run(reply) {
|
|
56
|
+
if (!prefs.edit().putString(name, encrypt(name, args.value)).commit()) throw IllegalStateException("could not write $PREFS")
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override fun remove(args: SecureStorageRemoveArgs, reply: AkanNativeVoidReply) {
|
|
61
|
+
if (!valid(args.key, reply)) return
|
|
62
|
+
val name = args.key
|
|
63
|
+
run(reply) {
|
|
64
|
+
prefs.edit().remove(name).commit()
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override fun keys(reply: AkanNativeReply<SecureStorageKeysResult>) = run(reply) { SecureStorageKeysResult(keys = readableKeys()) }
|
|
69
|
+
|
|
70
|
+
override fun clear(reply: AkanNativeVoidReply) = run(reply) {
|
|
71
|
+
prefs.edit().clear().commit()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override fun destroy() {
|
|
75
|
+
worker.shutdown()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private fun valid(key: String, reply: AkanNativeReply<*>): Boolean {
|
|
79
|
+
if (key.isNotEmpty()) return true
|
|
80
|
+
reply.reject(AkanNativeErrorCode.INVALID_ARGS, "key must be a non-empty string")
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private fun <T> run(reply: AkanNativeReply<T>, block: () -> T) {
|
|
85
|
+
worker.execute {
|
|
86
|
+
try {
|
|
87
|
+
reply.resolve(block())
|
|
88
|
+
} catch (e: Exception) { // GeneralSecurityException, KeyStoreException, ProviderException
|
|
89
|
+
Log.e("AkanNative", "secure-storage ${reply.call.method} failed", e)
|
|
90
|
+
reply.reject(AkanNativeErrorCode.INTERNAL, "secure-storage: $e")
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** The keystore key; with [create], generated when missing (and whatever was stored without it is dropped). */
|
|
96
|
+
private fun secretKey(create: Boolean): SecretKey? {
|
|
97
|
+
key?.let { return it }
|
|
98
|
+
val store = KeyStore.getInstance(KEYSTORE).apply { load(null) }
|
|
99
|
+
(store.getKey(ALIAS, null) as? SecretKey)?.let { return it.also { key = it } }
|
|
100
|
+
if (!create) return null
|
|
101
|
+
if (prefs.all.isNotEmpty()) {
|
|
102
|
+
Log.w("AkanNative", "secure-storage: the keystore key is gone (restore or device transfer), dropping ${prefs.all.size} entries")
|
|
103
|
+
prefs.edit().clear().commit()
|
|
104
|
+
}
|
|
105
|
+
val generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE)
|
|
106
|
+
generator.init(
|
|
107
|
+
KeyGenParameterSpec.Builder(ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
|
|
108
|
+
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
|
|
109
|
+
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
|
|
110
|
+
.setKeySize(256)
|
|
111
|
+
.build(),
|
|
112
|
+
)
|
|
113
|
+
return generator.generateKey().also { key = it }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private fun encrypt(name: String, value: String): String {
|
|
117
|
+
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
118
|
+
cipher.init(Cipher.ENCRYPT_MODE, secretKey(create = true))
|
|
119
|
+
cipher.updateAAD(aad(name))
|
|
120
|
+
val iv = cipher.iv
|
|
121
|
+
return FORMAT + Base64.encodeToString(iv + cipher.doFinal(value.toByteArray(Charsets.UTF_8)), Base64.NO_WRAP)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* null when the entry can never be read with the current key (another key, another name, or
|
|
126
|
+
* damaged: AEADBadTagException). Anything else the keystore throws may pass (a busy or
|
|
127
|
+
* restarting keystore daemon): it is thrown, the call fails, and the entry stays.
|
|
128
|
+
*/
|
|
129
|
+
private fun decrypt(name: String, stored: String, key: SecretKey): String? {
|
|
130
|
+
val bytes = if (stored.startsWith(FORMAT)) runCatching { Base64.decode(stored.substring(FORMAT.length), Base64.NO_WRAP) }.getOrNull() else null
|
|
131
|
+
if (bytes == null || bytes.size < IV_BYTES + TAG_BITS / 8) return null
|
|
132
|
+
return try {
|
|
133
|
+
val cipher = Cipher.getInstance(TRANSFORMATION)
|
|
134
|
+
cipher.init(Cipher.DECRYPT_MODE, key, GCMParameterSpec(TAG_BITS, bytes, 0, IV_BYTES))
|
|
135
|
+
cipher.updateAAD(aad(name))
|
|
136
|
+
String(cipher.doFinal(bytes, IV_BYTES, bytes.size - IV_BYTES), Charsets.UTF_8)
|
|
137
|
+
} catch (e: AEADBadTagException) {
|
|
138
|
+
null
|
|
139
|
+
} catch (e: KeyPermanentlyInvalidatedException) {
|
|
140
|
+
// The key can never decrypt again: drop it with every entry, so the next set() starts over.
|
|
141
|
+
KeyStore.getInstance(KEYSTORE).apply { load(null) }.deleteEntry(ALIAS)
|
|
142
|
+
this.key = null
|
|
143
|
+
prefs.edit().clear().commit()
|
|
144
|
+
throw e
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private fun read(name: String): String? {
|
|
149
|
+
val stored = prefs.getString(name, null) ?: return null
|
|
150
|
+
val key = secretKey(create = false) ?: return null
|
|
151
|
+
return decrypt(name, stored, key) ?: run {
|
|
152
|
+
Log.w("AkanNative", "secure-storage: $name cannot be decrypted, removing it")
|
|
153
|
+
prefs.edit().remove(name).commit()
|
|
154
|
+
null
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Only keys get() can return; unreadable entries are removed on the way. */
|
|
159
|
+
private fun readableKeys(): List<String> {
|
|
160
|
+
val all = prefs.all
|
|
161
|
+
if (all.isEmpty()) return emptyList()
|
|
162
|
+
val key = secretKey(create = false) ?: return emptyList()
|
|
163
|
+
val readable = ArrayList<String>()
|
|
164
|
+
val editor = prefs.edit()
|
|
165
|
+
var dropped = false
|
|
166
|
+
for ((name, stored) in all) {
|
|
167
|
+
if (stored is String && decrypt(name, stored, key) != null) readable.add(name) else { editor.remove(name); dropped = true }
|
|
168
|
+
}
|
|
169
|
+
if (dropped) editor.commit()
|
|
170
|
+
return readable.sorted()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private fun aad(name: String): ByteArray = "akan-native.secure-storage\u0000$name".toByteArray(Charsets.UTF_8)
|
|
174
|
+
|
|
175
|
+
private companion object {
|
|
176
|
+
const val PREFS = "akan-native.secure-storage"
|
|
177
|
+
const val KEYSTORE = "AndroidKeyStore"
|
|
178
|
+
const val ALIAS = "akan-native.secure-storage"
|
|
179
|
+
const val TRANSFORMATION = "AES/GCM/NoPadding"
|
|
180
|
+
const val FORMAT = "1:"
|
|
181
|
+
const val IV_BYTES = 12
|
|
182
|
+
const val TAG_BITS = 128
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Security
|
|
3
|
+
|
|
4
|
+
/// Keychain generic passwords: service "<bundle id>.akan-native.secure-storage", account = key, data = UTF-8.
|
|
5
|
+
/// - kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: readable in the background once the device
|
|
6
|
+
/// was unlocked after boot, never synced to iCloud Keychain and never restored onto another
|
|
7
|
+
/// device from a backup (expo-secure-store and capacitor secure storage default to WhenUnlocked,
|
|
8
|
+
/// which breaks token refresh in background tasks).
|
|
9
|
+
/// - Keychain items outlive the app: they are still there after an uninstall and reinstall. Wiping
|
|
10
|
+
/// them on "first launch" (a UserDefaults flag) is a known trap, because a prewarmed launch before
|
|
11
|
+
/// the first unlock reads UserDefaults as empty; apps that want it call clear() themselves.
|
|
12
|
+
/// - SecItem calls block on securityd, so they run on a serial queue (also keeps set/get ordered).
|
|
13
|
+
/// - Update first, add on errSecItemNotFound: SecItemAdd on an existing item fails with errSecDuplicateItem.
|
|
14
|
+
/// Arguments arrive decoded and type-checked by the generated SecureStoragePluginSpec (PL-10).
|
|
15
|
+
final class SecureStoragePlugin: SecureStoragePluginSpec {
|
|
16
|
+
static let id = "secure-storage"
|
|
17
|
+
private let service: String
|
|
18
|
+
private let queue = DispatchQueue(label: "com.akanjs.secure-storage")
|
|
19
|
+
|
|
20
|
+
init(context: AkanNativePluginContext) {
|
|
21
|
+
service = "\(Bundle.main.bundleIdentifier ?? "akan-native").akan-native.secure-storage"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func get(_ args: SecureStorageGetArgs, _ reply: AkanNativeReply<SecureStorageGetResult>) {
|
|
25
|
+
guard Self.valid(args.key, reply) else { return }
|
|
26
|
+
let key = args.key
|
|
27
|
+
let service = self.service
|
|
28
|
+
queue.async { Self.finish(reply) { try SecureStorageGetResult(value: Self.read(service, key)) } }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func set(_ args: SecureStorageSetArgs, _ reply: AkanNativeReply<Void>) {
|
|
32
|
+
guard Self.valid(args.key, reply) else { return }
|
|
33
|
+
let key = args.key
|
|
34
|
+
let service = self.service
|
|
35
|
+
let value = args.value
|
|
36
|
+
queue.async { Self.finish(reply) { try Self.write(service, key, Data(value.utf8)) } }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
func remove(_ args: SecureStorageRemoveArgs, _ reply: AkanNativeReply<Void>) {
|
|
40
|
+
guard Self.valid(args.key, reply) else { return }
|
|
41
|
+
let key = args.key
|
|
42
|
+
let service = self.service
|
|
43
|
+
queue.async {
|
|
44
|
+
Self.finish(reply) {
|
|
45
|
+
try Self.check(SecItemDelete(Self.query(service, key) as CFDictionary), allowNotFound: true)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func keys(_ reply: AkanNativeReply<SecureStorageKeysResult>) {
|
|
51
|
+
let service = self.service
|
|
52
|
+
queue.async { Self.finish(reply) { try SecureStorageKeysResult(keys: Self.accounts(service)) } }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func clear(_ reply: AkanNativeReply<Void>) {
|
|
56
|
+
let service = self.service
|
|
57
|
+
// On iOS SecItemDelete removes every match (on macOS' file-based keychain only the first).
|
|
58
|
+
queue.async {
|
|
59
|
+
Self.finish(reply) {
|
|
60
|
+
try Self.check(SecItemDelete(Self.query(service, nil) as CFDictionary), allowNotFound: true)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private static func valid<T>(_ key: String, _ reply: AkanNativeReply<T>) -> Bool {
|
|
66
|
+
if !key.isEmpty { return true }
|
|
67
|
+
reply.reject(.invalidArgs, "key must be a non-empty string")
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// MARK: Keychain (off the main actor)
|
|
72
|
+
|
|
73
|
+
private struct KeychainError: Error {
|
|
74
|
+
let status: OSStatus
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
nonisolated private static func finish<T>(_ reply: AkanNativeReply<T>, _ body: () throws -> T) {
|
|
78
|
+
do {
|
|
79
|
+
reply.resolve(try body())
|
|
80
|
+
} catch let error as KeychainError {
|
|
81
|
+
let text = SecCopyErrorMessageString(error.status, nil) as String? ?? "OSStatus \(error.status)"
|
|
82
|
+
let hint =
|
|
83
|
+
switch error.status {
|
|
84
|
+
// Before the first unlock after a reboot (prewarmed launch).
|
|
85
|
+
case errSecInteractionNotAllowed: " (the device has not been unlocked since it started)"
|
|
86
|
+
// An ad-hoc signed simulator build without the application-identifier entitlement
|
|
87
|
+
// (Xcode embeds it as simulated entitlements, a __TEXT,__entitlements section).
|
|
88
|
+
case errSecMissingEntitlement: " (the app has no application-identifier entitlement)"
|
|
89
|
+
default: ""
|
|
90
|
+
}
|
|
91
|
+
reply.reject(.internalError, "keychain: \(text)\(hint)")
|
|
92
|
+
} catch {
|
|
93
|
+
reply.reject(.internalError, "\(error)")
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
nonisolated private static func query(_ service: String, _ account: String?) -> [String: Any] {
|
|
98
|
+
var query: [String: Any] = [kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service]
|
|
99
|
+
if let account { query[kSecAttrAccount as String] = account }
|
|
100
|
+
return query
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
nonisolated private static func check(_ status: OSStatus, allowNotFound: Bool = false) throws {
|
|
104
|
+
if status == errSecSuccess || (allowNotFound && status == errSecItemNotFound) { return }
|
|
105
|
+
throw KeychainError(status: status)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
nonisolated private static func read(_ service: String, _ account: String) throws -> String? {
|
|
109
|
+
var query = query(service, account)
|
|
110
|
+
query[kSecReturnData as String] = true
|
|
111
|
+
query[kSecMatchLimit as String] = kSecMatchLimitOne
|
|
112
|
+
var result: CFTypeRef?
|
|
113
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
114
|
+
if status == errSecItemNotFound { return nil }
|
|
115
|
+
try check(status)
|
|
116
|
+
guard let data = result as? Data else { return nil }
|
|
117
|
+
guard let text = String(data: data, encoding: .utf8) else {
|
|
118
|
+
throw NSError(domain: "akan-native", code: 1, userInfo: [NSLocalizedDescriptionKey: "\(account) does not hold UTF-8 text"])
|
|
119
|
+
}
|
|
120
|
+
return text
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
nonisolated private static func write(_ service: String, _ account: String, _ data: Data) throws {
|
|
124
|
+
let attributes: [String: Any] = [
|
|
125
|
+
kSecValueData as String: data,
|
|
126
|
+
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
|
|
127
|
+
]
|
|
128
|
+
let status = SecItemUpdate(query(service, account) as CFDictionary, attributes as CFDictionary)
|
|
129
|
+
if status != errSecItemNotFound { return try check(status) }
|
|
130
|
+
let add = query(service, account).merging(attributes) { $1 }
|
|
131
|
+
try check(SecItemAdd(add as CFDictionary, nil))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
nonisolated private static func accounts(_ service: String) throws -> [String] {
|
|
135
|
+
var query = query(service, nil)
|
|
136
|
+
query[kSecReturnAttributes as String] = true
|
|
137
|
+
query[kSecMatchLimit as String] = kSecMatchLimitAll
|
|
138
|
+
var result: CFTypeRef?
|
|
139
|
+
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
|
140
|
+
if status == errSecItemNotFound { return [] }
|
|
141
|
+
try check(status)
|
|
142
|
+
let items = result as? [[String: Any]] ?? []
|
|
143
|
+
return items.compactMap { $0[kSecAttrAccount as String] as? String }.sorted()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "secure-storage",
|
|
3
|
+
"apiVersion": 1,
|
|
4
|
+
"methods": ["get", "set", "remove", "keys", "clear"],
|
|
5
|
+
"events": [],
|
|
6
|
+
"codegen": true,
|
|
7
|
+
"web": null,
|
|
8
|
+
"desktop": "./src/desktop.ts",
|
|
9
|
+
"ios": {
|
|
10
|
+
"sources": ["ios/*.swift"],
|
|
11
|
+
"class": "SecureStoragePlugin",
|
|
12
|
+
"frameworks": ["Security"]
|
|
13
|
+
},
|
|
14
|
+
"android": {
|
|
15
|
+
"sources": ["android/*.kt"],
|
|
16
|
+
"class": "com.akanjs.plugins.securestorage.SecureStoragePlugin"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { AkanNativeError } from "../../../packages/core/src/index.ts";
|
|
7
|
+
import { type DesktopContext, defineDesktopPlugin } from "../../../packages/desktop/src/plugin.ts";
|
|
8
|
+
import type { SecureStorageApi } from "./index.ts";
|
|
9
|
+
|
|
10
|
+
const SECURITY = "/usr/bin/security";
|
|
11
|
+
const ACCOUNT = "data-key";
|
|
12
|
+
/** The in-process item's account (another item than the tool's, see above). */
|
|
13
|
+
const APP_ACCOUNT = "data-key.app";
|
|
14
|
+
const NOT_FOUND = 44;
|
|
15
|
+
const DUPLICATE = 45;
|
|
16
|
+
|
|
17
|
+
export interface DesktopSecureStorageOptions {
|
|
18
|
+
/** Keychain service of the data key. Default `<app id>.akan-native.secure-storage`. */
|
|
19
|
+
service?: (ctx: DesktopContext) => string;
|
|
20
|
+
/** The encrypted values. Default `<appDataDir>/secure-storage.json`. */
|
|
21
|
+
file?: (ctx: DesktopContext) => string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface Store {
|
|
25
|
+
/**
|
|
26
|
+
* Set on Windows and Linux, and on macOS when the app is signed with a Team ID: the key lives in
|
|
27
|
+
* an item the shell reads and writes (keychain.* ops), not through /usr/bin/security.
|
|
28
|
+
*/
|
|
29
|
+
shell: DesktopContext["shell"] | null;
|
|
30
|
+
/** The account of the shell's item: APP_ACCOUNT on macOS (see above), ACCOUNT elsewhere. */
|
|
31
|
+
account: string;
|
|
32
|
+
service: string;
|
|
33
|
+
label: string;
|
|
34
|
+
file: string;
|
|
35
|
+
key: Buffer | null;
|
|
36
|
+
reading: Promise<Buffer | null> | null;
|
|
37
|
+
creating: Promise<Buffer> | null;
|
|
38
|
+
entries: Map<string, string> | null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function run(argv: string[], input?: string): Promise<{ code: number; out: string; err: string }> {
|
|
42
|
+
const proc = Bun.spawn(argv, {
|
|
43
|
+
stdin: input === undefined ? "ignore" : new Blob([input]),
|
|
44
|
+
stdout: "pipe",
|
|
45
|
+
stderr: "pipe",
|
|
46
|
+
});
|
|
47
|
+
const [out, err, code] = await Promise.all([
|
|
48
|
+
new Response(proc.stdout).text(),
|
|
49
|
+
new Response(proc.stderr).text(),
|
|
50
|
+
proc.exited,
|
|
51
|
+
]);
|
|
52
|
+
return { code, out, err };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** A word for `security -i`, whose tokenizer takes "…" with \" and \\ escapes. Lines cannot hold control characters. */
|
|
56
|
+
export function quoteForSecurity(text: string): string {
|
|
57
|
+
const printable = [...text].map((c) => (c.charCodeAt(0) < 0x20 || c.charCodeAt(0) === 0x7f ? " " : c)).join("");
|
|
58
|
+
return `"${printable.replace(/[\\"]/g, "\\$&")}"`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const hexKey = (store: Store, hex: string) => {
|
|
62
|
+
if (!/^[0-9a-f]{64}$/.test(hex))
|
|
63
|
+
throw new AkanNativeError(
|
|
64
|
+
"INTERNAL",
|
|
65
|
+
`the stored item ${store.service} (${store.account}) is not an akan-native secure storage key`,
|
|
66
|
+
);
|
|
67
|
+
return Buffer.from(hex, "hex");
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
async function readKey(store: Store): Promise<Buffer | null> {
|
|
71
|
+
if (store.shell) {
|
|
72
|
+
const { value } = (await store.shell("keychain.get", { service: store.service, account: store.account })) as {
|
|
73
|
+
value: string | null;
|
|
74
|
+
};
|
|
75
|
+
if (value) return hexKey(store, value);
|
|
76
|
+
if (process.platform !== "darwin") return null;
|
|
77
|
+
const old = await readToolKey(store);
|
|
78
|
+
if (!old) return null;
|
|
79
|
+
await store.shell("keychain.set", {
|
|
80
|
+
service: store.service,
|
|
81
|
+
account: store.account,
|
|
82
|
+
value: old.toString("hex"),
|
|
83
|
+
label: store.label,
|
|
84
|
+
});
|
|
85
|
+
await run([SECURITY, "delete-generic-password", "-s", store.service, "-a", ACCOUNT]);
|
|
86
|
+
return old;
|
|
87
|
+
}
|
|
88
|
+
return readToolKey(store);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function readToolKey(store: Store): Promise<Buffer | null> {
|
|
92
|
+
const { code, out, err } = await run([SECURITY, "find-generic-password", "-s", store.service, "-a", ACCOUNT, "-w"]);
|
|
93
|
+
if (code === NOT_FOUND) return null;
|
|
94
|
+
if (code !== 0)
|
|
95
|
+
throw new AkanNativeError(
|
|
96
|
+
"INTERNAL",
|
|
97
|
+
`reading the secure storage key from the Keychain failed (${code}): ${err.trim()}`,
|
|
98
|
+
);
|
|
99
|
+
const hex = out.trim();
|
|
100
|
+
if (!/^[0-9a-f]{64}$/.test(hex))
|
|
101
|
+
throw new AkanNativeError(
|
|
102
|
+
"INTERNAL",
|
|
103
|
+
`the Keychain item ${store.service} is not an akan-native secure storage key`,
|
|
104
|
+
);
|
|
105
|
+
return Buffer.from(hex, "hex");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function createKey(store: Store): Promise<Buffer> {
|
|
109
|
+
const hex = randomBytes(32).toString("hex");
|
|
110
|
+
if (store.shell) {
|
|
111
|
+
const existing = await readKey(store);
|
|
112
|
+
if (existing) return existing;
|
|
113
|
+
|
|
114
|
+
await store.shell("keychain.set", {
|
|
115
|
+
service: store.service,
|
|
116
|
+
account: store.account,
|
|
117
|
+
value: hex,
|
|
118
|
+
label: store.label,
|
|
119
|
+
});
|
|
120
|
+
return Buffer.from(hex, "hex");
|
|
121
|
+
}
|
|
122
|
+
const command = [
|
|
123
|
+
"add-generic-password",
|
|
124
|
+
"-s",
|
|
125
|
+
quoteForSecurity(store.service),
|
|
126
|
+
"-a",
|
|
127
|
+
quoteForSecurity(ACCOUNT),
|
|
128
|
+
"-l",
|
|
129
|
+
quoteForSecurity(store.label),
|
|
130
|
+
"-j",
|
|
131
|
+
quoteForSecurity(
|
|
132
|
+
"akan-native: encrypts this app's secure-storage.json. Deleting it makes the stored values unreadable.",
|
|
133
|
+
),
|
|
134
|
+
|
|
135
|
+
"-X",
|
|
136
|
+
Buffer.from(hex, "latin1").toString("hex"),
|
|
137
|
+
].join(" ");
|
|
138
|
+
const { code, err } = await run([SECURITY, "-i"], `${command}\n`);
|
|
139
|
+
if (code === DUPLICATE) {
|
|
140
|
+
const existing = await readKey(store);
|
|
141
|
+
if (existing) return existing;
|
|
142
|
+
}
|
|
143
|
+
if (code !== 0)
|
|
144
|
+
throw new AkanNativeError(
|
|
145
|
+
"INTERNAL",
|
|
146
|
+
`storing the secure storage key in the Keychain failed (${code}): ${err.trim()}`,
|
|
147
|
+
);
|
|
148
|
+
return Buffer.from(hex, "hex");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function entries(store: Store): Map<string, string> {
|
|
152
|
+
if (store.entries) return store.entries;
|
|
153
|
+
const map = new Map<string, string>();
|
|
154
|
+
if (existsSync(store.file)) {
|
|
155
|
+
try {
|
|
156
|
+
const data = JSON.parse(readFileSync(store.file, "utf8")) as { v?: unknown; entries?: Record<string, unknown> };
|
|
157
|
+
if (data.v === 1 && data.entries && typeof data.entries === "object") {
|
|
158
|
+
for (const [key, value] of Object.entries(data.entries)) if (typeof value === "string") map.set(key, value);
|
|
159
|
+
}
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error(`[akan-native] ${store.file} is unreadable, starting empty`, error);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
store.entries = map;
|
|
165
|
+
return map;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function save(store: Store): void {
|
|
169
|
+
mkdirSync(dirname(store.file), { recursive: true });
|
|
170
|
+
|
|
171
|
+
const tmp = `${store.file}.tmp`;
|
|
172
|
+
writeFileSync(tmp, JSON.stringify({ v: 1, entries: Object.fromEntries(entries(store)) }), { mode: 0o600 });
|
|
173
|
+
renameSync(tmp, store.file);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function dataKey(store: Store, create: true): Promise<Buffer>;
|
|
177
|
+
function dataKey(store: Store, create: false): Promise<Buffer | null>;
|
|
178
|
+
function dataKey(store: Store, create: boolean): Promise<Buffer | null> {
|
|
179
|
+
if (store.key) return Promise.resolve(store.key);
|
|
180
|
+
if (create) {
|
|
181
|
+
|
|
182
|
+
store.creating ??= (async () => {
|
|
183
|
+
let key = await readKey(store);
|
|
184
|
+
if (!key) {
|
|
185
|
+
key = await createKey(store);
|
|
186
|
+
|
|
187
|
+
if (entries(store).size > 0) {
|
|
188
|
+
entries(store).clear();
|
|
189
|
+
save(store);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
store.key = key;
|
|
193
|
+
return key;
|
|
194
|
+
})().finally(() => {
|
|
195
|
+
store.creating = null;
|
|
196
|
+
});
|
|
197
|
+
return store.creating;
|
|
198
|
+
}
|
|
199
|
+
store.reading ??= readKey(store)
|
|
200
|
+
.then((key) => {
|
|
201
|
+
if (key) store.key = key;
|
|
202
|
+
return key;
|
|
203
|
+
})
|
|
204
|
+
.finally(() => {
|
|
205
|
+
store.reading = null;
|
|
206
|
+
});
|
|
207
|
+
return store.reading;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** AAD binds each value to its key: swapping entries in the file makes them unreadable. */
|
|
211
|
+
const aad = (name: string) => Buffer.from(`akan-native.secure-storage\0${name}`, "utf8");
|
|
212
|
+
|
|
213
|
+
export function encrypt(key: Buffer, name: string, value: string): string {
|
|
214
|
+
const iv = randomBytes(12);
|
|
215
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
216
|
+
cipher.setAAD(aad(name));
|
|
217
|
+
const body = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
218
|
+
return Buffer.concat([iv, body, cipher.getAuthTag()]).toString("base64");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** null when the entry was written with another key, for another name, or is damaged. */
|
|
222
|
+
export function decrypt(key: Buffer, name: string, blob: string): string | null {
|
|
223
|
+
try {
|
|
224
|
+
const bytes = Buffer.from(blob, "base64");
|
|
225
|
+
if (bytes.length < 12 + 16) return null;
|
|
226
|
+
const decipher = createDecipheriv("aes-256-gcm", key, bytes.subarray(0, 12));
|
|
227
|
+
decipher.setAAD(aad(name));
|
|
228
|
+
decipher.setAuthTag(bytes.subarray(bytes.length - 16));
|
|
229
|
+
return Buffer.concat([decipher.update(bytes.subarray(12, bytes.length - 16)), decipher.final()]).toString("utf8");
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function checkKey(key: unknown): string {
|
|
236
|
+
if (typeof key !== "string" || key.length === 0)
|
|
237
|
+
throw new AkanNativeError("INVALID_ARGS", "key must be a non-empty string");
|
|
238
|
+
return key;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** shell.json of the running .app says it is signed with a Team ID (see above). */
|
|
242
|
+
function signedWithTeam(): boolean {
|
|
243
|
+
const macos = dirname(process.execPath);
|
|
244
|
+
const shell = join(dirname(macos), "Resources", "shell.json");
|
|
245
|
+
try {
|
|
246
|
+
return (JSON.parse(readFileSync(shell, "utf8")) as { signing?: string }).signing === "team";
|
|
247
|
+
} catch {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function createDesktopSecureStorage(options: DesktopSecureStorageOptions = {}) {
|
|
253
|
+
const stores = new Map<string, Store>();
|
|
254
|
+
const storeFor = (ctx: DesktopContext): Store => {
|
|
255
|
+
const service = options.service?.(ctx) ?? `${ctx.app.id}.akan-native.secure-storage`;
|
|
256
|
+
const file = options.file?.(ctx) ?? join(ctx.appDataDir, "secure-storage.json");
|
|
257
|
+
const id = `${service}\0${file}`;
|
|
258
|
+
let store = stores.get(id);
|
|
259
|
+
if (!store) {
|
|
260
|
+
const mac = process.platform === "darwin";
|
|
261
|
+
const shell = !mac || signedWithTeam() ? ctx.shell : null;
|
|
262
|
+
store = {
|
|
263
|
+
shell,
|
|
264
|
+
account: mac ? APP_ACCOUNT : ACCOUNT,
|
|
265
|
+
service,
|
|
266
|
+
label: `${ctx.app.name} secure storage`,
|
|
267
|
+
file,
|
|
268
|
+
key: null,
|
|
269
|
+
reading: null,
|
|
270
|
+
creating: null,
|
|
271
|
+
entries: null,
|
|
272
|
+
};
|
|
273
|
+
stores.set(id, store);
|
|
274
|
+
}
|
|
275
|
+
return store;
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
return defineDesktopPlugin<SecureStorageApi>({
|
|
279
|
+
id: "secure-storage",
|
|
280
|
+
methods: {
|
|
281
|
+
async get(args, ctx) {
|
|
282
|
+
const name = checkKey(args?.key);
|
|
283
|
+
const store = storeFor(ctx);
|
|
284
|
+
const blob = entries(store).get(name);
|
|
285
|
+
if (blob === undefined) return { value: null };
|
|
286
|
+
const key = await dataKey(store, false);
|
|
287
|
+
const value = key ? decrypt(key, name, blob) : null;
|
|
288
|
+
if (value === null && key && entries(store).get(name) === blob) {
|
|
289
|
+
entries(store).delete(name);
|
|
290
|
+
save(store);
|
|
291
|
+
}
|
|
292
|
+
return { value };
|
|
293
|
+
},
|
|
294
|
+
async set(args, ctx) {
|
|
295
|
+
const name = checkKey(args?.key);
|
|
296
|
+
if (typeof args.value !== "string") throw new AkanNativeError("INVALID_ARGS", "value must be a string");
|
|
297
|
+
const store = storeFor(ctx);
|
|
298
|
+
const key = await dataKey(store, true);
|
|
299
|
+
entries(store).set(name, encrypt(key, name, args.value));
|
|
300
|
+
save(store);
|
|
301
|
+
},
|
|
302
|
+
remove(args, ctx) {
|
|
303
|
+
const name = checkKey(args?.key);
|
|
304
|
+
const store = storeFor(ctx);
|
|
305
|
+
if (entries(store).delete(name)) save(store);
|
|
306
|
+
},
|
|
307
|
+
async keys(_args, ctx) {
|
|
308
|
+
const store = storeFor(ctx);
|
|
309
|
+
if (entries(store).size === 0) return { keys: [] };
|
|
310
|
+
const key = await dataKey(store, false);
|
|
311
|
+
if (!key) return { keys: [] };
|
|
312
|
+
|
|
313
|
+
const readable = [...entries(store)].filter(([name, blob]) => decrypt(key, name, blob) !== null);
|
|
314
|
+
if (readable.length !== entries(store).size) {
|
|
315
|
+
store.entries = new Map(readable);
|
|
316
|
+
save(store);
|
|
317
|
+
}
|
|
318
|
+
return { keys: readable.map(([name]) => name).sort() };
|
|
319
|
+
},
|
|
320
|
+
clear(_args, ctx) {
|
|
321
|
+
const store = storeFor(ctx);
|
|
322
|
+
|
|
323
|
+
if (entries(store).size > 0 || existsSync(store.file)) {
|
|
324
|
+
entries(store).clear();
|
|
325
|
+
save(store);
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export default createDesktopSecureStorage();
|