@memberjunction/react-runtime 5.36.0 → 5.37.0

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.
@@ -1,17 +1,17 @@
1
1
 
2
- > @memberjunction/react-runtime@5.36.0 build
2
+ > @memberjunction/react-runtime@5.37.0 build
3
3
  > npm run build:node && npm run build:umd
4
4
 
5
5
 
6
- > @memberjunction/react-runtime@5.36.0 build:node
6
+ > @memberjunction/react-runtime@5.37.0 build:node
7
7
  > tsc
8
8
 
9
9
 
10
- > @memberjunction/react-runtime@5.36.0 build:umd
10
+ > @memberjunction/react-runtime@5.37.0 build:umd
11
11
  > webpack --config webpack.umd.config.cjs
12
12
 
13
13
  [BABEL] Note: The code generator has deoptimised the styling of /home/runner/work/MJ/MJ/packages/MJCoreEntities/dist/generated/entity_subclasses.js as it exceeds the max of 500KB.
14
- asset runtime.umd.js 7.34 MiB [compared for emit] [big] (name: main)
14
+ asset runtime.umd.js 7.35 MiB [compared for emit] [big] (name: main)
15
15
  asset 324.runtime.umd.js 199 KiB [compared for emit]
16
16
  asset 490.runtime.umd.js 182 KiB [compared for emit] (id hint: vendors)
17
17
  orphan modules 7.36 MiB [orphan] 533 modules
@@ -28,4 +28,4 @@ cacheable modules 7.5 MiB
28
28
  ../../MJCore/dist/index.js + 81 modules 1.53 MiB [built] [code generated]
29
29
  ../../MJGlobal/dist/index.js + 17 modules 236 KiB [built] [code generated]
30
30
  ../../GraphQLDataProvider/dist/index.mjs 178 KiB [built] [code generated]
31
- webpack 5.105.0 compiled successfully in 77315 ms
31
+ webpack 5.105.0 compiled successfully in 74689 ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @memberjunction/react-runtime
2
2
 
3
+ ## 5.37.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [dadbde9]
8
+ - Updated dependencies [4f15f31]
9
+ - @memberjunction/graphql-dataprovider@5.37.0
10
+ - @memberjunction/core@5.37.0
11
+ - @memberjunction/core-entities@5.37.0
12
+ - @memberjunction/interactive-component-types@5.37.0
13
+ - @memberjunction/global@5.37.0
14
+
3
15
  ## 5.36.0
4
16
 
5
17
  ### Patch Changes
@@ -59,7 +59,7 @@ var re=Object.defineProperty;var y=(m,e)=>re(m,"name",{value:e,configurable:!0})
59
59
  ResultsJSON
60
60
  }
61
61
  }
