1
- type Fn = ( ...args : any [ ] ) => any ;
2
- type Constants = typeof constants ;
3
- type TagKeys = { [ K in keyof Constants ] : K extends `${ string } _TAG` ? K : never } [ keyof Constants ] ;
4
- type TagNameMap = { [ K in TagKeys ] : K extends `${ infer P } _TAG` ? P : never }
5
- type TagType = { [ K in TagKeys as TagNameMap [ K ] ] : Constants [ K ] } ;
1
+ import type { Closable , TagType } from './main' ;
6
2
7
- import type { Value } from './types' ;
3
+ import {
4
+ CLEAR_TAG ,
5
+ DELETE_TAG ,
6
+ GLOBAL_SELECTOR ,
7
+ MOVE_TAG ,
8
+ NULL_SELECTOR ,
9
+ PUSH_TAG ,
10
+ REPLACE_TAG ,
11
+ SET_TAG ,
12
+ SPLICE_TAG
13
+ } from './constants' ;
8
14
9
- import * as _constants from './constants ' ;
15
+ import { Immutable , Tag } from './main ' ;
10
16
11
- import { clonedeep } from './utils' ;
17
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/clear-usage } */
18
+ export type ClearTag = typeof CLEAR_TAG ;
12
19
13
- import AccessorCache from './model/accessor-cache' ;
20
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/delete-usage } */
21
+ export type DeleteTag = typeof DELETE_TAG ;
14
22
15
- import { Connection } from './connection' ;
23
+ export type GlobalSelector = typeof GLOBAL_SELECTOR ;
16
24
17
- export const constants = _constants ;
25
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/move-usage } */
26
+ export type MoveTag = typeof MOVE_TAG ;
18
27
19
- export const Tag = { } as Readonly < TagType > ;
20
- for ( let k in constants ) {
21
- if ( ! k . endsWith ( '-TAG' ) ) { continue }
22
- // istanbul ignore next
23
- Tag [ k . slice ( 0 , - 4 ) ] = constants [ k ] ;
28
+ export type NullSelector = typeof NULL_SELECTOR ;
29
+
30
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/push-usage } */
31
+ export type PushTag = typeof PUSH_TAG ;
32
+
33
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/replace-usage } */
34
+ export type ReplaceTag = typeof REPLACE_TAG ;
35
+
36
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/set-usage } */
37
+ export type SetTag = typeof SET_TAG ;
38
+
39
+ /** @see {@link https://auto-immutable.js.org/api/set/method/tags/splice-usage } */
40
+ export type SpliceTag = typeof SPLICE_TAG ;
41
+
42
+ export type KeyType = number | string | symbol ;
43
+
44
+ export type ScalarType = boolean | KeyType ;
45
+
46
+ export type Cloneable < T extends object > = T & {
47
+ clone ?: ( ...args : Array < any > ) => T ;
48
+ cloneNode ?: ( deep : true , ...args : Array < any > ) => T ;
24
49
} ;
25
- Object . freeze ( Tag ) ;
26
50
27
- export const deps = {
28
- assignCache : < T extends Value > ( initValue : T ) => new AccessorCache ( clonedeep ( initValue ) ) ,
29
- numCreated : 0
51
+ export type ValueObject = { [ x : KeyType ] : BaseType | Function } ;
52
+ export type ValueObjectCloneable = Cloneable < ValueObject > ;
53
+ export type Value = ValueObject | ValueObjectCloneable ;
54
+
55
+ export interface UpdateStats { hasChanges : boolean } ;
56
+
57
+ export type BaseType = Array < any > | ScalarType | Value | { } | object ;
58
+
59
+ /** As in {"@@CLEAR":* } is a parameterless command. Parameters have not effect */
60
+ export type ClearCommand = { [ CLEAR_TAG ] : any } ;
61
+
62
+ /** As in {"@@DELETE": [property keys to delete] } */
63
+ export type DeleteCommand < T > = { [ DELETE_TAG ] : Array < keyof T > }
64
+
65
+ /** As in {"@@MOVE": [-/+fromIndex, -/+toIndex, +numItems? ] }. numItems = 1 by default. */
66
+ export type MoveCommand = { [ MOVE_TAG ] : [ number , number , number ?] }
67
+
68
+ /** As in {"@@PUSH": [new items] } */
69
+ export type PushCommand = { [ PUSH_TAG ] : Array < any > }
70
+
71
+ /** As in {"@@REPLACE": Replacement value } */
72
+ export type ReplaceCommand = { [ REPLACE_TAG ] : BaseType }
73
+
74
+ /** As in {"@@SET": Replacement value } */
75
+ export type SetCommand = { [ SET_TAG ] : BaseType | ( < V > ( currentValue : V ) => any ) }
76
+
77
+ /** As in {"@@SPLICE": [-/+fromIndex, +deleteCount <n >= 0>, ...newItems? ] }. numItems = undefined by default. */
78
+ export type SpliceCommand = { [ SPLICE_TAG ] : [ number , number , ...Array < any > ] }
79
+
80
+ export type TagCommand < T extends TagType , P extends Value | Array < any > = Value > =
81
+ T extends ClearTag ? ClearCommand :
82
+ T extends DeleteTag ? DeleteCommand < P > :
83
+ T extends MoveTag ? MoveCommand :
84
+ T extends PushTag ? PushCommand :
85
+ T extends ReplaceTag ? ReplaceCommand :
86
+ T extends SetTag ? SetCommand :
87
+ T extends SpliceTag ? SpliceCommand : never ;
88
+
89
+ export interface AccessorPayload { [ propertyPath : string ] : Atom } ;
90
+
91
+ export interface AccessorResponse { [ propertyPath : string ] : Atom [ "value" ] } ; // [Readonly<any> };
92
+
93
+ export type Changes < T extends Value > = UpdatePayload < T > | UpdatePayloadArray < T > ;
94
+
95
+ export type Listener = < T extends Value > ( changes : Changes < T > ) => void ;
96
+
97
+ export type UpdatePayloadCore < T extends Array < any > | Value > =
98
+ | ClearTag
99
+ | TagCommand < TagType , T >
100
+ | Value
101
+ | T extends { }
102
+ ? T | Partial < {
103
+ [ K in keyof T ] : T [ K ] extends Array < any > | Value
104
+ ? UpdatePayload < T [ K ] >
105
+ : UpdatePayload < Value >
106
+ } >
107
+ : T ;
108
+ export type UpdatePayloadCoreCloneable < T extends Array < any > | Value > = Cloneable < UpdatePayloadCore < T > >
109
+ export type UpdatePayload < T extends Array < any > | Value > = UpdatePayloadCore < T > | UpdatePayloadCoreCloneable < T > ;
110
+
111
+ export type UpdatePayloadArrayCore < T extends Array < any > | Value > = Array < UpdatePayload < T > > ;
112
+ export type UpdatePayloadArrayCoreCloneable < T extends Array < any > | Value > = Cloneable < UpdatePayloadArrayCore < T > > ;
113
+ export type UpdatePayloadArray < T extends Array < any > | Value > = UpdatePayloadArrayCore < T > | UpdatePayloadArrayCoreCloneable < T > ;
114
+
115
+ import type Atom from './model/atom' ;
116
+
117
+ export type { Connection } from './connection' ;
118
+
119
+ export type { Closable , TagType } ;
120
+
121
+ export { Immutable , Tag } ;
122
+
123
+ export {
124
+ CLEAR_TAG ,
125
+ DELETE_TAG ,
126
+ GLOBAL_SELECTOR ,
127
+ MOVE_TAG ,
128
+ NULL_SELECTOR ,
129
+ PUSH_TAG ,
130
+ REPLACE_TAG ,
131
+ SET_TAG ,
132
+ SPLICE_TAG
30
133
} ;
31
134
32
- export class Closable {
33
-
34
- #closed = false ;
35
- #listeners = new Set < Fn > ( ) ;
36
-
37
- get closed ( ) { return this . #closed }
38
-
39
- @invoke
40
- close ( ) {
41
- this . #listeners. forEach ( f => f ( ) )
42
- this . #closed = true ;
43
- }
44
-
45
- @invoke
46
- onClose ( fn : Fn ) {
47
- const _fn = ( ) => {
48
- fn ( ) ;
49
- this . #offClose( _fn ) ;
50
- }
51
- this . #listeners. add ( _fn ) ;
52
- return ( ) => this . #offClose( _fn ) ;
53
- }
54
-
55
- @invoke
56
- #offClose( fn : Fn ) { this . #listeners. delete ( fn ) }
57
-
58
- }
59
-
60
- export class Immutable < T extends Value = Value > extends Closable {
61
-
62
- static #cacheMap = new WeakMap < Immutable < Value > , AccessorCache < Value > > ( ) ;
63
-
64
- #numConnectionsCreated = 0 ;
65
-
66
- constructor ( initValue : T ) {
67
- super ( ) ;
68
- Immutable . #cacheMap. set ( this , deps . assignCache ( initValue ) ) ;
69
- deps . numCreated ++ ;
70
- }
71
-
72
- close ( ) {
73
- super . close ( ) ;
74
- Immutable . #cacheMap. delete ( this ) ;
75
- }
76
-
77
- @invoke
78
- connect ( ) {
79
- return new Connection (
80
- `${ deps . numCreated } :${ ++ this . #numConnectionsCreated } ` , {
81
- key : this ,
82
- map : Immutable . #cacheMap
83
- }
84
- ) ;
85
- }
86
- }
87
-
88
- function invoke < C > ( method : Function , context : C ) {
89
- return function (
90
- this : Closable ,
91
- ...args : Array < any >
92
- ) {
93
- if ( this . closed ) { return }
94
- return method . apply ( this , args ) } ;
95
- }
135
+ export default Immutable ;
0 commit comments