@coherent.js/state 1.0.0-beta.5 → 1.0.0-beta.7
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/dist/index.js.map +7 -0
- package/dist/reactive-state.js +512 -0
- package/dist/reactive-state.js.map +7 -0
- package/dist/state-manager.js +102 -0
- package/dist/state-manager.js.map +7 -0
- package/dist/state-persistence.js +472 -0
- package/dist/state-persistence.js.map +7 -0
- package/dist/state-validation.js +621 -0
- package/dist/state-validation.js.map +7 -0
- package/package.json +13 -3
- package/types/index.d.ts +364 -39
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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 * @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: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\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 (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(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
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coherent.js/state",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.7",
|
|
4
4
|
"description": "Reactive state management for Coherent.js applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,14 +25,22 @@
|
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "git+https://github.com/Tomdrouv1/coherent.js.git"
|
|
27
27
|
},
|
|
28
|
+
"homepage": "https://github.com/Tomdrouv1/coherent.js",
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/Tomdrouv1/coherent.js/issues"
|
|
31
|
+
},
|
|
28
32
|
"publishConfig": {
|
|
29
33
|
"access": "public"
|
|
30
34
|
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=20.0.0"
|
|
37
|
+
},
|
|
31
38
|
"peerDependencies": {
|
|
32
|
-
"@coherent.js/core": "1.0.0-beta.
|
|
39
|
+
"@coherent.js/core": "1.0.0-beta.7"
|
|
33
40
|
},
|
|
34
41
|
"types": "./types/index.d.ts",
|
|
35
42
|
"files": [
|
|
43
|
+
"dist/",
|
|
36
44
|
"LICENSE",
|
|
37
45
|
"README.md",
|
|
38
46
|
"types/"
|
|
@@ -40,6 +48,8 @@
|
|
|
40
48
|
"sideEffects": false,
|
|
41
49
|
"scripts": {
|
|
42
50
|
"build": "node build.mjs",
|
|
43
|
-
"clean": "rm -rf dist"
|
|
51
|
+
"clean": "rm -rf dist",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest"
|
|
44
54
|
}
|
|
45
55
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -3,138 +3,463 @@
|
|
|
3
3
|
* @module @coherent.js/state
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import type { CoherentNode, ComponentState } from '@coherent.js/core';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Core Store Types
|
|
10
|
+
// ============================================================================
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Typed state store with subscribe and update capabilities
|
|
14
|
+
* @template T - The shape of the state object
|
|
15
|
+
*/
|
|
16
|
+
export interface Store<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
17
|
+
/**
|
|
18
|
+
* Get the current state
|
|
19
|
+
*/
|
|
20
|
+
getState(): T;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Update state with partial object or updater function
|
|
24
|
+
*/
|
|
25
|
+
setState(partial: Partial<T> | ((state: T) => Partial<T>)): void;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to state changes
|
|
29
|
+
* @returns Unsubscribe function
|
|
30
|
+
*/
|
|
31
|
+
subscribe(listener: (state: T, prevState: T) => void): () => void;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Destroy the store and clean up subscriptions
|
|
35
|
+
*/
|
|
36
|
+
destroy(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Store creation options
|
|
41
|
+
* @template T - The shape of the state object
|
|
42
|
+
*/
|
|
43
|
+
export interface StoreOptions<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
44
|
+
/** Initial state */
|
|
45
|
+
initialState: T;
|
|
46
|
+
/** Persistence configuration */
|
|
47
|
+
persist?: {
|
|
48
|
+
/** Storage key */
|
|
49
|
+
key: string;
|
|
50
|
+
/** Storage adapter (localStorage, sessionStorage, or custom) */
|
|
51
|
+
storage?: Storage;
|
|
52
|
+
/** Custom serialization */
|
|
53
|
+
serialize?: (state: T) => string;
|
|
54
|
+
/** Custom deserialization */
|
|
55
|
+
deserialize?: (value: string) => T;
|
|
56
|
+
/** Debounce persistence writes (ms) */
|
|
57
|
+
debounce?: number;
|
|
58
|
+
};
|
|
59
|
+
/** Enable devtools integration */
|
|
60
|
+
devtools?: boolean;
|
|
61
|
+
/** Store name for debugging */
|
|
62
|
+
name?: string;
|
|
63
|
+
/** Middleware functions */
|
|
64
|
+
middleware?: Array<StoreMiddleware<T>>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Store middleware function
|
|
69
|
+
*/
|
|
70
|
+
export type StoreMiddleware<T> = (
|
|
71
|
+
state: T,
|
|
72
|
+
action: string,
|
|
73
|
+
payload?: unknown
|
|
74
|
+
) => T | void;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create a typed state store
|
|
78
|
+
*/
|
|
79
|
+
export function createStore<T extends Record<string, unknown>>(
|
|
80
|
+
options: StoreOptions<T>
|
|
81
|
+
): Store<T>;
|
|
82
|
+
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// Selector Types
|
|
85
|
+
// ============================================================================
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create a derived selector from store state
|
|
89
|
+
* @template T - Store state type
|
|
90
|
+
* @template R - Return type of selector
|
|
91
|
+
*/
|
|
92
|
+
export function createSelector<T extends Record<string, unknown>, R>(
|
|
93
|
+
store: Store<T>,
|
|
94
|
+
selector: (state: T) => R
|
|
95
|
+
): () => R;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create a memoized selector with dependencies
|
|
99
|
+
*/
|
|
100
|
+
export function createMemoizedSelector<T extends Record<string, unknown>, D extends unknown[], R>(
|
|
101
|
+
store: Store<T>,
|
|
102
|
+
dependencies: (...args: D) => unknown[],
|
|
103
|
+
selector: (state: T, ...deps: D) => R
|
|
104
|
+
): (...args: D) => R;
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Action Types
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Action type helper for type-safe actions
|
|
112
|
+
* @template T - Store state type
|
|
113
|
+
* @template P - Payload type (void for no payload)
|
|
114
|
+
*/
|
|
115
|
+
export type Action<T, P = void> = P extends void
|
|
116
|
+
? () => Partial<T>
|
|
117
|
+
: (payload: P) => Partial<T>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Create typed action creators
|
|
121
|
+
*/
|
|
122
|
+
export function createActions<
|
|
123
|
+
T extends Record<string, unknown>,
|
|
124
|
+
A extends Record<string, Action<T, unknown>>
|
|
125
|
+
>(
|
|
126
|
+
store: Store<T>,
|
|
127
|
+
actions: A
|
|
128
|
+
): {
|
|
129
|
+
[K in keyof A]: A[K] extends Action<T, infer P>
|
|
130
|
+
? P extends void
|
|
131
|
+
? () => void
|
|
132
|
+
: (payload: P) => void
|
|
133
|
+
: never;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Reactive State Types
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Observer callback type
|
|
142
|
+
*/
|
|
143
|
+
export interface Observer<T = unknown> {
|
|
9
144
|
(value: T, oldValue: T): void;
|
|
10
145
|
}
|
|
11
146
|
|
|
12
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Observable value wrapper
|
|
149
|
+
*/
|
|
150
|
+
export class Observable<T = unknown> {
|
|
13
151
|
constructor(initialValue: T);
|
|
152
|
+
|
|
153
|
+
/** Get current value */
|
|
14
154
|
get(): T;
|
|
155
|
+
|
|
156
|
+
/** Set new value */
|
|
15
157
|
set(value: T): void;
|
|
158
|
+
|
|
159
|
+
/** Subscribe to changes */
|
|
16
160
|
subscribe(observer: Observer<T>): () => void;
|
|
161
|
+
|
|
162
|
+
/** Unsubscribe observer */
|
|
17
163
|
unsubscribe(observer: Observer<T>): void;
|
|
164
|
+
|
|
165
|
+
/** Notify all observers */
|
|
18
166
|
notify(): void;
|
|
19
167
|
}
|
|
20
168
|
|
|
21
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Reactive state options
|
|
171
|
+
*/
|
|
172
|
+
export interface ReactiveStateOptions<T = unknown> {
|
|
173
|
+
/** Initial state value */
|
|
22
174
|
initialValue: T;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
175
|
+
/** Computed properties */
|
|
176
|
+
computed?: Record<string, (state: T) => unknown>;
|
|
177
|
+
/** Property watchers */
|
|
178
|
+
watchers?: Record<string, Observer<unknown>>;
|
|
179
|
+
/** Middleware functions */
|
|
180
|
+
middleware?: Array<(state: T, action: string, payload?: unknown) => T | void>;
|
|
26
181
|
}
|
|
27
182
|
|
|
28
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Reactive state class with computed properties and watchers
|
|
185
|
+
*/
|
|
186
|
+
export class ReactiveState<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
29
187
|
constructor(options: ReactiveStateOptions<T>);
|
|
188
|
+
|
|
189
|
+
/** Get a property value */
|
|
30
190
|
get<K extends keyof T>(key: K): T[K];
|
|
191
|
+
|
|
192
|
+
/** Set a property value */
|
|
31
193
|
set<K extends keyof T>(key: K, value: T[K]): void;
|
|
194
|
+
|
|
195
|
+
/** Update multiple properties */
|
|
32
196
|
update(partial: Partial<T>): void;
|
|
197
|
+
|
|
198
|
+
/** Subscribe to all changes */
|
|
33
199
|
subscribe(observer: Observer<T>): () => void;
|
|
200
|
+
|
|
201
|
+
/** Watch a specific property */
|
|
34
202
|
watch<K extends keyof T>(key: K, observer: Observer<T[K]>): () => void;
|
|
203
|
+
|
|
204
|
+
/** Get full state */
|
|
35
205
|
getState(): T;
|
|
206
|
+
|
|
207
|
+
/** Reset to initial state */
|
|
36
208
|
reset(): void;
|
|
37
209
|
}
|
|
38
210
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Create a reactive state instance
|
|
213
|
+
*/
|
|
214
|
+
export function createReactiveState<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
215
|
+
options: ReactiveStateOptions<T>
|
|
216
|
+
): ReactiveState<T>;
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Create a simple observable value
|
|
220
|
+
*/
|
|
221
|
+
export function observable<T = unknown>(initialValue: T): Observable<T>;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Create a computed observable
|
|
225
|
+
*/
|
|
226
|
+
export function computed<T = unknown>(
|
|
227
|
+
fn: () => T,
|
|
228
|
+
dependencies: Observable<unknown>[]
|
|
229
|
+
): Observable<T>;
|
|
42
230
|
|
|
231
|
+
/**
|
|
232
|
+
* State utility functions
|
|
233
|
+
*/
|
|
43
234
|
export const stateUtils: {
|
|
235
|
+
/** Batch multiple state updates */
|
|
44
236
|
batch<T>(fn: () => T): T;
|
|
237
|
+
/** Run updates in a transaction */
|
|
45
238
|
transaction<T>(fn: () => T): T;
|
|
239
|
+
/** Freeze state (make immutable) */
|
|
46
240
|
freeze<T>(state: T): Readonly<T>;
|
|
241
|
+
/** Deep clone state */
|
|
47
242
|
clone<T>(state: T): T;
|
|
48
243
|
};
|
|
49
244
|
|
|
50
|
-
//
|
|
245
|
+
// ============================================================================
|
|
246
|
+
// SSR-Compatible State Manager
|
|
247
|
+
// ============================================================================
|
|
51
248
|
|
|
52
|
-
|
|
249
|
+
/**
|
|
250
|
+
* State manager options
|
|
251
|
+
*/
|
|
252
|
+
export interface StateManagerOptions<T = unknown> {
|
|
253
|
+
/** Initial state */
|
|
53
254
|
initialState?: T;
|
|
255
|
+
/** Enable persistence */
|
|
54
256
|
persist?: boolean;
|
|
257
|
+
/** Persistence key */
|
|
55
258
|
key?: string;
|
|
259
|
+
/** Middleware functions */
|
|
56
260
|
middleware?: Array<(state: T, action: string) => T | void>;
|
|
57
261
|
}
|
|
58
262
|
|
|
59
|
-
|
|
263
|
+
/**
|
|
264
|
+
* Simple state interface
|
|
265
|
+
*/
|
|
266
|
+
export interface State<T = unknown> {
|
|
267
|
+
/** Get current state */
|
|
60
268
|
get(): T;
|
|
269
|
+
/** Set new state */
|
|
61
270
|
set(value: T): void;
|
|
271
|
+
/** Update with partial */
|
|
62
272
|
update(partial: Partial<T>): void;
|
|
273
|
+
/** Subscribe to changes */
|
|
63
274
|
subscribe(listener: (state: T) => void): () => void;
|
|
275
|
+
/** Reset to initial state */
|
|
64
276
|
reset(): void;
|
|
65
277
|
}
|
|
66
278
|
|
|
67
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Create a simple state container
|
|
281
|
+
*/
|
|
282
|
+
export function createState<T = unknown>(
|
|
283
|
+
initialState: T,
|
|
284
|
+
options?: StateManagerOptions<T>
|
|
285
|
+
): State<T>;
|
|
68
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Global state manager for SSR
|
|
289
|
+
*/
|
|
69
290
|
export const globalStateManager: {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
291
|
+
/** Get state by key */
|
|
292
|
+
getState<T = unknown>(key: string): T | undefined;
|
|
293
|
+
/** Set state by key */
|
|
294
|
+
setState<T = unknown>(key: string, value: T): void;
|
|
295
|
+
/** Subscribe to state key */
|
|
296
|
+
subscribe<T = unknown>(key: string, listener: (state: T) => void): () => void;
|
|
297
|
+
/** Clear state (optionally by key) */
|
|
73
298
|
clear(key?: string): void;
|
|
74
299
|
};
|
|
75
300
|
|
|
76
|
-
//
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Context API
|
|
303
|
+
// ============================================================================
|
|
77
304
|
|
|
78
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Context value wrapper
|
|
307
|
+
*/
|
|
308
|
+
export interface ContextValue<T = unknown> {
|
|
79
309
|
value: T;
|
|
80
310
|
subscribers: Set<(value: T) => void>;
|
|
81
311
|
}
|
|
82
312
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
export function
|
|
313
|
+
/**
|
|
314
|
+
* Provide a context value
|
|
315
|
+
*/
|
|
316
|
+
export function provideContext<T = unknown>(key: string, value: T): void;
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Create a context provider
|
|
320
|
+
*/
|
|
321
|
+
export function createContextProvider<T = unknown>(
|
|
322
|
+
key: string,
|
|
323
|
+
value: T
|
|
324
|
+
): { key: string; value: T };
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Use/consume a context value
|
|
328
|
+
*/
|
|
329
|
+
export function useContext<T = unknown>(key: string, defaultValue?: T): T;
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Restore context from saved state
|
|
333
|
+
*/
|
|
334
|
+
export function restoreContext(contexts: Record<string, unknown>): void;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Clear all context stacks
|
|
338
|
+
*/
|
|
87
339
|
export function clearAllContexts(): void;
|
|
88
340
|
|
|
89
|
-
//
|
|
341
|
+
// ============================================================================
|
|
342
|
+
// Persistent State
|
|
343
|
+
// ============================================================================
|
|
90
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Persistence adapter interface
|
|
347
|
+
*/
|
|
91
348
|
export interface PersistenceAdapter {
|
|
349
|
+
/** Get item from storage */
|
|
92
350
|
getItem(key: string): Promise<string | null> | string | null;
|
|
351
|
+
/** Set item in storage */
|
|
93
352
|
setItem(key: string, value: string): Promise<void> | void;
|
|
353
|
+
/** Remove item from storage */
|
|
94
354
|
removeItem(key: string): Promise<void> | void;
|
|
95
355
|
}
|
|
96
356
|
|
|
97
|
-
|
|
357
|
+
/**
|
|
358
|
+
* Persistent state options
|
|
359
|
+
*/
|
|
360
|
+
export interface PersistentStateOptions<T = unknown> extends StateManagerOptions<T> {
|
|
361
|
+
/** Required: storage key */
|
|
98
362
|
key: string;
|
|
363
|
+
/** Storage adapter */
|
|
99
364
|
storage?: PersistenceAdapter;
|
|
365
|
+
/** Custom serialization */
|
|
100
366
|
serialize?: (state: T) => string;
|
|
367
|
+
/** Custom deserialization */
|
|
101
368
|
deserialize?: (data: string) => T;
|
|
369
|
+
/** Debounce writes (ms) */
|
|
102
370
|
debounce?: number;
|
|
103
371
|
}
|
|
104
372
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
export function
|
|
373
|
+
/**
|
|
374
|
+
* Create a persistent state
|
|
375
|
+
*/
|
|
376
|
+
export function createPersistentState<T = unknown>(
|
|
377
|
+
options: PersistentStateOptions<T>
|
|
378
|
+
): State<T>;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Wrap state with localStorage persistence
|
|
382
|
+
*/
|
|
383
|
+
export function withLocalStorage<T = unknown>(state: State<T>, key: string): State<T>;
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Wrap state with sessionStorage persistence
|
|
387
|
+
*/
|
|
388
|
+
export function withSessionStorage<T = unknown>(state: State<T>, key: string): State<T>;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Wrap state with IndexedDB persistence
|
|
392
|
+
*/
|
|
393
|
+
export function withIndexedDB<T = unknown>(
|
|
394
|
+
state: State<T>,
|
|
395
|
+
key: string,
|
|
396
|
+
dbName?: string
|
|
397
|
+
): Promise<State<T>>;
|
|
109
398
|
|
|
110
|
-
//
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Validated State
|
|
401
|
+
// ============================================================================
|
|
111
402
|
|
|
112
|
-
|
|
403
|
+
/**
|
|
404
|
+
* Validation rule function
|
|
405
|
+
*/
|
|
406
|
+
export interface ValidationRule<T = unknown> {
|
|
113
407
|
(value: T): boolean | string;
|
|
114
408
|
}
|
|
115
409
|
|
|
116
|
-
|
|
117
|
-
|
|
410
|
+
/**
|
|
411
|
+
* Validated state options
|
|
412
|
+
*/
|
|
413
|
+
export interface ValidatedStateOptions<T extends Record<string, unknown> = Record<string, unknown>>
|
|
414
|
+
extends StateManagerOptions<T> {
|
|
415
|
+
/** Validation rules by property */
|
|
416
|
+
validators: { [K in keyof T]?: ValidationRule<T[K]>[] };
|
|
417
|
+
/** Validate on every change */
|
|
118
418
|
validateOnChange?: boolean;
|
|
419
|
+
/** Throw on validation failure */
|
|
119
420
|
strict?: boolean;
|
|
120
421
|
}
|
|
121
422
|
|
|
122
|
-
|
|
123
|
-
|
|
423
|
+
/**
|
|
424
|
+
* Validated state interface
|
|
425
|
+
*/
|
|
426
|
+
export interface ValidatedState<T extends Record<string, unknown> = Record<string, unknown>>
|
|
427
|
+
extends State<T> {
|
|
428
|
+
/** Validate current state */
|
|
429
|
+
validate(): { valid: boolean; errors: { [K in keyof T]?: string[] } };
|
|
430
|
+
/** Check if state is valid */
|
|
124
431
|
isValid(): boolean;
|
|
125
|
-
|
|
432
|
+
/** Get validation errors */
|
|
433
|
+
getErrors(): { [K in keyof T]?: string[] };
|
|
126
434
|
}
|
|
127
435
|
|
|
128
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Create a validated state
|
|
438
|
+
*/
|
|
439
|
+
export function createValidatedState<T extends Record<string, unknown> = Record<string, unknown>>(
|
|
440
|
+
options: ValidatedStateOptions<T>
|
|
441
|
+
): ValidatedState<T>;
|
|
129
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Built-in validators
|
|
445
|
+
*/
|
|
130
446
|
export const validators: {
|
|
447
|
+
/** Required value */
|
|
131
448
|
required(message?: string): ValidationRule;
|
|
449
|
+
/** Minimum length */
|
|
132
450
|
minLength(length: number, message?: string): ValidationRule;
|
|
451
|
+
/** Maximum length */
|
|
133
452
|
maxLength(length: number, message?: string): ValidationRule;
|
|
453
|
+
/** Minimum value */
|
|
134
454
|
min(value: number, message?: string): ValidationRule;
|
|
455
|
+
/** Maximum value */
|
|
135
456
|
max(value: number, message?: string): ValidationRule;
|
|
457
|
+
/** Pattern matching */
|
|
136
458
|
pattern(regex: RegExp, message?: string): ValidationRule;
|
|
459
|
+
/** Email format */
|
|
137
460
|
email(message?: string): ValidationRule;
|
|
461
|
+
/** URL format */
|
|
138
462
|
url(message?: string): ValidationRule;
|
|
139
|
-
|
|
463
|
+
/** Custom validator */
|
|
464
|
+
custom(fn: (value: unknown) => boolean | string): ValidationRule;
|
|
140
465
|
};
|