@signal-tree/angular 15.1.1 → 15.1.2

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
@@ -81,3 +81,29 @@ const profileModel = toWritableSignal(tree.$.profile, injector, {
81
81
  Application components
82
82
  should normally receive a read-only `$` plus explicit operation services for
83
83
  writes and asynchronous work.
84
+
85
+ ## Initial values and external reactivity
86
+
87
+ Pass initial values to `signalTree()`, not existing Angular signals. Direct
88
+ signals (including readonly and computed signals) at the root or a nested branch
89
+ are rejected with a path-specific error, and known signal types are rejected by
90
+ TypeScript. SignalTree creates its own native signals so it owns their writes.
91
+
92
+ ```ts
93
+ import { signal, untracked } from '@angular/core';
94
+ import { leaf, signalTree } from '@signal-tree/angular';
95
+
96
+ const existing = signal(1);
97
+ const tree = signalTree({ count: leaf(untracked(existing)) });
98
+ ```
99
+
100
+ This takes an independent snapshot; later writes to `existing` do not update
101
+ `tree`. For an object snapshot, copy the value too if you need independent object
102
+ identity. `leaf(existing)` explicitly stores the signal itself as data. Reading
103
+ that leaf returns the original signal; its inner writes remain outside tree
104
+ transactions and restoration.
105
+
106
+ Validation stops at explicit `leaf(...)`, marker definitions, arrays and built-in
107
+ terminal values. Their contents remain data, not separately owned tree locations.
108
+ Ordinary functions remain valid callable data. These checks apply to initial
109
+ construction, not arbitrary later writes or foreign reactivity from other libraries.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{ANGULAR_OBSERVATION_ADAPTER}from"./lib/observation-adapter.js";import{createSignalTreeFactory}from"@signal-tree/kernel/adapter";import{asReadonly as asReadonly$1}from"@signal-tree/kernel";export*from"@signal-tree/kernel";import{defineStore}from"./lib/define-store.js";import{toWritableSignal}from"./lib/to-writable-signal.js";const signalTree=createSignalTreeFactory(ANGULAR_OBSERVATION_ADAPTER);const asReadonly=asReadonly$1;export{asReadonly,defineStore,signalTree,toWritableSignal};
1
+ import{ANGULAR_OBSERVATION_ADAPTER}from"./lib/observation-adapter.js";import{createSignalTreeFactory}from"@signal-tree/kernel/adapter";import{asReadonly as asReadonly$1}from"@signal-tree/kernel";export*from"@signal-tree/kernel";import{prepareConstructionInput}from"./lib/construction-input.js";import{defineStore}from"./lib/define-store.js";import{toWritableSignal}from"./lib/to-writable-signal.js";const createAngularTree=createSignalTreeFactory(ANGULAR_OBSERVATION_ADAPTER);const signalTree=(initialState,config)=>createAngularTree(prepareConstructionInput(initialState),config);const asReadonly=asReadonly$1;export{asReadonly,defineStore,signalTree,toWritableSignal};
@@ -0,0 +1 @@
1
+ import{isSignal}from"@angular/core";import{isConstructionBranch}from"@signal-tree/kernel/adapter";function prepareConstructionInput(initialState){const branches=new WeakMap;const visit=(value,path)=>{if(isSignal(value)){throw new TypeError(`SignalTree: Angular signal at ${path}. Pass an initial value or leaf(untracked(existing)) for an independent snapshot. Use leaf(existing) only to store the signal as data; its writes remain external to the tree.`)}if(!isConstructionBranch(value))return value;const previous=branches.get(value);if(previous)return previous;const prepared=Object.create(null);branches.set(value,prepared);for(const key of Object.getOwnPropertySymbols(value)){const descriptor=Object.getOwnPropertyDescriptor(value,key);if(descriptor)Object.defineProperty(prepared,key,descriptor)}for(const[key,child]of Object.entries(value)){prepared[key]=key==="__proto__"?child:visit(child,`${path}[${JSON.stringify(key)}]`)}return prepared};return visit(initialState,"$")}export{prepareConstructionInput};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signal-tree/angular",
3
- "version": "15.1.1",
3
+ "version": "15.1.2",
4
4
  "description": "Angular realization for SignalTree.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  "llms.txt"
26
26
  ],
27
27
  "dependencies": {
28
- "@signal-tree/kernel": "15.1.1"
28
+ "@signal-tree/kernel": "15.1.2"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@angular/core": "^20.0.0 || ^21.0.0 || ^22.0.0",
package/src/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  /** Angular observation plus the complete SignalTree application surface. */
2
2
  import './lib/carrier.js';
3
- import type { AccessibleNodeOf, EntityNodeOf, EntitySignalOf, EntitySignalWithSlicesOf, ISignalTreeOf, LeafOf, ReadonlyStoreOf, ReadonlyViewOf, SignalTreeFactoryOf, TreeNodeOf } from '@signal-tree/kernel/adapter';
4
- export declare const signalTree: SignalTreeFactoryOf<"angular">;
3
+ import type { AccessibleNodeOf, EntityNodeOf, EntitySignalOf, EntitySignalWithSlicesOf, ISignalTreeOf, LeafOf, ReadonlyStoreOf, ReadonlyViewOf, TreeNodeOf } from '@signal-tree/kernel/adapter';
4
+ import { type FrameworkSignalTreeFactory } from './lib/construction-input.js';
5
+ /** Construct native Angular leaves from values; external signals require leaf(). */
6
+ export declare const signalTree: FrameworkSignalTreeFactory;
5
7
  export type TreeNode<T> = TreeNodeOf<T, 'angular'>;
6
8
  export type WritableLeaf<T> = LeafOf<T, 'angular'>;
7
9
  export type AccessibleNode<T> = AccessibleNodeOf<T, 'angular'>;
@@ -0,0 +1,9 @@
1
+ import { type Signal } from '@angular/core';
2
+ import type { SignalTreeFactoryOf } from '@signal-tree/kernel/adapter';
3
+ export type FrameworkSignalTreeFactory = SignalTreeFactoryOf<'angular', Signal<unknown>>;
4
+ /**
5
+ * Read each branch property once, so accessor-backed definitions cannot change
6
+ * between validation and construction. Terminal data retains its identity.
7
+ * No reactive primitive is read, subscribed to, or adopted here.
8
+ */
9
+ export declare function prepareConstructionInput(initialState: object): object;