# WiréJS | Değişken değil, kablo kullanın ! # Açıklama WiréJS, dizinlenmiş akıllı değişkenler oluşturup kendi kendini yönetebilen veri değişimini kolayca yönetebilen sistemler oluşturabileceğiniz yapılar kurmanıza olanak sağlayan sistemdir. Verileri wriré içerisinden oluşturarak değişimleri ile etkileyecek diğer değişkenleri bağımsız yapılar içinde yazabilirsiniz. Ayrıca verilerinizi sistematik olarak depolar bu sayede veri türünü okuma ve yazma olaylarını denetleyebilirsiniz (getter/setter) # Kullanım örneği ## Veri yazma Tanım ```typescript declare function é(name: string, value: any): void; ``` ### Basit `name` ve `value` değerlerini `é` fonksiyonuna aktardığınızda bu ismi ve değeri global olarak depolar. Bu değeri istediğiniz herhangi bir noktada kullanabilirsiniz ```javascript // İlk argümanı isim ve ikinci argümanı değer olarak alır ve depolar é('name', 'John'); é('surname', 'Carter'); é('age', '34'); ``` ### Gelişmiş `name` alanına verdiğiniz değerler dosya sistemi benzeri dizinlenmiş olarak saklanır. Teknik olarak `/` ile ayırdığınız her alan için sistem o alan klasör gibi davranır ve son eğik çizgiden sonraki isme o değeri kaydeder. Teknik olarak `name`, `surname` ve `age` değerleri `userform` adı altında tutulur ve izlenir ```javascript é("userform/name/value", "John"); é("userform/name/required", true); é("userform/surname/value", "carter"); é("userform/surname/required", true); é("userform/age/value", "17"); é("userform/age/required", false); ``` ## Veri okuma Tanım ```typescript declare function é(name: string): any; ``` ### Basit Bir değeri okumak için `é` fonksiyonune değerin ismini yazmanız yeterli ```javascript let name = é("name"); console.log(name) // --> john ``` ### Gelişmiş Sistem yanlızca değerleri döner, dizinleri vermez. Bu yüzden değişkenin tam ismini kullanmanız gerekir ```javascript é("userform/name/value", "John"); é("userform") // ----> undefined é("userform/name") // ----> undefined é("userform/name/value") // ----> "John" !! é("userform/name/value/other") // ----> undefined ``` ## Veriyi izleme Tanım ```typescript declare function é(callback: function, variables:string[]): any; ``` `variables` ismindeki veriler değiştiğinde `callback` fonksiyonunu tetikler. ### Basit ```javascript é("number1", 20); é("number2", 40); é("number3", 60); é("average", 0); é(() => { let total = é("number1") + é("number2") + é("number3"); é("average", total / 3); },["number1","number2","number3"]); ``` Yukarıdaki kodda `number` isimli değişkenlerin herhangi birinin değişmesi durumunda en alttaki fonksiyonumuz çalışarak `average` değerini güncelleyecektir. Değişiklik izleme tiplemeleride dikkate alan karmaşık bir karşılaştırma algoritması üzerinden yapılır böylecek number, string, boolean değişimleri dışında array ve object tipli değişkenlerin değerleri izlene rekürsif bir şekilde izlenir ```javascript é("number1", 20); é("number1", 20); // does nothing, no write, no access é("number1", 21); // change detected, writed é("number1", 21); // does nothing, no write, no access é("object_variable", {var1: true,arr2: [1,2,3,[2]],callback: () => {}}); é("object_variable", {var1: true,arr2: [1,2,3,[2]],callback: () => {}}); // does nothing, no write, no access é("object_variable", {var1: true,arr2: [1,2,3,[3]],callback: () => {}}); // does nothing, no write, no access ``` ### Gelişmiş Ayrıca dizinlenmiş veriler için iç değerlerin değişimi, üst dizinlerden de izlenebilir ```javascript é("userform/register/name/value", "John"); é("userform/register/name/required", true); é("userform/register/surname/value", "carter"); é("userform/register/surname/required", true); é("userform/register/age/value", "17"); é("userform/register/age/required", false); é(()=>{ console.log("changed userform -> register") },["userform/register"]); ``` `userform/register` dizinin altındaki herhangi bir değerin değişmesi durumunda callback çağırılacaktır ## Okuma arabirimi (Middleware) ```typescript declare namespace é { function read(name: string, callback: (value:any) => any): void; } ``` Okuma arabirimi bir değerin saklanmasından sonra `é` fonksiyonu üzerinden geri çağırılması durumunda durumunda devreye girer. Bazı verileri saklandığı gibi değilde, farklı bir formatta almak istediğinizde kullanışlıdır. Nesneye yönelik dillerde getter gibidir **ancak burda değişkenin bulunması zorunlu değildir**, önce getter daha sonra değer belirlenebilir ```javascript é.read("code",usernameValue => { return `CODE#` + usernameValue; }); é("code", 117); console.log(é("code")) // ---> CODE#117 ``` ```javascript é("person", null); é("person/name", "John"); é("person/surname", "Carter"); é.read('person',function(){ return é("person/name") + " " + é("person/surname"); }) console.log(é("person")) // ---> "John Carter" é("person/name", "Bell"); console.log(é("person")) // ---> "Bell Carter" ``` ## Yazma arabirimi (Middleware) ```typescript declare namespace é { function write(name: string, callback: (value:any) => any): void; } ``` Yazma arabirimi bir verinin kaydedilmesi sırasında devreye girer ve verilen verinin depolanmadan önce ek kontroller yapılmasına değiştirilmesini sağlamak için kullanılabilir. Nesneye yönelik dillerde setter gibidir **ancak burda değişkenin bulunması zorunlu değildir**, önce setter daha sonra değer belirlenebilir Bir değerin tipinin değiştirilmesi ```javascript é("integer_value", 217.7525); é.write("integer_value",usernameValue => { return parseInt(usernameValue); }); console.log(é("integer_value")) // ---> 217 ``` Bir listenin içerisindeki null verilerinin çıkarılarak saklanması ```javascript é.write("numberList",usernameValue => { return usernameValue.filter(e => e != null) }); é("numberList", [1, null, 7, 63, 74, null, 7, 15]); console.log(é("numberList")) // ---> [1, 7, 63, 74, 7, 15] ``` > [!WARNING] Dikkat > getter ve setter metotları belirlendiği andan itibaren devreye girer, kendinden önce ve sonraki depolama veya okuma operasyonlarına karışmaz ## Veriyi kısıtlama ```typescript declare namespace é { function typedLock(name: string, {instance?:Function, type?:string, nullable?:boolean}): void; } ``` ### Veri tipini kısıtlama `typedLock` fonksiyonu belirlenen `name` değeri için tipleme ve değersizlik (nullable) kısıtlamalarını uygular. Bu tipleme isteğe bağlı olarak değiştirilebilir veya tekrar belirlenebilir ```javascript é("person/name", "John"); é.typedLock("person/name",{ type: "string", nullable: false }); é("person/name", null); // ----> Uncaught Error: value is not typeof number é("person/name", 27); /// -----> Uncaught Error: value is not typeof string ``` ### Veri tipi kısıtını kaldırma `typedLock` fonksiyonu belirlenen `name` değeri için tipleme ve değersizlik (nullable) kısıtlama kurallarını siler ```javascript é("person/name", "John"); é.typedLock("person/name",{ type: "string", nullable: false }); é("person/name", null); // ----> Uncaught Error: value is not typeof number é("person/name", 27); /// -----> Uncaught Error: value is not typeof string é.typedUnLock("person/name"); é("person/name", null); // ----> success, allowed! é("person/name", 27); /// -----> success, allowed ! ``` ## Seti temizleme WiréJS'de veriler ile arabirim ve veri tipi kısıtlayıcıları vs. ayrı ayrı tutulur. Veri bellek içerisinden silinse veya null değeri verilse dahil dinleyiciler aktif olarak çalışır. ```typescript declare namespace é { function delete(name: string): void; } ``` Verilen veri isminden tüm verileri, kısıtlayıcıları, okuma ve yazma arabirimlerini temizler. ```javascript é("name", "john"); // use updated callback é(()=> console.log("name changed"),['name']); // use setter callback é.read('name',value => `--${value}--`); é('name'); // ---> "--john---" é('name','Bell'); // ---> name changed // Delete name value, remove updated callbacks and setter callbacks é.delete("name"); é('name'); // ---> undefined é('name','Kyra'); // ---> do nothing.... é('name','Oliver'); // ---> do nothing.... é('name'); // ---> "Oliver" ``` ## Detaylar ### DOM ile birlikte kullanma ```javascript let nameInput = document.createElement("input"); // input değiştiğinde bildir nameInput.oninput = () => é('name', nameInput.value); é.read('name/valid',value => value.trim() != ""); let surnameInput = document.createElement("input"); // input değiştiğinde bildir surnameInput.oninput = () => é('surname', surnameInput.value); é.read('surname/valid',value => value.trim() != ""); let errorSpan = document.createElement("span"); é(() => surnameInput.value = é('message'),['message']); let submitButton = document.createElement("button"); submitButton.disabled = true; // submit_isActive değeri değiştiğinde disabled özelliğini değiştir é(() => { submitButton.disabled = !é("submit_isActive") },["submit_isActive"]); é(()=>{ if(é("name/valid") && é("surname/valid")){ é('message', "Form's input is valid") é("submit_isActive", true) }else{ é('message', "Please fill all inputs") é("submit_isActive", false) } },["name","surname"]); ``` ### Fark algoritmasını değiştirme Bazen verilerin değişimini algılamak için tipleri veya verinin içeriği kontrol etmek gereksiz olabilir. Senaryonuzu karmaşık veriler dışında basit primitive veriler üzerine kurguluyorsanız fark algoritmasını basitleştirerek performansı yarı yarıya artırabilirsiniz ```typescript declare namespace é { function diff(callback: (oldValue?:any, newValue?:any) => boolean): void; } ``` Belirli bir verinin farklı bir algoritma kullanılarak karşılaştırılmasını sağlar Örneğin sizin için basit bir (tipleme korumasız) bir karşılaştırma yetiyor olabilir ```javascript é("number", 4); é("number", 5); // ----> changed é.diff("number", (oldValue, newValue) => oldValue != newValue); é("number", 6); // ----> changed ! é("number", 0); // ----> changed ! é("number", false); // ----> no change é("number", null); // ----> no change é("number", undefined); // ----> no change é("number", []); // ----> no change é("number", 3); // ----> changed ! é("number", 1); // ----> changed ! é("number", true); // ----> no change ``` Veya ortalaması aynı olan bir listenin eşitlenmesi gereksiz bir durum olabilir ```javascript é("numberList", [ 0, 1, 2, 3]); é("numberList", [-1, 1, 2, 3, 4]); // ----> changed ! é.diff("numberList", (oldValue, newValue) => { let oldValueSum = oldValue.reduce((sum, num) => sum + num, 0) / oldValue.length; let newValue = newValue.reduce((sum, num) => sum + num, 0) / newValue.length; return oldValueSum != newValue }); é("numberList", [2]); é("numberList", [ 1, 2, 3]); // ----> no change, no write é("numberList", [ 0, 1, 2, 3, 4]); // ----> no change, no write é("numberList", [-2, 0, 2, 4, 6]); // ----> no change, no write é("numberList", [+1, 2, 3, 4, 5]) // ----> changed ! ``` Bu karşılaştırmanın sonucunu depolamadığı gibi aynı zamanda dinleyicileride çalıştırmayacaktır