62
- `,t=[];for(const n of this.PendingTransactions)t.push({EntityName:n.BaseEntity.EntityInfo.Name,EntityObjectJSON:await n.BaseEntity.GetDataObjectJSON(),OperationType:n.OperationType});const r={group:{Items:t,Variables:this.Variables.map(n=>({Name:n.Name,ItemIndex:this.MapVariableEntityObjectToPosition(n),FieldName:n.FieldName,Type:n.Type}))}},s=await this._provider.ExecuteGQL(e,r);if(s&&s.ExecuteTransactionGroup){const n=s.ExecuteTransactionGroup,a=[];for(let i=0;i<this.PendingTransactions.length;i++){const o=n.ResultsJSON[i],l=(0,_memberjunction_global__WEBPACK_IMPORTED_MODULE_2__/* .SafeJSONParse */ .NG)(o),u=this.PendingTransactions[i];a.push(new _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .TransactionResult */ .qTq(u,l,l!==null))}return a}else throw new Error("Failed to execute transaction group")}}const we=900*1e3;class P{static{y(this,"FireAndForgetHelper")}static async Execute(e){const t=e.operationLabel??e.mutationFieldName;let r,s;try{const{promise:n,resolve:a,reject:i}=P.createCompletionPromise();s=P.setupTimeout(i,e.timeoutMs,e.timeoutErrorMessage),r=P.subscribeToPubSub(e,a,s);const o=await P.executeMutation(e);if(!e.validateAck(o)){s&&clearTimeout(s);const l=o?.errorMessage??"Server rejected the request";return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)(`[FireAndForget:${t}] Server rejected: ${l}`),e.createErrorResult(l)}return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[FireAndForget:${t}] Server accepted, waiting for completion via WebSocket`),await n}catch(n){throw s&&clearTimeout(s),(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)(`[FireAndForget:${t}] Error: ${n.message}`),n}finally{s&&clearTimeout(s),r&&r.unsubscribe()}}static createCompletionPromise(){let e,t;return{promise:new Promise((s,n)=>{e=s,t=n}),resolve:e,reject:t}}static setupTimeout(e,t,r){const s=t??we,n=r??"The operation may still be running on the server but the client timed out after 15 minutes. Please refresh the page to check the latest status.";return setTimeout(()=>{e(new Error(n))},s)}static subscribeToPubSub(e,t,r){const s=e.dataProvider.sessionId,n=e.operationLabel??e.mutationFieldName;return e.dataProvider.PushStatusUpdates(s).subscribe(a=>{try{const i=JSON.parse(a);e.onMessage&&e.onMessage(i),e.isCompletionEvent(i)&&(clearTimeout(r),(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[FireAndForget:${n}] Completion event received`),t(e.extractResult(i)))}catch(i){console.error(`[FireAndForget:${n}] Failed to parse PubSub message:`,i)}})}static async executeMutation(e){return(await e.dataProvider.ExecuteGQL(e.mutation,e.variables))[e.mutationFieldName]}}class z{static{y(this,"GraphQLAIClient")}constructor(e){this._dataProvider=e}async RunAIPrompt(e){try{const t=(0,graphql_request__WEBPACK_IMPORTED_MODULE_0__/* .gql */ .J1)`
62
+ `,t=[];for(const n of this.PendingTransactions)t.push({EntityName:n.BaseEntity.EntityInfo.Name,EntityObjectJSON:await n.BaseEntity.GetDataObjectJSON(),OperationType:n.OperationType});const r={group:{Items:t,Variables:this.Variables.map(n=>({Name:n.Name,ItemIndex:this.MapVariableEntityObjectToPosition(n),FieldName:n.FieldName,Type:n.Type}))}},s=await this._provider.ExecuteGQL(e,r);if(s&&s.ExecuteTransactionGroup){const n=s.ExecuteTransactionGroup,a=[];for(let i=0;i<this.PendingTransactions.length;i++){const o=n.ResultsJSON[i],l=(0,_memberjunction_global__WEBPACK_IMPORTED_MODULE_2__/* .SafeJSONParse */ .NG)(o),u=this.PendingTransactions[i];a.push(new _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .TransactionResult */ .qTq(u,l,l!==null))}return a}else throw new Error("Failed to execute transaction group")}}const we=3600*1e3;class P{static{y(this,"FireAndForgetHelper")}static async Execute(e){const t=e.operationLabel??e.mutationFieldName;let r,s;try{const{promise:n,resolve:a,reject:i}=P.createCompletionPromise();s=P.setupTimeout(i,e.timeoutMs,e.timeoutErrorMessage),r=P.subscribeToPubSub(e,a,s);const o=await P.executeMutation(e);if(!e.validateAck(o)){s&&clearTimeout(s);const l=o?.errorMessage??"Server rejected the request";return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)(`[FireAndForget:${t}] Server rejected: ${l}`),e.createErrorResult(l)}return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[FireAndForget:${t}] Server accepted, waiting for completion via WebSocket`),await n}catch(n){throw s&&clearTimeout(s),(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)(`[FireAndForget:${t}] Error: ${n.message}`),n}finally{s&&clearTimeout(s),r&&r.unsubscribe()}}static createCompletionPromise(){let e,t;return{promise:new Promise((s,n)=>{e=s,t=n}),resolve:e,reject:t}}static setupTimeout(e,t,r){const s=t??we,n=r??"The operation may still be running on the server but the client timed out after 15 minutes. Please refresh the page to check the latest status.";return setTimeout(()=>{e(new Error(n))},s)}static subscribeToPubSub(e,t,r){const s=e.dataProvider.sessionId,n=e.operationLabel??e.mutationFieldName;return e.dataProvider.PushStatusUpdates(s).subscribe(a=>{try{const i=JSON.parse(a);e.onMessage&&e.onMessage(i),e.isCompletionEvent(i)&&(clearTimeout(r),(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[FireAndForget:${n}] Completion event received`),t(e.extractResult(i)))}catch(i){console.error(`[FireAndForget:${n}] Failed to parse PubSub message:`,i)}})}static async executeMutation(e){return(await e.dataProvider.ExecuteGQL(e.mutation,e.variables))[e.mutationFieldName]}}class z{static{y(this,"GraphQLAIClient")}constructor(e){this._dataProvider=e}async RunAIPrompt(e){try{const t=(0,graphql_request__WEBPACK_IMPORTED_MODULE_0__/* .gql */ .J1)`
63
63
  mutation RunAIPrompt(
64
64
  $promptId: String!,
65
65
  $data: String,
@@ -350,7 +350,7 @@ var re=Object.defineProperty;var y=(m,e)=>re(m,"name",{value:e,configurable:!0})
350
350
  }
351
351
  }
352
352
  }
353
- `,r={entityDocumentID:e.entityDocumentID};e.maxRecords!==void 0&&(r.maxRecords=e.maxRecords),e.filter!==void 0&&(r.filter=e.filter);const s=await this._dataProvider.ExecuteGQL(t,r);if(!s?.FetchEntityVectors)throw new Error("Invalid response from server");return s.FetchEntityVectors}catch(t){const r=t;return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)("GraphQLAIClient.FetchEntityVectors failed",void 0,r),{Success:!1,Results:[],TotalCount:0,ElapsedMs:0,ErrorMessage:r.message||"Unknown error"}}}}const L="5.36.0",$="default";class H{static{y(this,"BrowserStorageProviderBase")}constructor(){this._storage=new Map}getCategoryMap(e){const t=e||$;let r=this._storage.get(t);return r||(r=new Map,this._storage.set(t,r)),r}async GetItem(e,t){const s=this.getCategoryMap(t||$).get(e);return s===void 0?null:s}async GetItems(e,t){const r=new Map;if(e.length===0)return r;const s=this.getCategoryMap(t||$);for(const n of new Set(e)){const a=s.get(n);r.set(n,a===void 0?null:a)}return r}async SetItem(e,t,r){this.getCategoryMap(r||$).set(e,t)}async Remove(e,t){this.getCategoryMap(t||$).delete(e)}async ClearCategory(e){const t=e||$;this._storage.delete(t)}async GetCategoryKeys(e){const t=this._storage.get(e||$);return t?Array.from(t.keys()):[]}}const Ce="MJ_Metadata",$e=0;function Pe(){try{const m=L.split("."),e=parseInt(m[0],10),t=parseInt(m[1],10);if(!Number.isFinite(e)||!Number.isFinite(t))throw new Error(`Could not parse major.minor from version "${L}"`);return e*1e3+t+$e}catch(m){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:m,message:"Failed to derive IDB version from PACKAGE_VERSION; using fallback 99999"}),99999}}y(Pe,"computeIdbVersion");const Ae=Pe(),X=["mj:default","mj:Metadata","mj:RunViewCache","mj:RunQueryCache","mj:DatasetCache"];class Y extends H{static{y(this,"BrowserIndexedDBStorageProvider")}constructor(){super(),this._dbReady=!1,this.dbPromise=(0,_tempfix_idb__WEBPACK_IMPORTED_MODULE_10__/* .openDB */ .P2)(Ce,Ae,{upgrade:y((e,t,r)=>{try{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrading IndexedDB schema v${t} \u2192 v${r} (package ${L}). Dropping all stores; caches will repopulate on first use.`);for(const s of Array.from(e.objectStoreNames))e.deleteObjectStore(s);for(const s of X)e.objectStoreNames.contains(s)||e.createObjectStore(s)}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}},"upgrade"),blocked:y((e,t)=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrade from v${e} to v${t} blocked by another tab. Close other tabs to allow the upgrade to proceed.`)},"blocked")}),this.dbPromise.then(e=>{this._dbReady=!0,e.onversionchange=()=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)("[IDBCache] DB schema upgraded in another tab \u2014 closing local connection."),e.close(),this._dbReady=!1}}).catch(e=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:e,message:"IndexedDB initialization failed: "+e?.message})})}get IsReady(){return this._dbReady}isKnownCategory(e){const t=`mj:${e}`;return X.includes(t)}getStoreName(e){const t=e||$;return this.isKnownCategory(t)?`mj:${t}`:"mj:default"}getStoreKey(e,t){const r=t||$;return this.isKnownCategory(r)?e:`[${r}]:${e}`}async SetItem(e,t,r){try{const s=await this.dbPromise,n=this.getStoreName(r),a=this.getStoreKey(e,r),i=s.transaction(n,"readwrite");await i.objectStore(n).put(t,a),await i.done}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}}async GetItem(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=await r.transaction(s).objectStore(s).get(n);return a===void 0?null:a}catch(r){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message}),null}}async GetItems(e,t){const r=new Map;if(e.length===0)return r;try{const s=await this.dbPromise,n=this.getStoreName(t),a=Array.from(new Set(e)),i=a.map(D=>this.getStoreKey(D,t)),o=s.transaction(n,"readonly"),l=o.objectStore(n),u=i.map(D=>l.get(D)),f=await Promise.all(u);await o.done;for(let D=0;D<a.length;D++){const p=f[D];r.set(a[D],p===void 0?null:p)}return r}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message});for(const n of new Set(e))r.set(n,null);return r}}async Remove(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=r.transaction(s,"readwrite");await a.objectStore(s).delete(n),await a.done}catch(r){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message})}}async ClearCategory(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e);if(this.isKnownCategory(r)){const n=t.transaction(s,"readwrite");await n.objectStore(s).clear(),await n.done}else{const n=`[${r}]:`,a=t.transaction("mj:default","readwrite"),i=a.objectStore("mj:default"),o=await i.getAllKeys();for(const l of o)typeof l=="string"&&l.startsWith(n)&&await i.delete(l);await a.done}}catch(t){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message})}}async GetCategoryKeys(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e),i=await t.transaction(s,"readonly").objectStore(s).getAllKeys();if(this.isKnownCategory(r))return i.map(l=>String(l));const o=`[${r}]:`;return i.map(l=>String(l)).filter(l=>l.startsWith(o)).map(l=>l.slice(o.length))}catch(t){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message}),[]}}}class be extends _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .ProviderConfigDataBase */ .dZq{static{y(this,"GraphQLProviderConfigData")}get Token(){return this.Data.Token}set Token(e){this.Data.Token=e}get MJAPIKey(){return this.Data.MJAPIKey}set MJAPIKey(e){this.Data.MJAPIKey=e}get UserAPIKey(){return this.Data.UserAPIKey}set UserAPIKey(e){this.Data.UserAPIKey=e}get URL(){return this.Data.URL}get WSURL(){return this.Data.WSURL}get RefreshTokenFunction(){return this.Data.RefreshFunction}get OnAuthenticationError(){return this.Data.OnAuthenticationError}set OnAuthenticationError(e){this.Data.OnAuthenticationError=e}constructor(e,t,r,s,n,a,i,o,l,u){super({Token:e,URL:t,WSURL:r,MJAPIKey:o,UserAPIKey:l,RefreshTokenFunction:s,OnAuthenticationError:u},n,a,i)}}class h extends _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .ProviderBase */ .Dny{static{y(this,"GraphQLDataProvider")}constructor(){super(),this._refreshPromise=null,this._dynamicHeaders=new Map,this._innerCurrentUserQueryString=`CurrentUser {
353
+ `,r={entityDocumentID:e.entityDocumentID};e.maxRecords!==void 0&&(r.maxRecords=e.maxRecords),e.filter!==void 0&&(r.filter=e.filter);const s=await this._dataProvider.ExecuteGQL(t,r);if(!s?.FetchEntityVectors)throw new Error("Invalid response from server");return s.FetchEntityVectors}catch(t){const r=t;return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogError */ .ZI8)("GraphQLAIClient.FetchEntityVectors failed",void 0,r),{Success:!1,Results:[],TotalCount:0,ElapsedMs:0,ErrorMessage:r.message||"Unknown error"}}}}const L="5.37.0",$="default";class H{static{y(this,"BrowserStorageProviderBase")}constructor(){this._storage=new Map}getCategoryMap(e){const t=e||$;let r=this._storage.get(t);return r||(r=new Map,this._storage.set(t,r)),r}async GetItem(e,t){const s=this.getCategoryMap(t||$).get(e);return s===void 0?null:s}async GetItems(e,t){const r=new Map;if(e.length===0)return r;const s=this.getCategoryMap(t||$);for(const n of new Set(e)){const a=s.get(n);r.set(n,a===void 0?null:a)}return r}async SetItem(e,t,r){this.getCategoryMap(r||$).set(e,t)}async Remove(e,t){this.getCategoryMap(t||$).delete(e)}async ClearCategory(e){const t=e||$;this._storage.delete(t)}async GetCategoryKeys(e){const t=this._storage.get(e||$);return t?Array.from(t.keys()):[]}}const Ce="MJ_Metadata",$e=0;function Pe(){try{const m=L.split("."),e=parseInt(m[0],10),t=parseInt(m[1],10);if(!Number.isFinite(e)||!Number.isFinite(t))throw new Error(`Could not parse major.minor from version "${L}"`);return e*1e3+t+$e}catch(m){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:m,message:"Failed to derive IDB version from PACKAGE_VERSION; using fallback 99999"}),99999}}y(Pe,"computeIdbVersion");const Ae=Pe(),X=["mj:default","mj:Metadata","mj:RunViewCache","mj:RunQueryCache","mj:DatasetCache"];class Y extends H{static{y(this,"BrowserIndexedDBStorageProvider")}constructor(){super(),this._dbReady=!1,this.dbPromise=(0,_tempfix_idb__WEBPACK_IMPORTED_MODULE_10__/* .openDB */ .P2)(Ce,Ae,{upgrade:y((e,t,r)=>{try{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrading IndexedDB schema v${t} \u2192 v${r} (package ${L}). Dropping all stores; caches will repopulate on first use.`);for(const s of Array.from(e.objectStoreNames))e.deleteObjectStore(s);for(const s of X)e.objectStoreNames.contains(s)||e.createObjectStore(s)}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}},"upgrade"),blocked:y((e,t)=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)(`[IDBCache] Upgrade from v${e} to v${t} blocked by another tab. Close other tabs to allow the upgrade to proceed.`)},"blocked")}),this.dbPromise.then(e=>{this._dbReady=!0,e.onversionchange=()=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogStatus */ .b09)("[IDBCache] DB schema upgraded in another tab \u2014 closing local connection."),e.close(),this._dbReady=!1}}).catch(e=>{(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:e,message:"IndexedDB initialization failed: "+e?.message})})}get IsReady(){return this._dbReady}isKnownCategory(e){const t=`mj:${e}`;return X.includes(t)}getStoreName(e){const t=e||$;return this.isKnownCategory(t)?`mj:${t}`:"mj:default"}getStoreKey(e,t){const r=t||$;return this.isKnownCategory(r)?e:`[${r}]:${e}`}async SetItem(e,t,r){try{const s=await this.dbPromise,n=this.getStoreName(r),a=this.getStoreKey(e,r),i=s.transaction(n,"readwrite");await i.objectStore(n).put(t,a),await i.done}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message})}}async GetItem(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=await r.transaction(s).objectStore(s).get(n);return a===void 0?null:a}catch(r){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message}),null}}async GetItems(e,t){const r=new Map;if(e.length===0)return r;try{const s=await this.dbPromise,n=this.getStoreName(t),a=Array.from(new Set(e)),i=a.map(D=>this.getStoreKey(D,t)),o=s.transaction(n,"readonly"),l=o.objectStore(n),u=i.map(D=>l.get(D)),f=await Promise.all(u);await o.done;for(let D=0;D<a.length;D++){const p=f[D];r.set(a[D],p===void 0?null:p)}return r}catch(s){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:s,message:s?.message});for(const n of new Set(e))r.set(n,null);return r}}async Remove(e,t){try{const r=await this.dbPromise,s=this.getStoreName(t),n=this.getStoreKey(e,t),a=r.transaction(s,"readwrite");await a.objectStore(s).delete(n),await a.done}catch(r){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:r,message:r?.message})}}async ClearCategory(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e);if(this.isKnownCategory(r)){const n=t.transaction(s,"readwrite");await n.objectStore(s).clear(),await n.done}else{const n=`[${r}]:`,a=t.transaction("mj:default","readwrite"),i=a.objectStore("mj:default"),o=await i.getAllKeys();for(const l of o)typeof l=="string"&&l.startsWith(n)&&await i.delete(l);await a.done}}catch(t){(0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message})}}async GetCategoryKeys(e){try{const t=await this.dbPromise,r=e||$,s=this.getStoreName(e),i=await t.transaction(s,"readonly").objectStore(s).getAllKeys();if(this.isKnownCategory(r))return i.map(l=>String(l));const o=`[${r}]:`;return i.map(l=>String(l)).filter(l=>l.startsWith(o)).map(l=>l.slice(o.length))}catch(t){return (0,_memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .LogErrorEx */ .Q1A)({error:t,message:t?.message}),[]}}}class be extends _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .ProviderConfigDataBase */ .dZq{static{y(this,"GraphQLProviderConfigData")}get Token(){return this.Data.Token}set Token(e){this.Data.Token=e}get MJAPIKey(){return this.Data.MJAPIKey}set MJAPIKey(e){this.Data.MJAPIKey=e}get UserAPIKey(){return this.Data.UserAPIKey}set UserAPIKey(e){this.Data.UserAPIKey=e}get URL(){return this.Data.URL}get WSURL(){return this.Data.WSURL}get RefreshTokenFunction(){return this.Data.RefreshFunction}get OnAuthenticationError(){return this.Data.OnAuthenticationError}set OnAuthenticationError(e){this.Data.OnAuthenticationError=e}constructor(e,t,r,s,n,a,i,o,l,u){super({Token:e,URL:t,WSURL:r,MJAPIKey:o,UserAPIKey:l,RefreshTokenFunction:s,OnAuthenticationError:u},n,a,i)}}class h extends _memberjunction_core__WEBPACK_IMPORTED_MODULE_1__/* .ProviderBase */ .Dny{static{y(this,"GraphQLDataProvider")}constructor(){super(),this._refreshPromise=null,this._dynamicHeaders=new Map,this._innerCurrentUserQueryString=`CurrentUser {
354
354
  ${this.userInfoString()}
355
355
  MJUserRoles_UserIDArray {
356
356
  ${this.userRoleInfoString()}
@@ -94428,6 +94428,13 @@ var MJConversationDetailEntityExtended_decorate = undefined && undefined.__decor
94428
94428
 
94429
94429
  /** `MJ: Resource Types.ID` for Conversations — seeded in the resource type catalog. */
94430
94430
  var CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04427';
94431
+ /**
94432
+ * Fields that represent the conversation owner's evaluation of an AI message.
94433
+ * Storage is a single value per message (no per-user rating column), so only
94434
+ * the owner may set or change them — even users with `Edit`-level grants on
94435
+ * the parent conversation cannot retroactively rewrite the owner's rating.
94436
+ */
94437
+ var OWNER_ONLY_RATING_FIELDS = ['UserRating', 'UserFeedback'];
94431
94438
  /**
94432
94439
  * Server-side defense-in-depth for conversation sharing. The Angular chat UI
94433
94440
  * disables the message input when the current user only holds `View` access,
@@ -94439,6 +94446,13 @@ var CONVERSATIONS_RESOURCE_TYPE_ID = '81D4BC3D-9FEB-EF11-B01A-286B35C04427';
94439
94446
  * 2. A grantee on `MJ: Resource Permissions` with `PermissionLevel` of
94440
94447
  * `Edit` or `Owner` (directly or via role) and `Status='Approved'`.
94441
94448
  *
94449
+ * Additionally, the **rating fields** (`UserRating` and `UserFeedback`) are
94450
+ * owner-only — even users with `Edit`-level grants on the conversation are
94451
+ * blocked from changing them, because the storage is a single value per
94452
+ * message (it represents the owner's evaluation, not per-grantee opinions).
94453
+ * MJ's permissions engine has no native primitive for per-field row-conditional
94454
+ * write rules, so this gate lives here rather than in `MJ: Entity Permissions`.
94455
+ *
94442
94456
  * Runs on the server only (`ProviderType === 'Database'`) — client-side
94443
94457
  * executions pass straight through to `super` so offline/optimistic paths
94444
94458
  * still work. `ResourcePermissionEngine`'s cache is used to avoid per-save
@@ -94505,7 +94519,7 @@ var MJConversationDetailEntityExtended = /*#__PURE__*/function (_MJConversationD
94505
94519
  value: function () {
94506
94520
  var _currentUserMayWrite = MJConversationDetailEntityExtended_asyncToGenerator(/*#__PURE__*/MJConversationDetailEntityExtended_regenerator().m(function _callee3() {
94507
94521
  var _this = this;
94508
- var provider, user, conversation, loaded, engine, grant, _t;
94522
+ var provider, user, conversation, loaded, isOwner, engine, grant, _t;
94509
94523
  return MJConversationDetailEntityExtended_regenerator().w(function (_context3) {
94510
94524
  while (1) switch (_context3.p = _context3.n) {
94511
94525
  case 0:
@@ -94538,50 +94552,80 @@ var MJConversationDetailEntityExtended = /*#__PURE__*/function (_MJConversationD
94538
94552
  }
94539
94553
  return _context3.a(2, true);
94540
94554
  case 5:
94541
- if (!(conversation.UserID && (0,MJGlobal_dist/* UUIDsEqual */.jd)(conversation.UserID, user.ID))) {
94555
+ isOwner = !!conversation.UserID && (0,MJGlobal_dist/* UUIDsEqual */.jd)(conversation.UserID, user.ID);
94556
+ if (!isOwner) {
94542
94557
  _context3.n = 6;
94543
94558
  break;
94544
94559
  }
94545
94560
  return _context3.a(2, true);
94546
94561
  case 6:
94562
+ if (!(this.dirtyRatingFieldNames().length > 0)) {
94563
+ _context3.n = 7;
94564
+ break;
94565
+ }
94566
+ this.RecordDenied('Only the conversation owner can set or change the rating and feedback on this message.');
94567
+ return _context3.a(2, false);
94568
+ case 7:
94547
94569
  engine = ResourcePermissionEngine.GetProviderInstance(provider, ResourcePermissionEngine);
94548
- _context3.n = 7;
94570
+ _context3.n = 8;
94549
94571
  return engine.Config(false, user);
94550
- case 7:
94572
+ case 8:
94551
94573
  grant = engine.GetUserAvailableResources(user, CONVERSATIONS_RESOURCE_TYPE_ID).find(function (p) {
94552
94574
  return (0,MJGlobal_dist/* UUIDsEqual */.jd)(p.ResourceRecordID, _this.ConversationID);
94553
94575
  });
94554
94576
  if (grant) {
94555
- _context3.n = 8;
94577
+ _context3.n = 9;
94556
94578
  break;
94557
94579
  }
94558
94580
  this.RecordDenied('You do not have access to this conversation.');
94559
94581
  return _context3.a(2, false);
94560
- case 8:
94582
+ case 9:
94561
94583
  if (!(grant.PermissionLevel === 'Edit' || grant.PermissionLevel === 'Owner')) {
94562
- _context3.n = 9;
94584
+ _context3.n = 10;
94563
94585
  break;
94564
94586
  }
94565
94587
  return _context3.a(2, true);
94566
- case 9:
94588
+ case 10:
94567
94589
  // Only View — block writes.
94568
94590
  this.RecordDenied('You have view-only access to this conversation.');
94569
94591
  return _context3.a(2, false);
94570
- case 10:
94571
- _context3.p = 10;
94592
+ case 11:
94593
+ _context3.p = 11;
94572
94594
  _t = _context3.v;
94573
94595
  (0,dist/* LogError */.ZI8)("MJConversationDetailEntityExtended.currentUserMayWrite failed: ".concat(_t instanceof Error ? _t.message : String(_t)));
94574
94596
  // Fail closed — safer to deny than silently allow a compromised write.
94575
94597
  this.RecordDenied('Unable to verify conversation permissions.');
94576
94598
  return _context3.a(2, false);
94577
94599
  }
94578
- }, _callee3, this, [[2, 10]]);
94600
+ }, _callee3, this, [[2, 11]]);
94579
94601
  }));
94580
94602
  function currentUserMayWrite() {
94581
94603
  return _currentUserMayWrite.apply(this, arguments);
94582
94604
  }
94583
94605
  return currentUserMayWrite;
94584
94606
  }()
94607
+ /**
94608
+ * Names of the rating/feedback fields that are dirty on this save.
94609
+ * Used by `currentUserMayWrite` to detect attempts by non-owners to
94610
+ * modify the owner-only fields and surface a specific denial message.
94611
+ */
94612
+ }, {
94613
+ key: "dirtyRatingFieldNames",
94614
+ value: function dirtyRatingFieldNames() {
94615
+ var _this2 = this;
94616
+ var matches = [];
94617
+ var _loop = function _loop() {
94618
+ var name = _OWNER_ONLY_RATING_FI[_i];
94619
+ var field = _this2.Fields.find(function (f) {
94620
+ return f.Name === name;
94621
+ });
94622
+ if (field !== null && field !== void 0 && field.Dirty) matches.push(name);
94623
+ };
94624
+ for (var _i = 0, _OWNER_ONLY_RATING_FI = OWNER_ONLY_RATING_FIELDS; _i < _OWNER_ONLY_RATING_FI.length; _i++) {
94625
+ _loop();
94626
+ }
94627
+ return matches;
94628
+ }
94585
94629
  /**
94586
94630
  * Populate `LatestResult.Message` so callers that inspect the save result
94587
94631
  * see why the write was refused rather than a generic failure.
@@ -95191,6 +95235,7 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95191
95235
  key: "LoadConversations",
95192
95236
  value: function () {
95193
95237
  var _LoadConversations = conversations_asyncToGenerator(/*#__PURE__*/conversations_regenerator().m(function _callee2(environmentId, contextUser) {
95238
+ var _result$Results;
95194
95239
  var forceRefresh,
95195
95240
  sharedPermissions,
95196
95241
  sharedConversationIds,
@@ -95199,6 +95244,8 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95199
95244
  sharedClause,
95200
95245
  filter,
95201
95246
  result,
95247
+ ownedConversationIds,
95248
+ trulySharedPermissions,
95202
95249
  _args2 = arguments;
95203
95250
  return conversations_regenerator().w(function (_context2) {
95204
95251
  while (1) switch (_context2.n) {
@@ -95221,19 +95268,14 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95221
95268
  sharedPermissions = ResourcePermissionEngine.Instance.GetUserAvailableResources(contextUser, conversations_CONVERSATIONS_RESOURCE_TYPE_ID);
95222
95269
  sharedConversationIds = sharedPermissions.map(function (p) {
95223
95270
  return p.ResourceRecordID;
95224
- }); // Build the "shared by" map for the sidebar/header UI. Requires one
95225
- // extra query to fetch grantor emails (the ResourcePermission view
95226
- // only denormalizes Name, not Email).
95271
+ });
95227
95272
  rv = new dist/* RunView */.JjF();
95228
- _context2.n = 3;
95229
- return this.rebuildSharedByMap(rv, sharedPermissions, contextUser);
95230
- case 3:
95231
95273
  ownershipClause = "UserID='".concat(contextUser.ID, "'");
95232
95274
  sharedClause = sharedConversationIds.length > 0 ? " OR ID IN (".concat(sharedConversationIds.map(function (id) {
95233
95275
  return "'".concat(id, "'");
95234
95276
  }).join(','), ")") : '';
95235
95277
  filter = "EnvironmentID='".concat(environmentId, "' AND (").concat(ownershipClause).concat(sharedClause, ") AND (IsArchived IS NULL OR IsArchived=0)");
95236
- _context2.n = 4;
95278
+ _context2.n = 3;
95237
95279
  return rv.RunView({
95238
95280
  EntityName: 'MJ: Conversations',
95239
95281
  ExtraFilter: filter,
@@ -95241,7 +95283,7 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95241
95283
  MaxRows: 1000,
95242
95284
  ResultType: 'entity_object'
95243
95285
  }, contextUser);
95244
- case 4:
95286
+ case 3:
95245
95287
  result = _context2.v;
95246
95288
  if (result.Success) {
95247
95289
  this._conversations$.next(result.Results || []);
@@ -95249,7 +95291,24 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95249
95291
  console.error('[ConversationEngine] Failed to load conversations:', result.ErrorMessage);
95250
95292
  this._conversations$.next([]);
95251
95293
  }
95252
- case 5:
95294
+ // Build the "shared by" map AFTER fetching conversations so we can
95295
+ // exclude permissions on conversations the user owns. A role-inherited
95296
+ // grant on the user's own conversation (e.g. they're in a role that
95297
+ // got View access via a feedback workflow) must NOT appear as
95298
+ // "shared with me at View level" — otherwise the chat UI would treat
95299
+ // their own conversation as read-only. See isReadOnlyView in
95300
+ // conversation-chat-area.component.
95301
+ ownedConversationIds = new Set(((_result$Results = result.Results) !== null && _result$Results !== void 0 ? _result$Results : []).filter(function (c) {
95302
+ return c.UserID && (0,MJGlobal_dist/* UUIDsEqual */.jd)(c.UserID, contextUser.ID);
95303
+ }).map(function (c) {
95304
+ return (0,MJGlobal_dist/* NormalizeUUID */.Xw)(c.ID);
95305
+ }));
95306
+ trulySharedPermissions = sharedPermissions.filter(function (p) {
95307
+ return !ownedConversationIds.has((0,MJGlobal_dist/* NormalizeUUID */.Xw)(p.ResourceRecordID));
95308
+ });
95309
+ _context2.n = 4;
95310
+ return this.rebuildSharedByMap(rv, trulySharedPermissions, contextUser);
95311
+ case 4:
95253
95312
  return _context2.a(2);
95254
95313
  }
95255
95314
  }, _callee2, this);
@@ -95269,7 +95328,7 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95269
95328
  key: "rebuildSharedByMap",
95270
95329
  value: (function () {
95271
95330
  var _rebuildSharedByMap = conversations_asyncToGenerator(/*#__PURE__*/conversations_regenerator().m(function _callee3(rv, sharedPermissions, contextUser) {
95272
- var grantorIds, emailByUserId, inClause, result, _result$Results, _iterator, _step, _u$Email, u, _iterator2, _step2, _perm$SharedByUserID, _perm$SharedByUser, _emailByUserId$get, _perm$PermissionLevel, perm;
95331
+ var grantorIds, emailByUserId, inClause, result, _result$Results2, _iterator, _step, _u$Email, u, _iterator2, _step2, _perm$SharedByUserID, _perm$SharedByUser, _emailByUserId$get, _perm$PermissionLevel, perm;
95273
95332
  return conversations_regenerator().w(function (_context3) {
95274
95333
  while (1) switch (_context3.n) {
95275
95334
  case 0:
@@ -95303,7 +95362,7 @@ var ConversationEngine = /*#__PURE__*/function (_BaseEngine) {
95303
95362
  case 2:
95304
95363
  result = _context3.v;
95305
95364
  if (result.Success) {
95306
- _iterator = conversations_createForOfIteratorHelper((_result$Results = result.Results) !== null && _result$Results !== void 0 ? _result$Results : []);
95365
+ _iterator = conversations_createForOfIteratorHelper((_result$Results2 = result.Results) !== null && _result$Results2 !== void 0 ? _result$Results2 : []);
95307
95366
  try {
95308
95367
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
95309
95368
  u = _step.value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/react-runtime",
3
- "version": "5.36.0",
3
+ "version": "5.37.0",
4
4
  "description": "Platform-agnostic React component runtime for MemberJunction. Provides core compilation, registry, and execution capabilities for React components in any JavaScript environment.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,11 +29,11 @@
29
29
  },
30
30
  "homepage": "https://github.com/MemberJunction/MJ#readme",
31
31
  "dependencies": {
32
- "@memberjunction/core": "5.36.0",
33
- "@memberjunction/global": "5.36.0",
34
- "@memberjunction/interactive-component-types": "5.36.0",
35
- "@memberjunction/core-entities": "5.36.0",
36
- "@memberjunction/graphql-dataprovider": "5.36.0",
32
+ "@memberjunction/core": "5.37.0",
33
+ "@memberjunction/global": "5.37.0",
34
+ "@memberjunction/interactive-component-types": "5.37.0",
35
+ "@memberjunction/core-entities": "5.37.0",
36
+ "@memberjunction/graphql-dataprovider": "5.37.0",
37
37
  "@babel/standalone": "^7.29.1",
38
38
  "rxjs": "^7.8.2"
39
39
  },