/// <summary> /// Delete attribute of base item before base item is deleted /// </summary> /// <param name="item">Base item about to be deleted</param> public void OnItemDelete(Item item) { if (item.HasData <JavascriptItemData>()) { var data = item.GetData <JavascriptItemData>(); JavascriptItemDataRepo.Delete(data); } }
/// <summary> /// Create attribute, if present, after item is created /// </summary> /// <param name="item">Base item just created from datastore</param> public void OnItemCreate(Item item) { if (item.HasData <JavascriptItemData>()) { var data = item.GetData <JavascriptItemData>(); data.DataItemId = item.Id; data.ScriptFunctions = GetFunctionDeclarations(data.Script); JavascriptItemDataRepo.Create(data); } }
/// <summary> /// Append attribute to base item when it is loaded /// </summary> /// <param name="item">Base item just read from datastore</param> public void OnItemRead(Item item) { var data = JavascriptItemDataRepo.Read(item); if (data != null) { item.Data.Add(data); item.AddProperty(typeof(JavascriptItemProperty), new JavascriptItemProperty() { }); ExecuteFunction(item, "onItemRead", item); } }
/// <summary> /// Append attribute to base item when it is loaded /// </summary> /// <param name="item">Base item about to be persisted to datastore</param> public void OnItemUpdate(Item item) { if (item.HasData <JavascriptItemData>()) { var data = item.GetData <JavascriptItemData>(); if (data.Id == Guid.Empty) { OnItemCreate(item); } else { data.ScriptFunctions = GetFunctionDeclarations(data.Script); JavascriptItemDataRepo.Update(data); } } else if (JavascriptItemDataRepo.Read(item) is JavascriptItemData data) { JavascriptItemDataRepo.Delete(data); } }
/// <summary> /// Execute onTick javascript function on all items that have it /// </summary> public void OnTick() { if (TickCount++ >= TickInterval) { Logger.LogInformation("Running item scripts"); var javascriptDatas = JavascriptItemDataRepo.Read(); javascriptDatas.ForEach(data => { if (data.ScriptFunctions.Contains(":onTick:", StringComparison.InvariantCultureIgnoreCase)) { var item = ItemManager.Read(data.DataItemId); if (item == null) { throw new BeforeOurTimeException($"No item ({data.DataItemId}) found for javascript data ({data.Id})"); } JavascriptItemDataManager.ExecuteFunction(item, "onTick"); } }); TickCount = 0; } }
/// <summary> /// Execute a javascript function of an item /// </summary> /// <param name="item"></param> /// <param name="name"></param> /// <param name="parameters"></param> /// <returns></returns> public object ExecuteFunction(Item item, string name, params object[] parameters) { object report = null; if (item.GetData <JavascriptItemData>() is JavascriptItemData data) { if (data.ScriptFunctions.Contains($":{name}:", StringComparison.InvariantCultureIgnoreCase) && data.Disabled == false) { try { lock (_lock) { JSEngine.EnterExecutionContext(JSEngine.GlobalEnvironment, JSEngine.GlobalEnvironment, null); SetupJintItem(JSEngine, item); JSEngine.Execute(data.Script); report = JSEngine.Invoke(name, parameters)?.ToObject(); JSEngine.LeaveExecutionContext(); } } catch (Exception e) { data.ErrCount += 1; data.ErrDescriptions += $"Executing {name}: {e.Message}\n"; Logger.LogException($"JS Engine executing {name} in {item.Id}", e); if (data.ErrCount >= 10) { data.Disabled = true; Logger.LogError($"Disabled javascript for item {item.Id}"); Logger.LogException($"JS Engine executing {name} in {item.Id}", e); } JavascriptItemDataRepo.Update(data); } } } return(report); }
/// <summary> /// Get all unique item identifiers of managed items /// </summary> /// <returns></returns> public List <Guid> GetItemIds() { var itemIds = JavascriptItemDataRepo.GetItemIds(); return(itemIds); }