@memberjunction/ng-user-avatar 6.2.0-edge.0 → 6.2.0-edge.1

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.
@@ -20,6 +20,8 @@ export declare class UserAvatarService {
20
20
  * @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })
21
21
  * @returns Promise<boolean> - true if avatar was synced and saved, false otherwise
22
22
  */
23
+ SyncFromImageUrl(user: MJUserEntity, imageUrl: string, authHeaders?: Record<string, string>): Promise<boolean>;
24
+ /** @deprecated Use {@link SyncFromImageUrl}. */
23
25
  syncFromImageUrl(user: MJUserEntity, imageUrl: string, authHeaders?: Record<string, string>): Promise<boolean>;
24
26
  /**
25
27
  * Converts a Blob to a Base64 data URI string
@@ -30,14 +32,20 @@ export declare class UserAvatarService {
30
32
  * Converts a File to a Base64 data URI string
31
33
  * Used for file uploads in settings UI
32
34
  */
35
+ FileToBase64(file: File): Promise<string>;
36
+ /** @deprecated Use {@link FileToBase64}. */
33
37
  fileToBase64(file: File): Promise<string>;
34
38
  /**
35
39
  * Validates if a string is a valid URL
36
40
  */
41
+ IsValidUrl(url: string): boolean;
42
+ /** @deprecated Use {@link IsValidUrl}. */
37
43
  isValidUrl(url: string): boolean;
38
44
  /**
39
45
  * Validates if a string is a valid Base64 data URI
40
46
  */
47
+ IsValidBase64DataUri(dataUri: string): boolean;
48
+ /** @deprecated Use {@link IsValidBase64DataUri}. */
41
49
  isValidBase64DataUri(dataUri: string): boolean;
42
50
  /**
43
51
  * Gets the display URL for an avatar based on user settings
@@ -47,10 +55,14 @@ export declare class UserAvatarService {
47
55
  * @param defaultUrl - Optional default URL if no avatar is set
48
56
  * @returns The URL to display, or null if using an icon
49
57
  */
58
+ GetAvatarDisplayUrl(user: MJUserEntity, defaultUrl?: string): string | null;
59
+ /** @deprecated Use {@link GetAvatarDisplayUrl}. */
50
60
  getAvatarDisplayUrl(user: MJUserEntity, defaultUrl?: string): string | null;
51
61
  /**
52
62
  * Gets the icon class for an avatar if using icon mode
53
63
  */
64
+ GetAvatarIconClass(user: MJUserEntity, defaultIcon?: string): string | null;
65
+ /** @deprecated Use {@link GetAvatarIconClass}. */
54
66
  getAvatarIconClass(user: MJUserEntity, defaultIcon?: string): string | null;
55
67
  static ɵfac: i0.ɵɵFactoryDeclaration<UserAvatarService, never>;
56
68
  static ɵprov: i0.ɵɵInjectableDeclaration<UserAvatarService>;
@@ -1 +1 @@
1
- {"version":3,"file":"user-avatar.service.d.ts","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;;AAG7D;;;;;;GAMG;AACH,qBAGa,iBAAiB;IAChB,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEpC;;;;;;;;OAQG;IACG,gBAAgB,CACpB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC;IAoCnB;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IASzC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAahC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAS9C;;;;;;;OAOG;IACH,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,GAAE,MAA0B,GAAG,MAAM,GAAG,IAAI;IAY9F;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,GAAE,MAA2B,GAAG,MAAM,GAAG,IAAI;yCAjIpF,iBAAiB;6CAAjB,iBAAiB;CA4I7B"}
1
+ {"version":3,"file":"user-avatar.service.d.ts","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;;AAG7D;;;;;;GAMG;AACH,qBAGa,iBAAiB;IAChB,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,UAAU;IAEpC;;;;;;;;OAQG;IACG,gBAAgB,CACpB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC;IAoCnB,gDAAgD;IAC1C,gBAAgB,CACpB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,OAAO,CAAC;IAInB;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IASzC,4CAA4C;IAC5C,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzC;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAahC,0CAA0C;IAC1C,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC;;OAEG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAS9C,oDAAoD;IACpD,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI9C;;;;;;;OAOG;IACH,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,GAAE,MAA0B,GAAG,MAAM,GAAG,IAAI;IAY9F,mDAAmD;IACnD,mBAAmB,CAAC,IAAI,EAAE,YAAY,EAAE,UAAU,GAAE,MAA0B,GAAG,MAAM,GAAG,IAAI;IAI9F;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,GAAE,MAA2B,GAAG,MAAM,GAAG,IAAI;IAY/F,kDAAkD;IAClD,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,GAAE,MAA2B,GAAG,MAAM,GAAG,IAAI;yCA3KpF,iBAAiB;6CAAjB,iBAAiB;CA8K7B"}
@@ -23,7 +23,7 @@ export class UserAvatarService {
23
23
  * @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })
