@coherent.js/state 1.1.2 → 2.0.0-rc.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.
- package/README.md +84 -15
- package/dist/index.js +922 -333
- package/dist/index.js.map +3 -3
- package/dist/reactive-state.js +468 -111
- package/dist/reactive-state.js.map +2 -2
- package/dist/state-manager.js +141 -38
- package/dist/state-manager.js.map +3 -3
- package/dist/state-persistence.js +239 -143
- package/dist/state-persistence.js.map +2 -2
- package/dist/state-validation.js +63 -41
- package/dist/state-validation.js.map +2 -2
- package/package.json +1 -4
- package/types/index.d.ts +143 -36
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/state-persistence.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * @fileoverview State Persistence for Coherent.js\n * Provides persistent state management with multiple storage backends\n * @module @coherent.js/core/state/state-persistence\n */\n\n/**\n * @typedef {'localStorage'|'sessionStorage'|'indexedDB'|'memory'} StorageType\n */\n\n/**\n * @typedef {Object} PersistenceOptions\n * @property {StorageType} [storage='localStorage'] - Storage backend to use\n * @property {string} [key='coherent-state'] - Storage key prefix\n * @property {boolean} [debounce=true] - Debounce state saves\n * @property {number} [debounceDelay=300] - Debounce delay in ms\n * @property {Function} [serialize=JSON.stringify] - Serialization function\n * @property {Function} [deserialize=JSON.parse] - Deserialization function\n * @property {Array<string>} [include] - Keys to include (whitelist)\n * @property {Array<string>} [exclude] - Keys to exclude (blacklist)\n * @property {boolean} [encrypt=false] - Encrypt stored data\n * @property {string} [encryptionKey] - Encryption key\n * @property {Function} [onSave] - Callback when state is saved\n * @property {Function} [onLoad] - Callback when state is loaded\n * @property {Function} [onError] - Error callback\n * @property {boolean} [versioning=false] - Enable versioning\n * @property {string} [version='1.0.0'] - Current version\n * @property {Function} [migrate] - Migration function for version changes\n * @property {number} [ttl] - Time to live in milliseconds\n * @property {boolean} [crossTab=false] - Enable cross-tab synchronization\n */\n\n/**\n * Storage adapter interface\n * @interface StorageAdapter\n */\n\n/**\n * LocalStorage adapter\n */\nclass LocalStorageAdapter {\n constructor() {\n this.available = typeof localStorage !== 'undefined';\n }\n\n async get(key) {\n if (!this.available) return null;\n try {\n return localStorage.getItem(key);\n } catch (error) {\n console.error('LocalStorage get error:', error);\n return null;\n }\n }\n\n async set(key, value) {\n if (!this.available) return false;\n try {\n localStorage.setItem(key, value);\n return true;\n } catch (error) {\n console.error('LocalStorage set error:', error);\n return false;\n }\n }\n\n async remove(key) {\n if (!this.available) return false;\n try {\n localStorage.removeItem(key);\n return true;\n } catch (error) {\n console.error('LocalStorage remove error:', error);\n return false;\n }\n }\n\n async clear() {\n if (!this.available) return false;\n try {\n localStorage.clear();\n return true;\n } catch (error) {\n console.error('LocalStorage clear error:', error);\n return false;\n }\n }\n}\n\n/**\n * SessionStorage adapter\n */\nclass SessionStorageAdapter {\n constructor() {\n this.available = typeof sessionStorage !== 'undefined';\n }\n\n async get(key) {\n if (!this.available) return null;\n try {\n return sessionStorage.getItem(key);\n } catch (error) {\n console.error('SessionStorage get error:', error);\n return null;\n }\n }\n\n async set(key, value) {\n if (!this.available) return false;\n try {\n sessionStorage.setItem(key, value);\n return true;\n } catch (error) {\n console.error('SessionStorage set error:', error);\n return false;\n }\n }\n\n async remove(key) {\n if (!this.available) return false;\n try {\n sessionStorage.removeItem(key);\n return true;\n } catch (error) {\n console.error('SessionStorage remove error:', error);\n return false;\n }\n }\n\n async clear() {\n if (!this.available) return false;\n try {\n sessionStorage.clear();\n return true;\n } catch (error) {\n console.error('SessionStorage clear error:', error);\n return false;\n }\n }\n}\n\n/**\n * IndexedDB adapter\n */\nclass IndexedDBAdapter {\n constructor(dbName = 'coherent-db', storeName = 'state') {\n this.dbName = dbName;\n this.storeName = storeName;\n this.available = typeof indexedDB !== 'undefined';\n this.db = null;\n }\n\n async init() {\n if (!this.available) return false;\n if (this.db) return true;\n\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => {\n console.error('IndexedDB open error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve(true);\n };\n\n request.onupgradeneeded = (event) => {\n const db = event.target.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n });\n }\n\n async get(key) {\n if (!this.available) return null;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n\n request.onerror = () => {\n console.error('IndexedDB get error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(request.result || null);\n };\n });\n }\n\n async set(key, value) {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n\n request.onerror = () => {\n console.error('IndexedDB set error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n\n async remove(key) {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.delete(key);\n\n request.onerror = () => {\n console.error('IndexedDB remove error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n\n async clear() {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.clear();\n\n request.onerror = () => {\n console.error('IndexedDB clear error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n}\n\n/**\n * Memory adapter (for testing or fallback)\n */\nclass MemoryAdapter {\n constructor() {\n this.storage = new Map();\n this.available = true;\n }\n\n async get(key) {\n return this.storage.get(key) || null;\n }\n\n async set(key, value) {\n this.storage.set(key, value);\n return true;\n }\n\n async remove(key) {\n return this.storage.delete(key);\n }\n\n async clear() {\n this.storage.clear();\n return true;\n }\n}\n\n/**\n * Simple encryption/decryption (basic XOR cipher)\n * For production, use Web Crypto API or a proper crypto library\n */\nclass SimpleEncryption {\n constructor(key) {\n this.key = key || 'default-key';\n }\n\n encrypt(text) {\n let result = '';\n for (let i = 0; i < text.length; i++) {\n result += String.fromCharCode(\n text.charCodeAt(i) ^ this.key.charCodeAt(i % this.key.length)\n );\n }\n return btoa(result);\n }\n\n decrypt(encrypted) {\n const text = atob(encrypted);\n let result = '';\n for (let i = 0; i < text.length; i++) {\n result += String.fromCharCode(\n text.charCodeAt(i) ^ this.key.charCodeAt(i % this.key.length)\n );\n }\n return result;\n }\n}\n\n/**\n * Create storage adapter\n * @param {StorageType} type - Storage type\n * @returns {StorageAdapter} Storage adapter instance\n */\nfunction createStorageAdapter(type) {\n switch (type) {\n case 'localStorage':\n return new LocalStorageAdapter();\n case 'sessionStorage':\n return new SessionStorageAdapter();\n case 'indexedDB':\n return new IndexedDBAdapter();\n case 'memory':\n return new MemoryAdapter();\n default:\n return new LocalStorageAdapter();\n }\n}\n\n/**\n * Create persistent state manager\n * @param {Object} initialState - Initial state\n * @param {PersistenceOptions} options - Persistence options\n * @returns {Object} Persistent state manager\n */\nexport function createPersistentState(initialState = {}, options = {}) {\n const opts = {\n storage: 'localStorage',\n key: 'coherent-state',\n debounce: true,\n debounceDelay: 300,\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n include: null,\n exclude: null,\n encrypt: false,\n encryptionKey: null,\n onSave: null,\n onLoad: null,\n onError: null,\n versioning: false,\n version: '1.0.0',\n migrate: null,\n ttl: null,\n crossTab: false,\n ...options\n };\n\n const adapter = createStorageAdapter(opts.storage);\n const encryption = opts.encrypt ? new SimpleEncryption(opts.encryptionKey) : null;\n\n let state = { ...initialState };\n let saveTimeout = null;\n const listeners = new Set();\n\n /**\n * Filter state keys based on include/exclude options\n * @param {Object} obj - State object\n * @returns {Object} Filtered state\n */\n function filterKeys(obj) {\n if (!obj || typeof obj !== 'object') return obj;\n\n // If include list is provided, only include those keys\n if (opts.include && Array.isArray(opts.include)) {\n const filtered = {};\n opts.include.forEach(key => {\n if (key in obj) {\n filtered[key] = obj[key];\n }\n });\n return filtered;\n }\n\n // If exclude list is provided, exclude those keys\n if (opts.exclude && Array.isArray(opts.exclude)) {\n const filtered = { ...obj };\n opts.exclude.forEach(key => {\n delete filtered[key];\n });\n return filtered;\n }\n\n return obj;\n }\n\n /**\n * Save state to storage\n * @param {boolean} immediate - Save immediately without debounce\n */\n async function save(immediate = false) {\n if (opts.debounce && !immediate) {\n clearTimeout(saveTimeout);\n saveTimeout = setTimeout(() => save(true), opts.debounceDelay);\n return;\n }\n\n try {\n const filteredState = filterKeys(state);\n const serialized = opts.serialize(filteredState);\n\n // Add metadata\n const data = {\n state: serialized,\n version: opts.version,\n timestamp: Date.now(),\n ttl: opts.ttl\n };\n\n let dataString = JSON.stringify(data);\n\n // Encrypt if enabled\n if (encryption) {\n dataString = encryption.encrypt(dataString);\n }\n\n await adapter.set(opts.key, dataString);\n\n // Call onSave callback\n if (opts.onSave) {\n opts.onSave(filteredState);\n }\n\n // Broadcast to other tabs if cross-tab sync is enabled\n if (opts.crossTab && typeof BroadcastChannel !== 'undefined') {\n const channel = new BroadcastChannel('coherent-state-sync');\n channel.postMessage({ type: 'state-update', state: filteredState });\n channel.close();\n }\n } catch (error) {\n console.error('State save error:', error);\n if (opts.onError) {\n opts.onError(error);\n }\n }\n }\n\n /**\n * Load state from storage\n */\n async function load() {\n try {\n let dataString = await adapter.get(opts.key);\n if (!dataString) return null;\n\n // Decrypt if enabled\n if (encryption) {\n dataString = encryption.decrypt(dataString);\n }\n\n const data = JSON.parse(dataString);\n\n // Check TTL\n if (data.ttl && data.timestamp) {\n const age = Date.now() - data.timestamp;\n if (age > data.ttl) {\n await adapter.remove(opts.key);\n return null;\n }\n }\n\n // Check version and migrate if needed\n if (opts.versioning && data.version !== opts.version) {\n if (opts.migrate) {\n const migrated = opts.migrate(data.state, data.version, opts.version);\n return opts.deserialize(migrated);\n }\n return null;\n }\n\n const loadedState = opts.deserialize(data.state);\n\n // Call onLoad callback\n if (opts.onLoad) {\n opts.onLoad(loadedState);\n }\n\n return loadedState;\n } catch (error) {\n console.error('State load error:', error);\n if (opts.onError) {\n opts.onError(error);\n }\n return null;\n }\n }\n\n /**\n * Subscribe to state changes\n * @param {Function} listener - Change listener\n * @returns {Function} Unsubscribe function\n */\n function subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }\n\n /**\n * Notify listeners of state changes\n * @param {Object} oldState - Previous state\n * @param {Object} newState - New state\n */\n function notifyListeners(oldState, newState) {\n listeners.forEach(listener => {\n try {\n listener(newState, oldState);\n } catch (error) {\n console.error('Listener error:', error);\n }\n });\n }\n\n /**\n * Get current state\n * @param {string} [key] - State key\n * @returns {*} State value or entire state\n */\n function getState(key) {\n return key ? state[key] : { ...state };\n }\n\n /**\n * Set state\n * @param {Object|Function} updates - State updates or updater function\n * @param {boolean} persist - Persist to storage\n */\n function setState(updates, persist = true) {\n const oldState = { ...state };\n\n if (typeof updates === 'function') {\n updates = updates(oldState);\n }\n\n state = { ...state, ...updates };\n\n notifyListeners(oldState, state);\n\n if (persist) {\n save();\n }\n }\n\n /**\n * Reset state to initial values\n * @param {boolean} persist - Persist to storage\n */\n function resetState(persist = true) {\n const oldState = { ...state };\n state = { ...initialState };\n notifyListeners(oldState, state);\n\n if (persist) {\n save(true);\n }\n }\n\n /**\n * Clear persisted state\n */\n async function clearStorage() {\n await adapter.remove(opts.key);\n }\n\n /**\n * Manually trigger persistence\n */\n async function persist() {\n await save(true);\n }\n\n /**\n * Restore state from storage\n */\n async function restore() {\n const loaded = await load();\n if (loaded) {\n const oldState = { ...state };\n state = { ...state, ...loaded };\n notifyListeners(oldState, state);\n return true;\n }\n return false;\n }\n\n // Setup cross-tab synchronization\n if (opts.crossTab && typeof BroadcastChannel !== 'undefined') {\n const channel = new BroadcastChannel('coherent-state-sync');\n channel.onmessage = (event) => {\n if (event.data.type === 'state-update') {\n const oldState = { ...state };\n state = { ...state, ...event.data.state };\n notifyListeners(oldState, state);\n }\n };\n }\n\n // Auto-restore on creation\n if (opts.storage !== 'memory') {\n restore();\n }\n\n return {\n getState,\n setState,\n resetState,\n subscribe,\n persist,\n restore,\n clearStorage,\n load,\n save: () => save(true),\n get adapter() {\n return adapter;\n }\n };\n}\n\n/**\n * Create persistent state with localStorage\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withLocalStorage(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'localStorage',\n key\n });\n}\n\n/**\n * Create persistent state with sessionStorage\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withSessionStorage(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'sessionStorage',\n key\n });\n}\n\n/**\n * Create persistent state with IndexedDB\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withIndexedDB(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'indexedDB',\n key\n });\n}\n\nexport default {\n createPersistentState,\n withLocalStorage,\n withSessionStorage,\n withIndexedDB,\n createStorageAdapter\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview State Persistence for Coherent.js\n * Provides persistent state management with multiple storage backends\n * @module @coherent.js/core/state/state-persistence\n */\n\n/**\n * @typedef {'localStorage'|'sessionStorage'|'indexedDB'|'memory'} StorageType\n */\n\n/**\n * @typedef {Object} PersistenceOptions\n * @property {StorageType} [storage='localStorage'] - Storage backend to use\n * @property {StorageAdapter} [adapter] - Custom storage backend; used as is,\n * also on the server\n * @property {string} [key='coherent-state'] - Storage key prefix\n * @property {boolean} [debounce=true] - Debounce state saves\n * @property {number} [debounceDelay=300] - Debounce delay in ms\n * @property {Function} [serialize=JSON.stringify] - Serialization function\n * @property {Function} [deserialize=JSON.parse] - Deserialization function\n * @property {Array<string>} [include] - Keys to include (whitelist)\n * @property {Array<string>} [exclude] - Keys to exclude (blacklist)\n * @property {boolean} [encrypt=false] - Obfuscate stored data with\n * `encryptionKey` (XOR \u2014 not encryption; anyone with the key, which ships\n * to the browser, can read it)\n * @property {string} [encryptionKey] - Obfuscation key; required with `encrypt`\n * @property {Function} [onSave] - Callback when state is saved\n * @property {Function} [onLoad] - Callback when state is loaded\n * @property {Function} [onError] - Error callback (load, save or storage failures)\n * @property {boolean} [versioning=false] - Enable versioning\n * @property {string} [version='1.0.0'] - Current version\n * @property {Function} [migrate] - Migration function for version changes\n * @property {number} [ttl] - Time to live in milliseconds\n * @property {boolean} [crossTab=false] - Enable cross-tab synchronization\n * @property {string} [dbName='coherent-db'] - IndexedDB database name (`storage: 'indexedDB'`)\n * @property {string} [storeName='state'] - IndexedDB object store name (`storage: 'indexedDB'`)\n */\n\n/**\n * Storage adapter interface: async get/set/remove/clear. `set` resolves to\n * `true` once the value is stored and rejects (or resolves `false`) when it\n * could not be.\n * @interface StorageAdapter\n */\n\n/**\n * Web Storage adapter (localStorage / sessionStorage). Storage errors, such as\n * QuotaExceededError, propagate to the caller.\n */\nclass WebStorageAdapter {\n constructor(storageName) {\n this.storageName = storageName;\n this.available = typeof globalThis[storageName] !== 'undefined' && globalThis[storageName] !== null;\n }\n\n get storage() {\n return globalThis[this.storageName];\n }\n\n async get(key) {\n if (!this.available) return null;\n return this.storage.getItem(key);\n }\n\n async set(key, value) {\n if (!this.available) return false;\n this.storage.setItem(key, value);\n return true;\n }\n\n async remove(key) {\n if (!this.available) return false;\n this.storage.removeItem(key);\n return true;\n }\n\n async clear() {\n if (!this.available) return false;\n this.storage.clear();\n return true;\n }\n}\n\n/**\n * LocalStorage adapter\n */\nclass LocalStorageAdapter extends WebStorageAdapter {\n constructor() {\n super('localStorage');\n }\n}\n\n/**\n * SessionStorage adapter\n */\nclass SessionStorageAdapter extends WebStorageAdapter {\n constructor() {\n super('sessionStorage');\n }\n}\n\n/**\n * IndexedDB adapter: values are kept in the object store `storeName` of the\n * database `dbName`.\n */\nclass IndexedDBAdapter {\n constructor(dbName = 'coherent-db', storeName = 'state') {\n this.dbName = dbName;\n this.storeName = storeName;\n this.available = typeof indexedDB !== 'undefined';\n this.db = null;\n this.opening = null;\n }\n\n /**\n * Open the database, creating the store in an upgrade. Without `version`,\n * opens the current version (creating version 1 for a new database).\n */\n open(version) {\n return new Promise((resolve, reject) => {\n const request = version === undefined\n ? indexedDB.open(this.dbName)\n : indexedDB.open(this.dbName, version);\n\n request.onerror = () => {\n console.error('IndexedDB open error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(request.result);\n };\n\n request.onupgradeneeded = (event) => {\n const db = event.target.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n });\n }\n\n async init() {\n if (!this.available) return false;\n if (this.db) return true;\n\n this.opening ??= (async () => {\n let db = await this.open();\n // The database already exists without this store (another store with\n // the same dbName created it): add the store in a version upgrade.\n if (!db.objectStoreNames.contains(this.storeName)) {\n const version = db.version + 1;\n db.close();\n db = await this.open(version);\n }\n // Let another store's upgrade proceed; reopen on the next access.\n db.onversionchange = () => {\n db.close();\n if (this.db === db) this.db = null;\n };\n this.db = db;\n return true;\n })().finally(() => {\n this.opening = null;\n });\n\n return this.opening;\n }\n\n async get(key) {\n if (!this.available) return null;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n\n request.onerror = () => {\n console.error('IndexedDB get error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(request.result || null);\n };\n });\n }\n\n async set(key, value) {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n\n request.onerror = () => {\n console.error('IndexedDB set error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n\n async remove(key) {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.delete(key);\n\n request.onerror = () => {\n console.error('IndexedDB remove error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n\n async clear() {\n if (!this.available) return false;\n await this.init();\n\n return new Promise((resolve, reject) => {\n const transaction = this.db.transaction([this.storeName], 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.clear();\n\n request.onerror = () => {\n console.error('IndexedDB clear error:', request.error);\n reject(request.error);\n };\n\n request.onsuccess = () => {\n resolve(true);\n };\n });\n }\n}\n\n/**\n * Memory adapter (for testing or fallback)\n */\nclass MemoryAdapter {\n constructor() {\n this.storage = new Map();\n this.available = true;\n }\n\n async get(key) {\n return this.storage.get(key) || null;\n }\n\n async set(key, value) {\n this.storage.set(key, value);\n return true;\n }\n\n async remove(key) {\n return this.storage.delete(key);\n }\n\n async clear() {\n this.storage.clear();\n return true;\n }\n}\n\n\n/**\n * Stand-in for browser storage on the server. Web Storage there (Node's\n * `--experimental-webstorage`, on by default in newer releases) is shared by\n * every request in the process, so one visitor's state would be restored into\n * another's render. Nothing is read or written.\n */\nclass ServerAdapter {\n constructor() {\n this.available = false;\n }\n\n async get() {\n return null;\n }\n\n async set() {\n return false;\n }\n\n async remove() {\n return false;\n }\n\n async clear() {\n return false;\n }\n}\n\nfunction toBase64(bytes) {\n let binary = '';\n for (let i = 0; i < bytes.length; i += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n }\n return btoa(binary);\n}\n\nfunction fromBase64(encoded) {\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\n/**\n * XOR obfuscation of the stored payload (option `encrypt`).\n *\n * This is NOT encryption: the key has to ship to the browser, and XOR with a\n * repeating key is trivially reversible. It only keeps casual readers of the\n * storage from seeing plain JSON. Do not store secrets in browser storage.\n *\n * Works on UTF-8 bytes, so any Unicode text round-trips.\n */\nclass XorObfuscation {\n constructor(key) {\n if (typeof key !== 'string' || key.length === 0) {\n throw new TypeError(\n 'createPersistentState: `encrypt: true` requires a non-empty `encryptionKey`. ' +\n 'It is XOR obfuscation, not encryption; there is no default key.'\n );\n }\n this.keyBytes = new globalThis.TextEncoder().encode(key);\n }\n\n xor(bytes) {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] ^= this.keyBytes[i % this.keyBytes.length];\n }\n return bytes;\n }\n\n encode(text) {\n return toBase64(this.xor(new globalThis.TextEncoder().encode(text)));\n }\n\n decode(encoded) {\n return new globalThis.TextDecoder().decode(this.xor(fromBase64(encoded)));\n }\n}\n\n/**\n * Create storage adapter\n * @param {StorageType} type - Storage type\n * @param {Pick<PersistenceOptions, 'dbName'|'storeName'>} [options] - IndexedDB\n * database and object store names\n * @returns {StorageAdapter} Storage adapter instance\n */\nfunction createStorageAdapter(type, options = {}) {\n switch (type) {\n case 'localStorage':\n return new LocalStorageAdapter();\n case 'sessionStorage':\n return new SessionStorageAdapter();\n case 'indexedDB':\n return new IndexedDBAdapter(options.dbName ?? undefined, options.storeName ?? undefined);\n case 'memory':\n return new MemoryAdapter();\n default:\n return new LocalStorageAdapter();\n }\n}\n\nfunction createInstanceId() {\n const cryptoApi = globalThis.crypto;\n if (cryptoApi && typeof cryptoApi.randomUUID === 'function') {\n return cryptoApi.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Create persistent state manager\n *\n * Unless the backend is `'memory'`, stored state is restored on creation;\n * `ready` settles once that is done. Keys set before then keep the value they\n * were set to rather than the stored one.\n *\n * On the server (no `window`), browser storage backends read and write\n * nothing and cross-tab sync is off; pass an explicit `adapter` to persist\n * there.\n *\n * @param {Object} initialState - Initial state\n * @param {PersistenceOptions} options - Persistence options\n * @returns {Object} Persistent state manager\n */\nexport function createPersistentState(initialState = {}, options = {}) {\n const opts = {\n storage: 'localStorage',\n adapter: null,\n key: 'coherent-state',\n debounce: true,\n debounceDelay: 300,\n serialize: JSON.stringify,\n deserialize: JSON.parse,\n include: null,\n exclude: null,\n encrypt: false,\n encryptionKey: null,\n onSave: null,\n onLoad: null,\n onError: null,\n versioning: false,\n version: '1.0.0',\n migrate: null,\n ttl: null,\n crossTab: false,\n ...options\n };\n\n const onServer = typeof window === 'undefined';\n const obfuscation = opts.encrypt ? new XorObfuscation(opts.encryptionKey) : null;\n\n let adapter;\n if (opts.adapter) {\n adapter = opts.adapter;\n } else if (onServer && opts.storage !== 'memory') {\n adapter = new ServerAdapter();\n } else {\n adapter = createStorageAdapter(opts.storage, opts);\n }\n\n const instanceId = createInstanceId();\n let state = { ...initialState };\n let saveTimeout = null;\n let destroyed = false;\n const listeners = new Set();\n\n // Keys written while the initial restore is in flight; it must not\n // overwrite them with the older stored values.\n let initialRestorePending = false;\n const touchedKeys = new Set();\n\n function reportError(error) {\n if (opts.onError) {\n opts.onError(error);\n } else {\n console.error('State persistence error:', error);\n }\n }\n\n /**\n * Filter state keys based on include/exclude options\n * @param {Object} obj - State object\n * @returns {Object} Filtered state\n */\n function filterKeys(obj) {\n if (!obj || typeof obj !== 'object') return obj;\n\n // If include list is provided, only include those keys\n if (opts.include && Array.isArray(opts.include)) {\n const filtered = {};\n opts.include.forEach(key => {\n if (key in obj) {\n filtered[key] = obj[key];\n }\n });\n return filtered;\n }\n\n // If exclude list is provided, exclude those keys\n if (opts.exclude && Array.isArray(opts.exclude)) {\n const filtered = { ...obj };\n opts.exclude.forEach(key => {\n delete filtered[key];\n });\n return filtered;\n }\n\n return obj;\n }\n\n // Cross-tab synchronisation: one channel per storage key, so unrelated\n // stores never merge each other's state, and messages carry the sender's\n // id so a store never applies its own update.\n let channel = null;\n if (opts.crossTab && !onServer && typeof BroadcastChannel !== 'undefined') {\n channel = new BroadcastChannel(`coherent-state-sync:${opts.key}`);\n channel.onmessage = (event) => {\n const message = event.data;\n if (destroyed || !message || message.type !== 'state-update' || message.source === instanceId) {\n return;\n }\n const oldState = { ...state };\n state = { ...state, ...message.state };\n notifyListeners(oldState, state);\n };\n // Node: do not keep the process alive for this channel\n channel.unref?.();\n }\n\n function broadcast(filteredState) {\n if (!channel) return;\n try {\n channel.postMessage({ type: 'state-update', source: instanceId, state: filteredState });\n } catch (error) {\n reportError(error);\n }\n }\n\n /**\n * Write the current state now.\n * @returns {Promise<boolean>} Whether it was stored\n */\n async function write() {\n if (adapter.available === false) {\n return false;\n }\n\n try {\n const filteredState = filterKeys(state);\n const serialized = opts.serialize(filteredState);\n\n // Add metadata\n const data = {\n state: serialized,\n version: opts.version,\n timestamp: Date.now(),\n ttl: opts.ttl\n };\n\n let dataString = JSON.stringify(data);\n\n if (obfuscation) {\n dataString = obfuscation.encode(dataString);\n }\n\n const stored = await adapter.set(opts.key, dataString);\n if (stored === false) {\n throw new Error(`State \"${opts.key}\" could not be written to storage`);\n }\n\n // Call onSave callback\n if (opts.onSave) {\n opts.onSave(filteredState);\n }\n\n broadcast(filteredState);\n return true;\n } catch (error) {\n reportError(error);\n return false;\n }\n }\n\n /**\n * Save state to storage\n * @param {boolean} immediate - Save immediately without debounce\n * @returns {Promise<boolean>|undefined} Whether it was stored (immediate saves)\n */\n function save(immediate = false) {\n if (destroyed) {\n return Promise.resolve(false);\n }\n\n if (opts.debounce && !immediate) {\n clearTimeout(saveTimeout);\n saveTimeout = setTimeout(() => {\n saveTimeout = null;\n write();\n }, opts.debounceDelay);\n return undefined;\n }\n\n clearTimeout(saveTimeout);\n saveTimeout = null;\n return write();\n }\n\n /**\n * Load state from storage\n */\n async function load() {\n try {\n let dataString = await adapter.get(opts.key);\n if (!dataString) return null;\n\n if (obfuscation) {\n dataString = obfuscation.decode(dataString);\n }\n\n const data = JSON.parse(dataString);\n\n // Check TTL\n if (data.ttl && data.timestamp) {\n const age = Date.now() - data.timestamp;\n if (age > data.ttl) {\n await adapter.remove(opts.key);\n return null;\n }\n }\n\n // Check version and migrate if needed\n if (opts.versioning && data.version !== opts.version) {\n if (opts.migrate) {\n const migrated = opts.migrate(data.state, data.version, opts.version);\n return opts.deserialize(migrated);\n }\n return null;\n }\n\n const loadedState = opts.deserialize(data.state);\n\n // Call onLoad callback\n if (opts.onLoad) {\n opts.onLoad(loadedState);\n }\n\n return loadedState;\n } catch (error) {\n reportError(error);\n return null;\n }\n }\n\n /**\n * Subscribe to state changes\n * @param {Function} listener - Change listener\n * @returns {Function} Unsubscribe function\n */\n function subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }\n\n /**\n * Notify listeners of state changes\n * @param {Object} oldState - Previous state\n * @param {Object} newState - New state\n */\n function notifyListeners(oldState, newState) {\n listeners.forEach(listener => {\n try {\n listener(newState, oldState);\n } catch (error) {\n console.error('Listener error:', error);\n }\n });\n }\n\n /**\n * Merge loaded state, optionally leaving keys touched since creation alone.\n * @returns {boolean} Whether stored state was found\n */\n function applyLoaded(loaded, skipTouched) {\n if (!loaded || typeof loaded !== 'object') {\n return false;\n }\n\n // Object.fromEntries defines keys as own data properties, so a stored\n // \"__proto__\" key cannot reach a prototype.\n const updates = Object.fromEntries(\n Object.entries(loaded).filter(([key]) => !skipTouched || !touchedKeys.has(key))\n );\n\n if (Object.keys(updates).length > 0) {\n const oldState = { ...state };\n state = { ...state, ...updates };\n notifyListeners(oldState, state);\n }\n return true;\n }\n\n /**\n * Get current state\n * @param {string} [key] - State key\n * @returns {*} State value or entire state\n */\n function getState(key) {\n return key ? state[key] : { ...state };\n }\n\n /**\n * Set state\n * @param {Object|Function} updates - State updates or updater function\n * @param {boolean} persist - Persist to storage\n */\n function setState(updates, persist = true) {\n const oldState = { ...state };\n\n if (typeof updates === 'function') {\n updates = updates(oldState);\n }\n\n if (initialRestorePending && updates && typeof updates === 'object') {\n for (const key of Object.keys(updates)) touchedKeys.add(key);\n }\n\n state = { ...state, ...updates };\n\n notifyListeners(oldState, state);\n\n if (persist) {\n save();\n }\n }\n\n /**\n * Reset state to initial values\n * @param {boolean} persist - Persist to storage\n */\n function resetState(persist = true) {\n const oldState = { ...state };\n\n if (initialRestorePending) {\n for (const key of Object.keys(oldState)) touchedKeys.add(key);\n for (const key of Object.keys(initialState)) touchedKeys.add(key);\n }\n\n state = { ...initialState };\n notifyListeners(oldState, state);\n\n if (persist) {\n save(true);\n }\n }\n\n /**\n * Clear persisted state\n */\n async function clearStorage() {\n try {\n await adapter.remove(opts.key);\n } catch (error) {\n reportError(error);\n }\n }\n\n /**\n * Manually trigger persistence\n * @returns {Promise<boolean>} Whether it was stored\n */\n async function persist() {\n return save(true);\n }\n\n /**\n * Restore state from storage\n * @returns {Promise<boolean>} Whether stored state was found\n */\n async function restore() {\n return applyLoaded(await load(), false);\n }\n\n /**\n * Stop syncing and saving: flushes a pending debounced save, closes the\n * cross-tab channel and drops listeners.\n * @returns {Promise<void>}\n */\n async function destroy() {\n if (destroyed) return;\n const pending = saveTimeout !== null;\n clearTimeout(saveTimeout);\n saveTimeout = null;\n if (pending) {\n await write();\n }\n destroyed = true;\n channel?.close();\n channel = null;\n listeners.clear();\n }\n\n // Auto-restore on creation\n let ready;\n if (opts.storage !== 'memory' || opts.adapter) {\n initialRestorePending = true;\n ready = load().then((loaded) => {\n initialRestorePending = false;\n if (destroyed) return false;\n const restored = applyLoaded(loaded, true);\n // Keys set meanwhile were saved without the restored ones; save the merge\n if (restored && touchedKeys.size > 0) save();\n touchedKeys.clear();\n return restored;\n });\n } else {\n ready = Promise.resolve(false);\n }\n\n return {\n getState,\n setState,\n resetState,\n subscribe,\n persist,\n restore,\n clearStorage,\n load,\n save: () => save(true),\n destroy,\n /** Settles once the automatic restore on creation is done */\n ready,\n get adapter() {\n return adapter;\n }\n };\n}\n\n/**\n * Create persistent state with localStorage\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withLocalStorage(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'localStorage',\n key\n });\n}\n\n/**\n * Create persistent state with sessionStorage\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withSessionStorage(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'sessionStorage',\n key\n });\n}\n\n/**\n * Create persistent state with IndexedDB\n * @param {Object} initialState - Initial state\n * @param {string} key - Storage key\n * @param {Partial<PersistenceOptions>} options - Additional options\n * @returns {Object} Persistent state manager\n */\nexport function withIndexedDB(initialState = {}, key = 'coherent-state', options = {}) {\n return createPersistentState(initialState, {\n ...options,\n storage: 'indexedDB',\n key\n });\n}\n\nexport default {\n createPersistentState,\n withLocalStorage,\n withSessionStorage,\n withIndexedDB,\n createStorageAdapter\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["persist"]
|
|
7
7
|
}
|
package/dist/state-validation.js
CHANGED
|
@@ -4,6 +4,61 @@ var EMAIL_MAX_LENGTH = 254;
|
|
|
4
4
|
function isEmailShaped(value) {
|
|
5
5
|
return typeof value === "string" && value.length <= EMAIL_MAX_LENGTH && EMAIL_PATTERN.test(value);
|
|
6
6
|
}
|
|
7
|
+
function matchesType(value, type) {
|
|
8
|
+
switch (type) {
|
|
9
|
+
case "array":
|
|
10
|
+
return Array.isArray(value);
|
|
11
|
+
case "null":
|
|
12
|
+
return value === null;
|
|
13
|
+
case "object":
|
|
14
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
15
|
+
case "integer":
|
|
16
|
+
return typeof value === "number" && Number.isInteger(value);
|
|
17
|
+
case "number":
|
|
18
|
+
return typeof value === "number" && !Number.isNaN(value);
|
|
19
|
+
default:
|
|
20
|
+
return typeof value === type;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function describeValue(value) {
|
|
24
|
+
if (value === null) return "null";
|
|
25
|
+
if (Array.isArray(value)) return "array";
|
|
26
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
27
|
+
return typeof value === "object" ? "object" : String(value);
|
|
28
|
+
}
|
|
29
|
+
function coerceTo(value, type) {
|
|
30
|
+
switch (type) {
|
|
31
|
+
case "string":
|
|
32
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
33
|
+
return { ok: !Number.isNaN(value), value: String(value) };
|
|
34
|
+
}
|
|
35
|
+
return { ok: false };
|
|
36
|
+
case "number":
|
|
37
|
+
case "integer": {
|
|
38
|
+
let number;
|
|
39
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
40
|
+
number = Number(value);
|
|
41
|
+
} else if (typeof value === "boolean") {
|
|
42
|
+
number = value ? 1 : 0;
|
|
43
|
+
} else {
|
|
44
|
+
return { ok: false };
|
|
45
|
+
}
|
|
46
|
+
const valid = type === "integer" ? Number.isInteger(number) : !Number.isNaN(number);
|
|
47
|
+
return valid ? { ok: true, value: number } : { ok: false };
|
|
48
|
+
}
|
|
49
|
+
case "boolean":
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
const normalized = value.trim().toLowerCase();
|
|
52
|
+
if (normalized === "true" || normalized === "1") return { ok: true, value: true };
|
|
53
|
+
if (normalized === "false" || normalized === "0" || normalized === "") return { ok: true, value: false };
|
|
54
|
+
return { ok: false };
|
|
55
|
+
}
|
|
56
|
+
if (value === 1 || value === 0) return { ok: true, value: value === 1 };
|
|
57
|
+
return { ok: false };
|
|
58
|
+
default:
|
|
59
|
+
return { ok: false };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
7
62
|
var SchemaValidator = class {
|
|
8
63
|
constructor(schema, options = {}) {
|
|
9
64
|
this.schema = schema;
|
|
@@ -26,10 +81,7 @@ var SchemaValidator = class {
|
|
|
26
81
|
if (schema.type) {
|
|
27
82
|
const typeResult = this.validateType(value, schema.type, path);
|
|
28
83
|
if (!typeResult.valid) {
|
|
29
|
-
errors
|
|
30
|
-
if (!this.options.coerce) {
|
|
31
|
-
return { valid: false, errors, value };
|
|
32
|
-
}
|
|
84
|
+
return { valid: false, errors: typeResult.errors, value };
|
|
33
85
|
}
|
|
34
86
|
coercedValue = typeResult.value;
|
|
35
87
|
}
|
|
@@ -87,47 +139,17 @@ var SchemaValidator = class {
|
|
|
87
139
|
const errors = [];
|
|
88
140
|
let coercedValue = value;
|
|
89
141
|
const types = Array.isArray(type) ? type : [type];
|
|
90
|
-
const isValid = types.some((t) =>
|
|
91
|
-
if (t === "array") return Array.isArray(value);
|
|
92
|
-
if (t === "null") return value === null;
|
|
93
|
-
if (t === "integer") return typeof value === "number" && Number.isInteger(value);
|
|
94
|
-
return typeof value === t;
|
|
95
|
-
});
|
|
142
|
+
const isValid = types.some((t) => matchesType(value, t));
|
|
96
143
|
if (!isValid) {
|
|
97
144
|
if (this.options.coerce) {
|
|
98
145
|
const primaryType = types[0];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
coercedValue = Number(value);
|
|
104
|
-
if (isNaN(coercedValue)) {
|
|
105
|
-
errors.push({
|
|
106
|
-
path,
|
|
107
|
-
message: `Cannot coerce "${value}" to number`,
|
|
108
|
-
type: "type",
|
|
109
|
-
value,
|
|
110
|
-
expected: primaryType
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
} else if (primaryType === "boolean") {
|
|
114
|
-
coercedValue = Boolean(value);
|
|
115
|
-
} else if (primaryType === "integer") {
|
|
116
|
-
coercedValue = parseInt(value, 10);
|
|
117
|
-
if (isNaN(coercedValue)) {
|
|
118
|
-
errors.push({
|
|
119
|
-
path,
|
|
120
|
-
message: `Cannot coerce "${value}" to integer`,
|
|
121
|
-
type: "type",
|
|
122
|
-
value,
|
|
123
|
-
expected: primaryType
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
} catch {
|
|
146
|
+
const coerced = coerceTo(value, primaryType);
|
|
147
|
+
if (coerced.ok) {
|
|
148
|
+
coercedValue = coerced.value;
|
|
149
|
+
} else {
|
|
128
150
|
errors.push({
|
|
129
151
|
path,
|
|
130
|
-
message: `Cannot coerce value to ${primaryType}`,
|
|
152
|
+
message: `Cannot coerce ${describeValue(value)} to ${primaryType}`,
|
|
131
153
|
type: "type",
|
|
132
154
|
value,
|
|
133
155
|
expected: primaryType
|
|
@@ -348,7 +370,7 @@ var SchemaValidator = class {
|
|
|
348
370
|
}
|
|
349
371
|
});
|
|
350
372
|
}
|
|
351
|
-
if (schema.additionalProperties === false
|
|
373
|
+
if (schema.additionalProperties === false || !this.options.allowUnknown && schema.properties) {
|
|
352
374
|
const allowedProps = new Set(Object.keys(schema.properties || {}));
|
|
353
375
|
Object.keys(value).forEach((prop) => {
|
|
354
376
|
if (!allowedProps.has(prop)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/state-validation.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * @fileoverview State Validation for Coherent.js\n * Provides JSON Schema validation and custom validators for state management\n * @module @coherent.js/core/state/state-validation\n */\n\n/**\n * Email shape check: a local part, then a dotted domain.\n *\n * Domain labels use `[^\\s@.]` rather than `[^\\s@]` so that the literal dot\n * separators are the only thing that can match a dot. Allowing `[^\\s@]+` on\n * both sides of `\\.` makes the split ambiguous, and a non-matching subject\n * with many dots (\"a@\" + \"a.\" * n + \" \") then costs O(n\u00B2) backtracking \u2014\n * CodeQL js/polynomial-redos.\n *\n * @private\n */\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@.]+(?:\\.[^\\s@.]+)+$/;\n\n/**\n * Longest address RFC 5321 permits, used to bound work before matching.\n * @private\n */\nconst EMAIL_MAX_LENGTH = 254;\n\n/**\n * Test whether a value has the shape of an email address.\n * @private\n * @param {unknown} value - Value to check\n * @returns {boolean} True if the value looks like an email address\n */\nfunction isEmailShaped(value) {\n return (\n typeof value === 'string' &&\n value.length <= EMAIL_MAX_LENGTH &&\n EMAIL_PATTERN.test(value)\n );\n}\n\n\n/**\n * @typedef {Object} ValidationOptions\n * @property {Object} [schema] - JSON Schema for validation\n * @property {Object<string, Function>} [validators] - Custom validator functions\n * @property {boolean} [strict=false] - Strict mode (throw on validation errors)\n * @property {boolean} [coerce=false] - Coerce types to match schema\n * @property {Function} [onError] - Validation error callback\n * @property {boolean} [validateOnSet=true] - Validate on state updates\n * @property {boolean} [validateOnGet=false] - Validate on state reads\n * @property {Array<string>} [required] - Required fields\n * @property {boolean} [allowUnknown=true] - Allow unknown properties\n */\n\n/**\n * @typedef {Object} ValidationResult\n * @property {boolean} valid - Whether validation passed\n * @property {Array<ValidationError>} errors - Array of validation errors\n * @property {*} value - Validated/coerced value\n */\n\n/**\n * @typedef {Object} ValidationError\n * @property {string} path - Property path that failed validation\n * @property {string} message - Error message\n * @property {string} type - Error type\n * @property {*} value - The invalid value\n * @property {*} expected - Expected value/type\n */\n\n/**\n * Simple JSON Schema validator\n */\nclass SchemaValidator {\n constructor(schema, options = {}) {\n this.schema = schema;\n this.options = {\n coerce: false,\n allowUnknown: true,\n ...options\n };\n }\n\n /**\n * Validate value against schema\n * @param {*} value - Value to validate\n * @param {Object} schema - Schema to validate against\n * @param {string} path - Current path in object\n * @returns {ValidationResult} Validation result\n */\n validate(value, schema = this.schema, path = '') {\n const errors = [];\n let coercedValue = value;\n\n // Type validation\n if (schema.type) {\n const typeResult = this.validateType(value, schema.type, path);\n if (!typeResult.valid) {\n errors.push(...typeResult.errors);\n if (!this.options.coerce) {\n return { valid: false, errors, value };\n }\n }\n coercedValue = typeResult.value;\n }\n\n // Enum validation\n if (schema.enum) {\n const enumResult = this.validateEnum(coercedValue, schema.enum, path);\n if (!enumResult.valid) {\n errors.push(...enumResult.errors);\n }\n }\n\n // String validations\n if (schema.type === 'string') {\n const stringResult = this.validateString(coercedValue, schema, path);\n if (!stringResult.valid) {\n errors.push(...stringResult.errors);\n }\n }\n\n // Number validations\n if (schema.type === 'number' || schema.type === 'integer') {\n const numberResult = this.validateNumber(coercedValue, schema, path);\n if (!numberResult.valid) {\n errors.push(...numberResult.errors);\n }\n }\n\n // Array validations\n if (schema.type === 'array') {\n const arrayResult = this.validateArray(coercedValue, schema, path);\n if (!arrayResult.valid) {\n errors.push(...arrayResult.errors);\n }\n coercedValue = arrayResult.value;\n }\n\n // Object validations\n if (schema.type === 'object') {\n const objectResult = this.validateObject(coercedValue, schema, path);\n if (!objectResult.valid) {\n errors.push(...objectResult.errors);\n }\n coercedValue = objectResult.value;\n }\n\n // Custom validation function\n if (schema.validate && typeof schema.validate === 'function') {\n const customResult = schema.validate(coercedValue);\n if (customResult !== true) {\n errors.push({\n path,\n message: typeof customResult === 'string' ? customResult : 'Custom validation failed',\n type: 'custom',\n value: coercedValue\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateType(value, type, path) {\n const actualType = Array.isArray(value) ? 'array' : typeof value;\n const errors = [];\n let coercedValue = value;\n\n // Support array of types\n const types = Array.isArray(type) ? type : [type];\n\n const isValid = types.some(t => {\n if (t === 'array') return Array.isArray(value);\n if (t === 'null') return value === null;\n if (t === 'integer') return typeof value === 'number' && Number.isInteger(value);\n return typeof value === t;\n });\n\n if (!isValid) {\n if (this.options.coerce) {\n // Try to coerce\n const primaryType = types[0];\n try {\n if (primaryType === 'string') {\n coercedValue = String(value);\n } else if (primaryType === 'number') {\n coercedValue = Number(value);\n if (isNaN(coercedValue)) {\n errors.push({\n path,\n message: `Cannot coerce \"${value}\" to number`,\n type: 'type',\n value,\n expected: primaryType\n });\n }\n } else if (primaryType === 'boolean') {\n coercedValue = Boolean(value);\n } else if (primaryType === 'integer') {\n coercedValue = parseInt(value, 10);\n if (isNaN(coercedValue)) {\n errors.push({\n path,\n message: `Cannot coerce \"${value}\" to integer`,\n type: 'type',\n value,\n expected: primaryType\n });\n }\n }\n } catch {\n errors.push({\n path,\n message: `Cannot coerce value to ${primaryType}`,\n type: 'type',\n value,\n expected: primaryType\n });\n }\n } else {\n errors.push({\n path,\n message: `Expected type ${types.join(' or ')}, got ${actualType}`,\n type: 'type',\n value,\n expected: type\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateEnum(value, enumValues, path) {\n const errors = [];\n if (!enumValues.includes(value)) {\n errors.push({\n path,\n message: `Value must be one of: ${enumValues.join(', ')}`,\n type: 'enum',\n value,\n expected: enumValues\n });\n }\n return { valid: errors.length === 0, errors };\n }\n\n validateString(value, schema, path) {\n const errors = [];\n\n if (schema.minLength !== undefined && value.length < schema.minLength) {\n errors.push({\n path,\n message: `String length must be >= ${schema.minLength}`,\n type: 'minLength',\n value\n });\n }\n\n if (schema.maxLength !== undefined && value.length > schema.maxLength) {\n errors.push({\n path,\n message: `String length must be <= ${schema.maxLength}`,\n type: 'maxLength',\n value\n });\n }\n\n if (schema.pattern) {\n const regex = new RegExp(schema.pattern);\n if (!regex.test(value)) {\n errors.push({\n path,\n message: `String does not match pattern: ${schema.pattern}`,\n type: 'pattern',\n value\n });\n }\n }\n\n if (schema.format) {\n const formatResult = this.validateFormat(value, schema.format, path);\n if (!formatResult.valid) {\n errors.push(...formatResult.errors);\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateFormat(value, format, path) {\n const errors = [];\n const formats = {\n email: EMAIL_PATTERN,\n url: /^https?:\\/\\/.+/,\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^\\d{4}-\\d{2}-\\d{2}$/,\n 'date-time': /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/\n };\n\n if (formats[format] && !formats[format].test(value)) {\n errors.push({\n path,\n message: `String does not match format: ${format}`,\n type: 'format',\n value,\n expected: format\n });\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateNumber(value, schema, path) {\n const errors = [];\n\n if (schema.minimum !== undefined && value < schema.minimum) {\n errors.push({\n path,\n message: `Number must be >= ${schema.minimum}`,\n type: 'minimum',\n value\n });\n }\n\n if (schema.maximum !== undefined && value > schema.maximum) {\n errors.push({\n path,\n message: `Number must be <= ${schema.maximum}`,\n type: 'maximum',\n value\n });\n }\n\n if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum) {\n errors.push({\n path,\n message: `Number must be > ${schema.exclusiveMinimum}`,\n type: 'exclusiveMinimum',\n value\n });\n }\n\n if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum) {\n errors.push({\n path,\n message: `Number must be < ${schema.exclusiveMaximum}`,\n type: 'exclusiveMaximum',\n value\n });\n }\n\n if (schema.multipleOf !== undefined && value % schema.multipleOf !== 0) {\n errors.push({\n path,\n message: `Number must be multiple of ${schema.multipleOf}`,\n type: 'multipleOf',\n value\n });\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateArray(value, schema, path) {\n const errors = [];\n const coercedValue = [...value];\n\n if (schema.minItems !== undefined && value.length < schema.minItems) {\n errors.push({\n path,\n message: `Array must have at least ${schema.minItems} items`,\n type: 'minItems',\n value\n });\n }\n\n if (schema.maxItems !== undefined && value.length > schema.maxItems) {\n errors.push({\n path,\n message: `Array must have at most ${schema.maxItems} items`,\n type: 'maxItems',\n value\n });\n }\n\n if (schema.uniqueItems) {\n const seen = new Set();\n const duplicates = [];\n value.forEach((item, index) => {\n const key = JSON.stringify(item);\n if (seen.has(key)) {\n duplicates.push(index);\n }\n seen.add(key);\n });\n if (duplicates.length > 0) {\n errors.push({\n path,\n message: 'Array items must be unique',\n type: 'uniqueItems',\n value\n });\n }\n }\n\n // Validate items\n if (schema.items) {\n value.forEach((item, index) => {\n const itemPath = `${path}[${index}]`;\n const itemResult = this.validate(item, schema.items, itemPath);\n if (!itemResult.valid) {\n errors.push(...itemResult.errors);\n }\n if (this.options.coerce) {\n coercedValue[index] = itemResult.value;\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateObject(value, schema, path) {\n const errors = [];\n const coercedValue = { ...value };\n\n // Required properties\n if (schema.required) {\n schema.required.forEach(prop => {\n if (!(prop in value)) {\n errors.push({\n path: path ? `${path}.${prop}` : prop,\n message: `Required property \"${prop}\" is missing`,\n type: 'required',\n value: undefined\n });\n }\n });\n }\n\n // Validate properties\n if (schema.properties) {\n Object.entries(schema.properties).forEach(([prop, propSchema]) => {\n if (prop in value) {\n const propPath = path ? `${path}.${prop}` : prop;\n const propResult = this.validate(value[prop], propSchema, propPath);\n if (!propResult.valid) {\n errors.push(...propResult.errors);\n }\n if (this.options.coerce) {\n coercedValue[prop] = propResult.value;\n }\n }\n });\n }\n\n // Additional properties\n if (schema.additionalProperties === false && !this.options.allowUnknown) {\n const allowedProps = new Set(Object.keys(schema.properties || {}));\n Object.keys(value).forEach(prop => {\n if (!allowedProps.has(prop)) {\n errors.push({\n path: path ? `${path}.${prop}` : prop,\n message: `Unknown property \"${prop}\"`,\n type: 'additionalProperties',\n value: value[prop]\n });\n }\n });\n }\n\n // Min/max properties\n const propCount = Object.keys(value).length;\n if (schema.minProperties !== undefined && propCount < schema.minProperties) {\n errors.push({\n path,\n message: `Object must have at least ${schema.minProperties} properties`,\n type: 'minProperties',\n value\n });\n }\n\n if (schema.maxProperties !== undefined && propCount > schema.maxProperties) {\n errors.push({\n path,\n message: `Object must have at most ${schema.maxProperties} properties`,\n type: 'maxProperties',\n value\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n}\n\n/**\n * Create validated state manager\n * @param {Object} initialState - Initial state\n * @param {ValidationOptions} options - Validation options\n * @returns {Object} Validated state manager\n */\nexport function createValidatedState(initialState = {}, options = {}) {\n const opts = {\n schema: null,\n validators: {},\n strict: false,\n coerce: false,\n onError: null,\n validateOnSet: true,\n validateOnGet: false,\n required: [],\n allowUnknown: true,\n ...options\n };\n\n const schemaValidator = opts.schema ? new SchemaValidator(opts.schema, {\n coerce: opts.coerce,\n allowUnknown: opts.allowUnknown\n }) : null;\n\n let state = { ...initialState };\n const listeners = new Set();\n const validationErrors = new Map();\n\n /**\n * Validate state\n * @param {Object} value - State to validate\n * @param {string} key - State key (for partial validation)\n * @returns {ValidationResult} Validation result\n */\n function validateState(value, key = null) {\n const errors = [];\n let validatedValue = value;\n\n // JSON Schema validation\n if (schemaValidator) {\n const schema = key && opts.schema.properties\n ? opts.schema.properties[key]\n : opts.schema;\n\n const result = schemaValidator.validate(value, schema, key || '');\n if (!result.valid) {\n errors.push(...result.errors);\n }\n validatedValue = result.value;\n }\n\n // Custom validators\n if (key && opts.validators[key]) {\n const validator = opts.validators[key];\n const result = validator(value);\n if (result !== true) {\n errors.push({\n path: key,\n message: typeof result === 'string' ? result : 'Validation failed',\n type: 'custom',\n value\n });\n }\n } else if (!key) {\n // Run custom validators for all fields when validating full state\n Object.entries(opts.validators).forEach(([fieldKey, validator]) => {\n if (fieldKey in value) {\n const result = validator(value[fieldKey]);\n if (result !== true) {\n errors.push({\n path: fieldKey,\n message: typeof result === 'string' ? result : 'Validation failed',\n type: 'custom',\n value: value[fieldKey]\n });\n }\n }\n });\n }\n\n // Required fields\n if (opts.required.length > 0 && !key) {\n opts.required.forEach(field => {\n if (!(field in value)) {\n errors.push({\n path: field,\n message: `Required field \"${field}\" is missing`,\n type: 'required',\n value: undefined\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: validatedValue\n };\n }\n\n /**\n * Get state\n * @param {string} key - State key\n * @returns {*} State value\n */\n function getState(key) {\n const value = key ? state[key] : { ...state };\n\n if (opts.validateOnGet) {\n const result = validateState(value, key);\n if (!result.valid) {\n validationErrors.set(key || '__root__', result.errors);\n if (opts.onError) {\n opts.onError(result.errors);\n }\n }\n }\n\n return value;\n }\n\n /**\n * Set state\n * @param {Object|Function} updates - State updates\n * @throws {Error} If validation fails in strict mode\n */\n function setState(updates) {\n const oldState = { ...state };\n\n if (typeof updates === 'function') {\n updates = updates(oldState);\n }\n\n // Create the new full state for validation\n const newState = { ...state, ...updates };\n\n // Validate before setting\n if (opts.validateOnSet) {\n const result = validateState(newState);\n\n if (!result.valid) {\n validationErrors.set('__root__', result.errors);\n\n if (opts.onError) {\n opts.onError(result.errors);\n }\n\n if (opts.strict) {\n const error = new Error('Validation failed');\n error.validationErrors = result.errors;\n throw error;\n }\n\n // Don't update state if validation fails in non-strict mode\n return;\n }\n\n // Use coerced value if coercion is enabled\n if (opts.coerce) {\n const updatedKeys = Object.keys(updates);\n const newUpdates = {};\n updatedKeys.forEach(key => {\n if (result.value[key] !== state[key]) {\n newUpdates[key] = result.value[key];\n }\n });\n updates = newUpdates;\n }\n\n // Clear errors on successful validation\n validationErrors.clear();\n }\n\n state = { ...state, ...updates };\n\n // Notify listeners\n listeners.forEach(listener => {\n try {\n listener(state, oldState);\n } catch (error) {\n console.error('Listener error:', error);\n }\n });\n }\n\n /**\n * Subscribe to state changes\n * @param {Function} listener - Change listener\n * @returns {Function} Unsubscribe function\n */\n function subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }\n\n /**\n * Get validation errors\n * @param {string} key - State key\n * @returns {Array<ValidationError>} Validation errors\n */\n function getErrors(key = '__root__') {\n return validationErrors.get(key) || [];\n }\n\n /**\n * Check if state is valid\n * @returns {boolean} Whether state is valid\n */\n function isValid() {\n const result = validateState(state);\n if (!result.valid) {\n validationErrors.set('__root__', result.errors);\n }\n return result.valid;\n }\n\n /**\n * Validate specific field\n * @param {string} key - Field key\n * @param {*} value - Field value\n * @returns {ValidationResult} Validation result\n */\n function validateField(key, value) {\n return validateState(value, key);\n }\n\n return {\n getState,\n setState,\n subscribe,\n getErrors,\n isValid,\n validateField,\n validate: () => validateState(state)\n };\n}\n\n/**\n * Common validators\n */\nexport const validators = {\n /**\n * Email validator\n * @param {string} value - Email to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n email: (value) => {\n if (typeof value !== 'string') return 'Email must be a string';\n if (!isEmailShaped(value)) return 'Invalid email format';\n return true;\n },\n\n /**\n * URL validator\n * @param {string} value - URL to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n url: (value) => {\n if (typeof value !== 'string') return 'URL must be a string';\n try {\n new URL(value);\n return true;\n } catch {\n return 'Invalid URL format';\n }\n },\n\n /**\n * Range validator\n * @param {number} min - Minimum value\n * @param {number} max - Maximum value\n * @returns {Function} Validator function\n */\n range: (min, max) => (value) => {\n if (typeof value !== 'number') return 'Value must be a number';\n if (value < min || value > max) return `Value must be between ${min} and ${max}`;\n return true;\n },\n\n /**\n * Length validator\n * @param {number} min - Minimum length\n * @param {number} max - Maximum length\n * @returns {Function} Validator function\n */\n length: (min, max) => (value) => {\n if (typeof value !== 'string') return 'Value must be a string';\n if (value.length < min || value.length > max) {\n return `Length must be between ${min} and ${max}`;\n }\n return true;\n },\n\n /**\n * Pattern validator\n * @param {RegExp|string} pattern - Pattern to match\n * @returns {Function} Validator function\n */\n pattern: (pattern) => (value) => {\n if (typeof value !== 'string') return 'Value must be a string';\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n if (!regex.test(value)) return `Value does not match pattern: ${pattern}`;\n return true;\n },\n\n /**\n * Required validator\n * @param {*} value - Value to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n required: (value) => {\n if (value === undefined || value === null || value === '') {\n return 'Value is required';\n }\n return true;\n }\n};\n\nexport default {\n createValidatedState,\n validators,\n SchemaValidator\n};\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * @fileoverview State Validation for Coherent.js\n * Provides JSON Schema validation and custom validators for state management\n * @module @coherent.js/core/state/state-validation\n */\n\n/**\n * Email shape check: a local part, then a dotted domain.\n *\n * Domain labels use `[^\\s@.]` rather than `[^\\s@]` so that the literal dot\n * separators are the only thing that can match a dot. Allowing `[^\\s@]+` on\n * both sides of `\\.` makes the split ambiguous, and a non-matching subject\n * with many dots (\"a@\" + \"a.\" * n + \" \") then costs O(n\u00B2) backtracking \u2014\n * CodeQL js/polynomial-redos.\n *\n * @private\n */\nconst EMAIL_PATTERN = /^[^\\s@]+@[^\\s@.]+(?:\\.[^\\s@.]+)+$/;\n\n/**\n * Longest address RFC 5321 permits, used to bound work before matching.\n * @private\n */\nconst EMAIL_MAX_LENGTH = 254;\n\n/**\n * Test whether a value has the shape of an email address.\n * @private\n * @param {unknown} value - Value to check\n * @returns {boolean} True if the value looks like an email address\n */\nfunction isEmailShaped(value) {\n return (\n typeof value === 'string' &&\n value.length <= EMAIL_MAX_LENGTH &&\n EMAIL_PATTERN.test(value)\n );\n}\n\n\n/**\n * @typedef {Object} ValidationOptions\n * @property {Object} [schema] - JSON Schema for validation\n * @property {Object<string, Function>} [validators] - Custom validator functions\n * @property {boolean} [strict=false] - Strict mode (throw on validation errors)\n * @property {boolean} [coerce=false] - Coerce types to match schema\n * @property {Function} [onError] - Validation error callback\n * @property {boolean} [validateOnSet=true] - Validate on state updates\n * @property {boolean} [validateOnGet=false] - Validate on state reads\n * @property {Array<string>} [required] - Required fields\n * @property {boolean} [allowUnknown=true] - Allow unknown properties\n */\n\n/**\n * @typedef {Object} ValidationResult\n * @property {boolean} valid - Whether validation passed\n * @property {Array<ValidationError>} errors - Array of validation errors\n * @property {*} value - Validated/coerced value\n */\n\n/**\n * @typedef {Object} ValidationError\n * @property {string} path - Property path that failed validation\n * @property {string} message - Error message\n * @property {string} type - Error type\n * @property {*} value - The invalid value\n * @property {*} expected - Expected value/type\n */\n\n/**\n * Whether a value has a JSON Schema type. `object` excludes null and arrays;\n * `number` excludes NaN, which JSON cannot represent.\n * @private\n */\nfunction matchesType(value, type) {\n switch (type) {\n case 'array':\n return Array.isArray(value);\n case 'null':\n return value === null;\n case 'object':\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n case 'integer':\n return typeof value === 'number' && Number.isInteger(value);\n case 'number':\n return typeof value === 'number' && !Number.isNaN(value);\n default:\n return typeof value === type;\n }\n}\n\n/** @private */\nfunction describeValue(value) {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n if (typeof value === 'string') return JSON.stringify(value);\n return typeof value === 'object' ? 'object' : String(value);\n}\n\n/**\n * Coerce a value to a JSON Schema type, refusing conversions that would\n * invent data: `Boolean('false')` is true, `Number('')` is 0 and\n * `String({})` is \"[object Object]\", so none of those are accepted.\n * @private\n * @returns {{ ok: boolean, value?: * }}\n */\nfunction coerceTo(value, type) {\n switch (type) {\n case 'string':\n if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') {\n return { ok: !Number.isNaN(value), value: String(value) };\n }\n return { ok: false };\n case 'number':\n case 'integer': {\n let number;\n if (typeof value === 'string' && value.trim() !== '') {\n number = Number(value);\n } else if (typeof value === 'boolean') {\n number = value ? 1 : 0;\n } else {\n return { ok: false };\n }\n const valid = type === 'integer' ? Number.isInteger(number) : !Number.isNaN(number);\n return valid ? { ok: true, value: number } : { ok: false };\n }\n case 'boolean':\n if (typeof value === 'string') {\n const normalized = value.trim().toLowerCase();\n if (normalized === 'true' || normalized === '1') return { ok: true, value: true };\n if (normalized === 'false' || normalized === '0' || normalized === '') return { ok: true, value: false };\n return { ok: false };\n }\n if (value === 1 || value === 0) return { ok: true, value: value === 1 };\n return { ok: false };\n default:\n return { ok: false };\n }\n}\n\n/**\n * Simple JSON Schema validator\n */\nclass SchemaValidator {\n constructor(schema, options = {}) {\n this.schema = schema;\n this.options = {\n coerce: false,\n allowUnknown: true,\n ...options\n };\n }\n\n /**\n * Validate value against schema\n * @param {*} value - Value to validate\n * @param {Object} schema - Schema to validate against\n * @param {string} path - Current path in object\n * @returns {ValidationResult} Validation result\n */\n validate(value, schema = this.schema, path = '') {\n const errors = [];\n let coercedValue = value;\n\n // Type validation. A value of the wrong type that could not be coerced\n // gets no further checks: they assume the declared type.\n if (schema.type) {\n const typeResult = this.validateType(value, schema.type, path);\n if (!typeResult.valid) {\n return { valid: false, errors: typeResult.errors, value };\n }\n coercedValue = typeResult.value;\n }\n\n // Enum validation\n if (schema.enum) {\n const enumResult = this.validateEnum(coercedValue, schema.enum, path);\n if (!enumResult.valid) {\n errors.push(...enumResult.errors);\n }\n }\n\n // String validations\n if (schema.type === 'string') {\n const stringResult = this.validateString(coercedValue, schema, path);\n if (!stringResult.valid) {\n errors.push(...stringResult.errors);\n }\n }\n\n // Number validations\n if (schema.type === 'number' || schema.type === 'integer') {\n const numberResult = this.validateNumber(coercedValue, schema, path);\n if (!numberResult.valid) {\n errors.push(...numberResult.errors);\n }\n }\n\n // Array validations\n if (schema.type === 'array') {\n const arrayResult = this.validateArray(coercedValue, schema, path);\n if (!arrayResult.valid) {\n errors.push(...arrayResult.errors);\n }\n coercedValue = arrayResult.value;\n }\n\n // Object validations\n if (schema.type === 'object') {\n const objectResult = this.validateObject(coercedValue, schema, path);\n if (!objectResult.valid) {\n errors.push(...objectResult.errors);\n }\n coercedValue = objectResult.value;\n }\n\n // Custom validation function\n if (schema.validate && typeof schema.validate === 'function') {\n const customResult = schema.validate(coercedValue);\n if (customResult !== true) {\n errors.push({\n path,\n message: typeof customResult === 'string' ? customResult : 'Custom validation failed',\n type: 'custom',\n value: coercedValue\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateType(value, type, path) {\n const actualType = Array.isArray(value) ? 'array' : typeof value;\n const errors = [];\n let coercedValue = value;\n\n // Support array of types\n const types = Array.isArray(type) ? type : [type];\n\n const isValid = types.some(t => matchesType(value, t));\n\n if (!isValid) {\n if (this.options.coerce) {\n // Try to coerce to the first declared type\n const primaryType = types[0];\n const coerced = coerceTo(value, primaryType);\n if (coerced.ok) {\n coercedValue = coerced.value;\n } else {\n errors.push({\n path,\n message: `Cannot coerce ${describeValue(value)} to ${primaryType}`,\n type: 'type',\n value,\n expected: primaryType\n });\n }\n } else {\n errors.push({\n path,\n message: `Expected type ${types.join(' or ')}, got ${actualType}`,\n type: 'type',\n value,\n expected: type\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateEnum(value, enumValues, path) {\n const errors = [];\n if (!enumValues.includes(value)) {\n errors.push({\n path,\n message: `Value must be one of: ${enumValues.join(', ')}`,\n type: 'enum',\n value,\n expected: enumValues\n });\n }\n return { valid: errors.length === 0, errors };\n }\n\n validateString(value, schema, path) {\n const errors = [];\n\n if (schema.minLength !== undefined && value.length < schema.minLength) {\n errors.push({\n path,\n message: `String length must be >= ${schema.minLength}`,\n type: 'minLength',\n value\n });\n }\n\n if (schema.maxLength !== undefined && value.length > schema.maxLength) {\n errors.push({\n path,\n message: `String length must be <= ${schema.maxLength}`,\n type: 'maxLength',\n value\n });\n }\n\n if (schema.pattern) {\n const regex = new RegExp(schema.pattern);\n if (!regex.test(value)) {\n errors.push({\n path,\n message: `String does not match pattern: ${schema.pattern}`,\n type: 'pattern',\n value\n });\n }\n }\n\n if (schema.format) {\n const formatResult = this.validateFormat(value, schema.format, path);\n if (!formatResult.valid) {\n errors.push(...formatResult.errors);\n }\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateFormat(value, format, path) {\n const errors = [];\n const formats = {\n email: EMAIL_PATTERN,\n url: /^https?:\\/\\/.+/,\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^\\d{4}-\\d{2}-\\d{2}$/,\n 'date-time': /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/\n };\n\n if (formats[format] && !formats[format].test(value)) {\n errors.push({\n path,\n message: `String does not match format: ${format}`,\n type: 'format',\n value,\n expected: format\n });\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateNumber(value, schema, path) {\n const errors = [];\n\n if (schema.minimum !== undefined && value < schema.minimum) {\n errors.push({\n path,\n message: `Number must be >= ${schema.minimum}`,\n type: 'minimum',\n value\n });\n }\n\n if (schema.maximum !== undefined && value > schema.maximum) {\n errors.push({\n path,\n message: `Number must be <= ${schema.maximum}`,\n type: 'maximum',\n value\n });\n }\n\n if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum) {\n errors.push({\n path,\n message: `Number must be > ${schema.exclusiveMinimum}`,\n type: 'exclusiveMinimum',\n value\n });\n }\n\n if (schema.exclusiveMaximum !== undefined && value >= schema.exclusiveMaximum) {\n errors.push({\n path,\n message: `Number must be < ${schema.exclusiveMaximum}`,\n type: 'exclusiveMaximum',\n value\n });\n }\n\n if (schema.multipleOf !== undefined && value % schema.multipleOf !== 0) {\n errors.push({\n path,\n message: `Number must be multiple of ${schema.multipleOf}`,\n type: 'multipleOf',\n value\n });\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n validateArray(value, schema, path) {\n const errors = [];\n const coercedValue = [...value];\n\n if (schema.minItems !== undefined && value.length < schema.minItems) {\n errors.push({\n path,\n message: `Array must have at least ${schema.minItems} items`,\n type: 'minItems',\n value\n });\n }\n\n if (schema.maxItems !== undefined && value.length > schema.maxItems) {\n errors.push({\n path,\n message: `Array must have at most ${schema.maxItems} items`,\n type: 'maxItems',\n value\n });\n }\n\n if (schema.uniqueItems) {\n const seen = new Set();\n const duplicates = [];\n value.forEach((item, index) => {\n const key = JSON.stringify(item);\n if (seen.has(key)) {\n duplicates.push(index);\n }\n seen.add(key);\n });\n if (duplicates.length > 0) {\n errors.push({\n path,\n message: 'Array items must be unique',\n type: 'uniqueItems',\n value\n });\n }\n }\n\n // Validate items\n if (schema.items) {\n value.forEach((item, index) => {\n const itemPath = `${path}[${index}]`;\n const itemResult = this.validate(item, schema.items, itemPath);\n if (!itemResult.valid) {\n errors.push(...itemResult.errors);\n }\n if (this.options.coerce) {\n coercedValue[index] = itemResult.value;\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n\n validateObject(value, schema, path) {\n const errors = [];\n const coercedValue = { ...value };\n\n // Required properties\n if (schema.required) {\n schema.required.forEach(prop => {\n if (!(prop in value)) {\n errors.push({\n path: path ? `${path}.${prop}` : prop,\n message: `Required property \"${prop}\" is missing`,\n type: 'required',\n value: undefined\n });\n }\n });\n }\n\n // Validate properties\n if (schema.properties) {\n Object.entries(schema.properties).forEach(([prop, propSchema]) => {\n if (prop in value) {\n const propPath = path ? `${path}.${prop}` : prop;\n const propResult = this.validate(value[prop], propSchema, propPath);\n if (!propResult.valid) {\n errors.push(...propResult.errors);\n }\n if (this.options.coerce) {\n coercedValue[prop] = propResult.value;\n }\n }\n });\n }\n\n // Additional properties: rejected by the schema's own\n // `additionalProperties: false`, or for any object schema that lists its\n // properties when the validator runs with `allowUnknown: false`\n if (schema.additionalProperties === false || (!this.options.allowUnknown && schema.properties)) {\n const allowedProps = new Set(Object.keys(schema.properties || {}));\n Object.keys(value).forEach(prop => {\n if (!allowedProps.has(prop)) {\n errors.push({\n path: path ? `${path}.${prop}` : prop,\n message: `Unknown property \"${prop}\"`,\n type: 'additionalProperties',\n value: value[prop]\n });\n }\n });\n }\n\n // Min/max properties\n const propCount = Object.keys(value).length;\n if (schema.minProperties !== undefined && propCount < schema.minProperties) {\n errors.push({\n path,\n message: `Object must have at least ${schema.minProperties} properties`,\n type: 'minProperties',\n value\n });\n }\n\n if (schema.maxProperties !== undefined && propCount > schema.maxProperties) {\n errors.push({\n path,\n message: `Object must have at most ${schema.maxProperties} properties`,\n type: 'maxProperties',\n value\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: coercedValue\n };\n }\n}\n\n/**\n * Create validated state manager\n * @param {Object} initialState - Initial state\n * @param {ValidationOptions} options - Validation options\n * @returns {Object} Validated state manager\n */\nexport function createValidatedState(initialState = {}, options = {}) {\n const opts = {\n schema: null,\n validators: {},\n strict: false,\n coerce: false,\n onError: null,\n validateOnSet: true,\n validateOnGet: false,\n required: [],\n allowUnknown: true,\n ...options\n };\n\n const schemaValidator = opts.schema ? new SchemaValidator(opts.schema, {\n coerce: opts.coerce,\n allowUnknown: opts.allowUnknown\n }) : null;\n\n let state = { ...initialState };\n const listeners = new Set();\n const validationErrors = new Map();\n\n /**\n * Validate state\n * @param {Object} value - State to validate\n * @param {string} key - State key (for partial validation)\n * @returns {ValidationResult} Validation result\n */\n function validateState(value, key = null) {\n const errors = [];\n let validatedValue = value;\n\n // JSON Schema validation\n if (schemaValidator) {\n const schema = key && opts.schema.properties\n ? opts.schema.properties[key]\n : opts.schema;\n\n const result = schemaValidator.validate(value, schema, key || '');\n if (!result.valid) {\n errors.push(...result.errors);\n }\n validatedValue = result.value;\n }\n\n // Custom validators\n if (key && opts.validators[key]) {\n const validator = opts.validators[key];\n const result = validator(value);\n if (result !== true) {\n errors.push({\n path: key,\n message: typeof result === 'string' ? result : 'Validation failed',\n type: 'custom',\n value\n });\n }\n } else if (!key) {\n // Run custom validators for all fields when validating full state\n Object.entries(opts.validators).forEach(([fieldKey, validator]) => {\n if (fieldKey in value) {\n const result = validator(value[fieldKey]);\n if (result !== true) {\n errors.push({\n path: fieldKey,\n message: typeof result === 'string' ? result : 'Validation failed',\n type: 'custom',\n value: value[fieldKey]\n });\n }\n }\n });\n }\n\n // Required fields\n if (opts.required.length > 0 && !key) {\n opts.required.forEach(field => {\n if (!(field in value)) {\n errors.push({\n path: field,\n message: `Required field \"${field}\" is missing`,\n type: 'required',\n value: undefined\n });\n }\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n value: validatedValue\n };\n }\n\n /**\n * Get state\n * @param {string} key - State key\n * @returns {*} State value\n */\n function getState(key) {\n const value = key ? state[key] : { ...state };\n\n if (opts.validateOnGet) {\n const result = validateState(value, key);\n if (!result.valid) {\n validationErrors.set(key || '__root__', result.errors);\n if (opts.onError) {\n opts.onError(result.errors);\n }\n }\n }\n\n return value;\n }\n\n /**\n * Set state\n * @param {Object|Function} updates - State updates\n * @throws {Error} If validation fails in strict mode\n */\n function setState(updates) {\n const oldState = { ...state };\n\n if (typeof updates === 'function') {\n updates = updates(oldState);\n }\n\n // Create the new full state for validation\n const newState = { ...state, ...updates };\n\n // Validate before setting\n if (opts.validateOnSet) {\n const result = validateState(newState);\n\n if (!result.valid) {\n validationErrors.set('__root__', result.errors);\n\n if (opts.onError) {\n opts.onError(result.errors);\n }\n\n if (opts.strict) {\n const error = new Error('Validation failed');\n error.validationErrors = result.errors;\n throw error;\n }\n\n // Don't update state if validation fails in non-strict mode\n return;\n }\n\n // Use coerced value if coercion is enabled\n if (opts.coerce) {\n const updatedKeys = Object.keys(updates);\n const newUpdates = {};\n updatedKeys.forEach(key => {\n if (result.value[key] !== state[key]) {\n newUpdates[key] = result.value[key];\n }\n });\n updates = newUpdates;\n }\n\n // Clear errors on successful validation\n validationErrors.clear();\n }\n\n state = { ...state, ...updates };\n\n // Notify listeners\n listeners.forEach(listener => {\n try {\n listener(state, oldState);\n } catch (error) {\n console.error('Listener error:', error);\n }\n });\n }\n\n /**\n * Subscribe to state changes\n * @param {Function} listener - Change listener\n * @returns {Function} Unsubscribe function\n */\n function subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }\n\n /**\n * Get validation errors\n * @param {string} key - State key\n * @returns {Array<ValidationError>} Validation errors\n */\n function getErrors(key = '__root__') {\n return validationErrors.get(key) || [];\n }\n\n /**\n * Check if state is valid\n * @returns {boolean} Whether state is valid\n */\n function isValid() {\n const result = validateState(state);\n if (!result.valid) {\n validationErrors.set('__root__', result.errors);\n }\n return result.valid;\n }\n\n /**\n * Validate specific field\n * @param {string} key - Field key\n * @param {*} value - Field value\n * @returns {ValidationResult} Validation result\n */\n function validateField(key, value) {\n return validateState(value, key);\n }\n\n return {\n getState,\n setState,\n subscribe,\n getErrors,\n isValid,\n validateField,\n validate: () => validateState(state)\n };\n}\n\n/**\n * Common validators\n */\nexport const validators = {\n /**\n * Email validator\n * @param {string} value - Email to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n email: (value) => {\n if (typeof value !== 'string') return 'Email must be a string';\n if (!isEmailShaped(value)) return 'Invalid email format';\n return true;\n },\n\n /**\n * URL validator\n * @param {string} value - URL to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n url: (value) => {\n if (typeof value !== 'string') return 'URL must be a string';\n try {\n new URL(value);\n return true;\n } catch {\n return 'Invalid URL format';\n }\n },\n\n /**\n * Range validator\n * @param {number} min - Minimum value\n * @param {number} max - Maximum value\n * @returns {Function} Validator function\n */\n range: (min, max) => (value) => {\n if (typeof value !== 'number') return 'Value must be a number';\n if (value < min || value > max) return `Value must be between ${min} and ${max}`;\n return true;\n },\n\n /**\n * Length validator\n * @param {number} min - Minimum length\n * @param {number} max - Maximum length\n * @returns {Function} Validator function\n */\n length: (min, max) => (value) => {\n if (typeof value !== 'string') return 'Value must be a string';\n if (value.length < min || value.length > max) {\n return `Length must be between ${min} and ${max}`;\n }\n return true;\n },\n\n /**\n * Pattern validator\n * @param {RegExp|string} pattern - Pattern to match\n * @returns {Function} Validator function\n */\n pattern: (pattern) => (value) => {\n if (typeof value !== 'string') return 'Value must be a string';\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n if (!regex.test(value)) return `Value does not match pattern: ${pattern}`;\n return true;\n },\n\n /**\n * Required validator\n * @param {*} value - Value to validate\n * @returns {boolean|string} True if valid, error message otherwise\n */\n required: (value) => {\n if (value === undefined || value === null || value === '') {\n return 'Value is required';\n }\n return true;\n }\n};\n\nexport default {\n createValidatedState,\n validators,\n SchemaValidator\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/state",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-rc.0",
|
|
4
4
|
"description": "Reactive state management for Coherent.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,9 +46,6 @@
|
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": ">=22.12.0"
|
|
48
48
|
},
|
|
49
|
-
"peerDependencies": {
|
|
50
|
-
"@coherent.js/core": "^1.1.2"
|
|
51
|
-
},
|
|
52
49
|
"types": "./types/index.d.ts",
|
|
53
50
|
"files": [
|
|
54
51
|
"dist/",
|