@sudobility/di_web 0.1.95 → 0.1.99

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/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { WebInfoService, createWebInfoService, initializeInfoService, getInfoService, resetInfoService, InfoBanner, useInfoBanner, type BannerState, type BannerStateListener, } from './info/index.js';
2
2
  export { FirebaseAnalyticsService, initializeFirebaseAnalytics, getAnalyticsService, resetAnalyticsService, type AnalyticsEventParams, initializeWebApp, type WebAppInitOptions, type RevenueCatConfig, } from './initialize/index.js';
3
3
  export { getFirebaseService, initializeFirebaseService, resetFirebaseService, WebFirebaseService, createWebFirebaseService, } from '@sudobility/di/web';
4
+ export { registerServiceWorker, unregisterServiceWorker, } from './sw/register.js';
4
5
  export type { AnalyticsEvent as FirebaseAnalyticsEvent, AnalyticsService, RemoteConfigValue, RemoteConfigService, FCMNotificationPayload, FCMDataPayload, FCMMessage, FCMPermissionState, FCMState, FCMService, FirebaseService, FirebaseConfig, FirebaseInitOptions, } from '@sudobility/di/web';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAEL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,oBAAoB,EAEzB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,cAAc,IAAI,sBAAsB,EACxC,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,GACpB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAEL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,oBAAoB,EAEzB,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAG1B,YAAY,EACV,cAAc,IAAI,sBAAsB,EACxC,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,cAAc,EACd,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,GACpB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { WebInfoService, createWebInfoService, initializeInfoService, getInfoService, resetInfoService, InfoBanner, useInfoBanner, } from './info/index.js';
2
2
  export { FirebaseAnalyticsService, initializeFirebaseAnalytics, getAnalyticsService, resetAnalyticsService, initializeWebApp, } from './initialize/index.js';
3
3
  export { getFirebaseService, initializeFirebaseService, resetFirebaseService, WebFirebaseService, createWebFirebaseService, } from '@sudobility/di/web';
4
+ export { registerServiceWorker, unregisterServiceWorker, } from './sw/register.js';
4
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,aAAa,GAGd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAEL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EAGrB,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,UAAU,EACV,aAAa,GAGd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAEL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EAGrB,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,kBAAkB,CAAC"}
@@ -13,7 +13,7 @@ export interface WebAppInitOptions {
13
13
  firebaseConfig: FirebaseConfig;
14
14
  revenueCatConfig?: RevenueCatConfig;
15
15
  initializeI18n?: () => void;
16
- registerServiceWorker?: () => void;
16
+ registerServiceWorker?: boolean | (() => void);
17
17
  initWebVitals?: () => void;
18
18
  }
19
19
  export declare function initializeWebApp(options: WebAppInitOptions): Promise<FirebaseAnalyticsService>;
