@nitra/cap 7.1.0 → 7.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ # Проверка и установка новой версии приложение в маркете
2
+
3
+ ## API
4
+
5
+ - [`updateApp(...)`](#updateapp)
6
+
7
+ ### updateApp(...)
8
+
9
+ ```typescript
10
+ updateApp(isImmediate: boolean | undefined, isMandatory: boolean | undefined ) => Promise<void>
11
+ ```
12
+
13
+ Проверка и установка новой версии приложение в маркете
14
+
15
+ Для **Android**, через [In-app updates](https://developer.android.com/guide/playcore/in-app-updates)]
16
+ Для **IOS**, открываем App Store
17
+
18
+ | Параметр | Тип | Описание |
19
+ |-------------------|-----------|-------------------------------------------------------------------|
20
+ | **`isImmediate`** | `boolean` | только Android, обновление "в полный" экран, по-умолчанию - false |
21
+ | **`isMandatory`** | `boolean` | только Android, обязательно обновление, по-умолчанию - false |
22
+
23
+ ---
@@ -0,0 +1,49 @@
1
+ import { Capacitor } from '@capacitor/core'
2
+ import {
3
+ AppUpdate,
4
+ AppUpdateAvailability,
5
+ FlexibleUpdateInstallStatus,
6
+ AppUpdateResultCode
7
+ } from '@capawesome/capacitor-app-update'
8
+
9
+ /**
10
+ * Проверка наличия обновления, для Android установка обновления, IOS - открытие AppStore
11
+ * @async
12
+ * @function updateApp
13
+ * @param {boolean} isImmediate - только Android, обновление "в полный" экран, по-умолчанию - false
14
+ * @param {boolean} isMandatory - только Android, обязательно обновление, по-умолчанию - false
15
+ */
16
+ export async function updateApp(isImmediate, isMandatory) {
17
+ if (!Capacitor.isNativePlatform() || !Capacitor.isPluginAvailable('AppUpdate')) {
18
+ return
19
+ }
20
+ const { updateAvailability } = await AppUpdate.getAppUpdateInfo()
21
+ if (updateAvailability !== AppUpdateAvailability.UPDATE_AVAILABLE) {
22
+ return
23
+ }
24
+ if (Capacitor.getPlatform() === 'ios') {
25
+ await AppUpdate.openAppStore()
26
+ return
27
+ }
28
+ if (Capacitor.getPlatform() === 'android') {
29
+ if (isImmediate) {
30
+ const appUpdateResult = await AppUpdate.performImmediateUpdate()
31
+ if (
32
+ isMandatory &&
33
+ (appUpdateResult.code === AppUpdateResultCode.CANCELED ||
34
+ appUpdateResult.code === AppUpdateResultCode.NOT_ALLOWED)
35
+ ) {
36
+ await updateApp(isImmediate, isMandatory)
37
+ }
38
+ } else {
39
+ AppUpdate.addListener('onFlexibleUpdateStateChange', flexibleUpdateState => {
40
+ if (flexibleUpdateState.installStatus === FlexibleUpdateInstallStatus.DOWNLOADED) {
41
+ AppUpdate.removeAllListeners()
42
+ AppUpdate.completeFlexibleUpdate()
43
+ }
44
+ })
45
+ await AppUpdate.startFlexibleUpdate()
46
+ }
47
+ return
48
+ }
49
+ }
package/auth/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { default as NCapLoginApple } from './NCapLoginApple.vue'
2
+ export { default as NCapLoginGoogle } from './NCapLoginGoogle.vue'
3
+ export { default as NCapLoginMulti } from './NCapLoginMulti.vue'
4
+ export { default as NDialog } from './NDialog.vue'
5
+ export { default as NForgotPass } from './NForgotPass.vue'
6
+ export { default as NLoginGoogle } from './NLoginGoogle.vue'
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './app-update'
2
+ export * from './save-token'
3
+ export * from './auth'
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@nitra/cap",
3
- "version": "7.1.0",
3
+ "version": "7.1.2",
4
4
  "description": "Nitra capacitor components",
5
5
  "type": "module",
6
6
  "exports": {
7
- ".": "./index.js",
8
- "./auth/*": "./auth/*"
7
+ ".": "./index.js"
9
8
  },
10
9
  "scripts": {
11
10
  "fix": "yarn dlx eslint --fix . && npx prettier --write . "
@@ -31,8 +30,5 @@
31
30
  "@nitra/vite-boot": "^3.7.1",
32
31
  "@simplewebauthn/browser": "^11.0.0",
33
32
  "firebase": "^12.3.0"
34
- },
35
- "files": [
36
- "auth"
37
- ]
33
+ }
38
34
  }
