From ef957871945fc0040325a7fe1131f88596a3f7c9 Mon Sep 17 00:00:00 2001 From: Timur Shemsedinov Date: Fri, 4 Jul 2025 02:47:50 +0300 Subject: [PATCH 1/2] Improve actions --- Enterprise/static/application.js | 16 ++++++++-------- Pragmatic/static/application.js | 17 +++++++++++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Enterprise/static/application.js b/Enterprise/static/application.js index 116e39c..5ce1138 100644 --- a/Enterprise/static/application.js +++ b/Enterprise/static/application.js @@ -23,7 +23,12 @@ const logger = new Logger('output'); const action = (id, handler) => { const element = document.getElementById(id); - if (element) element.onclick = handler; + if (!element) return; + element.onclick = () => { + handler().catch((error) => { + logger.log(error.message); + }); + }; }; const db = new Database('EnterpriseApplication', 1, (db) => { @@ -38,7 +43,6 @@ const userService = new UserService(userRepository); action('add', async () => { const name = prompt('Enter user name:'); const age = parseInt(prompt('Enter age:'), 10); - if (!name || !Number.isInteger(age)) return; const user = await userService.createUser(name, age); logger.log('Added:', user); }); @@ -49,12 +53,8 @@ action('get', async () => { }); action('update', async () => { - try { - const user = await userService.incrementAge(1); - logger.log('Updated:', user); - } catch (err) { - logger.log(err.message); - } + const user = await userService.incrementAge(1); + logger.log('Updated:', user); }); action('delete', async () => { diff --git a/Pragmatic/static/application.js b/Pragmatic/static/application.js index 3ee086b..be3772f 100644 --- a/Pragmatic/static/application.js +++ b/Pragmatic/static/application.js @@ -67,11 +67,16 @@ const actions = { }, }; -const init = () => { - for (const [id, handler] of Object.entries(actions)) { - const element = document.getElementById(id); - if (element) element.onclick = handler; - } +const action = (id, handler) => { + const element = document.getElementById(id); + if (!element) return; + element.onclick = () => { + handler().catch((error) => { + logger.log(error.message); + }); + }; }; -init(); +for (const [id, handler] of Object.entries(actions)) { + action(id, handler); +} From 6a64bfc6caa7fcee81f50d08824d2a4fb6e9705f Mon Sep 17 00:00:00 2001 From: Timur Shemsedinov Date: Fri, 4 Jul 2025 02:54:47 +0300 Subject: [PATCH 2/2] Implement schema validation add creation --- Pragmatic/static/application.js | 8 +++++--- Pragmatic/static/storage.js | 29 +++++++++++++++++++++++++---- Pragmatic/test/database.js | 22 ++++++++++------------ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/Pragmatic/static/application.js b/Pragmatic/static/application.js index be3772f..443c254 100644 --- a/Pragmatic/static/application.js +++ b/Pragmatic/static/application.js @@ -20,16 +20,18 @@ class Logger { const logger = new Logger('output'); const schemas = { - user: { keyPath: 'id', autoIncrement: true }, + user: { + id: { type: 'int', primary: true }, + name: { type: 'str', index: true }, + age: { type: 'int' }, + }, }; const db = await new Database('Example', { version: 1, schemas }); const actions = { add: async () => { const name = prompt('Enter user name:'); - if (!name) return; const age = parseInt(prompt('Enter age:'), 10); - if (!Number.isInteger(age)) return; const user = { name, age }; await db.insert({ store: 'user', record: user }); logger.log('Added:', user); diff --git a/Pragmatic/static/storage.js b/Pragmatic/static/storage.js index dce6f4b..89416fb 100644 --- a/Pragmatic/static/storage.js +++ b/Pragmatic/static/storage.js @@ -33,10 +33,12 @@ class Database { #upgrade(db) { for (const [name, schema] of Object.entries(this.#schemas)) { if (!db.objectStoreNames.contains(name)) { - const store = db.createObjectStore(name, schema); - const indexes = schema.indexes ?? []; - for (const { name: idxName, keyPath, options } of indexes) { - store.createIndex(idxName, keyPath, options); + const options = { keyPath: 'id', autoIncrement: true }; + const store = db.createObjectStore(name, options); + for (const [field, def] of Object.entries(schema)) { + if (name !== 'id' && def.index) { + store.createIndex(field, field, { unique: false }); + } } } } @@ -59,11 +61,30 @@ class Database { }); } + validate({ store, record }) { + const schema = this.#schemas[store]; + if (!schema) throw new Error(`Schema for ${store} is not defined`); + for (const [key, val] of Object.entries(record)) { + const field = schema[key]; + const name = `Field ${store}.${key}`; + if (!field) throw new Error(`${name} is not defined`); + if (field.type === 'int') { + if (Number.isInteger(val)) continue; + throw new Error(`${name} expected to be integer`); + } else if (field.type === 'str') { + if (typeof val === 'string') continue; + throw new Error(`${name} expected to be string`); + } + } + } + insert({ store, record }) { + this.validate({ store, record }); return this.#exec(store, (objectStore) => objectStore.add(record)); } update({ store, record }) { + this.validate({ store, record }); return this.#exec(store, (objectStore) => objectStore.put(record)); } diff --git a/Pragmatic/test/database.js b/Pragmatic/test/database.js index a2bd587..d48f7c0 100644 --- a/Pragmatic/test/database.js +++ b/Pragmatic/test/database.js @@ -3,13 +3,16 @@ import assert from 'node:assert/strict'; import 'fake-indexeddb/auto'; import { Database } from '../static/storage.js'; +const schemas = { + user: { + id: { type: 'int', primary: true }, + name: { type: 'str', index: true }, + age: { type: 'int' }, + }, +}; + test('Pragmatic: Database CRUD + DSL', async () => { - const db = await new Database('PragmaticDB', { - version: 1, - schemas: { - user: { keyPath: 'id', autoIncrement: true }, - }, - }); + const db = await new Database('PragmaticDB', { version: 1, schemas }); // Insert await db.insert({ store: 'user', record: { name: 'Marcus', age: 20 } }); @@ -74,12 +77,7 @@ test('Pragmatic: Database CRUD + DSL', async () => { }); test('Pragmatic: Complex DSL', async () => { - const db = await new Database('ComplexDB', { - version: 1, - schemas: { - user: { keyPath: 'id', autoIncrement: true }, - }, - }); + const db = await new Database('ComplexDB', { version: 1, schemas }); await db.insert({ store: 'user', record: { name: 'Marcus', age: 20 } }); await db.insert({ store: 'user', record: { name: 'Lucius', age: 20 } });