@gost-kit/svelte 0.1.1 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @gost-kit/svelte
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - e89218e: Add synchronous store.reset({ excluded }) with fresh scope state factories.
8
+
9
+ Breaking change for the current 0.x API: StoreConfig.initState now requires a
10
+ zero-argument factory, and Store gained a required reset member. Existing
11
+ implementers of Store (test doubles, wrappers) must add reset; adapters can use
12
+ common's framework-independent createReset. Replace initState: initialState()
13
+ with initState: initialState.
14
+ Excluded root scopes retain current references; all other scopes use fresh defaults
15
+ in a single state update. Reset does not cancel running effects or suppress late responses.
16
+
17
+ Reset failures are reported through the store's onError as ResetError with
18
+ kind: 'reset' and no action. StoreError now includes this variant; handlers
19
+ reading action/effect must first narrow kind. Without a handler, report uses the
20
+ existing console fallback. Errors during reset no longer propagate to its caller.
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [3a39e51]
25
+ - Updated dependencies [e89218e]
26
+ - @gost-kit/common@0.3.0
27
+
3
28
  ## 0.1.1
4
29
 
5
30
  ### Patch Changes
package/README.md CHANGED
@@ -8,13 +8,15 @@ The store implementation lives in `src/shell/domain/createStore.svelte.ts`.
8
8
  import { createStore } from '@gost-kit/svelte';
9
9
 
10
10
  const counter = createStore<number, { type: 'IncrementAction' }, never>({
11
- initState: 0,
11
+ initState: () => 0,
12
12
  reducer: (state) => ({ state: state + 1, effects: [] }),
13
13
  effector: async () => {},
14
14
  });
15
15
 
16
16
  await counter.dispatch({ type: 'IncrementAction' });
17
17
  // counter.state is now 1; reading it in a Svelte template is reactive.
18
+ counter.reset();
19
+ // counter.state is now 0.
18
20
  ```
19
21
 
20
22
  `createStore` accepts `StoreConfig` and returns `Store`, both exported from
@@ -23,9 +25,61 @@ merge or deeply proxy state. Each instance has independent state. Dispatch,
23
25
  parallel effects, awaited nested dispatch and error reporting are implemented
24
26
  by `@gost-kit/common` without a framework dependency.
25
27
 
28
+ `initState` is a synchronous factory called without arguments once when creating
29
+ the store and once per reset. Migrate `initState: initialState()` to
30
+ `initState: initialState`. Each scope has its own factory; the root composes them:
31
+
32
+ ```ts
33
+ import { define } from '@gost-kit/common';
34
+
35
+ const usersState = define.state<UsersState>((options = {}) => ({
36
+ data: [],
37
+ errors: [],
38
+ ...options,
39
+ }));
40
+ const rootState = define.state<RootState>((options = {}) => ({
41
+ users: usersState(),
42
+ auth: authState(),
43
+ ...options,
44
+ }));
45
+
46
+ // In store config: initState: rootState
47
+ // In reducer tests: rootState({ users: usersState({ errors: [apiError()] }) })
48
+ ```
49
+
50
+ The factories above use application-defined state types and error/auth factories.
51
+ Each call should allocate fresh mutable nested defaults. Supplied overrides are
52
+ used by reference with a shallow replacement; the store does not clone them.
53
+ `define.state(object)` shares nested defaults and cannot guarantee this freshness.
54
+
55
+ `store.reset()` resets all state. `store.reset({ excluded: ['auth'] })` preserves
56
+ the current `auth` reference and resets other scopes. The list is readonly and
57
+ checked against root keys, not action namespaces. An absent/empty list is a full
58
+ reset. The entire root factory runs even for excluded scopes, followed by a
59
+ single state publication. Reset returns void and retains the same store/dispatch.
60
+
61
+ Partial reset supports fixed object roots with independent scopes. Primitive,
62
+ array, function and union roots permit full reset only at the type level; a union
63
+ inside a scope is fine. Union detection uses the represented TypeScript type;
64
+ type widening or assertions can erase that information. Runtime checks do not
65
+ detect unions. An excluded key is preserved only if it is an own property of both
66
+ the current and initial roots. Missing or inherited keys are skipped, including
67
+ optional scopes deleted or added by reducers. Such scopes take their presence
68
+ and value from the initial root. Errors during reset go to the store's `onError`
69
+ as `{ kind: 'reset', error }`; reset stops without throwing outward. Factory or
70
+ validation failures leave state unchanged. Without `onError`, the shared reporter
71
+ logs the failure to console. Initial creation still calls the factory directly:
72
+ if that fails, creation throws and no store is returned.
73
+
74
+ Reset does not cancel pending effects or ignore late responses. A later dispatch
75
+ reads the current state after reset and may populate it again. Routing and request
76
+ cancellation belong to the application.
77
+
26
78
  The optional `onError` callback is supplied when the store is created, for example
27
79
  to connect application logging. Replacing it on the original config afterwards
28
80
  does not change the store's handler.
81
+ The same snapshot rule applies to `initState`: replacing it on config does not
82
+ change the factory captured by an existing store.
29
83
 
30
84
  Select a feature before computing its presentation:
31
85
 
@@ -1,22 +1,26 @@
1
- import { createDispatch, } from '@gost-kit/common';
1
+ import { createDispatch, createReset, } from '@gost-kit/common';
2
2
  export const createStore = ({ initState, reducer, effector, onError, }) => {
3
3
  // Reducers replace complete immutable state; deep proxies are unnecessary.
4
- let state = $state.raw(initState);
4
+ let state = $state.raw(initState());
5
+ const readState = () => {
6
+ return state;
7
+ };
8
+ const writeState = (next) => {
9
+ state = next;
10
+ };
5
11
  const dispatch = createDispatch({
6
- readState: () => {
7
- return state;
8
- },
9
- writeState: (next) => {
10
- state = next;
11
- },
12
+ readState,
13
+ writeState,
12
14
  reducer,
13
15
  effector,
14
16
  onError,
15
17
  });
18
+ const reset = createReset({ initState, readState, writeState, onError });
16
19
  return {
17
20
  get state() {
18
21
  return state;
19
22
  },
20
23
  dispatch,
24
+ reset,
21
25
  };
22
26
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gost-kit/svelte",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Svelte bindings for GOST functional core.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  "prepack": "npm run build"
26
26
  },
27
27
  "dependencies": {
28
- "@gost-kit/common": "^0.2.0"
28
+ "@gost-kit/common": "^0.3.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "svelte": "^5.57.2"