24
24
  * @returns Promise<boolean> - true if avatar was synced and saved, false otherwise
25
25
  */
26
- async syncFromImageUrl(user, imageUrl, authHeaders) {
26
+ async SyncFromImageUrl(user, imageUrl, authHeaders) {
27
27
  try {
28
28
  if (!imageUrl || imageUrl.trim().length === 0) {
29
29
  console.warn('No image URL provided for avatar sync');
@@ -53,6 +53,10 @@ export class UserAvatarService {
53
53
  return false;
54
54
  }
55
55
  }
56
+ /** @deprecated Use {@link SyncFromImageUrl}. */
57
+ async syncFromImageUrl(user, imageUrl, authHeaders) {
58
+ return this.SyncFromImageUrl(user, imageUrl, authHeaders);
59
+ }
56
60
  /**
57
61
  * Converts a Blob to a Base64 data URI string
58
62
  * Returns format: "data:image/png;base64,iVBORw0KG..."
@@ -69,7 +73,7 @@ export class UserAvatarService {
69
73
  * Converts a File to a Base64 data URI string
70
74
  * Used for file uploads in settings UI
71
75
  */
72
- fileToBase64(file) {
76
+ FileToBase64(file) {
73
77
  return new Promise((resolve, reject) => {
74
78
  const reader = new FileReader();
75
79
  reader.onload = () => resolve(reader.result);
@@ -77,10 +81,14 @@ export class UserAvatarService {
77
81
  reader.readAsDataURL(file);
78
82
  });
79
83
  }
84
+ /** @deprecated Use {@link FileToBase64}. */
85
+ fileToBase64(file) {
86
+ return this.FileToBase64(file);
87
+ }
80
88
  /**
81
89
  * Validates if a string is a valid URL
82
90
  */
83
- isValidUrl(url) {
91
+ IsValidUrl(url) {
84
92
  if (!url || url.trim().length === 0) {
85
93
  return false;
86
94
  }
@@ -92,16 +100,24 @@ export class UserAvatarService {
92
100
  return false;
93
101
  }
94
102
  }
103
+ /** @deprecated Use {@link IsValidUrl}. */
104
+ isValidUrl(url) {
105
+ return this.IsValidUrl(url);
106
+ }
95
107
  /**
96
108
  * Validates if a string is a valid Base64 data URI
97
109
  */
98
- isValidBase64DataUri(dataUri) {
110
+ IsValidBase64DataUri(dataUri) {
99
111
  if (!dataUri || !dataUri.startsWith('data:')) {
100
112
  return false;
101
113
  }
102
114
  const regex = /^data:image\/(png|jpeg|jpg|gif|webp);base64,/;
103
115
  return regex.test(dataUri);
104
116
  }
117
+ /** @deprecated Use {@link IsValidBase64DataUri}. */
118
+ isValidBase64DataUri(dataUri) {
119
+ return this.IsValidBase64DataUri(dataUri);
120
+ }
105
121
  /**
106
122
  * Gets the display URL for an avatar based on user settings
107
123
  * Priority: UserImageURL > UserImageIconClass > default
@@ -110,7 +126,7 @@ export class UserAvatarService {
110
126
  * @param defaultUrl - Optional default URL if no avatar is set
111
127
  * @returns The URL to display, or null if using an icon
112
128
  */
113
- getAvatarDisplayUrl(user, defaultUrl = 'assets/user.png') {
129
+ GetAvatarDisplayUrl(user, defaultUrl = 'assets/user.png') {
114
130
  if (user.UserImageURL) {
115
131
  return user.UserImageURL;
116
132
  }
@@ -119,10 +135,14 @@ export class UserAvatarService {
119
135
  }
120
136
  return defaultUrl;
121
137
  }
138
+ /** @deprecated Use {@link GetAvatarDisplayUrl}. */
139
+ getAvatarDisplayUrl(user, defaultUrl = 'assets/user.png') {
140
+ return this.GetAvatarDisplayUrl(user, defaultUrl);
141
+ }
122
142
  /**
123
143
  * Gets the icon class for an avatar if using icon mode
124
144
  */
125
- getAvatarIconClass(user, defaultIcon = 'fa-solid fa-user') {
145
+ GetAvatarIconClass(user, defaultIcon = 'fa-solid fa-user') {
126
146
  if (user.UserImageIconClass) {
127
147
  return user.UserImageIconClass;
128
148
  }
@@ -131,6 +151,10 @@ export class UserAvatarService {
131
151
  }
132
152
  return null;
133
153
  }
154
+ /** @deprecated Use {@link GetAvatarIconClass}. */
155
+ getAvatarIconClass(user, defaultIcon = 'fa-solid fa-user') {
156
+ return this.GetAvatarIconClass(user, defaultIcon);
157
+ }
134
158
  static ɵfac = function UserAvatarService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || UserAvatarService)(i0.ɵɵinject(i1.HttpClient)); };
135
159
  static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: UserAvatarService, factory: UserAvatarService.ɵfac, providedIn: 'root' });
136
160
  }
@@ -1 +1 @@
1
- {"version":3,"file":"user-avatar.service.js","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { MJUserEntity } from '@memberjunction/core-entities';\nimport { firstValueFrom } from 'rxjs';\n\n/**\n * Service for managing user avatar operations across the application.\n *\n * NOTE: This service does NOT depend on any Explorer-specific packages to remain\n * usable across different Angular applications. All auth provider logic should\n * be handled by the calling code.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UserAvatarService {\n constructor(private http: HttpClient) {}\n\n /**\n * Syncs user avatar from an image URL (typically from auth provider profile).\n * Downloads the image, converts to Base64, and saves to the user entity.\n *\n * @param user - The MJUserEntity to update with avatar data\n * @param imageUrl - URL to the image (can be from Microsoft Graph, Google, etc.)\n * @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })\n * @returns Promise<boolean> - true if avatar was synced and saved, false otherwise\n */\n async syncFromImageUrl(\n user: MJUserEntity,\n imageUrl: string,\n authHeaders?: Record<string, string>\n ): Promise<boolean> {\n try {\n if (!imageUrl || imageUrl.trim().length === 0) {\n console.warn('No image URL provided for avatar sync');\n return false;\n }\n\n // Fetch the image as a blob\n const headers: Record<string, string> = authHeaders || {};\n const blob: Blob = await firstValueFrom(\n this.http.get(imageUrl, { headers, responseType: 'blob' })\n );\n\n // Convert blob to Base64 data URI\n const base64 = await this.blobToBase64(blob);\n\n // Update user entity\n user.UserImageURL = base64;\n user.UserImageIconClass = null; // Clear icon if we have an image\n\n // Save to database\n const saved = await user.Save();\n\n if (saved) {\n console.log('Successfully synced avatar from image URL');\n return true;\n } else {\n console.warn('Failed to save avatar to database');\n return false;\n }\n } catch (error) {\n console.warn('Could not sync avatar from image URL:', error);\n return false;\n }\n }\n\n /**\n * Converts a Blob to a Base64 data URI string\n * Returns format: \"data:image/png;base64,iVBORw0KG...\"\n */\n private blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n }\n\n /**\n * Converts a File to a Base64 data URI string\n * Used for file uploads in settings UI\n */\n fileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = error => reject(error);\n reader.readAsDataURL(file);\n });\n }\n\n /**\n * Validates if a string is a valid URL\n */\n isValidUrl(url: string): boolean {\n if (!url || url.trim().length === 0) {\n return false;\n }\n\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Validates if a string is a valid Base64 data URI\n */\n isValidBase64DataUri(dataUri: string): boolean {\n if (!dataUri || !dataUri.startsWith('data:')) {\n return false;\n }\n\n const regex = /^data:image\\/(png|jpeg|jpg|gif|webp);base64,/;\n return regex.test(dataUri);\n }\n\n /**\n * Gets the display URL for an avatar based on user settings\n * Priority: UserImageURL > UserImageIconClass > default\n *\n * @param user - The MJUserEntity\n * @param defaultUrl - Optional default URL if no avatar is set\n * @returns The URL to display, or null if using an icon\n */\n getAvatarDisplayUrl(user: MJUserEntity, defaultUrl: string = 'assets/user.png'): string | null {\n if (user.UserImageURL) {\n return user.UserImageURL;\n }\n\n if (user.UserImageIconClass) {\n return null; // Indicates icon should be used instead\n }\n\n return defaultUrl;\n }\n\n /**\n * Gets the icon class for an avatar if using icon mode\n */\n getAvatarIconClass(user: MJUserEntity, defaultIcon: string = 'fa-solid fa-user'): string | null {\n if (user.UserImageIconClass) {\n return user.UserImageIconClass;\n }\n\n if (!user.UserImageURL) {\n return defaultIcon;\n }\n\n return null;\n }\n}\n"]}
1
+ {"version":3,"file":"user-avatar.service.js","sourceRoot":"","sources":["../../src/lib/user-avatar.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { MJUserEntity } from '@memberjunction/core-entities';\nimport { firstValueFrom } from 'rxjs';\n\n/**\n * Service for managing user avatar operations across the application.\n *\n * NOTE: This service does NOT depend on any Explorer-specific packages to remain\n * usable across different Angular applications. All auth provider logic should\n * be handled by the calling code.\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class UserAvatarService {\n constructor(private http: HttpClient) {}\n\n /**\n * Syncs user avatar from an image URL (typically from auth provider profile).\n * Downloads the image, converts to Base64, and saves to the user entity.\n *\n * @param user - The MJUserEntity to update with avatar data\n * @param imageUrl - URL to the image (can be from Microsoft Graph, Google, etc.)\n * @param authHeaders - Optional headers for authenticated requests (e.g., { 'Authorization': 'Bearer token' })\n * @returns Promise<boolean> - true if avatar was synced and saved, false otherwise\n */\n async SyncFromImageUrl(\n user: MJUserEntity,\n imageUrl: string,\n authHeaders?: Record<string, string>\n ): Promise<boolean> {\n try {\n if (!imageUrl || imageUrl.trim().length === 0) {\n console.warn('No image URL provided for avatar sync');\n return false;\n }\n\n // Fetch the image as a blob\n const headers: Record<string, string> = authHeaders || {};\n const blob: Blob = await firstValueFrom(\n this.http.get(imageUrl, { headers, responseType: 'blob' })\n );\n\n // Convert blob to Base64 data URI\n const base64 = await this.blobToBase64(blob);\n\n // Update user entity\n user.UserImageURL = base64;\n user.UserImageIconClass = null; // Clear icon if we have an image\n\n // Save to database\n const saved = await user.Save();\n\n if (saved) {\n console.log('Successfully synced avatar from image URL');\n return true;\n } else {\n console.warn('Failed to save avatar to database');\n return false;\n }\n } catch (error) {\n console.warn('Could not sync avatar from image URL:', error);\n return false;\n }\n }\n\n /** @deprecated Use {@link SyncFromImageUrl}. */\n async syncFromImageUrl(\n user: MJUserEntity,\n imageUrl: string,\n authHeaders?: Record<string, string>\n ): Promise<boolean> {\n return this.SyncFromImageUrl(user, imageUrl, authHeaders);\n }\n\n /**\n * Converts a Blob to a Base64 data URI string\n * Returns format: \"data:image/png;base64,iVBORw0KG...\"\n */\n private blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => resolve(reader.result as string);\n reader.onerror = reject;\n reader.readAsDataURL(blob);\n });\n }\n\n /**\n * Converts a File to a Base64 data URI string\n * Used for file uploads in settings UI\n */\n FileToBase64(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = error => reject(error);\n reader.readAsDataURL(file);\n });\n }\n\n /** @deprecated Use {@link FileToBase64}. */\n fileToBase64(file: File): Promise<string> {\n return this.FileToBase64(file);\n }\n\n /**\n * Validates if a string is a valid URL\n */\n IsValidUrl(url: string): boolean {\n if (!url || url.trim().length === 0) {\n return false;\n }\n\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n }\n\n /** @deprecated Use {@link IsValidUrl}. */\n isValidUrl(url: string): boolean {\n return this.IsValidUrl(url);\n }\n\n /**\n * Validates if a string is a valid Base64 data URI\n */\n IsValidBase64DataUri(dataUri: string): boolean {\n if (!dataUri || !dataUri.startsWith('data:')) {\n return false;\n }\n\n const regex = /^data:image\\/(png|jpeg|jpg|gif|webp);base64,/;\n return regex.test(dataUri);\n }\n\n /** @deprecated Use {@link IsValidBase64DataUri}. */\n isValidBase64DataUri(dataUri: string): boolean {\n return this.IsValidBase64DataUri(dataUri);\n }\n\n /**\n * Gets the display URL for an avatar based on user settings\n * Priority: UserImageURL > UserImageIconClass > default\n *\n * @param user - The MJUserEntity\n * @param defaultUrl - Optional default URL if no avatar is set\n * @returns The URL to display, or null if using an icon\n */\n GetAvatarDisplayUrl(user: MJUserEntity, defaultUrl: string = 'assets/user.png'): string | null {\n if (user.UserImageURL) {\n return user.UserImageURL;\n }\n\n if (user.UserImageIconClass) {\n return null; // Indicates icon should be used instead\n }\n\n return defaultUrl;\n }\n\n /** @deprecated Use {@link GetAvatarDisplayUrl}. */\n getAvatarDisplayUrl(user: MJUserEntity, defaultUrl: string = 'assets/user.png'): string | null {\n return this.GetAvatarDisplayUrl(user, defaultUrl);\n }\n\n /**\n * Gets the icon class for an avatar if using icon mode\n */\n GetAvatarIconClass(user: MJUserEntity, defaultIcon: string = 'fa-solid fa-user'): string | null {\n if (user.UserImageIconClass) {\n return user.UserImageIconClass;\n }\n\n if (!user.UserImageURL) {\n return defaultIcon;\n }\n\n return null;\n }\n\n /** @deprecated Use {@link GetAvatarIconClass}. */\n getAvatarIconClass(user: MJUserEntity, defaultIcon: string = 'fa-solid fa-user'): string | null {\n return this.GetAvatarIconClass(user, defaultIcon);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-user-avatar",
3
- "version": "6.2.0-edge.0",
3
+ "version": "6.2.0-edge.1",
4
4
  "description": "MemberJunction: Angular User Avatar Service - Manages user avatar synchronization from auth providers and avatar operations",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -27,9 +27,9 @@
27
27
  "rxjs": "^7.8.2"
28
28
  },
29
29
  "dependencies": {
30
- "@memberjunction/core": "6.2.0-edge.0",
31
- "@memberjunction/core-entities": "6.2.0-edge.0",
32
- "@memberjunction/global": "6.2.0-edge.0",
30
+ "@memberjunction/core": "6.2.0-edge.1",
31
+ "@memberjunction/core-entities": "6.2.0-edge.1",
32
+ "@memberjunction/global": "6.2.0-edge.1",
33
33
  "tslib": "^2.8.1"
34
34
  },
35
35
  "sideEffects": false,