@@ -1 +1 @@
1
- {"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../src/initialize/initialize.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,oBAAoB,GAC1B,CAAC;AASF,MAAM,WAAW,gBAAgB;IAE/B,MAAM,EAAE,MAAM,CAAC;IAGf,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,eAAe,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD;AAKD,MAAM,WAAW,iBAAiB;IAEhC,cAAc,EAAE,cAAc,CAAC;IAG/B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAGpC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAG5B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAC;IAGnC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAsBD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,wBAAwB,CAAC,CAiEnC"}
1
+ {"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../src/initialize/initialize.ts"],"names":[],"mappings":"AAMA,OAAO,EAIL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,oBAAoB,GAC1B,CAAC;AASF,MAAM,WAAW,gBAAgB;IAE/B,MAAM,EAAE,MAAM,CAAC;IAGf,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,eAAe,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD;AAKD,MAAM,WAAW,iBAAiB;IAEhC,cAAc,EAAE,cAAc,CAAC;IAG/B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAGpC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAG5B,qBAAqB,CAAC,EAAE,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;IAG/C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAsBD,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,wBAAwB,CAAC,CAqEnC"}
@@ -31,7 +31,11 @@ export async function initializeWebApp(options) {
31
31
  if (initializeI18n) {
32
32
  initializeI18n();
33
33
  }
34
- if (registerServiceWorker) {
34
+ if (registerServiceWorker === true) {
35
+ const { registerServiceWorker: register } = await import('../sw/register.js');
36
+ register();
37
+ }
38
+ else if (typeof registerServiceWorker === 'function') {
35
39
  registerServiceWorker();
36
40
  }
37
41
  if (initWebVitals) {
@@ -1 +1 @@
1
- {"version":3,"file":"initialize.js","sourceRoot":"","sources":["../../src/initialize/initialize.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,GAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,GAEtB,CAAC;AA+DF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAA0B;IAE1B,MAAM,EACJ,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,aAAa,GACd,GAAG,OAAO,CAAC;IAGZ,wBAAwB,EAAE,CAAC;IAG3B,yBAAyB,CAAC,cAAc,CAAC,CAAC;IAG1C,MAAM,SAAS,GAAG,2BAA2B,EAAE,CAAC;IAKhD,wBAAwB,EAAE,CAAC;IAG3B,qBAAqB,EAAE,CAAC;IAGxB,IAAI,gBAAgB,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YACrE,MAAM,YAAY,GAAG,gBAAgB,CAAC,YAAY,IAAI,IAAI,CAAC;YAC3D,MAAM,MAAM,GAAG,YAAY;gBACzB,CAAC,CAAC,gBAAgB,CAAC,MAAM;gBACzB,CAAC,CAAC,gBAAgB,CAAC,aAAa,IAAI,gBAAgB,CAAC,MAAM,CAAC;YAE9D,eAAe,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACnD,eAAe,CAAC,sBAAsB,CAAC;gBACrC,OAAO,EAAE,eAAe,CAAC,uBAAuB,EAAE;gBAClD,QAAQ,EAAE,gBAAgB,CAAC,eAAe,IAAI;oBAC5C,SAAS,EAAE,MAAM;oBACjB,IAAI,EAAE,MAAM;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,uFAAuF,EACvF,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IAGD,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,EAAE,CAAC;IACnB,CAAC;IAGD,IAAI,qBAAqB,EAAE,CAAC;QAC1B,qBAAqB,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,EAAE,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"initialize.js","sourceRoot":"","sources":["../../src/initialize/initialize.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,GAGtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,GAEtB,CAAC;AA+DF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAA0B;IAE1B,MAAM,EACJ,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,aAAa,GACd,GAAG,OAAO,CAAC;IAGZ,wBAAwB,EAAE,CAAC;IAG3B,yBAAyB,CAAC,cAAc,CAAC,CAAC;IAG1C,MAAM,SAAS,GAAG,2BAA2B,EAAE,CAAC;IAKhD,wBAAwB,EAAE,CAAC;IAG3B,qBAAqB,EAAE,CAAC;IAGxB,IAAI,gBAAgB,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,8BAA8B,CAAC,CAAC;YACrE,MAAM,YAAY,GAAG,gBAAgB,CAAC,YAAY,IAAI,IAAI,CAAC;YAC3D,MAAM,MAAM,GAAG,YAAY;gBACzB,CAAC,CAAC,gBAAgB,CAAC,MAAM;gBACzB,CAAC,CAAC,gBAAgB,CAAC,aAAa,IAAI,gBAAgB,CAAC,MAAM,CAAC;YAE9D,eAAe,CAAC,0BAA0B,CAAC,MAAM,CAAC,CAAC;YACnD,eAAe,CAAC,sBAAsB,CAAC;gBACrC,OAAO,EAAE,eAAe,CAAC,uBAAuB,EAAE;gBAClD,QAAQ,EAAE,gBAAgB,CAAC,eAAe,IAAI;oBAC5C,SAAS,EAAE,MAAM;oBACjB,IAAI,EAAE,MAAM;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CACX,uFAAuF,EACvF,KAAK,CACN,CAAC;QACJ,CAAC;IACH,CAAC;IAGD,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,EAAE,CAAC;IACnB,CAAC;IAGD,IAAI,qBAAqB,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,GACvC,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpC,QAAQ,EAAE,CAAC;IACb,CAAC;SAAM,IAAI,OAAO,qBAAqB,KAAK,UAAU,EAAE,CAAC;QACvD,qBAAqB,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,aAAa,EAAE,CAAC;QAClB,aAAa,EAAE,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,108 @@
1
+ // Firebase Cloud Messaging Service Worker
2
+ // This file must be served from the root domain for FCM to work properly
3
+
4
+ // Import Firebase scripts for the service worker
5
+ importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js');
6
+ importScripts('https://www.gstatic.com/firebasejs/10.7.1/firebase-messaging-compat.js');
7
+
8
+ // Initialize Firebase in the service worker
9
+ // Note: This configuration should match your main app's Firebase config
10
+ const firebaseConfig = {
11
+ apiKey: process.env.VITE_FIREBASE_API_KEY,
12
+ authDomain: process.env.VITE_FIREBASE_AUTH_DOMAIN,
13
+ projectId: process.env.VITE_FIREBASE_PROJECT_ID,
14
+ storageBucket: process.env.VITE_FIREBASE_STORAGE_BUCKET,
15
+ messagingSenderId: process.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
16
+ appId: process.env.VITE_FIREBASE_APP_ID,
17
+ measurementId: process.env.VITE_FIREBASE_MEASUREMENT_ID,
18
+ };
19
+
20
+ // Check if Firebase is already initialized
21
+ if (!firebase.apps.length) {
22
+ firebase.initializeApp(firebaseConfig);
23
+ }
24
+
25
+ // Initialize Firebase Cloud Messaging
26
+ const messaging = firebase.messaging();
27
+
28
+ // Handle background messages
29
+ messaging.onBackgroundMessage(payload => {
30
+ const notificationTitle = payload.notification?.title || 'New Email';
31
+ const notificationOptions = {
32
+ body: payload.notification?.body || 'You have received a new email',
33
+ icon: '/favicon.ico',
34
+ badge: '/favicon.ico',
35
+ tag: 'email-notification',
36
+ data: {
37
+ url: payload.data?.url || '/mail',
38
+ emailId: payload.data?.emailId,
39
+ timestamp: Date.now(),
40
+ },
41
+ actions: [
42
+ {
43
+ action: 'view',
44
+ title: 'View Email',
45
+ icon: '/favicon.ico',
46
+ },
47
+ {
48
+ action: 'dismiss',
49
+ title: 'Dismiss',
50
+ },
51
+ ],
52
+ requireInteraction: true,
53
+ silent: false,
54
+ };
55
+
56
+ // Show notification
57
+ self.registration.showNotification(notificationTitle, notificationOptions);
58
+ });
59
+
60
+ // Handle notification clicks
61
+ self.addEventListener('notificationclick', event => {
62
+ event.notification.close();
63
+
64
+ if (event.action === 'view') {
65
+ // Open or focus the email app
66
+ const urlToOpen = event.notification.data?.url || '/mail';
67
+
68
+ event.waitUntil(
69
+ clients
70
+ .matchAll({
71
+ type: 'window',
72
+ includeUncontrolled: true,
73
+ })
74
+ .then(clientList => {
75
+ // Check if app is already open
76
+ for (const client of clientList) {
77
+ if (client.url.includes(self.location.origin)) {
78
+ client.focus();
79
+ client.navigate(urlToOpen);
80
+ return;
81
+ }
82
+ }
83
+
84
+ // Open new window if app isn't open
85
+ if (clients.openWindow) {
86
+ return clients.openWindow(urlToOpen);
87
+ }
88
+ })
89
+ );
90
+ } else if (event.action === 'dismiss') {
91
+ // Just close the notification (already closed above)
92
+ }
93
+ });
94
+
95
+ // Handle notification close events
96
+ self.addEventListener('notificationclose', event => {
97
+ // Notification closed
98
+ });
99
+
100
+ // Optional: Handle push events directly (if using custom push server)
101
+ self.addEventListener('push', event => {
102
+ if (event.data) {
103
+ const data = event.data.json();
104
+
105
+ // Handle custom push notifications if needed
106
+ // This is typically handled by FCM automatically
107
+ }
108
+ });
@@ -0,0 +1,3 @@
1
+ export { registerServiceWorker, unregisterServiceWorker } from './register.js';
2
+ export { serviceWorkerPlugin, type ServiceWorkerPluginOptions, } from './vite-plugin-service-worker.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sw/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { registerServiceWorker, unregisterServiceWorker } from './register.js';
2
+ export { serviceWorkerPlugin, } from './vite-plugin-service-worker.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sw/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,mBAAmB,GAEpB,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,8 @@
1
+ declare global {
2
+ interface ImportMeta {
3
+ readonly env: Record<string, string | boolean | undefined>;
4
+ }
5
+ }
6
+ export declare function registerServiceWorker(): void;
7
+ export declare function unregisterServiceWorker(): void;
8
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/sw/register.ts"],"names":[],"mappings":"AAKA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;KAC5D;CACF;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAkC5C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAM9C"}
@@ -0,0 +1,36 @@
1
+ export function registerServiceWorker() {
2
+ if ('serviceWorker' in navigator && import.meta.env['PROD']) {
3
+ window.addEventListener('load', async () => {
4
+ try {
5
+ const registration = await navigator.serviceWorker.register('/sw.js', {
6
+ scope: '/',
7
+ });
8
+ setInterval(() => {
9
+ registration.update();
10
+ }, 24 * 60 * 60 * 1000);
11
+ registration.addEventListener('updatefound', () => {
12
+ const newWorker = registration.installing;
13
+ if (newWorker) {
14
+ newWorker.addEventListener('statechange', () => {
15
+ if (newWorker.state === 'installed' &&
16
+ navigator.serviceWorker.controller) {
17
+ console.info('New content available, refresh to update');
18
+ }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ catch (error) {
24
+ console.error('Service worker registration failed:', error);
25
+ }
26
+ });
27
+ }
28
+ }
29
+ export function unregisterServiceWorker() {
30
+ if ('serviceWorker' in navigator) {
31
+ navigator.serviceWorker.ready.then((registration) => {
32
+ registration.unregister();
33
+ });
34
+ }
35
+ }
36
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/sw/register.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,qBAAqB;IACnC,IAAI,eAAe,IAAI,SAAS,IAAK,MAAM,CAAC,IAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5E,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE;YACzC,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE;oBACpE,KAAK,EAAE,GAAG;iBACX,CAAC,CAAC;gBAGH,WAAW,CACT,GAAG,EAAE;oBACH,YAAY,CAAC,MAAM,EAAE,CAAC;gBACxB,CAAC,EACD,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CACpB,CAAC;gBAEF,YAAY,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;oBAChD,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC;oBAC1C,IAAI,SAAS,EAAE,CAAC;wBACd,SAAS,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE;4BAC7C,IACE,SAAS,CAAC,KAAK,KAAK,WAAW;gCAC/B,SAAS,CAAC,aAAa,CAAC,UAAU,EAClC,CAAC;gCACD,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;4BAC3D,CAAC;wBACH,CAAC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,IAAI,eAAe,IAAI,SAAS,EAAE,CAAC;QACjC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE;YAClD,YAAY,CAAC,UAAU,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
package/dist/sw/sw.js ADDED
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Shared Service Worker for Sudobility Web Apps
3
+ * Implements caching strategies with TTL-based expiration and size limits
4
+ */
5
+
6
+ const CACHE_VERSION = 'v1';
7
+ const STATIC_CACHE = `sudobility-static-${CACHE_VERSION}`;
8
+ const DYNAMIC_CACHE = `sudobility-dynamic-${CACHE_VERSION}`;
9
+ const IMAGE_CACHE = `sudobility-images-${CACHE_VERSION}`;
10
+
11
+ // TTL per cache type
12
+ const CACHE_TTL = {
13
+ [STATIC_CACHE]: 7 * 24 * 60 * 60 * 1000, // 7 days
14
+ [DYNAMIC_CACHE]: 24 * 60 * 60 * 1000, // 1 day
15
+ [IMAGE_CACHE]: 30 * 24 * 60 * 60 * 1000, // 30 days
16
+ };
17
+
18
+ // Cache size limits
19
+ const CACHE_LIMITS = {
20
+ [STATIC_CACHE]: 100,
21
+ [DYNAMIC_CACHE]: 50,
22
+ [IMAGE_CACHE]: 30,
23
+ };
24
+
25
+ // Files to precache on install
26
+ const PRECACHE_URLS = ['/', '/manifest.json'];
27
+
28
+ // CDN domains allowed for caching
29
+ const ALLOWED_CDN_DOMAINS = ['cdn.jsdelivr.net', 'unpkg.com'];
30
+
31
+ // Install event - precache essential files
32
+ self.addEventListener('install', event => {
33
+ event.waitUntil(
34
+ caches.open(STATIC_CACHE).then(cache => {
35
+ return cache.addAll(PRECACHE_URLS);
36
+ })
37
+ );
38
+ self.skipWaiting();
39
+ });
40
+
41
+ // Activate event - clean up old caches
42
+ self.addEventListener('activate', event => {
43
+ const CURRENT_CACHES = [STATIC_CACHE, DYNAMIC_CACHE, IMAGE_CACHE];
44
+ const LEGACY_PREFIXES = ['web3mail-', 'shapeshyft-'];
45
+
46
+ event.waitUntil(
47
+ caches
48
+ .keys()
49
+ .then(cacheNames => {
50
+ return Promise.all(
51
+ cacheNames
52
+ .filter(name => {
53
+ // Remove old sudobility caches
54
+ if (name.startsWith('sudobility-') && !CURRENT_CACHES.includes(name)) {
55
+ return true;
56
+ }
57
+ // Remove legacy app-specific caches
58
+ return LEGACY_PREFIXES.some(prefix => name.startsWith(prefix));
59
+ })
60
+ .map(name => caches.delete(name))
61
+ );
62
+ })
63
+ .then(() => self.clients.claim())
64
+ );
65
+ });
66
+
67
+ // Trim cache to limit size
68
+ async function trimCache(cacheName, maxItems) {
69
+ const cache = await caches.open(cacheName);
70
+ const keys = await cache.keys();
71
+ if (keys.length > maxItems) {
72
+ await cache.delete(keys[0]);
73
+ return trimCache(cacheName, maxItems);
74
+ }
75
+ }
76
+
77
+ // Check if a cached response has expired
78
+ function isExpired(response, cacheName) {
79
+ const maxAge = CACHE_TTL[cacheName];
80
+ if (!maxAge) return false;
81
+
82
+ const dateHeader = response.headers.get('date');
83
+ if (!dateHeader) return false;
84
+
85
+ return Date.now() - new Date(dateHeader).getTime() > maxAge;
86
+ }
87
+
88
+ // Fetch event - implement caching strategies
89
+ self.addEventListener('fetch', event => {
90
+ const { request } = event;
91
+ const url = new URL(request.url);
92
+
93
+ // Skip non-GET requests
94
+ if (request.method !== 'GET') return;
95
+
96
+ // Skip chrome-extension and other non-http(s) requests
97
+ if (!url.protocol.startsWith('http')) return;
98
+
99
+ // Skip Google Fonts - they have their own caching and SW intercept causes CSP issues
100
+ if (
101
+ url.hostname.includes('fonts.googleapis.com') ||
102
+ url.hostname.includes('fonts.gstatic.com')
103
+ ) {
104
+ return;
105
+ }
106
+
107
+ // Skip non-same-origin requests unless on CDN allowlist
108
+ if (
109
+ url.origin !== location.origin &&
110
+ !ALLOWED_CDN_DOMAINS.some(domain => url.hostname.includes(domain))
111
+ ) {
112
+ return;
113
+ }
114
+
115
+ // Skip API requests
116
+ if (url.pathname.startsWith('/api/') || url.hostname.startsWith('api.')) return;
117
+
118
+ // Strategy: Cache First for static assets (JS, CSS, fonts)
119
+ if (
120
+ url.pathname.match(/\.(js|css|woff2?|ttf|eot)$/) ||
121
+ url.pathname.startsWith('/assets/')
122
+ ) {
123
+ event.respondWith(cacheFirst(request, STATIC_CACHE));
124
+ return;
125
+ }
126
+
127
+ // Strategy: Cache First for images
128
+ if (url.pathname.match(/\.(png|jpg|jpeg|svg|webp|gif|ico)$/)) {
129
+ event.respondWith(cacheFirst(request, IMAGE_CACHE));
130
+ event.waitUntil(trimCache(IMAGE_CACHE, CACHE_LIMITS[IMAGE_CACHE]));
131
+ return;
132
+ }
133
+
134
+ // Strategy: Stale While Revalidate for locale files
135
+ if (url.pathname.startsWith('/locales/')) {
136
+ event.respondWith(staleWhileRevalidate(request, DYNAMIC_CACHE));
137
+ return;
138
+ }
139
+
140
+ // Strategy: Network First for HTML pages
141
+ if (
142
+ request.headers.get('accept')?.includes('text/html') ||
143
+ url.pathname === '/' ||
144
+ !url.pathname.includes('.')
145
+ ) {
146
+ event.respondWith(networkFirst(request, DYNAMIC_CACHE));
147
+ event.waitUntil(trimCache(DYNAMIC_CACHE, CACHE_LIMITS[DYNAMIC_CACHE]));
148
+ return;
149
+ }
150
+
151
+ // Default: Network First
152
+ event.respondWith(networkFirst(request, DYNAMIC_CACHE));
153
+ });
154
+
155
+ // Cache First strategy - with TTL expiration
156
+ async function cacheFirst(request, cacheName) {
157
+ const cache = await caches.open(cacheName);
158
+ const cached = await cache.match(request);
159
+
160
+ if (cached && !isExpired(cached, cacheName)) {
161
+ return cached;
162
+ }
163
+
164
+ try {
165
+ const response = await fetch(request);
166
+ if (response.ok) {
167
+ cache.put(request, response.clone());
168
+ }
169
+ return response;
170
+ } catch (error) {
171
+ if (cached) return cached;
172
+ return caches.match('/');
173
+ }
174
+ }
175
+
176
+ // Network First strategy
177
+ async function networkFirst(request, cacheName) {
178
+ const cache = await caches.open(cacheName);
179
+
180
+ try {
181
+ const response = await fetch(request);
182
+ if (response.ok) {
183
+ cache.put(request, response.clone());
184
+ }
185
+ return response;
186
+ } catch (error) {
187
+ const cached = await cache.match(request);
188
+ if (cached) return cached;
189
+ if (request.headers.get('accept')?.includes('text/html')) {
190
+ return caches.match('/');
191
+ }
192
+ throw error;
193
+ }
194
+ }
195
+
196
+ // Stale While Revalidate strategy
197
+ async function staleWhileRevalidate(request, cacheName) {
198
+ const cache = await caches.open(cacheName);
199
+ const cached = await cache.match(request);
200
+
201
+ const fetchPromise = fetch(request).then(response => {
202
+ if (response.ok) {
203
+ cache.put(request, response.clone());
204
+ }
205
+ return response;
206
+ });
207
+
208
+ return cached || fetchPromise;
209
+ }
210
+
211
+ // Handle messages from the main thread
212
+ self.addEventListener('message', event => {
213
+ if (event.data?.type === 'SKIP_WAITING') {
214
+ self.skipWaiting();
215
+ }
216
+ });
217
+
218
+ // Background sync for failed requests
219
+ self.addEventListener('sync', event => {
220
+ if (event.tag === 'background-sync') {
221
+ event.waitUntil(doBackgroundSync());
222
+ }
223
+ });
224
+
225
+ async function doBackgroundSync() {
226
+ const cache = await caches.open(DYNAMIC_CACHE);
227
+ const requests = await cache.keys();
228
+
229
+ for (const request of requests) {
230
+ try {
231
+ await fetch(request);
232
+ await cache.delete(request);
233
+ } catch (error) {
234
+ // Will retry on next sync
235
+ }
236
+ }
237
+ }
238
+
239
+ // Push notification handler
240
+ self.addEventListener('push', event => {
241
+ if (!event.data) return;
242
+
243
+ try {
244
+ const data = event.data.json();
245
+ const { title, body, icon, badge, data: notificationData } = data;
246
+
247
+ event.waitUntil(
248
+ self.registration.showNotification(title || 'Notification', {
249
+ body,
250
+ icon: icon || '/favicon-192.png',
251
+ badge: badge || '/favicon-96.png',
252
+ data: notificationData,
253
+ requireInteraction: true,
254
+ actions: [
255
+ { action: 'open', title: 'Open App' },
256
+ { action: 'dismiss', title: 'Dismiss' },
257
+ ],
258
+ })
259
+ );
260
+ } catch (error) {
261
+ console.error('[SW] Push notification error:', error);
262
+ }
263
+ });
264
+
265
+ // Notification click handler
266
+ self.addEventListener('notificationclick', event => {
267
+ event.notification.close();
268
+
269
+ if (event.action === 'dismiss') return;
270
+
271
+ const urlToOpen = event.notification.data?.url || '/';
272
+
273
+ event.waitUntil(
274
+ self.clients.matchAll({ type: 'window' }).then(clients => {
275
+ for (const client of clients) {
276
+ if (client.url === urlToOpen && 'focus' in client) {
277
+ return client.focus();
278
+ }
279
+ }
280
+ if (self.clients.openWindow) {
281
+ return self.clients.openWindow(urlToOpen);
282
+ }
283
+ })
284
+ );
285
+ });
@@ -0,0 +1,30 @@
1
+ export interface ServiceWorkerPluginOptions {
2
+ includeFirebaseMessaging?: boolean;
3
+ }
4
+ interface MiddlewareRequest {
5
+ url?: string;
6
+ }
7
+ interface MiddlewareResponse {
8
+ setHeader: (k: string, v: string) => void;
9
+ end: (s: string) => void;
10
+ }
11
+ interface ViteDevServer {
12
+ middlewares: {
13
+ use: (fn: (req: MiddlewareRequest, res: MiddlewareResponse, next: () => void) => void) => void;
14
+ };
15
+ }
16
+ interface EmitContext {
17
+ emitFile: (file: {
18
+ type: string;
19
+ fileName: string;
20
+ source: string;
21
+ }) => void;
22
+ }
23
+ interface VitePlugin {
24
+ name: string;
25
+ configureServer: (server: ViteDevServer) => void;
26
+ generateBundle: (this: EmitContext) => void;
27
+ }
28
+ export declare function serviceWorkerPlugin(options?: ServiceWorkerPluginOptions): VitePlugin;
29
+ export {};
30
+ //# sourceMappingURL=vite-plugin-service-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin-service-worker.d.ts","sourceRoot":"","sources":["../../src/sw/vite-plugin-service-worker.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,0BAA0B;IAEzC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CACpC;AAED,UAAU,iBAAiB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,kBAAkB;IAC1B,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1B;AAED,UAAU,aAAa;IACrB,WAAW,EAAE;QACX,GAAG,EAAE,CACH,EAAE,EAAE,CACF,GAAG,EAAE,iBAAiB,EACtB,GAAG,EAAE,kBAAkB,EACvB,IAAI,EAAE,MAAM,IAAI,KACb,IAAI,KACN,IAAI,CAAC;KACX,CAAC;CACH;AAED,UAAU,WAAW;IACnB,QAAQ,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CAC9E;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IACjD,cAAc,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAC7C;AAED,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,UAAU,CAgDZ"}
@@ -0,0 +1,43 @@
1
+ import { readFileSync } from 'fs';
2
+ import { resolve, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ export function serviceWorkerPlugin(options = {}) {
5
+ const { includeFirebaseMessaging = false } = options;
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ const swPath = resolve(__dirname, 'sw.js');
8
+ const firebaseSwPath = resolve(__dirname, 'firebase-messaging-sw.js');
9
+ return {
10
+ name: 'sudobility-service-worker',
11
+ configureServer(server) {
12
+ server.middlewares.use((req, res, next) => {
13
+ if (req.url === '/sw.js') {
14
+ res.setHeader('Content-Type', 'application/javascript');
15
+ res.end(readFileSync(swPath, 'utf-8'));
16
+ return;
17
+ }
18
+ if (includeFirebaseMessaging &&
19
+ req.url === '/firebase-messaging-sw.js') {
20
+ res.setHeader('Content-Type', 'application/javascript');
21
+ res.end(readFileSync(firebaseSwPath, 'utf-8'));
22
+ return;
23
+ }
24
+ next();
25
+ });
26
+ },
27
+ generateBundle() {
28
+ this.emitFile({
29
+ type: 'asset',
30
+ fileName: 'sw.js',
31
+ source: readFileSync(swPath, 'utf-8'),
32
+ });
33
+ if (includeFirebaseMessaging) {
34
+ this.emitFile({
35
+ type: 'asset',
36
+ fileName: 'firebase-messaging-sw.js',
37
+ source: readFileSync(firebaseSwPath, 'utf-8'),
38
+ });
39
+ }
40
+ },
41
+ };
42
+ }
43
+ //# sourceMappingURL=vite-plugin-service-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite-plugin-service-worker.js","sourceRoot":"","sources":["../../src/sw/vite-plugin-service-worker.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAsCpC,MAAM,UAAU,mBAAmB,CACjC,UAAsC,EAAE;IAExC,MAAM,EAAE,wBAAwB,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAGrD,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,0BAA0B,CAAC,CAAC;IAEtE,OAAO;QACL,IAAI,EAAE,2BAA2B;QAEjC,eAAe,CAAC,MAAqB;YACnC,MAAM,CAAC,WAAW,CAAC,GAAG,CACpB,CAAC,GAAsB,EAAE,GAAuB,EAAE,IAAgB,EAAE,EAAE;gBACpE,IAAI,GAAG,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;oBACzB,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;oBACxD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;oBACvC,OAAO;gBACT,CAAC;gBACD,IACE,wBAAwB;oBACxB,GAAG,CAAC,GAAG,KAAK,2BAA2B,EACvC,CAAC;oBACD,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;oBACxD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;oBAC/C,OAAO;gBACT,CAAC;gBACD,IAAI,EAAE,CAAC;YACT,CAAC,CACF,CAAC;QACJ,CAAC;QAED,cAAc;YACZ,IAAI,CAAC,QAAQ,CAAC;gBACZ,IAAI,EAAE,OAAO;gBACb,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC;aACtC,CAAC,CAAC;YAEH,IAAI,wBAAwB,EAAE,CAAC;gBAC7B,IAAI,CAAC,QAAQ,CAAC;oBACZ,IAAI,EAAE,OAAO;oBACb,QAAQ,EAAE,0BAA0B;oBACpC,MAAM,EAAE,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC;iBAC9C,CAAC,CAAC;YACL,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/di_web",
3
- "version": "0.1.95",
3
+ "version": "0.1.99",
4
4
  "description": "Web implementations of dependency injection services for Sudobility",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,10 +9,14 @@
9
9
  ".": {
10
10
  "import": "./dist/index.js",
11
11
  "types": "./dist/index.d.ts"
12
+ },
13
+ "./vite": {
14
+ "import": "./dist/sw/vite-plugin-service-worker.js",
15
+ "types": "./dist/sw/vite-plugin-service-worker.d.ts"
12
16
  }
13
17
  },
14
18
  "scripts": {
15
- "build": "tsc",
19
+ "build": "tsc && cp src/sw/sw.js dist/sw/sw.js && cp src/sw/firebase-messaging-sw.js dist/sw/firebase-messaging-sw.js",
16
20
  "build:watch": "tsc --watch",
17
21
  "clean": "rm -rf dist",
18
22
  "test": "vitest run",
@@ -38,10 +42,11 @@
38
42
  "author": "Sudobility Inc",
39
43
  "license": "BUSL-1.1",
40
44
  "peerDependencies": {
41
- "@sudobility/components": "^5.0.6",
45
+ "@sudobility/components": "^5.0.7",
42
46
  "@sudobility/di": "^1.5.34",
43
47
  "@sudobility/types": "^1.9.50",
44
- "react": "^18.0.0 || ^19.0.0"
48
+ "react": "^18.0.0 || ^19.0.0",
49
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0"
45
50
  },
46
51
  "repository": {
47
52
  "type": "git",
@@ -50,11 +55,14 @@
50
55
  "peerDependenciesMeta": {
51
56
  "@sudobility/subscription_lib": {
52
57
  "optional": true
58
+ },
59
+ "vite": {
60
+ "optional": true
53
61
  }
54
62
  },
55
63
  "devDependencies": {
56
64
  "@eslint/js": "^9.38.0",
57
- "@sudobility/components": "^5.0.6",
65
+ "@sudobility/components": "^5.0.7",
58
66
  "@sudobility/di": "^1.5.34",
59
67
  "@sudobility/subscription_lib": "^0.0.14",
60
68
  "@sudobility/types": "^1.9.50",
@@ -70,6 +78,7 @@
70
78
  "prettier": "^3.6.2",
71
79
  "react": "^19.1.0",
72
80
  "typescript": "^5.9.3",
81
+ "vite": "^7.1.12",
73
82
  "vitest": "^3.2.4"
74
83
  },
75
84
  "publishConfig": {