svstate 1.0.0 → 1.1.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 CHANGED
@@ -5,6 +5,8 @@
5
5
  [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D20-green.svg)](https://nodejs.org/)
6
6
  [![Svelte 5](https://img.shields.io/badge/Svelte-5-orange.svg)](https://svelte.dev/)
7
7
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
8
+ [![Tests](https://img.shields.io/badge/tests-300%2B-brightgreen.svg)]()
9
+ [![Coverage](https://img.shields.io/badge/coverage-%3E98%25-brightgreen.svg)]()
8
10
 
9
11
  > **Deep reactive proxy with validation, snapshot/undo, and side effects — built for complex, real-world applications.**
10
12
 
package/dist/index.js CHANGED
@@ -1,10 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stringValidator = exports.numberValidator = exports.dateValidator = exports.arrayValidator = exports.createSvState = void 0;
4
- var state_svelte_1 = require("./state.svelte");
5
- Object.defineProperty(exports, "createSvState", { enumerable: true, get: function () { return state_svelte_1.createSvState; } });
6
- var validators_1 = require("./validators");
7
- Object.defineProperty(exports, "arrayValidator", { enumerable: true, get: function () { return validators_1.arrayValidator; } });
8
- Object.defineProperty(exports, "dateValidator", { enumerable: true, get: function () { return validators_1.dateValidator; } });
9
- Object.defineProperty(exports, "numberValidator", { enumerable: true, get: function () { return validators_1.numberValidator; } });
10
- Object.defineProperty(exports, "stringValidator", { enumerable: true, get: function () { return validators_1.stringValidator; } });
1
+ export { createSvState } from './state.svelte';
2
+ export { arrayValidator, dateValidator, numberValidator, stringValidator } from './validators';
package/dist/proxy.js CHANGED
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChangeProxy = void 0;
4
1
  const isProxiable = (value) => typeof value === 'object' &&
5
2
  value !== null &&
6
3
  !(value instanceof Date) &&
@@ -11,10 +8,10 @@ const isProxiable = (value) => typeof value === 'object' &&
11
8
  !(value instanceof RegExp) &&
12
9
  !(value instanceof Error) &&
13
10
  !(value instanceof Promise);
14
- const ChangeProxy = (source, changed) => {
11
+ export const ChangeProxy = (source, changed) => {
15
12
  const createProxy = (target, parentPath) => new Proxy(target, {
16
- get(object, property, receiver) {
17
- const value = Reflect.get(object, property, receiver);
13
+ get(object, property) {
14
+ const value = object[property];
18
15
  if (isProxiable(value)) {
19
16
  const pathSegment = Number.isInteger(Number(property)) ? '' : String(property);
20
17
  const childPath = pathSegment ? (parentPath ? `${parentPath}.${pathSegment}` : pathSegment) : parentPath;
@@ -22,10 +19,10 @@ const ChangeProxy = (source, changed) => {
22
19
  }
23
20
  return value;
24
21
  },
25
- set(object, property, incomingValue, receiver) {
26
- const oldValue = Reflect.get(object, property, receiver);
22
+ set(object, property, incomingValue) {
23
+ const oldValue = object[property];
27
24
  if (oldValue !== incomingValue) {
28
- Reflect.set(object, property, incomingValue, receiver);
25
+ object[property] = incomingValue;
29
26
  const pathSegment = Number.isInteger(Number(property)) ? '' : String(property);
30
27
  const fullPath = pathSegment ? (parentPath ? `${parentPath}.${pathSegment}` : pathSegment) : parentPath;
31
28
  changed(data, fullPath, incomingValue, oldValue);
@@ -36,4 +33,3 @@ const ChangeProxy = (source, changed) => {
36
33
  const data = createProxy(source, '');
37
34
  return data;
38
35
  };
39
- exports.ChangeProxy = ChangeProxy;
@@ -1,8 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSvState = createSvState;
4
- const store_1 = require("svelte/store");
5
- const proxy_1 = require("./proxy");
1
+ import { derived, get, writable } from 'svelte/store';
2
+ import { ChangeProxy } from './proxy';
6
3
  const checkHasErrors = (validator) => Object.values(validator).some((item) => (typeof item === 'string' ? !!item : checkHasErrors(item)));
7
4
  const hasAnyErrors = ($errors) => !!$errors && checkHasErrors($errors);
8
5
  const deepClone = (object) => {
@@ -13,9 +10,8 @@ const deepClone = (object) => {
13
10
  if (Array.isArray(object))
14
11
  return object.map((item) => deepClone(item));
15
12
  const cloned = {};
16
- for (const key in object)
17
- if (Object.prototype.hasOwnProperty.call(object, key))
18
- cloned[key] = deepClone(object[key]);
13
+ for (const key of Object.keys(object))
14
+ cloned[key] = deepClone(object[key]);
19
15
  return cloned;
20
16
  };
21
17
  const defaultOptions = {
@@ -24,18 +20,18 @@ const defaultOptions = {
24
20
  allowConcurrentActions: false,
25
21
  persistActionError: false
26
22
  };
27
- function createSvState(init, actuators, options) {
23
+ export function createSvState(init, actuators, options) {
28
24
  const usedOptions = { ...defaultOptions, ...options };
29
25
  const { validator, effect } = actuators ?? {};
30
- const errors = (0, store_1.writable)();
31
- const hasErrors = (0, store_1.derived)(errors, hasAnyErrors);
32
- const isDirty = (0, store_1.writable)(false);
33
- const actionInProgress = (0, store_1.writable)(false);
34
- const actionError = (0, store_1.writable)();
35
- const snapshots = (0, store_1.writable)([{ title: 'Initial', data: deepClone(init) }]);
26
+ const errors = writable();
27
+ const hasErrors = derived(errors, hasAnyErrors);
28
+ const isDirty = writable(false);
29
+ const actionInProgress = writable(false);
30
+ const actionError = writable();
31
+ const snapshots = writable([{ title: 'Initial', data: deepClone(init) }]);
36
32
  const stateObject = $state(init);
37
33
  const createSnapshot = (title, replace = true) => {
38
- const currentSnapshots = (0, store_1.get)(snapshots);
34
+ const currentSnapshots = get(snapshots);
39
35
  const createdSnapshot = { title, data: deepClone(stateObject) };
40
36
  const lastSnapshot = currentSnapshots.at(-1);
41
37
  if (replace && lastSnapshot && lastSnapshot.title === title)
@@ -64,7 +60,7 @@ function createSvState(init, actuators, options) {
64
60
  });
65
61
  }
66
62
  };
67
- const data = (0, proxy_1.ChangeProxy)(stateObject, (target, property, currentValue, oldValue) => {
63
+ const data = ChangeProxy(stateObject, (target, property, currentValue, oldValue) => {
68
64
  if (!usedOptions.persistActionError)
69
65
  actionError.set(undefined);
70
66
  isDirty.set(true);
@@ -76,7 +72,7 @@ function createSvState(init, actuators, options) {
76
72
  if (validator)
77
73
  errors.set(validator(data));
78
74
  const execute = async (parameters) => {
79
- if (!usedOptions.allowConcurrentActions && (0, store_1.get)(actionInProgress))
75
+ if (!usedOptions.allowConcurrentActions && get(actionInProgress))
80
76
  return;
81
77
  actionError.set(undefined);
82
78
  actionInProgress.set(true);
@@ -96,7 +92,7 @@ function createSvState(init, actuators, options) {
96
92
  }
97
93
  };
98
94
  const rollback = (steps = 1) => {
99
- const currentSnapshots = (0, store_1.get)(snapshots);
95
+ const currentSnapshots = get(snapshots);
100
96
  if (currentSnapshots.length <= 1)
101
97
  return;
102
98
  const targetIndex = Math.max(0, currentSnapshots.length - 1 - steps);
@@ -109,7 +105,7 @@ function createSvState(init, actuators, options) {
109
105
  errors.set(validator(data));
110
106
  };
111
107
  const reset = () => {
112
- const currentSnapshots = (0, store_1.get)(snapshots);
108
+ const currentSnapshots = get(snapshots);
113
109
  const initialSnapshot = currentSnapshots[0];
114
110
  if (!initialSnapshot)
115
111
  return;
@@ -1,16 +1,10 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stringValidator = stringValidator;
4
- exports.numberValidator = numberValidator;
5
- exports.arrayValidator = arrayValidator;
6
- exports.dateValidator = dateValidator;
7
1
  const prepareOps = {
8
2
  trim: (s) => s.trim(),
9
3
  normalize: (s) => s.replaceAll(/\s{2,}/g, ' '),
10
- upper: (s) => s.toLocaleUpperCase(),
11
- lower: (s) => s.toLocaleLowerCase()
4
+ upper: (s) => s.toUpperCase(),
5
+ lower: (s) => s.toLowerCase()
12
6
  };
13
- function stringValidator(input, ...prepares) {
7
+ export function stringValidator(input, ...prepares) {
14
8
  let error = '';
15
9
  const setError = (message) => {
16
10
  if (!error)
@@ -39,12 +33,12 @@ function stringValidator(input, ...prepares) {
39
33
  return builder;
40
34
  },
41
35
  uppercase() {
42
- if (!error && processedInput !== processedInput.toLocaleUpperCase())
36
+ if (!error && processedInput !== processedInput.toUpperCase())
43
37
  setError('Uppercase only');
44
38
  return builder;
45
39
  },
46
40
  lowercase() {
47
- if (!error && processedInput !== processedInput.toLocaleLowerCase())
41
+ if (!error && processedInput !== processedInput.toLowerCase())
48
42
  setError('Lowercase only');
49
43
  return builder;
50
44
  },
@@ -113,7 +107,7 @@ function stringValidator(input, ...prepares) {
113
107
  };
114
108
  return builder;
115
109
  }
116
- function numberValidator(input) {
110
+ export function numberValidator(input) {
117
111
  let error = '';
118
112
  const setError = (message) => {
119
113
  if (!error)
@@ -185,7 +179,7 @@ function numberValidator(input) {
185
179
  };
186
180
  return builder;
187
181
  }
188
- function arrayValidator(input) {
182
+ export function arrayValidator(input) {
189
183
  let error = '';
190
184
  const setError = (message) => {
191
185
  if (!error)
@@ -227,7 +221,7 @@ function arrayValidator(input) {
227
221
  };
228
222
  return builder;
229
223
  }
230
- function dateValidator(input) {
224
+ export function dateValidator(input) {
231
225
  let error = '';
232
226
  const setError = (message) => {
233
227
  if (!error)
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "svstate",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Supercharged $state() for Svelte 5: deep reactive proxy with validation, cross-field rules, computed & side-effects",
5
5
  "author": "BCsabaEngine",
6
6
  "license": "ISC",
7
+ "type": "module",
7
8
  "main": "./dist/index.js",
8
9
  "types": "./dist/index.d.ts",
9
10
  "exports": {
10
11
  ".": {
11
12
  "types": "./dist/index.d.ts",
12
- "default": "./dist/index.js"
13
+ "import": "./dist/index.js"
13
14
  }
14
15
  },
15
16
  "engines": {
@@ -54,8 +55,8 @@
54
55
  "devDependencies": {
55
56
  "@sveltejs/vite-plugin-svelte": "^6.2.4",
56
57
  "@types/node": "^25.0.9",
57
- "@typescript-eslint/eslint-plugin": "^8.53.0",
58
- "@typescript-eslint/parser": "^8.53.0",
58
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
59
+ "@typescript-eslint/parser": "^8.53.1",
59
60
  "@vitest/coverage-v8": "^4.0.17",
60
61
  "eslint": "^9.39.2",
61
62
  "eslint-config-prettier": "^10.1.8",
@@ -63,7 +64,7 @@
63
64
  "eslint-plugin-unicorn": "^62.0.0",
64
65
  "nodemon": "^3.1.11",
65
66
  "prettier": "^3.8.0",
66
- "svelte": "^5.46.4",
67
+ "svelte": "^5.47.1",
67
68
  "ts-node": "^10.9.2",
68
69
  "tsx": "^4.21.0",
69
70
  "typescript": "^5.9.3",