@coaction/history 1.5.0 → 2.0.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 +2 -2
- package/dist/index.d.mts +15 -14
- package/dist/index.d.ts +15 -14
- package/dist/index.js +245 -194
- package/dist/index.mjs +245 -168
- package/package.json +31 -36
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @coaction/history
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|
[](https://www.npmjs.com/package/@coaction/history)
|
|
5
5
|

|
|
6
6
|
|
|
@@ -40,4 +40,4 @@ store.getState().increment();
|
|
|
40
40
|
|
|
41
41
|
## Documentation
|
|
42
42
|
|
|
43
|
-
You can find the documentation [here](https://github.com/
|
|
43
|
+
You can find the documentation [here](https://github.com/coactionjs/coaction).
|
package/dist/index.d.mts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { Middleware } from
|
|
1
|
+
import { Middleware } from "coaction";
|
|
2
2
|
|
|
3
|
+
//#region packages/coaction-history/src/index.d.ts
|
|
3
4
|
type HistoryOptions<T extends object> = {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
limit?: number;
|
|
6
|
+
partialize?: (state: T) => object;
|
|
6
7
|
};
|
|
7
|
-
type HistoryApi<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
type HistoryApi<_T extends object> = {
|
|
9
|
+
undo: () => boolean;
|
|
10
|
+
redo: () => boolean;
|
|
11
|
+
clear: () => void;
|
|
12
|
+
canUndo: () => boolean;
|
|
13
|
+
canRedo: () => boolean;
|
|
14
|
+
getPast: () => object[];
|
|
15
|
+
getFuture: () => object[];
|
|
15
16
|
};
|
|
16
|
-
declare const history: <T extends object>(
|
|
17
|
-
|
|
18
|
-
export {
|
|
17
|
+
declare const history: <T extends object>(options?: HistoryOptions<T>) => Middleware<T>;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HistoryApi, HistoryOptions, history };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import { Middleware } from
|
|
1
|
+
import { Middleware } from "coaction";
|
|
2
2
|
|
|
3
|
+
//#region packages/coaction-history/src/index.d.ts
|
|
3
4
|
type HistoryOptions<T extends object> = {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
limit?: number;
|
|
6
|
+
partialize?: (state: T) => object;
|
|
6
7
|
};
|
|
7
|
-
type HistoryApi<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
type HistoryApi<_T extends object> = {
|
|
9
|
+
undo: () => boolean;
|
|
10
|
+
redo: () => boolean;
|
|
11
|
+
clear: () => void;
|
|
12
|
+
canUndo: () => boolean;
|
|
13
|
+
canRedo: () => boolean;
|
|
14
|
+
getPast: () => object[];
|
|
15
|
+
getFuture: () => object[];
|
|
15
16
|
};
|
|
16
|
-
declare const history: <T extends object>(
|
|
17
|
-
|
|
18
|
-
export {
|
|
17
|
+
declare const history: <T extends object>(options?: HistoryOptions<T>) => Middleware<T>;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HistoryApi, HistoryOptions, history };
|
package/dist/index.js
CHANGED
|
@@ -1,200 +1,251 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let coaction = require("coaction");
|
|
3
|
+
//#region packages/coaction-history/src/index.ts
|
|
4
|
+
const historySuppressionSymbol = Symbol.for("coaction.history.suppress");
|
|
5
|
+
const isUnsafeKey = (key) => typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
|
|
6
|
+
const getOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key) && !isUnsafeKey(key));
|
|
7
|
+
const setOwnEnumerable = (target, key, value) => {
|
|
8
|
+
if (isUnsafeKey(key)) return;
|
|
9
|
+
target[key] = value;
|
|
9
10
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
12
|
+
const toSnapshot = (state, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
13
|
+
if (Array.isArray(state)) {
|
|
14
|
+
if (visited.has(state)) return visited.get(state);
|
|
15
|
+
const next = [];
|
|
16
|
+
next.length = state.length;
|
|
17
|
+
visited.set(state, next);
|
|
18
|
+
const stateRecord = state;
|
|
19
|
+
const nextRecord = next;
|
|
20
|
+
for (const key of getOwnEnumerableKeys(state)) {
|
|
21
|
+
const value = stateRecord[key];
|
|
22
|
+
if (typeof value === "function") continue;
|
|
23
|
+
setOwnEnumerable(nextRecord, key, toSnapshot(value, visited));
|
|
24
|
+
}
|
|
25
|
+
return next;
|
|
26
|
+
}
|
|
27
|
+
if (typeof state === "object" && state !== null) {
|
|
28
|
+
if (!isObjectRecord(state)) return state;
|
|
29
|
+
if (visited.has(state)) return visited.get(state);
|
|
30
|
+
const next = {};
|
|
31
|
+
visited.set(state, next);
|
|
32
|
+
for (const key of getOwnEnumerableKeys(state)) {
|
|
33
|
+
const value = state[key];
|
|
34
|
+
if (typeof value === "function") continue;
|
|
35
|
+
setOwnEnumerable(next, key, toSnapshot(value, visited));
|
|
36
|
+
}
|
|
37
|
+
return next;
|
|
38
|
+
}
|
|
39
|
+
return state;
|
|
17
40
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return visited.get(state);
|
|
43
|
-
}
|
|
44
|
-
const next = {};
|
|
45
|
-
visited.set(state, next);
|
|
46
|
-
for (const key of Object.keys(state)) {
|
|
47
|
-
const value = state[key];
|
|
48
|
-
if (typeof value === "function") {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
next[key] = toSnapshot(value, visited);
|
|
52
|
-
}
|
|
53
|
-
return next;
|
|
54
|
-
}
|
|
55
|
-
return state;
|
|
41
|
+
const isEqual = (a, b, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
42
|
+
if (Object.is(a, b)) return true;
|
|
43
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
44
|
+
const aIsArray = Array.isArray(a);
|
|
45
|
+
const bIsArray = Array.isArray(b);
|
|
46
|
+
if (aIsArray || bIsArray) {
|
|
47
|
+
if (!aIsArray || !bIsArray || a.length !== b.length) return false;
|
|
48
|
+
} else if (!isObjectRecord(a) || !isObjectRecord(b)) return false;
|
|
49
|
+
let seenTargets = visited.get(a);
|
|
50
|
+
if (!seenTargets) {
|
|
51
|
+
seenTargets = /* @__PURE__ */ new WeakSet();
|
|
52
|
+
visited.set(a, seenTargets);
|
|
53
|
+
} else if (seenTargets.has(b)) return true;
|
|
54
|
+
seenTargets.add(b);
|
|
55
|
+
const aObject = a;
|
|
56
|
+
const bObject = b;
|
|
57
|
+
const aKeys = getOwnEnumerableKeys(aObject);
|
|
58
|
+
const bKeys = getOwnEnumerableKeys(bObject);
|
|
59
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
60
|
+
for (const key of aKeys) {
|
|
61
|
+
if (!Object.prototype.hasOwnProperty.call(bObject, key)) return false;
|
|
62
|
+
if (!isEqual(aObject[key], bObject[key], visited)) return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
56
65
|
};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
let seenTargets = visited.get(a);
|
|
76
|
-
if (!seenTargets) {
|
|
77
|
-
seenTargets = /* @__PURE__ */ new WeakSet();
|
|
78
|
-
visited.set(a, seenTargets);
|
|
79
|
-
} else if (seenTargets.has(b)) {
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
seenTargets.add(b);
|
|
83
|
-
const aObject = a;
|
|
84
|
-
const bObject = b;
|
|
85
|
-
const aKeys = Object.keys(aObject);
|
|
86
|
-
const bKeys = Object.keys(bObject);
|
|
87
|
-
if (aKeys.length !== bKeys.length) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
for (const key of aKeys) {
|
|
91
|
-
if (!Object.prototype.hasOwnProperty.call(bObject, key)) {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
if (!isEqual(aObject[key], bObject[key], visited)) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return true;
|
|
66
|
+
const hasCircularReference = (value, ancestors = /* @__PURE__ */ new WeakSet(), seen = /* @__PURE__ */ new WeakSet()) => {
|
|
67
|
+
if (typeof value !== "object" || value === null) return false;
|
|
68
|
+
if (!Array.isArray(value) && !isObjectRecord(value)) return false;
|
|
69
|
+
if (ancestors.has(value)) return true;
|
|
70
|
+
if (seen.has(value)) return false;
|
|
71
|
+
seen.add(value);
|
|
72
|
+
ancestors.add(value);
|
|
73
|
+
for (const key of getOwnEnumerableKeys(value)) {
|
|
74
|
+
const child = value[key];
|
|
75
|
+
if (typeof child !== "function" && hasCircularReference(child, ancestors, seen)) return true;
|
|
76
|
+
}
|
|
77
|
+
ancestors.delete(value);
|
|
78
|
+
return false;
|
|
99
79
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
for (const key of Object.keys(next)) {
|
|
109
|
-
target[key] = toSnapshot(next[key]);
|
|
110
|
-
}
|
|
80
|
+
const applySnapshot = (target, nextState, currentState) => {
|
|
81
|
+
const next = nextState;
|
|
82
|
+
const current = currentState;
|
|
83
|
+
const snapshotVisited = /* @__PURE__ */ new WeakMap();
|
|
84
|
+
snapshotVisited.set(nextState, target);
|
|
85
|
+
if (Array.isArray(target) && Array.isArray(nextState)) target.length = nextState.length;
|
|
86
|
+
for (const key of getOwnEnumerableKeys(current)) if (!Object.prototype.hasOwnProperty.call(next, key)) delete target[key];
|
|
87
|
+
for (const key of getOwnEnumerableKeys(next)) setOwnEnumerable(target, key, toSnapshot(next[key], snapshotVisited));
|
|
111
88
|
};
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
pushPast(previous);
|
|
136
|
-
future.length = 0;
|
|
137
|
-
}
|
|
138
|
-
return result;
|
|
139
|
-
};
|
|
140
|
-
const api = {
|
|
141
|
-
undo: () => {
|
|
142
|
-
const previous = past.pop();
|
|
143
|
-
if (!previous) {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
const current = getSnapshot();
|
|
147
|
-
future.push(current);
|
|
148
|
-
isTimeTraveling = true;
|
|
149
|
-
try {
|
|
150
|
-
baseSetState((draft) => {
|
|
151
|
-
applySnapshot(
|
|
152
|
-
draft,
|
|
153
|
-
previous,
|
|
154
|
-
current
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
} finally {
|
|
158
|
-
isTimeTraveling = false;
|
|
159
|
-
}
|
|
160
|
-
return true;
|
|
161
|
-
},
|
|
162
|
-
redo: () => {
|
|
163
|
-
const next = future.pop();
|
|
164
|
-
if (!next) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
const current = getSnapshot();
|
|
168
|
-
past.push(current);
|
|
169
|
-
isTimeTraveling = true;
|
|
170
|
-
try {
|
|
171
|
-
baseSetState((draft) => {
|
|
172
|
-
applySnapshot(
|
|
173
|
-
draft,
|
|
174
|
-
next,
|
|
175
|
-
current
|
|
176
|
-
);
|
|
177
|
-
});
|
|
178
|
-
} finally {
|
|
179
|
-
isTimeTraveling = false;
|
|
180
|
-
}
|
|
181
|
-
return true;
|
|
182
|
-
},
|
|
183
|
-
clear: () => {
|
|
184
|
-
past.length = 0;
|
|
185
|
-
future.length = 0;
|
|
186
|
-
},
|
|
187
|
-
canUndo: () => past.length > 0,
|
|
188
|
-
canRedo: () => future.length > 0,
|
|
189
|
-
getPast: () => [...past],
|
|
190
|
-
getFuture: () => [...future]
|
|
191
|
-
};
|
|
192
|
-
Object.assign(store, {
|
|
193
|
-
history: api
|
|
194
|
-
});
|
|
195
|
-
return store;
|
|
89
|
+
const isPatchableObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && isObjectRecord(value);
|
|
90
|
+
const applyPartialSnapshot = (target, nextState, currentState, visited = /* @__PURE__ */ new WeakMap(), snapshotVisited = /* @__PURE__ */ new WeakMap()) => {
|
|
91
|
+
if (!snapshotVisited.has(nextState)) snapshotVisited.set(nextState, target);
|
|
92
|
+
let seenCurrentStates = visited.get(nextState);
|
|
93
|
+
if (!seenCurrentStates) {
|
|
94
|
+
seenCurrentStates = /* @__PURE__ */ new WeakSet();
|
|
95
|
+
visited.set(nextState, seenCurrentStates);
|
|
96
|
+
} else if (seenCurrentStates.has(currentState)) return;
|
|
97
|
+
seenCurrentStates.add(currentState);
|
|
98
|
+
const next = nextState;
|
|
99
|
+
const current = currentState;
|
|
100
|
+
if (Array.isArray(target) && Array.isArray(nextState)) target.length = nextState.length;
|
|
101
|
+
for (const key of getOwnEnumerableKeys(current)) if (!Object.prototype.hasOwnProperty.call(next, key)) delete target[key];
|
|
102
|
+
for (const key of getOwnEnumerableKeys(next)) {
|
|
103
|
+
const nextValue = next[key];
|
|
104
|
+
const currentValue = current[key];
|
|
105
|
+
const targetValue = target[key];
|
|
106
|
+
if (isPatchableObject(nextValue) && isPatchableObject(currentValue) && isPatchableObject(targetValue)) {
|
|
107
|
+
applyPartialSnapshot(targetValue, nextValue, currentValue, visited, snapshotVisited);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
setOwnEnumerable(target, key, toSnapshot(nextValue, snapshotVisited));
|
|
111
|
+
}
|
|
196
112
|
};
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
113
|
+
const cloneSnapshotList = (snapshots) => snapshots.map((snapshot) => toSnapshot(snapshot));
|
|
114
|
+
const history = (options = {}) => (store) => {
|
|
115
|
+
if (store.share === "client") throw new Error("history() is not supported in client store mode. Apply history() to the main shared store instead.");
|
|
116
|
+
const { limit = 100, partialize = (state) => state } = options;
|
|
117
|
+
const applyHistorySnapshot = options.partialize ? applyPartialSnapshot : applySnapshot;
|
|
118
|
+
const applyStore = store.apply?.bind(store);
|
|
119
|
+
const past = [];
|
|
120
|
+
const future = [];
|
|
121
|
+
let isTimeTraveling = false;
|
|
122
|
+
let isSetStateRecording = false;
|
|
123
|
+
let suppressionDepth = 0;
|
|
124
|
+
let lastSnapshot;
|
|
125
|
+
let unsubscribeStore;
|
|
126
|
+
const getSnapshot = () => toSnapshot(partialize(store.getPureState()));
|
|
127
|
+
const runWithoutRecording = (callback) => {
|
|
128
|
+
suppressionDepth += 1;
|
|
129
|
+
try {
|
|
130
|
+
return callback();
|
|
131
|
+
} finally {
|
|
132
|
+
suppressionDepth -= 1;
|
|
133
|
+
lastSnapshot = getSnapshot();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const pushPast = (snapshot) => {
|
|
137
|
+
past.push(snapshot);
|
|
138
|
+
if (past.length > limit) past.shift();
|
|
139
|
+
};
|
|
140
|
+
const recordChange = (previous, current) => {
|
|
141
|
+
if (!isEqual(previous, current)) {
|
|
142
|
+
pushPast(previous);
|
|
143
|
+
future.length = 0;
|
|
144
|
+
}
|
|
145
|
+
lastSnapshot = current;
|
|
146
|
+
};
|
|
147
|
+
const applyTimeTravelSnapshot = (snapshot, current) => {
|
|
148
|
+
if (applyStore && hasCircularReference(snapshot)) {
|
|
149
|
+
const nextState = toSnapshot(store.getPureState());
|
|
150
|
+
applyHistorySnapshot(nextState, snapshot, current);
|
|
151
|
+
applyStore(nextState);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
baseSetState((draft) => {
|
|
155
|
+
applyHistorySnapshot(draft, snapshot, current);
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
const cancelReadySubscription = (0, coaction.onStoreReady)(store, () => {
|
|
159
|
+
lastSnapshot = getSnapshot();
|
|
160
|
+
unsubscribeStore = store.subscribe(() => {
|
|
161
|
+
const current = getSnapshot();
|
|
162
|
+
if (isSetStateRecording || isTimeTraveling || suppressionDepth > 0) {
|
|
163
|
+
lastSnapshot = current;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
recordChange(lastSnapshot ?? current, current);
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
const baseSetState = store.setState;
|
|
170
|
+
store.setState = (next, updater) => {
|
|
171
|
+
const previous = getSnapshot();
|
|
172
|
+
isSetStateRecording = true;
|
|
173
|
+
let result;
|
|
174
|
+
try {
|
|
175
|
+
result = baseSetState(next, updater);
|
|
176
|
+
} finally {
|
|
177
|
+
isSetStateRecording = false;
|
|
178
|
+
}
|
|
179
|
+
if (isTimeTraveling || suppressionDepth > 0) {
|
|
180
|
+
lastSnapshot = getSnapshot();
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
recordChange(previous, getSnapshot());
|
|
184
|
+
return result;
|
|
185
|
+
};
|
|
186
|
+
Object.assign(store, { history: {
|
|
187
|
+
undo: () => {
|
|
188
|
+
const previous = past.pop();
|
|
189
|
+
if (!previous) return false;
|
|
190
|
+
const current = getSnapshot();
|
|
191
|
+
future.push(current);
|
|
192
|
+
isTimeTraveling = true;
|
|
193
|
+
try {
|
|
194
|
+
applyTimeTravelSnapshot(previous, current);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
future.pop();
|
|
197
|
+
past.push(previous);
|
|
198
|
+
throw error;
|
|
199
|
+
} finally {
|
|
200
|
+
isTimeTraveling = false;
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
},
|
|
204
|
+
redo: () => {
|
|
205
|
+
const next = future.pop();
|
|
206
|
+
if (!next) return false;
|
|
207
|
+
const current = getSnapshot();
|
|
208
|
+
past.push(current);
|
|
209
|
+
isTimeTraveling = true;
|
|
210
|
+
try {
|
|
211
|
+
applyTimeTravelSnapshot(next, current);
|
|
212
|
+
} catch (error) {
|
|
213
|
+
past.pop();
|
|
214
|
+
future.push(next);
|
|
215
|
+
throw error;
|
|
216
|
+
} finally {
|
|
217
|
+
isTimeTraveling = false;
|
|
218
|
+
}
|
|
219
|
+
return true;
|
|
220
|
+
},
|
|
221
|
+
clear: () => {
|
|
222
|
+
past.length = 0;
|
|
223
|
+
future.length = 0;
|
|
224
|
+
},
|
|
225
|
+
canUndo: () => past.length > 0,
|
|
226
|
+
canRedo: () => future.length > 0,
|
|
227
|
+
getPast: () => cloneSnapshotList(past),
|
|
228
|
+
getFuture: () => cloneSnapshotList(future)
|
|
229
|
+
} });
|
|
230
|
+
Object.defineProperty(store, historySuppressionSymbol, {
|
|
231
|
+
configurable: true,
|
|
232
|
+
value: runWithoutRecording
|
|
233
|
+
});
|
|
234
|
+
if (typeof store.destroy === "function") {
|
|
235
|
+
const baseDestroy = store.destroy;
|
|
236
|
+
let destroyed = false;
|
|
237
|
+
store.destroy = () => {
|
|
238
|
+
if (destroyed) return;
|
|
239
|
+
destroyed = true;
|
|
240
|
+
cancelReadySubscription();
|
|
241
|
+
unsubscribeStore?.();
|
|
242
|
+
unsubscribeStore = void 0;
|
|
243
|
+
const metadataStore = store;
|
|
244
|
+
if (metadataStore[historySuppressionSymbol] === runWithoutRecording) delete metadataStore[historySuppressionSymbol];
|
|
245
|
+
baseDestroy();
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
return store;
|
|
249
|
+
};
|
|
250
|
+
//#endregion
|
|
251
|
+
exports.history = history;
|
package/dist/index.mjs
CHANGED
|
@@ -1,173 +1,250 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
for (const item of state) {
|
|
10
|
-
next.push(toSnapshot(item, visited));
|
|
11
|
-
}
|
|
12
|
-
return next;
|
|
13
|
-
}
|
|
14
|
-
if (typeof state === "object" && state !== null) {
|
|
15
|
-
if (visited.has(state)) {
|
|
16
|
-
return visited.get(state);
|
|
17
|
-
}
|
|
18
|
-
const next = {};
|
|
19
|
-
visited.set(state, next);
|
|
20
|
-
for (const key of Object.keys(state)) {
|
|
21
|
-
const value = state[key];
|
|
22
|
-
if (typeof value === "function") {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
next[key] = toSnapshot(value, visited);
|
|
26
|
-
}
|
|
27
|
-
return next;
|
|
28
|
-
}
|
|
29
|
-
return state;
|
|
1
|
+
import { onStoreReady } from "coaction";
|
|
2
|
+
//#region packages/coaction-history/src/index.ts
|
|
3
|
+
const historySuppressionSymbol = Symbol.for("coaction.history.suppress");
|
|
4
|
+
const isUnsafeKey = (key) => typeof key === "string" && (key === "__proto__" || key === "prototype" || key === "constructor");
|
|
5
|
+
const getOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key) && !isUnsafeKey(key));
|
|
6
|
+
const setOwnEnumerable = (target, key, value) => {
|
|
7
|
+
if (isUnsafeKey(key)) return;
|
|
8
|
+
target[key] = value;
|
|
30
9
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const bKeys = Object.keys(bObject);
|
|
61
|
-
if (aKeys.length !== bKeys.length) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
for (const key of aKeys) {
|
|
65
|
-
if (!Object.prototype.hasOwnProperty.call(bObject, key)) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
if (!isEqual(aObject[key], bObject[key], visited)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
10
|
+
const isObjectRecord = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
11
|
+
const toSnapshot = (state, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
12
|
+
if (Array.isArray(state)) {
|
|
13
|
+
if (visited.has(state)) return visited.get(state);
|
|
14
|
+
const next = [];
|
|
15
|
+
next.length = state.length;
|
|
16
|
+
visited.set(state, next);
|
|
17
|
+
const stateRecord = state;
|
|
18
|
+
const nextRecord = next;
|
|
19
|
+
for (const key of getOwnEnumerableKeys(state)) {
|
|
20
|
+
const value = stateRecord[key];
|
|
21
|
+
if (typeof value === "function") continue;
|
|
22
|
+
setOwnEnumerable(nextRecord, key, toSnapshot(value, visited));
|
|
23
|
+
}
|
|
24
|
+
return next;
|
|
25
|
+
}
|
|
26
|
+
if (typeof state === "object" && state !== null) {
|
|
27
|
+
if (!isObjectRecord(state)) return state;
|
|
28
|
+
if (visited.has(state)) return visited.get(state);
|
|
29
|
+
const next = {};
|
|
30
|
+
visited.set(state, next);
|
|
31
|
+
for (const key of getOwnEnumerableKeys(state)) {
|
|
32
|
+
const value = state[key];
|
|
33
|
+
if (typeof value === "function") continue;
|
|
34
|
+
setOwnEnumerable(next, key, toSnapshot(value, visited));
|
|
35
|
+
}
|
|
36
|
+
return next;
|
|
37
|
+
}
|
|
38
|
+
return state;
|
|
73
39
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
40
|
+
const isEqual = (a, b, visited = /* @__PURE__ */ new WeakMap()) => {
|
|
41
|
+
if (Object.is(a, b)) return true;
|
|
42
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
43
|
+
const aIsArray = Array.isArray(a);
|
|
44
|
+
const bIsArray = Array.isArray(b);
|
|
45
|
+
if (aIsArray || bIsArray) {
|
|
46
|
+
if (!aIsArray || !bIsArray || a.length !== b.length) return false;
|
|
47
|
+
} else if (!isObjectRecord(a) || !isObjectRecord(b)) return false;
|
|
48
|
+
let seenTargets = visited.get(a);
|
|
49
|
+
if (!seenTargets) {
|
|
50
|
+
seenTargets = /* @__PURE__ */ new WeakSet();
|
|
51
|
+
visited.set(a, seenTargets);
|
|
52
|
+
} else if (seenTargets.has(b)) return true;
|
|
53
|
+
seenTargets.add(b);
|
|
54
|
+
const aObject = a;
|
|
55
|
+
const bObject = b;
|
|
56
|
+
const aKeys = getOwnEnumerableKeys(aObject);
|
|
57
|
+
const bKeys = getOwnEnumerableKeys(bObject);
|
|
58
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
59
|
+
for (const key of aKeys) {
|
|
60
|
+
if (!Object.prototype.hasOwnProperty.call(bObject, key)) return false;
|
|
61
|
+
if (!isEqual(aObject[key], bObject[key], visited)) return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
85
64
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
};
|
|
100
|
-
const baseSetState = store.setState;
|
|
101
|
-
store.setState = (next, updater) => {
|
|
102
|
-
const previous = getSnapshot();
|
|
103
|
-
const result = baseSetState(next, updater);
|
|
104
|
-
if (isTimeTraveling) {
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
const current = getSnapshot();
|
|
108
|
-
if (!isEqual(previous, current)) {
|
|
109
|
-
pushPast(previous);
|
|
110
|
-
future.length = 0;
|
|
111
|
-
}
|
|
112
|
-
return result;
|
|
113
|
-
};
|
|
114
|
-
const api = {
|
|
115
|
-
undo: () => {
|
|
116
|
-
const previous = past.pop();
|
|
117
|
-
if (!previous) {
|
|
118
|
-
return false;
|
|
119
|
-
}
|
|
120
|
-
const current = getSnapshot();
|
|
121
|
-
future.push(current);
|
|
122
|
-
isTimeTraveling = true;
|
|
123
|
-
try {
|
|
124
|
-
baseSetState((draft) => {
|
|
125
|
-
applySnapshot(
|
|
126
|
-
draft,
|
|
127
|
-
previous,
|
|
128
|
-
current
|
|
129
|
-
);
|
|
130
|
-
});
|
|
131
|
-
} finally {
|
|
132
|
-
isTimeTraveling = false;
|
|
133
|
-
}
|
|
134
|
-
return true;
|
|
135
|
-
},
|
|
136
|
-
redo: () => {
|
|
137
|
-
const next = future.pop();
|
|
138
|
-
if (!next) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
const current = getSnapshot();
|
|
142
|
-
past.push(current);
|
|
143
|
-
isTimeTraveling = true;
|
|
144
|
-
try {
|
|
145
|
-
baseSetState((draft) => {
|
|
146
|
-
applySnapshot(
|
|
147
|
-
draft,
|
|
148
|
-
next,
|
|
149
|
-
current
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
} finally {
|
|
153
|
-
isTimeTraveling = false;
|
|
154
|
-
}
|
|
155
|
-
return true;
|
|
156
|
-
},
|
|
157
|
-
clear: () => {
|
|
158
|
-
past.length = 0;
|
|
159
|
-
future.length = 0;
|
|
160
|
-
},
|
|
161
|
-
canUndo: () => past.length > 0,
|
|
162
|
-
canRedo: () => future.length > 0,
|
|
163
|
-
getPast: () => [...past],
|
|
164
|
-
getFuture: () => [...future]
|
|
165
|
-
};
|
|
166
|
-
Object.assign(store, {
|
|
167
|
-
history: api
|
|
168
|
-
});
|
|
169
|
-
return store;
|
|
65
|
+
const hasCircularReference = (value, ancestors = /* @__PURE__ */ new WeakSet(), seen = /* @__PURE__ */ new WeakSet()) => {
|
|
66
|
+
if (typeof value !== "object" || value === null) return false;
|
|
67
|
+
if (!Array.isArray(value) && !isObjectRecord(value)) return false;
|
|
68
|
+
if (ancestors.has(value)) return true;
|
|
69
|
+
if (seen.has(value)) return false;
|
|
70
|
+
seen.add(value);
|
|
71
|
+
ancestors.add(value);
|
|
72
|
+
for (const key of getOwnEnumerableKeys(value)) {
|
|
73
|
+
const child = value[key];
|
|
74
|
+
if (typeof child !== "function" && hasCircularReference(child, ancestors, seen)) return true;
|
|
75
|
+
}
|
|
76
|
+
ancestors.delete(value);
|
|
77
|
+
return false;
|
|
170
78
|
};
|
|
171
|
-
|
|
172
|
-
|
|
79
|
+
const applySnapshot = (target, nextState, currentState) => {
|
|
80
|
+
const next = nextState;
|
|
81
|
+
const current = currentState;
|
|
82
|
+
const snapshotVisited = /* @__PURE__ */ new WeakMap();
|
|
83
|
+
snapshotVisited.set(nextState, target);
|
|
84
|
+
if (Array.isArray(target) && Array.isArray(nextState)) target.length = nextState.length;
|
|
85
|
+
for (const key of getOwnEnumerableKeys(current)) if (!Object.prototype.hasOwnProperty.call(next, key)) delete target[key];
|
|
86
|
+
for (const key of getOwnEnumerableKeys(next)) setOwnEnumerable(target, key, toSnapshot(next[key], snapshotVisited));
|
|
173
87
|
};
|
|
88
|
+
const isPatchableObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && isObjectRecord(value);
|
|
89
|
+
const applyPartialSnapshot = (target, nextState, currentState, visited = /* @__PURE__ */ new WeakMap(), snapshotVisited = /* @__PURE__ */ new WeakMap()) => {
|
|
90
|
+
if (!snapshotVisited.has(nextState)) snapshotVisited.set(nextState, target);
|
|
91
|
+
let seenCurrentStates = visited.get(nextState);
|
|
92
|
+
if (!seenCurrentStates) {
|
|
93
|
+
seenCurrentStates = /* @__PURE__ */ new WeakSet();
|
|
94
|
+
visited.set(nextState, seenCurrentStates);
|
|
95
|
+
} else if (seenCurrentStates.has(currentState)) return;
|
|
96
|
+
seenCurrentStates.add(currentState);
|
|
97
|
+
const next = nextState;
|
|
98
|
+
const current = currentState;
|
|
99
|
+
if (Array.isArray(target) && Array.isArray(nextState)) target.length = nextState.length;
|
|
100
|
+
for (const key of getOwnEnumerableKeys(current)) if (!Object.prototype.hasOwnProperty.call(next, key)) delete target[key];
|
|
101
|
+
for (const key of getOwnEnumerableKeys(next)) {
|
|
102
|
+
const nextValue = next[key];
|
|
103
|
+
const currentValue = current[key];
|
|
104
|
+
const targetValue = target[key];
|
|
105
|
+
if (isPatchableObject(nextValue) && isPatchableObject(currentValue) && isPatchableObject(targetValue)) {
|
|
106
|
+
applyPartialSnapshot(targetValue, nextValue, currentValue, visited, snapshotVisited);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
setOwnEnumerable(target, key, toSnapshot(nextValue, snapshotVisited));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
const cloneSnapshotList = (snapshots) => snapshots.map((snapshot) => toSnapshot(snapshot));
|
|
113
|
+
const history = (options = {}) => (store) => {
|
|
114
|
+
if (store.share === "client") throw new Error("history() is not supported in client store mode. Apply history() to the main shared store instead.");
|
|
115
|
+
const { limit = 100, partialize = (state) => state } = options;
|
|
116
|
+
const applyHistorySnapshot = options.partialize ? applyPartialSnapshot : applySnapshot;
|
|
117
|
+
const applyStore = store.apply?.bind(store);
|
|
118
|
+
const past = [];
|
|
119
|
+
const future = [];
|
|
120
|
+
let isTimeTraveling = false;
|
|
121
|
+
let isSetStateRecording = false;
|
|
122
|
+
let suppressionDepth = 0;
|
|
123
|
+
let lastSnapshot;
|
|
124
|
+
let unsubscribeStore;
|
|
125
|
+
const getSnapshot = () => toSnapshot(partialize(store.getPureState()));
|
|
126
|
+
const runWithoutRecording = (callback) => {
|
|
127
|
+
suppressionDepth += 1;
|
|
128
|
+
try {
|
|
129
|
+
return callback();
|
|
130
|
+
} finally {
|
|
131
|
+
suppressionDepth -= 1;
|
|
132
|
+
lastSnapshot = getSnapshot();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const pushPast = (snapshot) => {
|
|
136
|
+
past.push(snapshot);
|
|
137
|
+
if (past.length > limit) past.shift();
|
|
138
|
+
};
|
|
139
|
+
const recordChange = (previous, current) => {
|
|
140
|
+
if (!isEqual(previous, current)) {
|
|
141
|
+
pushPast(previous);
|
|
142
|
+
future.length = 0;
|
|
143
|
+
}
|
|
144
|
+
lastSnapshot = current;
|
|
145
|
+
};
|
|
146
|
+
const applyTimeTravelSnapshot = (snapshot, current) => {
|
|
147
|
+
if (applyStore && hasCircularReference(snapshot)) {
|
|
148
|
+
const nextState = toSnapshot(store.getPureState());
|
|
149
|
+
applyHistorySnapshot(nextState, snapshot, current);
|
|
150
|
+
applyStore(nextState);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
baseSetState((draft) => {
|
|
154
|
+
applyHistorySnapshot(draft, snapshot, current);
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
const cancelReadySubscription = onStoreReady(store, () => {
|
|
158
|
+
lastSnapshot = getSnapshot();
|
|
159
|
+
unsubscribeStore = store.subscribe(() => {
|
|
160
|
+
const current = getSnapshot();
|
|
161
|
+
if (isSetStateRecording || isTimeTraveling || suppressionDepth > 0) {
|
|
162
|
+
lastSnapshot = current;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
recordChange(lastSnapshot ?? current, current);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
const baseSetState = store.setState;
|
|
169
|
+
store.setState = (next, updater) => {
|
|
170
|
+
const previous = getSnapshot();
|
|
171
|
+
isSetStateRecording = true;
|
|
172
|
+
let result;
|
|
173
|
+
try {
|
|
174
|
+
result = baseSetState(next, updater);
|
|
175
|
+
} finally {
|
|
176
|
+
isSetStateRecording = false;
|
|
177
|
+
}
|
|
178
|
+
if (isTimeTraveling || suppressionDepth > 0) {
|
|
179
|
+
lastSnapshot = getSnapshot();
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
recordChange(previous, getSnapshot());
|
|
183
|
+
return result;
|
|
184
|
+
};
|
|
185
|
+
Object.assign(store, { history: {
|
|
186
|
+
undo: () => {
|
|
187
|
+
const previous = past.pop();
|
|
188
|
+
if (!previous) return false;
|
|
189
|
+
const current = getSnapshot();
|
|
190
|
+
future.push(current);
|
|
191
|
+
isTimeTraveling = true;
|
|
192
|
+
try {
|
|
193
|
+
applyTimeTravelSnapshot(previous, current);
|
|
194
|
+
} catch (error) {
|
|
195
|
+
future.pop();
|
|
196
|
+
past.push(previous);
|
|
197
|
+
throw error;
|
|
198
|
+
} finally {
|
|
199
|
+
isTimeTraveling = false;
|
|
200
|
+
}
|
|
201
|
+
return true;
|
|
202
|
+
},
|
|
203
|
+
redo: () => {
|
|
204
|
+
const next = future.pop();
|
|
205
|
+
if (!next) return false;
|
|
206
|
+
const current = getSnapshot();
|
|
207
|
+
past.push(current);
|
|
208
|
+
isTimeTraveling = true;
|
|
209
|
+
try {
|
|
210
|
+
applyTimeTravelSnapshot(next, current);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
past.pop();
|
|
213
|
+
future.push(next);
|
|
214
|
+
throw error;
|
|
215
|
+
} finally {
|
|
216
|
+
isTimeTraveling = false;
|
|
217
|
+
}
|
|
218
|
+
return true;
|
|
219
|
+
},
|
|
220
|
+
clear: () => {
|
|
221
|
+
past.length = 0;
|
|
222
|
+
future.length = 0;
|
|
223
|
+
},
|
|
224
|
+
canUndo: () => past.length > 0,
|
|
225
|
+
canRedo: () => future.length > 0,
|
|
226
|
+
getPast: () => cloneSnapshotList(past),
|
|
227
|
+
getFuture: () => cloneSnapshotList(future)
|
|
228
|
+
} });
|
|
229
|
+
Object.defineProperty(store, historySuppressionSymbol, {
|
|
230
|
+
configurable: true,
|
|
231
|
+
value: runWithoutRecording
|
|
232
|
+
});
|
|
233
|
+
if (typeof store.destroy === "function") {
|
|
234
|
+
const baseDestroy = store.destroy;
|
|
235
|
+
let destroyed = false;
|
|
236
|
+
store.destroy = () => {
|
|
237
|
+
if (destroyed) return;
|
|
238
|
+
destroyed = true;
|
|
239
|
+
cancelReadySubscription();
|
|
240
|
+
unsubscribeStore?.();
|
|
241
|
+
unsubscribeStore = void 0;
|
|
242
|
+
const metadataStore = store;
|
|
243
|
+
if (metadataStore[historySuppressionSymbol] === runWithoutRecording) delete metadataStore[historySuppressionSymbol];
|
|
244
|
+
baseDestroy();
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
return store;
|
|
248
|
+
};
|
|
249
|
+
//#endregion
|
|
250
|
+
export { history };
|
package/package.json
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coaction/history",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A undo/redo middleware for Coaction",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"state",
|
|
7
6
|
"coaction",
|
|
8
|
-
"middleware",
|
|
9
7
|
"history",
|
|
10
|
-
"
|
|
11
|
-
"redo"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"Michael Lin <unadlib@gmail.com> (https://github.com/unadlib)"
|
|
8
|
+
"middleware",
|
|
9
|
+
"redo",
|
|
10
|
+
"state",
|
|
11
|
+
"undo"
|
|
15
12
|
],
|
|
16
|
-
"homepage": "https://github.com/
|
|
13
|
+
"homepage": "https://github.com/coactionjs/coaction/tree/main/packages/coaction-history#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/coactionjs/coaction/issues"
|
|
16
|
+
},
|
|
17
17
|
"license": "MIT",
|
|
18
|
+
"author": "unadlib",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/coactionjs/coaction.git",
|
|
22
|
+
"directory": "packages/coaction-history"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"sideEffects": false,
|
|
18
28
|
"main": "dist/index.js",
|
|
19
29
|
"module": "dist/index.mjs",
|
|
30
|
+
"types": "dist/index.d.ts",
|
|
20
31
|
"exports": {
|
|
21
32
|
".": {
|
|
22
33
|
"types": "./dist/index.d.ts",
|
|
@@ -26,39 +37,23 @@
|
|
|
26
37
|
},
|
|
27
38
|
"./package.json": "./package.json"
|
|
28
39
|
},
|
|
29
|
-
"types": "dist/index.d.ts",
|
|
30
|
-
"sideEffects": false,
|
|
31
|
-
"files": [
|
|
32
|
-
"dist"
|
|
33
|
-
],
|
|
34
|
-
"repository": {
|
|
35
|
-
"type": "git",
|
|
36
|
-
"url": "https://github.com/unadlib/coaction.git",
|
|
37
|
-
"directory": "packages/coaction-history"
|
|
38
|
-
},
|
|
39
|
-
"bugs": {
|
|
40
|
-
"url": "https://github.com/unadlib/coaction/issues"
|
|
41
|
-
},
|
|
42
|
-
"peerDependencies": {
|
|
43
|
-
"coaction": "^1.5.0"
|
|
44
|
-
},
|
|
45
|
-
"peerDependenciesMeta": {
|
|
46
|
-
"coaction": {
|
|
47
|
-
"optional": true
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
"devDependencies": {
|
|
51
|
-
"coaction": "1.5.0"
|
|
52
|
-
},
|
|
53
40
|
"publishConfig": {
|
|
54
41
|
"access": "public",
|
|
55
42
|
"provenance": true
|
|
56
43
|
},
|
|
57
|
-
"
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"coaction": "2.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"coaction": "^2.0.0"
|
|
49
|
+
},
|
|
50
|
+
"authors": [
|
|
51
|
+
"Michael Lin <unadlib@gmail.com> (https://github.com/unadlib)"
|
|
52
|
+
],
|
|
58
53
|
"scripts": {
|
|
59
54
|
"clean": "rm -rf dist",
|
|
60
55
|
"test": "vitest run test",
|
|
61
|
-
"build": "
|
|
62
|
-
"dev": "
|
|
56
|
+
"build": "node ../../scripts/build-package.mjs",
|
|
57
|
+
"dev": "node ../../scripts/build-package.mjs --watch"
|
|
63
58
|
}
|
|
64
59
|
}
|