@signaltree/core 7.0.1 → 7.1.1
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 +101 -0
- package/dist/index.js +2 -1
- package/dist/lib/internals/materialize-markers.js +19 -13
- package/dist/lib/markers/entity-map.js +20 -0
- package/dist/lib/markers/status.js +6 -0
- package/dist/lib/markers/stored.js +6 -0
- package/dist/lib/signal-tree.js +10 -1
- package/dist/lib/types.js +1 -7
- package/package.json +3 -47
- package/src/lib/internals/materialize-markers.d.ts +1 -0
- package/src/lib/markers/entity-map.d.ts +4 -0
- package/src/lib/markers/status.d.ts +7 -6
- package/src/lib/types.d.ts +2 -5
- package/src/lib/utils.d.ts +1 -16
- package/LICENSE +0 -54
package/README.md
CHANGED
|
@@ -36,6 +36,26 @@ import { batching } from '@signaltree/core/enhancers/batching';
|
|
|
36
36
|
- Core + batching: ~9.3 KB gzipped (barrel vs subpath: identical)
|
|
37
37
|
- Unused enhancers: **automatically excluded** by tree-shaking
|
|
38
38
|
|
|
39
|
+
### Marker Tree-Shaking (Self-Registering)
|
|
40
|
+
|
|
41
|
+
Built-in markers (`entityMap()`, `status()`, `stored()`) are **self-registering** - they only add their processor code when you actually use them:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
// ✅ Only status() code is bundled (entityMap and stored tree-shaken out)
|
|
45
|
+
import { signalTree, status } from '@signaltree/core';
|
|
46
|
+
const tree = signalTree({ loadState: status() });
|
|
47
|
+
|
|
48
|
+
// ✅ Minimal bundle - no marker code included
|
|
49
|
+
import { signalTree } from '@signaltree/core';
|
|
50
|
+
const tree = signalTree({ count: 0 });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**How it works:**
|
|
54
|
+
|
|
55
|
+
- Each marker factory (`status()`, `stored()`, `entityMap()`) registers its processor on first call
|
|
56
|
+
- If you never call a marker factory, its code is completely eliminated
|
|
57
|
+
- Zero import-time side effects - registration is lazy and automatic
|
|
58
|
+
|
|
39
59
|
**When to use subpath imports:**
|
|
40
60
|
|
|
41
61
|
- Older bundlers (webpack <5) with poor tree-shaking
|
|
@@ -796,6 +816,87 @@ tree.update((state) => ({
|
|
|
796
816
|
}));
|
|
797
817
|
```
|
|
798
818
|
|
|
819
|
+
### 7) Extensibility: Custom Markers & Enhancers
|
|
820
|
+
|
|
821
|
+
SignalTree is designed for extensibility. Create your own **markers** (state placeholders that materialize into specialized signals) and **enhancers** (functions that augment trees with additional capabilities).
|
|
822
|
+
|
|
823
|
+
#### Custom Marker Example
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
import { signal, Signal } from '@angular/core';
|
|
827
|
+
import { registerMarkerProcessor, signalTree } from '@signaltree/core';
|
|
828
|
+
|
|
829
|
+
// 1. Define marker symbol and interface
|
|
830
|
+
const VALIDATED_MARKER = Symbol('VALIDATED_MARKER');
|
|
831
|
+
|
|
832
|
+
interface ValidatedMarker<T> {
|
|
833
|
+
[VALIDATED_MARKER]: true;
|
|
834
|
+
defaultValue: T;
|
|
835
|
+
validator: (value: T) => string | null;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// 2. Create marker factory
|
|
839
|
+
function validated<T>(defaultValue: T, validator: (value: T) => string | null): ValidatedMarker<T> {
|
|
840
|
+
return { [VALIDATED_MARKER]: true, defaultValue, validator };
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// 3. Type guard
|
|
844
|
+
function isValidatedMarker(value: unknown): value is ValidatedMarker<unknown> {
|
|
845
|
+
return Boolean(value && typeof value === 'object' && (value as any)[VALIDATED_MARKER] === true);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// 4. Register materializer (call once at app startup)
|
|
849
|
+
registerMarkerProcessor(isValidatedMarker, (marker) => {
|
|
850
|
+
const valueSignal = signal(marker.defaultValue);
|
|
851
|
+
const errorSignal = signal<string | null>(marker.validator(marker.defaultValue));
|
|
852
|
+
return {
|
|
853
|
+
get: () => valueSignal(),
|
|
854
|
+
set: (v: any) => {
|
|
855
|
+
valueSignal.set(v);
|
|
856
|
+
errorSignal.set(marker.validator(v));
|
|
857
|
+
},
|
|
858
|
+
error: errorSignal.asReadonly(),
|
|
859
|
+
isValid: () => errorSignal() === null,
|
|
860
|
+
};
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
// 5. Usage
|
|
864
|
+
const tree = signalTree({
|
|
865
|
+
email: validated('', (v) => (v.includes('@') ? null : 'Invalid email')),
|
|
866
|
+
});
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
#### Custom Enhancer Example
|
|
870
|
+
|
|
871
|
+
```typescript
|
|
872
|
+
import { signal, Signal } from '@angular/core';
|
|
873
|
+
import type { ISignalTree } from '@signaltree/core';
|
|
874
|
+
|
|
875
|
+
interface WithLogger {
|
|
876
|
+
log(message: string): void;
|
|
877
|
+
history: Signal<string[]>;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function withLogger(config?: { maxHistory?: number }) {
|
|
881
|
+
const maxHistory = config?.maxHistory ?? 100;
|
|
882
|
+
return <T>(tree: ISignalTree<T>): ISignalTree<T> & WithLogger => {
|
|
883
|
+
const historySignal = signal<string[]>([]);
|
|
884
|
+
return Object.assign(tree, {
|
|
885
|
+
log: (msg: string) => historySignal.update((h) => [...h, `[${new Date().toLocaleTimeString()}] ${msg}`].slice(-maxHistory)),
|
|
886
|
+
history: historySignal.asReadonly(),
|
|
887
|
+
});
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// Usage
|
|
892
|
+
const tree = signalTree({ count: 0 }).with(withLogger());
|
|
893
|
+
tree.log('Tree created');
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
> 📖 **Full guide**: [Custom Markers & Enhancers](https://github.com/JBorgia/signaltree/blob/main/docs/custom-markers-enhancers.md)
|
|
897
|
+
>
|
|
898
|
+
> 📱 **Interactive demo**: [Demo App](/custom-extensions)
|
|
899
|
+
|
|
799
900
|
## Error handling examples
|
|
800
901
|
|
|
801
902
|
### Manual async error handling
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { signalTree } from './lib/signal-tree.js';
|
|
2
|
-
export { ENHANCER_META
|
|
2
|
+
export { ENHANCER_META } from './lib/types.js';
|
|
3
3
|
export { isDerivedMarker } from './lib/markers/derived.js';
|
|
4
4
|
export { LoadingState, isStatusMarker, status } from './lib/markers/status.js';
|
|
5
5
|
export { isStoredMarker, stored } from './lib/markers/stored.js';
|
|
@@ -18,6 +18,7 @@ export { devTools, enableDevTools, fullDevTools, productionDevTools } from './en
|
|
|
18
18
|
export { createAsyncOperation, trackAsync } from './lib/async-helpers.js';
|
|
19
19
|
export { TREE_PRESETS, combinePresets, createPresetConfig, getAvailablePresets, validatePreset } from './enhancers/presets/lib/presets.js';
|
|
20
20
|
export { SIGNAL_TREE_CONSTANTS, SIGNAL_TREE_MESSAGES } from './lib/constants.js';
|
|
21
|
+
export { entityMap } from './lib/markers/entity-map.js';
|
|
21
22
|
export { deepEqual, deepEqual as equal } from './deep-equal.js';
|
|
22
23
|
export { parsePath } from './parse-path.js';
|
|
23
24
|
export { isBuiltInObject } from './is-built-in-object.js';
|
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
import { isSignal } from '@angular/core';
|
|
2
|
-
import { createEntitySignal } from '../entity-signal.js';
|
|
3
|
-
import { createStatusSignal, isStatusMarker } from '../markers/status.js';
|
|
4
|
-
import { createStoredSignal, isStoredMarker } from '../markers/stored.js';
|
|
5
2
|
import { getPathNotifier } from '../path-notifier.js';
|
|
6
3
|
import { isNodeAccessor } from '../utils.js';
|
|
7
4
|
|
|
8
|
-
function isEntityMapMarker(value) {
|
|
9
|
-
return Boolean(value && typeof value === 'object' && value['__isEntityMap'] === true);
|
|
10
|
-
}
|
|
11
5
|
const MARKER_PROCESSORS = [];
|
|
6
|
+
function isRegisteredMarker(value) {
|
|
7
|
+
if (value === null || typeof value !== 'object') {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
if (Object.getOwnPropertySymbols(value).length === 0) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
for (const processor of MARKER_PROCESSORS) {
|
|
14
|
+
if (processor.check(value)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
12
20
|
function registerMarkerProcessor(check, create) {
|
|
21
|
+
const alreadyRegistered = MARKER_PROCESSORS.some(p => p.check === check);
|
|
22
|
+
if (alreadyRegistered) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
13
25
|
MARKER_PROCESSORS.push({
|
|
14
26
|
check,
|
|
15
27
|
create: create
|
|
16
28
|
});
|
|
17
29
|
}
|
|
18
|
-
registerMarkerProcessor(isEntityMapMarker, (marker, notifier, path) => {
|
|
19
|
-
const cfg = marker.__entityMapConfig ?? {};
|
|
20
|
-
return createEntitySignal(cfg, notifier, path);
|
|
21
|
-
});
|
|
22
|
-
registerMarkerProcessor(isStatusMarker, marker => createStatusSignal(marker));
|
|
23
|
-
registerMarkerProcessor(isStoredMarker, marker => createStoredSignal(marker));
|
|
24
30
|
function materializeMarkers(node, notifier, path = []) {
|
|
25
31
|
if (node == null) return;
|
|
26
32
|
if (typeof node !== 'object' && typeof node !== 'function') return;
|
|
@@ -63,4 +69,4 @@ function materializeMarkers(node, notifier, path = []) {
|
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
export { materializeMarkers, registerMarkerProcessor };
|
|
72
|
+
export { isRegisteredMarker, materializeMarkers, registerMarkerProcessor };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createEntitySignal } from '../entity-signal.js';
|
|
2
|
+
import { registerMarkerProcessor } from '../internals/materialize-markers.js';
|
|
3
|
+
import { isEntityMapMarker } from '../utils.js';
|
|
4
|
+
|
|
5
|
+
let entityMapRegistered = false;
|
|
6
|
+
function entityMap(config) {
|
|
7
|
+
if (!entityMapRegistered) {
|
|
8
|
+
entityMapRegistered = true;
|
|
9
|
+
registerMarkerProcessor(isEntityMapMarker, (marker, notifier, path) => {
|
|
10
|
+
const cfg = marker.__entityMapConfig ?? {};
|
|
11
|
+
return createEntitySignal(cfg, notifier, path);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
__isEntityMap: true,
|
|
16
|
+
__entityMapConfig: config ?? {}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { entityMap };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { signal, computed } from '@angular/core';
|
|
2
|
+
import { registerMarkerProcessor } from '../internals/materialize-markers.js';
|
|
2
3
|
|
|
3
4
|
const STATUS_MARKER = Symbol('STATUS_MARKER');
|
|
4
5
|
var LoadingState;
|
|
@@ -8,7 +9,12 @@ var LoadingState;
|
|
|
8
9
|
LoadingState["Loaded"] = "LOADED";
|
|
9
10
|
LoadingState["Error"] = "ERROR";
|
|
10
11
|
})(LoadingState || (LoadingState = {}));
|
|
12
|
+
let statusRegistered = false;
|
|
11
13
|
function status(initialState = LoadingState.NotLoaded) {
|
|
14
|
+
if (!statusRegistered) {
|
|
15
|
+
statusRegistered = true;
|
|
16
|
+
registerMarkerProcessor(isStatusMarker, createStatusSignal);
|
|
17
|
+
}
|
|
12
18
|
return {
|
|
13
19
|
[STATUS_MARKER]: true,
|
|
14
20
|
initialState
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { signal } from '@angular/core';
|
|
2
|
+
import { registerMarkerProcessor } from '../internals/materialize-markers.js';
|
|
2
3
|
|
|
3
4
|
const STORED_MARKER = Symbol('STORED_MARKER');
|
|
5
|
+
let storedRegistered = false;
|
|
4
6
|
function stored(key, defaultValue, options = {}) {
|
|
7
|
+
if (!storedRegistered) {
|
|
8
|
+
storedRegistered = true;
|
|
9
|
+
registerMarkerProcessor(isStoredMarker, createStoredSignal);
|
|
10
|
+
}
|
|
5
11
|
return {
|
|
6
12
|
[STORED_MARKER]: true,
|
|
7
13
|
key,
|
package/dist/lib/signal-tree.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { signal, isSignal } from '@angular/core';
|
|
2
2
|
import { SIGNAL_TREE_MESSAGES, SIGNAL_TREE_CONSTANTS } from './constants.js';
|
|
3
3
|
import { batchScope } from './internals/batch-scope.js';
|
|
4
|
-
import { materializeMarkers } from './internals/materialize-markers.js';
|
|
4
|
+
import { isRegisteredMarker, materializeMarkers } from './internals/materialize-markers.js';
|
|
5
5
|
import { applyDerivedFactories } from './internals/merge-derived.js';
|
|
6
6
|
import { isStatusMarker } from './markers/status.js';
|
|
7
7
|
import { isStoredMarker } from './markers/stored.js';
|
|
@@ -160,6 +160,15 @@ function createSignalStore(obj, equalityFn) {
|
|
|
160
160
|
store[key] = value;
|
|
161
161
|
continue;
|
|
162
162
|
}
|
|
163
|
+
if (isRegisteredMarker(value)) {
|
|
164
|
+
store[key] = value;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
168
|
+
if (value !== null && typeof value === 'object' && !Array.isArray(value) && Object.getOwnPropertySymbols(value).length > 0) {
|
|
169
|
+
console.warn(`SignalTree: Object at "${key}" has Symbol keys but doesn't match any ` + `registered marker processor. If this is a custom marker, ensure ` + `registerMarkerProcessor() is called BEFORE creating the tree.`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
163
172
|
if (isSignal(value)) {
|
|
164
173
|
store[key] = value;
|
|
165
174
|
continue;
|
package/dist/lib/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signaltree/core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"description": "Lightweight, type-safe signal-based state management for Angular. Core package providing hierarchical signal trees, basic entity management, and async actions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -13,51 +13,7 @@
|
|
|
13
13
|
"import": "./dist/index.js",
|
|
14
14
|
"default": "./dist/index.js"
|
|
15
15
|
},
|
|
16
|
-
"./
|
|
17
|
-
"types": "./src/enhancers/index.d.ts",
|
|
18
|
-
"import": "./dist/enhancers/index.js",
|
|
19
|
-
"default": "./dist/enhancers/index.js"
|
|
20
|
-
},
|
|
21
|
-
"./enhancers/batching": {
|
|
22
|
-
"types": "./src/enhancers/batching/index.d.ts",
|
|
23
|
-
"import": "./dist/enhancers/batching/index.js",
|
|
24
|
-
"default": "./dist/enhancers/batching/index.js"
|
|
25
|
-
},
|
|
26
|
-
"./enhancers/middleware": {
|
|
27
|
-
"types": "./src/enhancers/middleware/index.d.ts",
|
|
28
|
-
"import": "./dist/enhancers/middleware/index.js",
|
|
29
|
-
"default": "./dist/enhancers/middleware/index.js"
|
|
30
|
-
},
|
|
31
|
-
"./enhancers/memoization": {
|
|
32
|
-
"types": "./src/enhancers/memoization/index.d.ts",
|
|
33
|
-
"import": "./dist/enhancers/memoization/index.js",
|
|
34
|
-
"default": "./dist/enhancers/memoization/index.js"
|
|
35
|
-
},
|
|
36
|
-
"./enhancers/time-travel": {
|
|
37
|
-
"types": "./src/enhancers/time-travel/index.d.ts",
|
|
38
|
-
"import": "./dist/enhancers/time-travel/index.js",
|
|
39
|
-
"default": "./dist/enhancers/time-travel/index.js"
|
|
40
|
-
},
|
|
41
|
-
"./enhancers/devtools": {
|
|
42
|
-
"types": "./src/enhancers/devtools/index.d.ts",
|
|
43
|
-
"import": "./dist/enhancers/devtools/index.js",
|
|
44
|
-
"default": "./dist/enhancers/devtools/index.js"
|
|
45
|
-
},
|
|
46
|
-
"./enhancers/presets": {
|
|
47
|
-
"types": "./src/enhancers/presets/index.d.ts",
|
|
48
|
-
"import": "./dist/enhancers/presets/index.js",
|
|
49
|
-
"default": "./dist/enhancers/presets/index.js"
|
|
50
|
-
},
|
|
51
|
-
"./enhancers/entities": {
|
|
52
|
-
"types": "./src/enhancers/entities/index.d.ts",
|
|
53
|
-
"import": "./dist/enhancers/entities/index.js",
|
|
54
|
-
"default": "./dist/enhancers/entities/index.js"
|
|
55
|
-
},
|
|
56
|
-
"./enhancers/serialization": {
|
|
57
|
-
"types": "./src/enhancers/serialization/index.d.ts",
|
|
58
|
-
"import": "./dist/enhancers/serialization/index.js",
|
|
59
|
-
"default": "./dist/enhancers/serialization/index.js"
|
|
60
|
-
}
|
|
16
|
+
"./package.json": "./package.json"
|
|
61
17
|
},
|
|
62
18
|
"peerDependencies": {
|
|
63
19
|
"@angular/core": "^20.0.0",
|
|
@@ -89,4 +45,4 @@
|
|
|
89
45
|
"src/**/*.d.ts",
|
|
90
46
|
"README.md"
|
|
91
47
|
]
|
|
92
|
-
}
|
|
48
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PathNotifier } from '../path-notifier';
|
|
2
|
+
export declare function isRegisteredMarker(value: unknown): boolean;
|
|
2
3
|
export declare function registerMarkerProcessor<T, R>(check: (value: unknown) => value is T, create: (marker: T, notifier: PathNotifier, path: string) => R): void;
|
|
3
4
|
export declare function materializeMarkers(node: unknown, notifier?: PathNotifier, path?: string[]): void;
|
|
4
5
|
export declare function hasMarkers(node: unknown, visited?: WeakSet<object>): boolean;
|
|
@@ -9,13 +9,14 @@ export declare enum LoadingState {
|
|
|
9
9
|
export interface StatusConfig {
|
|
10
10
|
initialState?: LoadingState;
|
|
11
11
|
}
|
|
12
|
-
export interface StatusMarker {
|
|
12
|
+
export interface StatusMarker<E = Error> {
|
|
13
13
|
[STATUS_MARKER]: true;
|
|
14
14
|
initialState: LoadingState;
|
|
15
|
+
readonly __errorType?: E;
|
|
15
16
|
}
|
|
16
|
-
export interface StatusSignal {
|
|
17
|
+
export interface StatusSignal<E = Error> {
|
|
17
18
|
state: WritableSignal<LoadingState>;
|
|
18
|
-
error: WritableSignal<
|
|
19
|
+
error: WritableSignal<E | null>;
|
|
19
20
|
isNotLoaded: Signal<boolean>;
|
|
20
21
|
isLoading: Signal<boolean>;
|
|
21
22
|
isLoaded: Signal<boolean>;
|
|
@@ -23,9 +24,9 @@ export interface StatusSignal {
|
|
|
23
24
|
setNotLoaded(): void;
|
|
24
25
|
setLoading(): void;
|
|
25
26
|
setLoaded(): void;
|
|
26
|
-
setError(error:
|
|
27
|
+
setError(error: E): void;
|
|
27
28
|
reset(): void;
|
|
28
29
|
}
|
|
29
|
-
export declare function status(initialState?: LoadingState): StatusMarker
|
|
30
|
+
export declare function status<E = Error>(initialState?: LoadingState): StatusMarker<E>;
|
|
30
31
|
export declare function isStatusMarker(value: unknown): value is StatusMarker;
|
|
31
|
-
export declare function createStatusSignal(marker: StatusMarker): StatusSignal
|
|
32
|
+
export declare function createStatusSignal<E = Error>(marker: StatusMarker<E>): StatusSignal<E>;
|
package/src/lib/types.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export interface NodeAccessor<T> {
|
|
|
34
34
|
(updater: (current: T) => T): void;
|
|
35
35
|
}
|
|
36
36
|
export type TreeNode<T> = {
|
|
37
|
-
[K in keyof T]: T[K] extends EntityMapMarker<infer E, infer Key> ? EntitySignal<E, Key> : T[K] extends StatusMarker ? StatusSignal : T[K] extends StoredMarker<infer V> ? StoredSignal<V> : T[K] extends Primitive ? CallableWritableSignal<T[K]> : T[K] extends readonly unknown[] ? CallableWritableSignal<T[K]> : T[K] extends Date | RegExp | Map<any, any> | Set<any> | Error | ((...args: unknown[]) => unknown) ? CallableWritableSignal<T[K]> : T[K] extends object ? NodeAccessor<T[K]> & TreeNode<T[K]> : CallableWritableSignal<T[K]>;
|
|
37
|
+
[K in keyof T]: T[K] extends EntityMapMarker<infer E, infer Key> ? EntitySignal<E, Key> : T[K] extends StatusMarker<infer Err> ? StatusSignal<Err> : T[K] extends StoredMarker<infer V> ? StoredSignal<V> : T[K] extends Primitive ? CallableWritableSignal<T[K]> : T[K] extends readonly unknown[] ? CallableWritableSignal<T[K]> : T[K] extends Date | RegExp | Map<any, any> | Set<any> | Error | ((...args: unknown[]) => unknown) ? CallableWritableSignal<T[K]> : T[K] extends object ? NodeAccessor<T[K]> & TreeNode<T[K]> : CallableWritableSignal<T[K]>;
|
|
38
38
|
};
|
|
39
39
|
export interface ISignalTree<T> extends NodeAccessor<T> {
|
|
40
40
|
readonly state: TreeNode<T>;
|
|
@@ -153,9 +153,7 @@ export interface EntityMapMarker<E, K extends string | number> {
|
|
|
153
153
|
readonly __isEntityMap: true;
|
|
154
154
|
readonly __entityMapConfig?: EntityConfig<E, K>;
|
|
155
155
|
}
|
|
156
|
-
export
|
|
157
|
-
id: infer I extends string | number;
|
|
158
|
-
} ? I : string>(config?: EntityConfig<E, K>): EntityMapMarker<E, K>;
|
|
156
|
+
export { entityMap } from './markers/entity-map';
|
|
159
157
|
export interface MutationOptions {
|
|
160
158
|
onError?: (error: Error) => void;
|
|
161
159
|
}
|
|
@@ -300,4 +298,3 @@ export type MinimalSignalTree<T> = ISignalTree<T> & EffectsMethods<T>;
|
|
|
300
298
|
export type SignalTree<T> = ISignalTree<T> & TreeNode<T>;
|
|
301
299
|
export type SignalTreeBase<T> = ISignalTree<T> & TreeNode<T>;
|
|
302
300
|
export declare function isSignalTree<T>(value: unknown): value is ISignalTree<T>;
|
|
303
|
-
export {};
|
package/src/lib/utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WritableSignal } from '@angular/core';
|
|
2
|
+
import { deepEqual, isBuiltInObject, parsePath } from '@signaltree/shared';
|
|
2
3
|
export { deepEqual };
|
|
3
4
|
export { deepEqual as equal };
|
|
4
5
|
export { isBuiltInObject };
|
|
@@ -10,22 +11,6 @@ export interface MemoryManager {
|
|
|
10
11
|
dispose(): void;
|
|
11
12
|
}
|
|
12
13
|
import type { NodeAccessor, TreeNode } from './types';
|
|
13
|
-
|
|
14
|
-
// Inlined from @signaltree/shared (internal package)
|
|
15
|
-
declare function deepEqual<T>(a: T, b: T): boolean;
|
|
16
|
-
declare function deepClone<T>(obj: T): T;
|
|
17
|
-
declare function isBuiltInObject(value: unknown): boolean;
|
|
18
|
-
declare function parsePath(path: string): string[];
|
|
19
|
-
declare class LRUCache<K, V> {
|
|
20
|
-
constructor(maxSize: number);
|
|
21
|
-
get(key: K): V | undefined;
|
|
22
|
-
set(key: K, value: V): void;
|
|
23
|
-
has(key: K): boolean;
|
|
24
|
-
delete(key: K): boolean;
|
|
25
|
-
clear(): void;
|
|
26
|
-
get size(): number;
|
|
27
|
-
}
|
|
28
|
-
declare const DEFAULT_PATH_CACHE_SIZE: number;
|
|
29
14
|
export declare function isNodeAccessor(value: unknown): value is NodeAccessor<unknown>;
|
|
30
15
|
export declare function isAnySignal(value: unknown): boolean;
|
|
31
16
|
export declare function toWritableSignal<T>(node: NodeAccessor<T>, injector?: unknown): WritableSignal<T>;
|
package/LICENSE
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
BUSINESS SOURCE LICENSE 1.1
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Jonathan D Borgia
|
|
4
|
-
|
|
5
|
-
This Business Source License 1.1 ("License") governs the use of the software and associated documentation files (the "Software"). You are granted a limited license to use the Software under the terms of this License.
|
|
6
|
-
|
|
7
|
-
1. Definitions
|
|
8
|
-
|
|
9
|
-
"Change Date" means the date on which the Change License set out in section 6 will apply to the Software. The Change Date for this release is 2028-09-05.
|
|
10
|
-
|
|
11
|
-
"Change License" means the open source license that will apply to the Software on and after the Change Date. The Change License for this release is the MIT License.
|
|
12
|
-
|
|
13
|
-
"Licensor" means the copyright owner granting rights under this License (Jonathan D Borgia).
|
|
14
|
-
|
|
15
|
-
"You" ("Licensee") means an individual or legal entity exercising rights under this License who has not violated the terms of this License or had their rights terminated.
|
|
16
|
-
|
|
17
|
-
2. License Grant
|
|
18
|
-
|
|
19
|
-
Subject to the terms and conditions of this License, Licensor hereby grants You a non-exclusive, non-transferable, worldwide license to use, reproduce, display, perform, and distribute the Software, and to make modifications and derivative works for internal use, until the Change Date.
|
|
20
|
-
|
|
21
|
-
3. Commercial Use
|
|
22
|
-
|
|
23
|
-
You may use the Software in commercial applications, including for providing services, selling products that include the Software, or otherwise exploiting the Software commercially, subject to the other terms of this License.
|
|
24
|
-
|
|
25
|
-
4. Limitations and Conditions
|
|
26
|
-
|
|
27
|
-
a. You may not remove or alter this License, the copyright notice, or notices of the Change Date.
|
|
28
|
-
|
|
29
|
-
b. You may not publicly offer a modified version of the Software that would directly compete with Licensor's public offering of the Software if doing so would circumvent the intent of this License.
|
|
30
|
-
|
|
31
|
-
c. Except as expressly provided in this License, no rights are granted to You under any patent or trademark of Licensor.
|
|
32
|
-
|
|
33
|
-
5. Disclaimer and Limitation of Liability
|
|
34
|
-
|
|
35
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. TO THE FULLEST EXTENT PERMITTED BY LAW, LICENSOR WILL NOT BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM OR RELATING TO THE SOFTWARE.
|
|
36
|
-
|
|
37
|
-
6. Change License
|
|
38
|
-
|
|
39
|
-
On and after the Change Date specified above, the Software will be licensed under the Change License (MIT License) on the same terms and conditions as set forth by that Change License.
|
|
40
|
-
|
|
41
|
-
7. Governing Law
|
|
42
|
-
|
|
43
|
-
This License will be governed by and construed in accordance with the laws of the State of New York, USA, without regard to conflict of law principles.
|
|
44
|
-
|
|
45
|
-
8. Accepting this License
|
|
46
|
-
|
|
47
|
-
You accept this License by copying, modifying, or distributing the Software or any portion thereof.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
LICENSE NOTE
|
|
52
|
-
|
|
53
|
-
- Original license file replaced on 2025-09-05 to Business Source License 1.1. Change Date: 2028-09-05. Change License: MIT.
|
|
54
|
-
or standard modifications for your own applications.
|