react-deepwatch 1.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/LICENSE +21 -0
- package/Util.d.ts +66 -0
- package/Util.d.ts.map +1 -0
- package/Util.js +178 -0
- package/Util.js.map +1 -0
- package/Util.ts +190 -0
- package/dist/mjs/Util.d.ts +66 -0
- package/dist/mjs/Util.d.ts.map +1 -0
- package/dist/mjs/Util.js +164 -0
- package/dist/mjs/Util.js.map +1 -0
- package/dist/mjs/index.d.ts +218 -0
- package/dist/mjs/index.d.ts.map +1 -0
- package/dist/mjs/index.js +821 -0
- package/dist/mjs/index.js.map +1 -0
- package/dist/mjs/preserve.d.ts +72 -0
- package/dist/mjs/preserve.d.ts.map +1 -0
- package/dist/mjs/preserve.js +374 -0
- package/dist/mjs/preserve.js.map +1 -0
- package/index.d.ts +218 -0
- package/index.d.ts.map +1 -0
- package/index.js +830 -0
- package/index.js.map +1 -0
- package/index.ts +1237 -0
- package/index_esm.mjs +6 -0
- package/mechanics.md +47 -0
- package/package.json +59 -0
- package/preserve.d.ts +72 -0
- package/preserve.d.ts.map +1 -0
- package/preserve.js +385 -0
- package/preserve.js.map +1 -0
- package/preserve.ts +492 -0
- package/readme.md +109 -0
package/dist/mjs/Util.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export function throwError(e) {
|
|
2
|
+
if (e !== null && e instanceof Error) {
|
|
3
|
+
throw e;
|
|
4
|
+
}
|
|
5
|
+
throw new Error(e);
|
|
6
|
+
}
|
|
7
|
+
export function reThrowWithHint(e, hint) {
|
|
8
|
+
try {
|
|
9
|
+
if (e instanceof Error) {
|
|
10
|
+
// Add hint to error:
|
|
11
|
+
e.message += `\n${hint}`;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch (x) {
|
|
15
|
+
}
|
|
16
|
+
throw e;
|
|
17
|
+
}
|
|
18
|
+
export function isObject(value) {
|
|
19
|
+
return value !== null && typeof value === "object";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A Map<K, Set<V>>. But automatically add a new Set if needed
|
|
23
|
+
*/
|
|
24
|
+
export class MapSet {
|
|
25
|
+
constructor() {
|
|
26
|
+
this.map = new Map();
|
|
27
|
+
}
|
|
28
|
+
add(key, value) {
|
|
29
|
+
let set = this.map.get(key);
|
|
30
|
+
if (set === undefined) {
|
|
31
|
+
set = new Set();
|
|
32
|
+
this.map.set(key, set);
|
|
33
|
+
}
|
|
34
|
+
set.add(value);
|
|
35
|
+
}
|
|
36
|
+
delete(key, value) {
|
|
37
|
+
let set = this.map.get(key);
|
|
38
|
+
if (set !== undefined) {
|
|
39
|
+
set.delete(value);
|
|
40
|
+
if (set.size === 0) {
|
|
41
|
+
this.map.delete(key); // Clean up
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
get(key) {
|
|
46
|
+
return this.map.get(key);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A WeakMap<K, Set<V>>. But automatically add a new Set if needed
|
|
51
|
+
*/
|
|
52
|
+
export class WeakMapSet extends MapSet {
|
|
53
|
+
constructor() {
|
|
54
|
+
super(...arguments);
|
|
55
|
+
//@ts-ignore
|
|
56
|
+
this.map = new WeakMap();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function arraysAreEqualsByPredicateFn(a, b, equalsFn) {
|
|
60
|
+
if (a.length !== b.length) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
for (const k in a) {
|
|
64
|
+
if (!equalsFn(a[k], b[k])) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
function diagnosis_jsonPath(key) {
|
|
71
|
+
if (!Number.isNaN(Number(key))) {
|
|
72
|
+
return `[${key}]`;
|
|
73
|
+
}
|
|
74
|
+
return `.${key}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Usage:
|
|
78
|
+
* <pre><code>
|
|
79
|
+
* const result = visitReplace(target, (value, visitChilds, context) => {
|
|
80
|
+
* return value === 'needle' ? 'replaced' : visitChilds(value, context)
|
|
81
|
+
* });
|
|
82
|
+
* </code></pre>
|
|
83
|
+
*
|
|
84
|
+
* @param value
|
|
85
|
+
* @param visitor
|
|
86
|
+
* @param trackPath whether to pass on the context object. This hurts performance because the path is concatted every time, so use it only when needed. Setting this to "onError" re-executes the visitprelace with the concetxt when an error was thrown
|
|
87
|
+
*/
|
|
88
|
+
export function visitReplace(value, visitor, trackPath = false) {
|
|
89
|
+
const visisitedObjects = new Set();
|
|
90
|
+
function visitChilds(value, context) {
|
|
91
|
+
if (value === null) {
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
else if (typeof value === "object") {
|
|
95
|
+
const obj = value;
|
|
96
|
+
if (visisitedObjects.has(obj)) {
|
|
97
|
+
return value; // don't iterate again
|
|
98
|
+
}
|
|
99
|
+
visisitedObjects.add(obj);
|
|
100
|
+
for (let k in obj) {
|
|
101
|
+
const keyInParent = k;
|
|
102
|
+
const childValue = obj[keyInParent];
|
|
103
|
+
let newValue = visitor(childValue, visitChilds, Object.assign(Object.assign({}, context), { parentObject: value, key: keyInParent, diagnosis_path: (context.diagnosis_path !== undefined ? `${context.diagnosis_path}${diagnosis_jsonPath(keyInParent)}` : undefined) }));
|
|
104
|
+
if (newValue !== childValue) { // Only if childValue really has changed. We don't want to interfer with setting a readonly property and trigger a proxy
|
|
105
|
+
// @ts-ignore
|
|
106
|
+
obj[keyInParent] = newValue;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
if (trackPath === "onError") {
|
|
113
|
+
try {
|
|
114
|
+
return visitor(value, visitChilds, {}); // Fast try without context
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
return visitReplace(value, visitor, true); // Try again with context
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return visitor(value, visitChilds, { diagnosis_path: trackPath ? "" : undefined });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Just do something the runtime can't optimize away
|
|
124
|
+
* @param value
|
|
125
|
+
*/
|
|
126
|
+
export function read(value) {
|
|
127
|
+
if (("" + value) == "blaaxyxzzzsdf") {
|
|
128
|
+
throw new Error("should never get here");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export function arraysAreShallowlyEqual(a, b) {
|
|
132
|
+
if (a.length !== b.length) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
for (let i = 0; i < a.length; i++) {
|
|
136
|
+
if (a[i] !== b[i]) { // TODO add option for object instance equality
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Like arraysAreShallowlyEqual but this time for an array of entries (tuple of 2 values) like from Map#entries()
|
|
144
|
+
* @param a
|
|
145
|
+
* @param b
|
|
146
|
+
*/
|
|
147
|
+
export function arraysWithEntriesAreShallowlyEqual(a, b) {
|
|
148
|
+
if (a.length !== b.length) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
for (let i = 0; i < a.length; i++) {
|
|
152
|
+
if (a[i][0] !== b[i][0]) { // TODO add option for object instance equality
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
if (a[i][1] !== b[i][1]) { // TODO add option for object instance equality
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
export function recordedReadsArraysAreEqual(a, b) {
|
|
162
|
+
return arraysAreEqualsByPredicateFn(a, b, (a, b) => a.equals(b));
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=Util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Util.js","sourceRoot":"","sources":["../../Util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { PreserveOptions } from "./preserve";
|
|
3
|
+
type WatchedComponentOptions = {
|
|
4
|
+
/**
|
|
5
|
+
* A fallback react tree to show when some `load(...)` statement in <strong>this</strong> component is loading.
|
|
6
|
+
* Use this if you have issues with screen flickering with <code><Suspense></code>.
|
|
7
|
+
*/
|
|
8
|
+
fallback?: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Wraps this component in a {@link https://react.dev/reference/react/memo memo} to prevent unnecessary re-renders.
|
|
11
|
+
* This is enabled by default, since watchedComponents smartly tracks deep changes of used props and knows when to rerender.
|
|
12
|
+
* Disable this only in a mixed scenario with non-watchedComponents, where they rely on the old way of fully re-rendering the whole tree to pass deep model data (=more than using shallow, primitive props) to the leaves. So this component does not block these re-renders in the middle.
|
|
13
|
+
* <p>
|
|
14
|
+
* Default: true
|
|
15
|
+
* </p>
|
|
16
|
+
*/
|
|
17
|
+
memo?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* TODO
|
|
20
|
+
* Normally, everything that's **taken** from props, {@link useWatchedState} or {@link watched} or load(...)'s result will be returned, wrapped in a proxy that watches for modifications.
|
|
21
|
+
* So far, so good, this can handle all stuff that's happening inside your component, but the outside world does not have these proxies. For example, when a parent component is not a watchedComponent, and passed in an object (i.e. the model) into this component via props.
|
|
22
|
+
* Therefore this component can also **patch** these objects to make them watchable.
|
|
23
|
+
*
|
|
24
|
+
*
|
|
25
|
+
* <p>Default: true</p>
|
|
26
|
+
*/
|
|
27
|
+
watchOutside?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* TODO: implement
|
|
30
|
+
* Preserves object instances in props by running the {@link preserve} function over the props (where the last value is memoized).
|
|
31
|
+
* <p>
|
|
32
|
+
* It's not recommended to enable this. Use only as a workaround when working with non-watched components where you have no control over. Better run {@link preserve} on the fetched source and keep a consistent-instance model in your app in the first place.
|
|
33
|
+
* </p>
|
|
34
|
+
*
|
|
35
|
+
* Note: Even with false, the `props` root object still keeps its instance (so it's save to watch `props.myFirstLevelProperty`).
|
|
36
|
+
* <p>
|
|
37
|
+
* Default: false
|
|
38
|
+
* </p>
|
|
39
|
+
*/
|
|
40
|
+
preserveProps?: boolean;
|
|
41
|
+
};
|
|
42
|
+
export declare function watchedComponent<PROPS extends object>(componentFn: (props: PROPS) => any, options?: WatchedComponentOptions): ((props: PROPS) => any) | import("react").MemoExoticComponent<(props: PROPS) => any>;
|
|
43
|
+
type WatchedOptions = {
|
|
44
|
+
/**
|
|
45
|
+
* TODO: Implement
|
|
46
|
+
* Called, when a deep property was changed through the proxy.
|
|
47
|
+
*/
|
|
48
|
+
onChange?: () => void;
|
|
49
|
+
/**
|
|
50
|
+
* TODO: Implement
|
|
51
|
+
* Called on a change to one of those properties, that were read-recorded in the component function (through the proxy of course).
|
|
52
|
+
* Reacts also on external changes / not done through the proxy.
|
|
53
|
+
*/
|
|
54
|
+
onRecordedChange?: () => void;
|
|
55
|
+
};
|
|
56
|
+
export declare function useWatchedState(initial: object, options?: WatchedOptions): object;
|
|
57
|
+
type LoadOptions = {
|
|
58
|
+
/**
|
|
59
|
+
* For {@link LoadOptions#preserve preserving} the result's object identity.
|
|
60
|
+
* Normally, this is obtained from the call stack information plus the {@link LoadOptions#key}.
|
|
61
|
+
*
|
|
62
|
+
* @see LoadOptions#key
|
|
63
|
+
*/
|
|
64
|
+
id?: string | number | object;
|
|
65
|
+
/**
|
|
66
|
+
* Helps identifying the load(...) call from inside a loop for {@link LoadOptions#preserve preserving} the result's object identity.
|
|
67
|
+
* @see LoadOptions#id
|
|
68
|
+
*/
|
|
69
|
+
key?: string | number;
|
|
70
|
+
/**
|
|
71
|
+
* If you specify a fallback, the component can be immediately rendered during loading.
|
|
72
|
+
* <p>
|
|
73
|
+
* undefined = undefined as fallback.
|
|
74
|
+
* </p>
|
|
75
|
+
*/
|
|
76
|
+
fallback?: unknown;
|
|
77
|
+
/**
|
|
78
|
+
* Performance: Will return the old value from a previous load, while this is still loading. This causes less disturbance (i.e. triggering dependent loads) while switching back to the fallback and then to a real value again.
|
|
79
|
+
* <p>Best used in combination with {@link isLoading} and {@link fallback}</p>
|
|
80
|
+
* <p>Default: false</p>
|
|
81
|
+
*/
|
|
82
|
+
silent?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Performance: Set to false, to mark following `load(...)` statements do not depend on the result. I.e when used only for immediate rendering or passed to child components only. I.e. <div>{load(...)}/div> or `<MySubComponent param={load(...)} />`:
|
|
85
|
+
* Therefore, the following `load(...)` statements may not need a reload and can run in parallel.
|
|
86
|
+
* <p>
|
|
87
|
+
* Default: true
|
|
88
|
+
* </p>
|
|
89
|
+
*/
|
|
90
|
+
critical?: boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Poll after this amount of milliseconds
|
|
93
|
+
*/
|
|
94
|
+
poll?: number;
|
|
95
|
+
/**
|
|
96
|
+
* {@link isLoading} Can filter for only the load(...) statements with this given name.
|
|
97
|
+
*/
|
|
98
|
+
name?: string;
|
|
99
|
+
/**
|
|
100
|
+
*
|
|
101
|
+
* <p>Default: true</p>
|
|
102
|
+
*/
|
|
103
|
+
preserve?: boolean | PreserveOptions;
|
|
104
|
+
};
|
|
105
|
+
type PollOptions = {
|
|
106
|
+
/**
|
|
107
|
+
* Interval in milliseconds
|
|
108
|
+
*/
|
|
109
|
+
interval: number;
|
|
110
|
+
/**
|
|
111
|
+
* - true = interval means loaderFn-start to loaderFn-start
|
|
112
|
+
* - false = interval means loaderFn-end to loaderFn-start (the longer loaderFn takes, the more time till next re-poll)
|
|
113
|
+
* <p>
|
|
114
|
+
* Default: true
|
|
115
|
+
* </p>
|
|
116
|
+
*/
|
|
117
|
+
fixedInterval?: boolean;
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Runs the async loaderFn and re-renders, if its promise was resolved. Also re-renders and re-runs loaderFn, when some of its watched dependencies, used prior or instantly in the loaderFn, change.
|
|
121
|
+
* Puts the component into suspense while loading. Throws an error when loaderFn throws an error or its promise is rejected. Resumes from react-error-boundary automatically when loaderFn was re-run(because of the above).
|
|
122
|
+
* <p>
|
|
123
|
+
* {@link https://github.com/bogeeee/react-deepwatch#and-less-loading-code Usage}.
|
|
124
|
+
* </p>
|
|
125
|
+
* @param loaderFn
|
|
126
|
+
* @param options
|
|
127
|
+
*/
|
|
128
|
+
export declare function load<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options?: Omit<LoadOptions, "fallback">): T;
|
|
129
|
+
/**
|
|
130
|
+
* Runs the async loaderFn and re-renders, if its promise was resolved. Also re-renders and re-runs loaderFn, when some of its watched dependencies, used prior or instantly in the loaderFn, change.
|
|
131
|
+
* Puts the component into suspense while loading. Throws an error when loaderFn throws an error or its promise is rejected. Resumes from react-error-boundary automatically when loaderFn was re-run(because of the above).
|
|
132
|
+
* <p>
|
|
133
|
+
* {@link https://github.com/bogeeee/react-deepwatch#and-less-loading-code Usage}.
|
|
134
|
+
* </p>
|
|
135
|
+
* @param loaderFn
|
|
136
|
+
* @param options
|
|
137
|
+
*/
|
|
138
|
+
export declare function load<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: LoadOptions & {
|
|
139
|
+
fallback: FALLBACK;
|
|
140
|
+
}): T | FALLBACK;
|
|
141
|
+
/**
|
|
142
|
+
* Probe if a <code>load(...)</code> statement directly inside this watchedComponent is currently loading.
|
|
143
|
+
* Note: It's mostly needed to also specify a {@link LoadOptions#fallback} in the load statement's options to produce a valid render result while loading. Otherwise the whole component goes into suspense.
|
|
144
|
+
* <p>
|
|
145
|
+
* Example. This uses isLoading() to determine if the Dropdown list should be faded/transparent during while items are loading:
|
|
146
|
+
* <pre><code>
|
|
147
|
+
* return <select style={{opacity: isLoading("dropdownItems")?0.5:1}}>
|
|
148
|
+
* {load(() => fetchMyDropdownItems(), {name: "dropdownItems", fallback: ["loading items"]}).map(i => <option value="{i}">{i}</option>)}
|
|
149
|
+
* </select>
|
|
150
|
+
* </code></pre>
|
|
151
|
+
* </p>
|
|
152
|
+
* <p>
|
|
153
|
+
* Caveat: You must not use this for a condition that cuts away a load(...) statement in the middle of your render code. This is because an extra render run is issued for isLoading() and the load(...) statements are re-matched by their order.
|
|
154
|
+
* </p>
|
|
155
|
+
* @param nameFilter When set, consider only those with the given {@link LoadOptions#name}. I.e. <code>load(..., {name: "myDropdownListEntries"})</code>
|
|
156
|
+
*
|
|
157
|
+
*/
|
|
158
|
+
export declare function isLoading(nameFilter?: string): boolean;
|
|
159
|
+
/**
|
|
160
|
+
* Probe if a <code>load(...)</code> statement directly inside this watchedComponent failed.
|
|
161
|
+
* <p>
|
|
162
|
+
* Example:
|
|
163
|
+
* <pre><code>
|
|
164
|
+
* if(loadFailed()) {
|
|
165
|
+
* return <div>Load failed: {loadFailed().message}</div>;
|
|
166
|
+
* }
|
|
167
|
+
*
|
|
168
|
+
* return <div>My component content {load(...)} </div>
|
|
169
|
+
* </code></pre>
|
|
170
|
+
* </p>
|
|
171
|
+
* <p>
|
|
172
|
+
* Caveat: You must not use this for a condition that cuts away a load(...) statement in the middle of your render code. This is because an extra render run is issued for loadFailed() and the load(...) statements are re-matched by their order.
|
|
173
|
+
* </p>
|
|
174
|
+
* @param nameFilter When set, consider only those with the given {@link LoadOptions#name}. I.e. <code>load(..., {name: "myDropdownListEntries"})</code>
|
|
175
|
+
* @returns unknown The thrown value of the loaderFn or undefined if everything is ok.
|
|
176
|
+
*/
|
|
177
|
+
export declare function loadFailed(nameFilter?: string): unknown;
|
|
178
|
+
/**
|
|
179
|
+
* Like {@link load}, but re-runs loaderFn regularly at the interval, specified in the options.
|
|
180
|
+
* <p>
|
|
181
|
+
* Example: <code>return <div>The current outside temperature is { poll( async () => await fetchTemperatureFromServer(), {interval: 1000} ) }° </div></code> *
|
|
182
|
+
* </p>
|
|
183
|
+
* <p>
|
|
184
|
+
* Polling is still continued in recoverable error cases, when
|
|
185
|
+
* </p>
|
|
186
|
+
* - loaderFn fails but your watchedComponent catches it and returns fine.
|
|
187
|
+
* - Your watchedComponent returns with an error(because of this loaderFn or some other reason) and it is wrapped in a react-error-boundary.
|
|
188
|
+
*
|
|
189
|
+
* <p>
|
|
190
|
+
* Note, that after the initial load, re-polling is done <strong>very silently</strong>. Meaning, there's no suspense / fallback / isLoading indicator involved.
|
|
191
|
+
* </p>
|
|
192
|
+
* @param loaderFn
|
|
193
|
+
* @param options
|
|
194
|
+
*/
|
|
195
|
+
export declare function poll<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: Omit<LoadOptions, "fallback"> & PollOptions): T;
|
|
196
|
+
/**
|
|
197
|
+
* Like {@link load}, but re-runs loaderFn regularly at the interval, specified in the options.
|
|
198
|
+
* <p>
|
|
199
|
+
* Example: <code>return <div>The current outside temperature is { async poll( await () => fetchTemperatureFromServer(), {interval: 1000} ) }° </div></code> *
|
|
200
|
+
* </p>
|
|
201
|
+
* <p>
|
|
202
|
+
* Polling is still continued in recoverable error cases, when
|
|
203
|
+
* </p>
|
|
204
|
+
* - loaderFn fails but your watchedComponent catches it and returns fine.
|
|
205
|
+
* - Your watchedComponent returns with an error(because of this loaderFn or some other reason) and it is wrapped in a react-error-boundary.
|
|
206
|
+
*
|
|
207
|
+
* <p>
|
|
208
|
+
* Note, that after the initial load, re-polling is done <strong>very silently</strong>. Meaning, there's no suspense / fallback / isLoading indicator involved.
|
|
209
|
+
* </p>
|
|
210
|
+
* @param loaderFn
|
|
211
|
+
* @param options
|
|
212
|
+
*/
|
|
213
|
+
export declare function poll<T, FALLBACK>(loaderFn: (oldResult?: T) => Promise<T>, options: LoadOptions & {
|
|
214
|
+
fallback: FALLBACK;
|
|
215
|
+
} & PollOptions): T | FALLBACK;
|
|
216
|
+
export declare function debug_tagComponent(name: string): void;
|
|
217
|
+
export {};
|
|
218
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../index.ts"],"names":[],"mappings":"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"}
|