ccstate 2.0.0 → 2.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 +42 -74
- package/debug/index.cjs +29 -4
- package/debug/index.d.cts +2 -1
- package/debug/index.d.ts +2 -1
- package/debug/index.js +29 -5
- package/index.cjs +29 -4
- package/index.d.cts +2 -1
- package/index.d.ts +2 -1
- package/index.js +29 -5
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<img src="https://github.com/user-attachments/assets/590797c8-6edf-45cc-8eae-028aef0b2cb3" width="240" >
|
|
2
|
+
|
|
3
|
+
---
|
|
2
4
|
|
|
3
5
|
[](https://coveralls.io/github/e7h4n/ccstate?branch=main)
|
|
4
6
|

|
|
@@ -8,17 +10,19 @@
|
|
|
8
10
|
[](https://codspeed.io/e7h4n/ccstate)
|
|
9
11
|
[](https://opensource.org/licenses/MIT)
|
|
10
12
|
|
|
13
|
+
English | [中文](README-zh.md)
|
|
14
|
+
|
|
11
15
|
CCState is a semantic, strict, and flexible state management library suitable for medium to large single-page applications with complex state management needs.
|
|
12
16
|
|
|
13
|
-
The name CCState comes from
|
|
17
|
+
The name of CCState comes from three basic data types: computed, command, and state.
|
|
14
18
|
|
|
15
19
|
## Quick Features
|
|
16
20
|
|
|
17
|
-
- Simple API design with
|
|
18
|
-
-
|
|
19
|
-
- Zero dependencies
|
|
20
|
-
-
|
|
21
|
-
-
|
|
21
|
+
- 💯 Simple & Intuitive: Crystal-clear API design with just 3 data types and 2 operations
|
|
22
|
+
- ✅ Rock-solid Reliability: Comprehensive test coverage reaching 100% branch coverage
|
|
23
|
+
- 🪶 Ultra-lightweight: Zero dependencies, only 500 lines of core code
|
|
24
|
+
- 💡 Framework Agnostic: Seamlessly works with React, Vanilla JS, or any UI framework
|
|
25
|
+
- 🚀 Blazing Fast: Optimized performance from day one, 2x-7x faster than Jotai across scenarios
|
|
22
26
|
|
|
23
27
|
## Getting Started
|
|
24
28
|
|
|
@@ -35,12 +39,12 @@ pnpm add ccstate
|
|
|
35
39
|
yarn add ccstate
|
|
36
40
|
```
|
|
37
41
|
|
|
38
|
-
### Create
|
|
42
|
+
### Create Data
|
|
39
43
|
|
|
40
|
-
Use `state` to
|
|
44
|
+
Use `state` to store a simple value unit, and use `computed` to create a derived computation logic:
|
|
41
45
|
|
|
42
46
|
```ts
|
|
43
|
-
//
|
|
47
|
+
// data.js
|
|
44
48
|
import { state, computed } from 'ccstate';
|
|
45
49
|
|
|
46
50
|
export const userId$ = state('');
|
|
@@ -54,14 +58,14 @@ export const user$ = computed(async (get) => {
|
|
|
54
58
|
});
|
|
55
59
|
```
|
|
56
60
|
|
|
57
|
-
### Use
|
|
61
|
+
### Use data in React
|
|
58
62
|
|
|
59
|
-
Use `useGet` and `useSet` hooks in React to get/set
|
|
63
|
+
Use `useGet` and `useSet` hooks in React to get/set data, and use `useResolved` to get Promise value.
|
|
60
64
|
|
|
61
65
|
```jsx
|
|
62
66
|
// App.js
|
|
63
67
|
import { useGet, useSet, useResolved } from 'ccstate';
|
|
64
|
-
import { userId$, user$ } from './
|
|
68
|
+
import { userId$, user$ } from './data';
|
|
65
69
|
|
|
66
70
|
export default function App() {
|
|
67
71
|
const userId = useGet(userId$);
|
|
@@ -114,7 +118,7 @@ Through these examples, you should have understood the basic usage of CCState. N
|
|
|
114
118
|
|
|
115
119
|
## Core APIs
|
|
116
120
|
|
|
117
|
-
CCState
|
|
121
|
+
CCState provides several simple concepts to help developers better manage application states. And it can be used as an external store to drive UI frameworks like React.
|
|
118
122
|
|
|
119
123
|
### State
|
|
120
124
|
|
|
@@ -137,7 +141,7 @@ store.set(callback$, () => {
|
|
|
137
141
|
store.get(callback$)(); // console log 'awesome ccstate'
|
|
138
142
|
```
|
|
139
143
|
|
|
140
|
-
These examples should be very easy to understand. You might notice a detail in the examples: all variables returned by `state` have a `$` suffix. This is a naming convention used to distinguish an
|
|
144
|
+
These examples should be very easy to understand. You might notice a detail in the examples: all variables returned by `state` have a `$` suffix. This is a naming convention used to distinguish an CCState data type from other regular types. CCState data types must be accessed through the store's get/set methods, and since it's common to convert an CCState data type to a regular type using get, the `$` suffix helps avoid naming conflicts.
|
|
141
145
|
|
|
142
146
|
### Store
|
|
143
147
|
|
|
@@ -153,7 +157,7 @@ const otherStore = createStore(); // another new Map()
|
|
|
153
157
|
otherStore.get(count$); // anotherMap[$count] ?? $count.init, returns 0
|
|
154
158
|
```
|
|
155
159
|
|
|
156
|
-
This should be easy to understand. If `Store` only needed to support `State` types, a simple Map would be sufficient. However, CCState needs to support two additional
|
|
160
|
+
This should be easy to understand. If `Store` only needed to support `State` types, a simple Map would be sufficient. However, CCState needs to support two additional data types. Next, let's introduce `Computed`, CCState's reactive computation unit.
|
|
157
161
|
|
|
158
162
|
### Computed
|
|
159
163
|
|
|
@@ -184,7 +188,7 @@ In most cases, side-effect free computation logic is extremely useful. They can
|
|
|
184
188
|
|
|
185
189
|
### Command
|
|
186
190
|
|
|
187
|
-
`Command` is CCState's logic unit for organizing side effects. It has both `set` and `get` accessors from the store, allowing it to not only read other
|
|
191
|
+
`Command` is CCState's logic unit for organizing side effects. It has both `set` and `get` accessors from the store, allowing it to not only read other data types but also modify `State` or call other `Command`.
|
|
188
192
|
|
|
189
193
|
```typescript
|
|
190
194
|
import { command, createStore } from 'ccstate';
|
|
@@ -303,18 +307,18 @@ All descendant components within the `StoreProvider` will use the provided store
|
|
|
303
307
|
|
|
304
308
|
You can place the `StoreProvider` inside or outside of `StrictMode`; the functionality is the same.
|
|
305
309
|
|
|
306
|
-
### Retrieving
|
|
310
|
+
### Retrieving Values
|
|
307
311
|
|
|
308
|
-
The most basic usage is to use `useGet` to retrieve the value
|
|
312
|
+
The most basic usage is to use `useGet` to retrieve the value from State or Computed.
|
|
309
313
|
|
|
310
314
|
```jsx
|
|
311
|
-
//
|
|
315
|
+
// data/count.ts
|
|
312
316
|
import { state } from 'ccstate';
|
|
313
317
|
export const count$ = state(0);
|
|
314
318
|
|
|
315
319
|
// App.tsx
|
|
316
320
|
import { useGet } from 'ccstate';
|
|
317
|
-
import { count$ } from './
|
|
321
|
+
import { count$ } from './data/count';
|
|
318
322
|
|
|
319
323
|
function App() {
|
|
320
324
|
const count = useGet(count$);
|
|
@@ -329,7 +333,7 @@ function App() {
|
|
|
329
333
|
Two other useful hooks are available when dealing with `Promise` values. First, we introduce `useLoadable`.
|
|
330
334
|
|
|
331
335
|
```jsx
|
|
332
|
-
//
|
|
336
|
+
// data/user.ts
|
|
333
337
|
import { computed } from 'ccstate';
|
|
334
338
|
|
|
335
339
|
export const user$ = computed(async () => {
|
|
@@ -338,7 +342,7 @@ export const user$ = computed(async () => {
|
|
|
338
342
|
|
|
339
343
|
// App.tsx
|
|
340
344
|
import { useLoadable } from 'ccstate';
|
|
341
|
-
import { user$ } from './
|
|
345
|
+
import { user$ } from './data/user';
|
|
342
346
|
|
|
343
347
|
function App() {
|
|
344
348
|
const user_ = useLoadable(user$);
|
|
@@ -349,7 +353,7 @@ function App() {
|
|
|
349
353
|
}
|
|
350
354
|
```
|
|
351
355
|
|
|
352
|
-
`useLoadable` accepts
|
|
356
|
+
`useLoadable` accepts Value/Computed that returns a `Promise` and wraps the result in a `Loadable` structure.
|
|
353
357
|
|
|
354
358
|
```typescript
|
|
355
359
|
type Loadable<T> =
|
|
@@ -373,7 +377,7 @@ Another useful hook is `useResolved`, which always returns the resolved value of
|
|
|
373
377
|
```jsx
|
|
374
378
|
// App.tsx
|
|
375
379
|
import { useResolved } from 'ccstate';
|
|
376
|
-
import { user$ } from './
|
|
380
|
+
import { user$ } from './data/user';
|
|
377
381
|
|
|
378
382
|
function App() {
|
|
379
383
|
const user = useResolved(user$);
|
|
@@ -396,11 +400,11 @@ export function useResolved<T>(atom: State<Promise<T>> | Computed<Promise<T>>):
|
|
|
396
400
|
|
|
397
401
|
### useLastLoadable & useLastResolved
|
|
398
402
|
|
|
399
|
-
In some scenarios, we want a refreshable Promise
|
|
403
|
+
In some scenarios, we want a refreshable Promise Computed to maintain its previous result during the refresh process instead of showing a loading state. CCState provides `useLastLoadable` and `useLastResolved` to achieve this functionality.
|
|
400
404
|
|
|
401
405
|
```jsx
|
|
402
406
|
import { useLoadable } from 'ccstate';
|
|
403
|
-
import { user$ } from './
|
|
407
|
+
import { user$ } from './data/user';
|
|
404
408
|
|
|
405
409
|
function App() {
|
|
406
410
|
const user_ = useLastLoadable(user$); // Keep the previous result during new user$ request, without triggering loading state
|
|
@@ -413,14 +417,14 @@ function App() {
|
|
|
413
417
|
|
|
414
418
|
`useLastResolved` behaves similarly - it always returns the last resolved value from a Promise Atom and won't reset to `undefined` when a new Promise is generated.
|
|
415
419
|
|
|
416
|
-
### Updating
|
|
420
|
+
### Updating State / Triggering Command
|
|
417
421
|
|
|
418
|
-
The `useSet` hook can be used to update the value of
|
|
422
|
+
The `useSet` hook can be used to update the value of State, or trigger Command. It returns a function equivalent to `store.set` when called.
|
|
419
423
|
|
|
420
424
|
```jsx
|
|
421
425
|
// App.tsx
|
|
422
426
|
import { useSet } from 'ccstate';
|
|
423
|
-
import { count$ } from './
|
|
427
|
+
import { count$ } from './data/count';
|
|
424
428
|
|
|
425
429
|
function App() {
|
|
426
430
|
const setCount = useSet(count$);
|
|
@@ -429,9 +433,9 @@ function App() {
|
|
|
429
433
|
}
|
|
430
434
|
```
|
|
431
435
|
|
|
432
|
-
### Testing &
|
|
436
|
+
### Testing & Debugging
|
|
433
437
|
|
|
434
|
-
Testing
|
|
438
|
+
Testing Value/Computed should be as simple as testing a Map.
|
|
435
439
|
|
|
436
440
|
```typescript
|
|
437
441
|
// counter.test.ts
|
|
@@ -453,22 +457,12 @@ Here are some tips to help you better debug during testing.
|
|
|
453
457
|
Use `ConsoleInterceptor` to log most store behaviors to the console during testing:
|
|
454
458
|
|
|
455
459
|
```typescript
|
|
456
|
-
import {
|
|
460
|
+
import { createConsoleDebugStore, state, computed, command } from 'ccstate';
|
|
457
461
|
|
|
458
462
|
const base$ = state(1, { debugLabel: 'base$' });
|
|
459
463
|
const derived$ = computed((get) => get(base$) * 2);
|
|
460
464
|
|
|
461
|
-
const
|
|
462
|
-
{
|
|
463
|
-
target: base$,
|
|
464
|
-
actions: new Set(['set']), // will only log set actions
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
target: derived$, // will log all actions
|
|
468
|
-
},
|
|
469
|
-
]);
|
|
470
|
-
|
|
471
|
-
const store = createDebugStore(interceptor);
|
|
465
|
+
const store = createConsoleDebugStore([base$, 'derived'], ['set', 'sub']); // log sub & set actions
|
|
472
466
|
store.set(base$, 1); // console: SET [V0:base$] 1
|
|
473
467
|
store.sub(
|
|
474
468
|
derived$,
|
|
@@ -484,9 +478,9 @@ CCState is inspired by Jotai. While Jotai is a great state management solution t
|
|
|
484
478
|
- Should reduce reactive capabilities, especially the `onMount` capability - the framework shouldn't provide this ability
|
|
485
479
|
- Some implicit magic operations, especially Promise wrapping, make the application execution process less transparent
|
|
486
480
|
|
|
487
|
-
To address these issues, I created CCState to express my thoughts on state management. Before detailing the differences from Jotai, we need to understand CCState's
|
|
481
|
+
To address these issues, I created CCState to express my thoughts on state management. Before detailing the differences from Jotai, we need to understand CCState's data types and subscription system.
|
|
488
482
|
|
|
489
|
-
### More
|
|
483
|
+
### More semantic data types
|
|
490
484
|
|
|
491
485
|
Like Jotai, CCState is also an Atom State solution. However, unlike Jotai, CCState doesn't expose Raw Atom, instead dividing Atoms into three types:
|
|
492
486
|
|
|
@@ -507,7 +501,7 @@ export const userIdChange$ = command(({ get, set }) => {
|
|
|
507
501
|
});
|
|
508
502
|
|
|
509
503
|
// ...
|
|
510
|
-
import { userId$, userIdChange$ } from './
|
|
504
|
+
import { userId$, userIdChange$ } from './data';
|
|
511
505
|
|
|
512
506
|
function setupPage() {
|
|
513
507
|
const store = createStore();
|
|
@@ -556,7 +550,7 @@ export function App() {
|
|
|
556
550
|
When designing CCState, we wanted the trigger points for value changes to be completely detached from React's Mount/Unmount lifecycle and completely decoupled from React's rendering behavior.
|
|
557
551
|
|
|
558
552
|
```jsx
|
|
559
|
-
//
|
|
553
|
+
// data.js
|
|
560
554
|
export const userId$ = state(0)
|
|
561
555
|
export const init$ = command(({set}) => {
|
|
562
556
|
const userId = // ... parse userId from location search
|
|
@@ -587,32 +581,6 @@ root.render(
|
|
|
587
581
|
);
|
|
588
582
|
```
|
|
589
583
|
|
|
590
|
-
## Practices
|
|
591
|
-
|
|
592
|
-
### Naming
|
|
593
|
-
|
|
594
|
-
Add the suffix `$` to atoms. Since we often need to get values from Atoms in many scenarios, adding the suffix after Atom can avoid naming conflicts.
|
|
595
|
-
|
|
596
|
-
```typescript
|
|
597
|
-
const count$ = state(0);
|
|
598
|
-
const double$ = computed((get) => get(count$) * 2);
|
|
599
|
-
const updateCount$ = command(({ get, set }, val) => {
|
|
600
|
-
set(count$, val);
|
|
601
|
-
});
|
|
602
|
-
|
|
603
|
-
// ...
|
|
604
|
-
const count = get(count$) // will not conflict with normal value
|
|
605
|
-
|
|
606
|
-
// in react component
|
|
607
|
-
const updateCount = useSet(updateCount$) // Command suffix is useful for this
|
|
608
|
-
|
|
609
|
-
return <button onClick={() => updateCount(10)}>update</button>
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
### Internal Atom
|
|
613
|
-
|
|
614
|
-
Feel free to create internal Atom. Atom is very lightweight. Creating an Atom should be just like creating a variable. Atoms don't necessarily need to be persisted or defined in the top-level scope - it's perfectly fine to create Atoms inside closures or pass new Atoms through containers.
|
|
615
|
-
|
|
616
584
|
## Changelog & TODO
|
|
617
585
|
|
|
618
586
|
[Changelog](packages/ccstate/CHANGELOG.md)
|
package/debug/index.cjs
CHANGED
|
@@ -1175,13 +1175,18 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1175
1175
|
_classCallCheck(this, ConsoleInterceptor);
|
|
1176
1176
|
_defineProperty(this, "shouldLog", function (atom, action) {
|
|
1177
1177
|
return _this.watches.some(function (watch) {
|
|
1178
|
+
var atomMatched = false;
|
|
1178
1179
|
if (typeof watch.target === 'string') {
|
|
1179
|
-
|
|
1180
|
+
atomMatched = atom.toString().includes(watch.target);
|
|
1181
|
+
} else if (watch.target instanceof RegExp) {
|
|
1182
|
+
atomMatched = watch.target.test(atom.toString());
|
|
1183
|
+
} else {
|
|
1184
|
+
atomMatched = watch.target === atom;
|
|
1180
1185
|
}
|
|
1181
|
-
if (
|
|
1182
|
-
return
|
|
1186
|
+
if (!atomMatched) {
|
|
1187
|
+
return false;
|
|
1183
1188
|
}
|
|
1184
|
-
return
|
|
1189
|
+
return !watch.actions || watch.actions.has(action);
|
|
1185
1190
|
});
|
|
1186
1191
|
});
|
|
1187
1192
|
_defineProperty(this, "get", function (atom$, fn) {
|
|
@@ -1256,6 +1261,25 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1256
1261
|
});
|
|
1257
1262
|
this.watches = watches;
|
|
1258
1263
|
});
|
|
1264
|
+
function createConsoleDebugStore(watches, defaultActions) {
|
|
1265
|
+
var parsedWatches = watches.map(function (watch) {
|
|
1266
|
+
if (typeof watch === 'string' || watch instanceof RegExp) {
|
|
1267
|
+
return {
|
|
1268
|
+
target: watch,
|
|
1269
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
if ('target' in watch) {
|
|
1273
|
+
return watch;
|
|
1274
|
+
}
|
|
1275
|
+
return {
|
|
1276
|
+
target: watch,
|
|
1277
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1278
|
+
};
|
|
1279
|
+
});
|
|
1280
|
+
var interceptor = new ConsoleInterceptor(parsedWatches);
|
|
1281
|
+
return createDebugStore(interceptor);
|
|
1282
|
+
}
|
|
1259
1283
|
|
|
1260
1284
|
var StoreEvent = /*#__PURE__*/function (_Event) {
|
|
1261
1285
|
function StoreEvent(type, eventId, targetAtom, state, time, args, result) {
|
|
@@ -1422,6 +1446,7 @@ exports.ConsoleInterceptor = ConsoleInterceptor;
|
|
|
1422
1446
|
exports.EventInterceptor = EventInterceptor;
|
|
1423
1447
|
exports.GLOBAL_CCSTATE_INTERCEPED_KEY = GLOBAL_CCSTATE_INTERCEPED_KEY;
|
|
1424
1448
|
exports.StoreEvent = StoreEvent;
|
|
1449
|
+
exports.createConsoleDebugStore = createConsoleDebugStore;
|
|
1425
1450
|
exports.createDebugStore = createDebugStore;
|
|
1426
1451
|
exports.nestedAtomToString = nestedAtomToString;
|
|
1427
1452
|
exports.setupDevtoolsInterceptor = setupDevtoolsInterceptor;
|
package/debug/index.d.cts
CHANGED
|
@@ -94,6 +94,7 @@ declare class ConsoleInterceptor implements StoreInterceptor {
|
|
|
94
94
|
unmount: <T>(atom$: State<T> | Computed<T>) => void;
|
|
95
95
|
notify: <T>(callback$: CallbackFunc<T>, fn: () => T) => void;
|
|
96
96
|
}
|
|
97
|
+
declare function createConsoleDebugStore(watches: (AtomWatch | string | RegExp | State<unknown> | Computed<unknown> | Command<unknown, unknown[]>)[], defaultActions?: StoreEventType[]): DebugStore;
|
|
97
98
|
|
|
98
99
|
declare class StoreEvent extends Event {
|
|
99
100
|
readonly eventId: number;
|
|
@@ -130,4 +131,4 @@ interface DevToolsHookMessage {
|
|
|
130
131
|
declare const GLOBAL_CCSTATE_INTERCEPED_KEY = "__CCSTATE_INTERCEPED__";
|
|
131
132
|
declare function setupDevtoolsInterceptor(targetWindow: Window, signal?: AbortSignal): EventInterceptor;
|
|
132
133
|
|
|
133
|
-
export { ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type PackedEventMessage, StoreEvent, type StoreEventType, type StoreInterceptor, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
|
134
|
+
export { ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type PackedEventMessage, StoreEvent, type StoreEventType, type StoreInterceptor, createConsoleDebugStore, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
package/debug/index.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ declare class ConsoleInterceptor implements StoreInterceptor {
|
|
|
94
94
|
unmount: <T>(atom$: State<T> | Computed<T>) => void;
|
|
95
95
|
notify: <T>(callback$: CallbackFunc<T>, fn: () => T) => void;
|
|
96
96
|
}
|
|
97
|
+
declare function createConsoleDebugStore(watches: (AtomWatch | string | RegExp | State<unknown> | Computed<unknown> | Command<unknown, unknown[]>)[], defaultActions?: StoreEventType[]): DebugStore;
|
|
97
98
|
|
|
98
99
|
declare class StoreEvent extends Event {
|
|
99
100
|
readonly eventId: number;
|
|
@@ -130,4 +131,4 @@ interface DevToolsHookMessage {
|
|
|
130
131
|
declare const GLOBAL_CCSTATE_INTERCEPED_KEY = "__CCSTATE_INTERCEPED__";
|
|
131
132
|
declare function setupDevtoolsInterceptor(targetWindow: Window, signal?: AbortSignal): EventInterceptor;
|
|
132
133
|
|
|
133
|
-
export { ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type PackedEventMessage, StoreEvent, type StoreEventType, type StoreInterceptor, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
|
134
|
+
export { ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type PackedEventMessage, StoreEvent, type StoreEventType, type StoreInterceptor, createConsoleDebugStore, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
package/debug/index.js
CHANGED
|
@@ -1173,13 +1173,18 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1173
1173
|
_classCallCheck(this, ConsoleInterceptor);
|
|
1174
1174
|
_defineProperty(this, "shouldLog", function (atom, action) {
|
|
1175
1175
|
return _this.watches.some(function (watch) {
|
|
1176
|
+
var atomMatched = false;
|
|
1176
1177
|
if (typeof watch.target === 'string') {
|
|
1177
|
-
|
|
1178
|
+
atomMatched = atom.toString().includes(watch.target);
|
|
1179
|
+
} else if (watch.target instanceof RegExp) {
|
|
1180
|
+
atomMatched = watch.target.test(atom.toString());
|
|
1181
|
+
} else {
|
|
1182
|
+
atomMatched = watch.target === atom;
|
|
1178
1183
|
}
|
|
1179
|
-
if (
|
|
1180
|
-
return
|
|
1184
|
+
if (!atomMatched) {
|
|
1185
|
+
return false;
|
|
1181
1186
|
}
|
|
1182
|
-
return
|
|
1187
|
+
return !watch.actions || watch.actions.has(action);
|
|
1183
1188
|
});
|
|
1184
1189
|
});
|
|
1185
1190
|
_defineProperty(this, "get", function (atom$, fn) {
|
|
@@ -1254,6 +1259,25 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1254
1259
|
});
|
|
1255
1260
|
this.watches = watches;
|
|
1256
1261
|
});
|
|
1262
|
+
function createConsoleDebugStore(watches, defaultActions) {
|
|
1263
|
+
var parsedWatches = watches.map(function (watch) {
|
|
1264
|
+
if (typeof watch === 'string' || watch instanceof RegExp) {
|
|
1265
|
+
return {
|
|
1266
|
+
target: watch,
|
|
1267
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
if ('target' in watch) {
|
|
1271
|
+
return watch;
|
|
1272
|
+
}
|
|
1273
|
+
return {
|
|
1274
|
+
target: watch,
|
|
1275
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1276
|
+
};
|
|
1277
|
+
});
|
|
1278
|
+
var interceptor = new ConsoleInterceptor(parsedWatches);
|
|
1279
|
+
return createDebugStore(interceptor);
|
|
1280
|
+
}
|
|
1257
1281
|
|
|
1258
1282
|
var StoreEvent = /*#__PURE__*/function (_Event) {
|
|
1259
1283
|
function StoreEvent(type, eventId, targetAtom, state, time, args, result) {
|
|
@@ -1416,4 +1440,4 @@ function setupDevtoolsInterceptor(targetWindow, signal) {
|
|
|
1416
1440
|
return interceptor;
|
|
1417
1441
|
}
|
|
1418
1442
|
|
|
1419
|
-
export { ConsoleInterceptor, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, StoreEvent, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
|
1443
|
+
export { ConsoleInterceptor, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, StoreEvent, createConsoleDebugStore, createDebugStore, nestedAtomToString, setupDevtoolsInterceptor };
|
package/index.cjs
CHANGED
|
@@ -1221,13 +1221,18 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1221
1221
|
_classCallCheck(this, ConsoleInterceptor);
|
|
1222
1222
|
_defineProperty(this, "shouldLog", function (atom, action) {
|
|
1223
1223
|
return _this.watches.some(function (watch) {
|
|
1224
|
+
var atomMatched = false;
|
|
1224
1225
|
if (typeof watch.target === 'string') {
|
|
1225
|
-
|
|
1226
|
+
atomMatched = atom.toString().includes(watch.target);
|
|
1227
|
+
} else if (watch.target instanceof RegExp) {
|
|
1228
|
+
atomMatched = watch.target.test(atom.toString());
|
|
1229
|
+
} else {
|
|
1230
|
+
atomMatched = watch.target === atom;
|
|
1226
1231
|
}
|
|
1227
|
-
if (
|
|
1228
|
-
return
|
|
1232
|
+
if (!atomMatched) {
|
|
1233
|
+
return false;
|
|
1229
1234
|
}
|
|
1230
|
-
return
|
|
1235
|
+
return !watch.actions || watch.actions.has(action);
|
|
1231
1236
|
});
|
|
1232
1237
|
});
|
|
1233
1238
|
_defineProperty(this, "get", function (atom$, fn) {
|
|
@@ -1302,6 +1307,25 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1302
1307
|
});
|
|
1303
1308
|
this.watches = watches;
|
|
1304
1309
|
});
|
|
1310
|
+
function createConsoleDebugStore(watches, defaultActions) {
|
|
1311
|
+
var parsedWatches = watches.map(function (watch) {
|
|
1312
|
+
if (typeof watch === 'string' || watch instanceof RegExp) {
|
|
1313
|
+
return {
|
|
1314
|
+
target: watch,
|
|
1315
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
if ('target' in watch) {
|
|
1319
|
+
return watch;
|
|
1320
|
+
}
|
|
1321
|
+
return {
|
|
1322
|
+
target: watch,
|
|
1323
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1324
|
+
};
|
|
1325
|
+
});
|
|
1326
|
+
var interceptor = new ConsoleInterceptor(parsedWatches);
|
|
1327
|
+
return createDebugStore(interceptor);
|
|
1328
|
+
}
|
|
1305
1329
|
|
|
1306
1330
|
var StoreEvent = /*#__PURE__*/function (_Event) {
|
|
1307
1331
|
function StoreEvent(type, eventId, targetAtom, state, time, args, result) {
|
|
@@ -1585,6 +1609,7 @@ exports.StoreEvent = StoreEvent;
|
|
|
1585
1609
|
exports.StoreProvider = StoreProvider;
|
|
1586
1610
|
exports.command = command;
|
|
1587
1611
|
exports.computed = computed;
|
|
1612
|
+
exports.createConsoleDebugStore = createConsoleDebugStore;
|
|
1588
1613
|
exports.createDebugStore = createDebugStore;
|
|
1589
1614
|
exports.createStore = createStore;
|
|
1590
1615
|
exports.nestedAtomToString = nestedAtomToString;
|
package/index.d.cts
CHANGED
|
@@ -105,6 +105,7 @@ declare class ConsoleInterceptor implements StoreInterceptor {
|
|
|
105
105
|
unmount: <T>(atom$: State<T> | Computed<T>) => void;
|
|
106
106
|
notify: <T>(callback$: CallbackFunc<T>, fn: () => T) => void;
|
|
107
107
|
}
|
|
108
|
+
declare function createConsoleDebugStore(watches: (AtomWatch | string | RegExp | State<unknown> | Computed<unknown> | Command<unknown, unknown[]>)[], defaultActions?: StoreEventType[]): DebugStore;
|
|
108
109
|
|
|
109
110
|
declare class StoreEvent extends Event {
|
|
110
111
|
readonly eventId: number;
|
|
@@ -163,4 +164,4 @@ declare function useLastLoadable<T>(atom: State<Promise<T>> | Computed<Promise<T
|
|
|
163
164
|
|
|
164
165
|
declare const StoreProvider: react.Provider<Store | null>;
|
|
165
166
|
|
|
166
|
-
export { type Command, type Computed, ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type Getter, type PackedEventMessage, type Read, type Setter, type State, type Store, StoreEvent, type StoreEventType, type StoreInterceptor, StoreProvider, type Subscribe, type Updater, type Write, command, computed, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
|
167
|
+
export { type Command, type Computed, ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type Getter, type PackedEventMessage, type Read, type Setter, type State, type Store, StoreEvent, type StoreEventType, type StoreInterceptor, StoreProvider, type Subscribe, type Updater, type Write, command, computed, createConsoleDebugStore, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
package/index.d.ts
CHANGED
|
@@ -105,6 +105,7 @@ declare class ConsoleInterceptor implements StoreInterceptor {
|
|
|
105
105
|
unmount: <T>(atom$: State<T> | Computed<T>) => void;
|
|
106
106
|
notify: <T>(callback$: CallbackFunc<T>, fn: () => T) => void;
|
|
107
107
|
}
|
|
108
|
+
declare function createConsoleDebugStore(watches: (AtomWatch | string | RegExp | State<unknown> | Computed<unknown> | Command<unknown, unknown[]>)[], defaultActions?: StoreEventType[]): DebugStore;
|
|
108
109
|
|
|
109
110
|
declare class StoreEvent extends Event {
|
|
110
111
|
readonly eventId: number;
|
|
@@ -163,4 +164,4 @@ declare function useLastLoadable<T>(atom: State<Promise<T>> | Computed<Promise<T
|
|
|
163
164
|
|
|
164
165
|
declare const StoreProvider: react.Provider<Store | null>;
|
|
165
166
|
|
|
166
|
-
export { type Command, type Computed, ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type Getter, type PackedEventMessage, type Read, type Setter, type State, type Store, StoreEvent, type StoreEventType, type StoreInterceptor, StoreProvider, type Subscribe, type Updater, type Write, command, computed, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
|
167
|
+
export { type Command, type Computed, ConsoleInterceptor, type DebugStore, type DevToolsHookMessage, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, type Getter, type PackedEventMessage, type Read, type Setter, type State, type Store, StoreEvent, type StoreEventType, type StoreInterceptor, StoreProvider, type Subscribe, type Updater, type Write, command, computed, createConsoleDebugStore, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
package/index.js
CHANGED
|
@@ -1219,13 +1219,18 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1219
1219
|
_classCallCheck(this, ConsoleInterceptor);
|
|
1220
1220
|
_defineProperty(this, "shouldLog", function (atom, action) {
|
|
1221
1221
|
return _this.watches.some(function (watch) {
|
|
1222
|
+
var atomMatched = false;
|
|
1222
1223
|
if (typeof watch.target === 'string') {
|
|
1223
|
-
|
|
1224
|
+
atomMatched = atom.toString().includes(watch.target);
|
|
1225
|
+
} else if (watch.target instanceof RegExp) {
|
|
1226
|
+
atomMatched = watch.target.test(atom.toString());
|
|
1227
|
+
} else {
|
|
1228
|
+
atomMatched = watch.target === atom;
|
|
1224
1229
|
}
|
|
1225
|
-
if (
|
|
1226
|
-
return
|
|
1230
|
+
if (!atomMatched) {
|
|
1231
|
+
return false;
|
|
1227
1232
|
}
|
|
1228
|
-
return
|
|
1233
|
+
return !watch.actions || watch.actions.has(action);
|
|
1229
1234
|
});
|
|
1230
1235
|
});
|
|
1231
1236
|
_defineProperty(this, "get", function (atom$, fn) {
|
|
@@ -1300,6 +1305,25 @@ var ConsoleInterceptor = /*#__PURE__*/_createClass(function ConsoleInterceptor(w
|
|
|
1300
1305
|
});
|
|
1301
1306
|
this.watches = watches;
|
|
1302
1307
|
});
|
|
1308
|
+
function createConsoleDebugStore(watches, defaultActions) {
|
|
1309
|
+
var parsedWatches = watches.map(function (watch) {
|
|
1310
|
+
if (typeof watch === 'string' || watch instanceof RegExp) {
|
|
1311
|
+
return {
|
|
1312
|
+
target: watch,
|
|
1313
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1314
|
+
};
|
|
1315
|
+
}
|
|
1316
|
+
if ('target' in watch) {
|
|
1317
|
+
return watch;
|
|
1318
|
+
}
|
|
1319
|
+
return {
|
|
1320
|
+
target: watch,
|
|
1321
|
+
actions: defaultActions ? new Set(defaultActions) : undefined
|
|
1322
|
+
};
|
|
1323
|
+
});
|
|
1324
|
+
var interceptor = new ConsoleInterceptor(parsedWatches);
|
|
1325
|
+
return createDebugStore(interceptor);
|
|
1326
|
+
}
|
|
1303
1327
|
|
|
1304
1328
|
var StoreEvent = /*#__PURE__*/function (_Event) {
|
|
1305
1329
|
function StoreEvent(type, eventId, targetAtom, state, time, args, result) {
|
|
@@ -1576,4 +1600,4 @@ function useLastResolved(atom) {
|
|
|
1576
1600
|
return loadable.state === 'hasData' ? loadable.data : undefined;
|
|
1577
1601
|
}
|
|
1578
1602
|
|
|
1579
|
-
export { ConsoleInterceptor, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, StoreEvent, StoreProvider, command, computed, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
|
1603
|
+
export { ConsoleInterceptor, EventInterceptor, GLOBAL_CCSTATE_INTERCEPED_KEY, StoreEvent, StoreProvider, command, computed, createConsoleDebugStore, createDebugStore, createStore, nestedAtomToString, setupDevtoolsInterceptor, state, useGet, useLastLoadable, useLastResolved, useLoadable, useResolved, useSet };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccstate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "CCState Core",
|
|
5
5
|
"private": false,
|
|
6
6
|
"repository": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "./index.cjs",
|
|
13
|
+
"module": "./index.js",
|
|
13
14
|
"exports": {
|
|
14
15
|
".": {
|
|
15
16
|
"import": "./index.js",
|