@@ -0,0 +1,121 @@
1
+ # Receiving and Saving User Push Tokens
2
+
3
+ ## Description
4
+
5
+ This library is designed to handle obtaining and saving Firebase push tokens on the client side. It supports both mobile platforms (via Capacitor) and web platforms. The main function, `saveToken`, retrieves a push token from Firebase, stores it locally, and sends it to your server.
6
+
7
+ This library interacts with Firebase for token management and Capacitor to check the platform and permissions. It ensures that push tokens are properly handled, regardless of whether the platform is iOS, Android, or Web.
8
+
9
+ ## API
10
+
11
+ ### `saveToken()`
12
+
13
+ ```typescript
14
+ saveToken() => Promise<void>
15
+ ```
16
+
17
+ ## usage the library
18
+
19
+ ### To use this package, you should add this env to your project where you want to provide push notifications
20
+
21
+ `VITE_APP=test`
22
+ `VITE_PROJECT_ID=test`
23
+ `VITE_VAPID_KEY=test`
24
+ `VITE_API_KEY=test`
25
+ `VITE_AUTH_DOMAIN=test`
26
+ `VITE_STORAGE_BUCKET=test`
27
+ `VITE_MESSAGING_SENDER_ID=test`
28
+ `VITE_APP_ID=test`
29
+
30
+ ## example in node
31
+
32
+ ### Using function after login
33
+
34
+ ```jsx
35
+ <template>
36
+ <n-code :on-token-checked="saveToken" />
37
+ </template>
38
+
39
+ <script setup>
40
+ import NCode from '@nitra/abie-components/auth/NCode.vue'
41
+ import { saveToken } from '@nitra/cap'
42
+
43
+ await saveToken()
44
+ </script>
45
+
46
+ <route lang="yaml">
47
+ meta:
48
+ layout: blank
49
+ </route>
50
+
51
+ ```
52
+
53
+ ## Environment Variable Validation with Vite
54
+
55
+ ### To ensure that the required environment variables are set and the sw.js file is added to the project, add the following to your vite.config.js
56
+
57
+ ```typescript
58
+ import { requireEnvVar } from '@nitra/vite-check-env'
59
+ import { defineConfig, loadEnv } from 'vite'
60
+ import { build } from 'esbuild'
61
+
62
+ export default {
63
+ plugins: [
64
+ {
65
+ name: 'nitra-service-worker-transform',
66
+ apply: 'build',
67
+ transformIndexHtml() {
68
+ build({
69
+ plugins: [env(loadEnv(mode, '.'))],
70
+ format: 'esm',
71
+ entryPoints: [path.join(process.cwd(), '../node_modules/@nitra/cap/save-token/sw.js')],
72
+ outfile: path.join(process.cwd(), 'dist', 'sw.js')
73
+ })
74
+ }
75
+ },
76
+ requireEnvVar([
77
+ 'VITE_VAPID_KEY',
78
+ 'VITE_APP',
79
+ 'VITE_API_KEY',
80
+ 'VITE_AUTH_DOMAIN',
81
+ 'VITE_PROJECT_ID',
82
+ 'VITE_STORAGE_BUCKET',
83
+ 'VITE_MESSAGING_SENDER_ID',
84
+ 'VITE_APP_ID'
85
+ ])
86
+ ]
87
+ }
88
+
89
+ function env(props) {
90
+ return {
91
+ name: 'env',
92
+ setup: build => {
93
+ const options = build.initialOptions
94
+ const define = options.define ?? {}
95
+ for (const k in props) {
96
+ define[`import.meta.env.${k}`] = JSON.stringify(props[k])
97
+ }
98
+ options.define = {
99
+ ...define
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ # For local test you can add this code
107
+ if (process.env.npm_lifecycle_event === 'start-remote-dev') {
108
+ proxy['^/n-push/.*'] = ''
109
+ } else {
110
+ proxy['^/n-push/.*'] = '<http://0.0.0.0:8090>'
111
+ }
112
+
113
+ /n-push/ - url of the notify project
114
+
115
+ The `notify project` is a server-side component designed to handle API requests for saving user push tokens. It uses the Fastify framework and JWT-based security for authentication.
116
+
117
+ ### Install the plugin in the project directory
118
+
119
+ ```typescript
120
+ yarn add -D @nitra/vite-check-env
121
+ ```
@@ -0,0 +1,108 @@
1
+ import { Capacitor } from '@capacitor/core'
2
+ import { FirebaseMessaging } from '@capacitor-firebase/messaging'
3
+ import { getToken } from '@nitra/vite-boot/token'
4
+ import { initializeApp, getApps } from 'firebase/app'
5
+
6
+ /**
7
+ * Save the Firebase push token for a given app and platform.
8
+ * @returns {Promise<void>}
9
+ */
10
+ export async function saveToken() {
11
+ try {
12
+ if (localStorage.getItem(`pushToken_${import.meta.env.VITE_APP}`)) {
13
+ console.log('Push Token is already exists.')
14
+
15
+ return
16
+ }
17
+
18
+ // Check if Firebase is already initialized
19
+ if (getApps().length === 0) {
20
+ initializeApp({
21
+ apiKey: import.meta.env.VITE_API_KEY,
22
+ authDomain: import.meta.env.VITE_AUTH_DOMAIN,
23
+ projectId: import.meta.env.VITE_PROJECT_ID,
24
+ storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
25
+ messagingSenderId: import.meta.env.VITE_MESSAGING_SENDER_ID,
26
+ appId: import.meta.env.VITE_APP_ID
27
+ })
28
+ }
29
+
30
+ if (Capacitor.isNativePlatform() && !Capacitor.isPluginAvailable('FirebaseMessaging')) {
31
+ console.error('FirebaseMessaging plugin is not available')
32
+
33
+ return
34
+ }
35
+
36
+ let permissions = await FirebaseMessaging.checkPermissions()
37
+
38
+ if (permissions.receive !== 'granted') {
39
+ console.warn('Permissions are not granted, try to request permissions...')
40
+
41
+ let permissionsRequest = await FirebaseMessaging.requestPermissions()
42
+
43
+ if (permissionsRequest.receive !== 'granted') {
44
+ console.error('Permissions are not granted, exiting...')
45
+
46
+ return
47
+ }
48
+ }
49
+
50
+ const pushToken = Capacitor.isNativePlatform()
51
+ ? await FirebaseMessaging.getToken() // For iOS/Android
52
+ : await getWebPushToken()
53
+
54
+ if (!pushToken?.token && typeof pushToken?.token !== 'string') {
55
+ console.error('Token is undefined exiting...')
56
+
57
+ return
58
+ }
59
+
60
+ await sendTokenToServer(pushToken.token)
61
+ } catch (error) {
62
+ console.error('Error while saving push token:', error)
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Get the Firebase push token for web platform.
68
+ * @returns {Promise<object>} Web Push token
69
+ */
70
+ async function getWebPushToken() {
71
+ try {
72
+ const serviceWorkerRegistration = await navigator.serviceWorker.register('sw.js', {
73
+ type: 'module'
74
+ })
75
+
76
+ return await FirebaseMessaging.getToken({
77
+ vapidKey: import.meta.env.VITE_VAPID_KEY,
78
+ serviceWorkerRegistration
79
+ })
80
+ } catch (error) {
81
+ console.error('Error getting web push token:', error)
82
+ throw error
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Send the Firebase push token to the server.
88
+ * @param {string} pushToken - The push token returned by Firebase Messaging.
89
+ * @returns {Promise<void>}
90
+ */
91
+ async function sendTokenToServer(pushToken) {
92
+ const response = await fetch('/n-push/save-user', {
93
+ method: 'POST',
94
+ headers: {
95
+ 'Content-Type': 'application/json',
96
+ authorization: `Bearer ${getToken()}`
97
+ },
98
+ body: JSON.stringify({
99
+ platform: Capacitor.getPlatform(),
100
+ app: import.meta.env.VITE_APP,
101
+ token: pushToken
102
+ })
103
+ })
104
+
105
+ if (response.ok) {
106
+ localStorage.setItem(`pushToken_${import.meta.env.VITE_APP}`, pushToken)
107
+ }
108
+ }
@@ -0,0 +1,13 @@
1
+ import { getMessaging } from 'https://www.gstatic.com/firebasejs/10.13.2/firebase-messaging-sw.js'
2
+ import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.13.2/firebase-app.js'
3
+
4
+ const firebaseApp = initializeApp({
5
+ apiKey: import.meta.env.VITE_API_KEY,
6
+ authDomain: import.meta.env.VITE_AUTH_DOMAIN,
7
+ projectId: import.meta.env.VITE_PROJECT_ID,
8
+ storageBucket: import.meta.env.VITE_STORAGE_BUCKET,
9
+ messagingSenderId: import.meta.env.VITE_MESSAGING_SENDER_ID,
10
+ appId: import.meta.env.VITE_APP_ID
11
+ })
12
+
13
+ export const messaging = getMessaging(firebaseApp)