@evolu/common 8.0.0-next.4 → 8.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/dist/src/Array.d.ts +279 -173
- package/dist/src/Array.d.ts.map +1 -1
- package/dist/src/Array.js +105 -101
- package/dist/src/Assert.d.ts +44 -44
- package/dist/src/Assert.d.ts.map +1 -1
- package/dist/src/Assert.js +44 -32
- package/dist/src/BigInt.d.ts +6 -3
- package/dist/src/BigInt.d.ts.map +1 -1
- package/dist/src/BigInt.js +5 -2
- package/dist/src/Brand.d.ts +27 -40
- package/dist/src/Brand.d.ts.map +1 -1
- package/dist/src/Buffer.d.ts +27 -11
- package/dist/src/Buffer.d.ts.map +1 -1
- package/dist/src/Cache.d.ts +9 -4
- package/dist/src/Cache.d.ts.map +1 -1
- package/dist/src/Cache.js +8 -3
- package/dist/src/Callbacks.d.ts +30 -19
- package/dist/src/Callbacks.d.ts.map +1 -1
- package/dist/src/Console.d.ts +145 -66
- package/dist/src/Console.d.ts.map +1 -1
- package/dist/src/Console.js +91 -43
- package/dist/src/Crypto.d.ts +85 -42
- package/dist/src/Crypto.d.ts.map +1 -1
- package/dist/src/Crypto.js +44 -20
- package/dist/src/Eq.d.ts +87 -21
- package/dist/src/Eq.d.ts.map +1 -1
- package/dist/src/Eq.js +67 -19
- package/dist/src/Error.d.ts +5 -3
- package/dist/src/Error.d.ts.map +1 -1
- package/dist/src/Error.js +16 -0
- package/dist/src/Function.d.ts +119 -58
- package/dist/src/Function.d.ts.map +1 -1
- package/dist/src/Function.js +86 -43
- package/dist/src/Http.d.ts +394 -0
- package/dist/src/Http.d.ts.map +1 -0
- package/dist/src/Http.js +102 -0
- package/dist/src/Identicon.d.ts +16 -7
- package/dist/src/Identicon.d.ts.map +1 -1
- package/dist/src/Identicon.js +14 -5
- package/dist/src/LeakDetector.d.ts +88 -0
- package/dist/src/LeakDetector.d.ts.map +1 -0
- package/dist/src/LeakDetector.js +86 -0
- package/dist/src/LockManager.d.ts +18 -9
- package/dist/src/LockManager.d.ts.map +1 -1
- package/dist/src/LockManager.js +7 -8
- package/dist/src/Lookup.d.ts +43 -13
- package/dist/src/Lookup.d.ts.map +1 -1
- package/dist/src/Lookup.js +28 -8
- package/dist/src/Microtask.d.ts +1 -1
- package/dist/src/Microtask.d.ts.map +1 -1
- package/dist/src/Microtask.js +3 -7
- package/dist/src/Number.d.ts +49 -13
- package/dist/src/Number.d.ts.map +1 -1
- package/dist/src/Number.js +34 -5
- package/dist/src/Object.d.ts +160 -40
- package/dist/src/Object.d.ts.map +1 -1
- package/dist/src/Object.js +92 -46
- package/dist/src/Option.d.ts +10 -7
- package/dist/src/Option.d.ts.map +1 -1
- package/dist/src/Option.js +9 -6
- package/dist/src/Order.d.ts +21 -21
- package/dist/src/Order.d.ts.map +1 -1
- package/dist/src/Order.js +18 -21
- package/dist/src/Platform.d.ts +31 -0
- package/dist/src/Platform.d.ts.map +1 -1
- package/dist/src/Platform.js +98 -0
- package/dist/src/Random.d.ts +32 -17
- package/dist/src/Random.d.ts.map +1 -1
- package/dist/src/Random.js +12 -8
- package/dist/src/Redacted.d.ts +43 -29
- package/dist/src/Redacted.d.ts.map +1 -1
- package/dist/src/Redacted.js +14 -3
- package/dist/src/Ref.d.ts +11 -3
- package/dist/src/Ref.d.ts.map +1 -1
- package/dist/src/Ref.js +2 -2
- package/dist/src/RefCount.d.ts +2 -6
- package/dist/src/RefCount.d.ts.map +1 -1
- package/dist/src/RefCount.js +33 -90
- package/dist/src/Relation.d.ts +70 -5
- package/dist/src/Relation.d.ts.map +1 -1
- package/dist/src/Relation.js +77 -2
- package/dist/src/Resource.d.ts +590 -155
- package/dist/src/Resource.d.ts.map +1 -1
- package/dist/src/Resource.js +592 -343
- package/dist/src/Result.d.ts +838 -191
- package/dist/src/Result.d.ts.map +1 -1
- package/dist/src/Result.js +163 -102
- package/dist/src/Schedule.d.ts +684 -231
- package/dist/src/Schedule.d.ts.map +1 -1
- package/dist/src/Schedule.js +766 -295
- package/dist/src/Set.d.ts +89 -40
- package/dist/src/Set.d.ts.map +1 -1
- package/dist/src/Set.js +50 -29
- package/dist/src/Sqlite.d.ts +29 -72
- package/dist/src/Sqlite.d.ts.map +1 -1
- package/dist/src/Sqlite.js +41 -46
- package/dist/src/StackTrace.d.ts +40 -0
- package/dist/src/StackTrace.d.ts.map +1 -0
- package/dist/src/StackTrace.js +140 -0
- package/dist/src/Store.d.ts +5 -4
- package/dist/src/Store.d.ts.map +1 -1
- package/dist/src/Store.js +5 -4
- package/dist/src/String.d.ts +7 -1
- package/dist/src/String.d.ts.map +1 -1
- package/dist/src/String.js +20 -7
- package/dist/src/Task.d.ts +3572 -1770
- package/dist/src/Task.d.ts.map +1 -1
- package/dist/src/Task.js +1879 -1274
- package/dist/src/Test.d.ts +17 -125
- package/dist/src/Test.d.ts.map +1 -1
- package/dist/src/Test.js +17 -68
- package/dist/src/Time.d.ts +108 -49
- package/dist/src/Time.d.ts.map +1 -1
- package/dist/src/Time.js +172 -73
- package/dist/src/Type.d.ts +3542 -1926
- package/dist/src/Type.d.ts.map +1 -1
- package/dist/src/Type.js +3070 -1784
- package/dist/src/Types.d.ts +200 -108
- package/dist/src/Types.d.ts.map +1 -1
- package/dist/src/Types.js +39 -8
- package/dist/src/WebSocket.d.ts +48 -23
- package/dist/src/WebSocket.d.ts.map +1 -1
- package/dist/src/WebSocket.js +15 -6
- package/dist/src/Worker.d.ts +94 -36
- package/dist/src/Worker.d.ts.map +1 -1
- package/dist/src/Worker.js +58 -24
- package/dist/src/index.d.ts +55 -52
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/intl/cs.d.ts +94 -0
- package/dist/src/intl/cs.d.ts.map +1 -0
- package/dist/src/intl/cs.js +220 -0
- package/dist/src/intl/index.d.ts +7 -0
- package/dist/src/intl/index.d.ts.map +1 -0
- package/dist/src/intl/index.js +6 -0
- package/dist/src/local-first/Db.d.ts +12 -8
- package/dist/src/local-first/Db.d.ts.map +1 -1
- package/dist/src/local-first/Db.js +109 -132
- package/dist/src/local-first/Error.d.ts +4 -4
- package/dist/src/local-first/Evolu.d.ts +338 -92
- package/dist/src/local-first/Evolu.d.ts.map +1 -1
- package/dist/src/local-first/Evolu.js +47 -55
- package/dist/src/local-first/LocalAuth.d.ts +4 -4
- package/dist/src/local-first/LocalAuth.d.ts.map +1 -1
- package/dist/src/local-first/Owner.d.ts +61 -24
- package/dist/src/local-first/Owner.d.ts.map +1 -1
- package/dist/src/local-first/Owner.js +45 -8
- package/dist/src/local-first/Protocol.d.ts +44 -31
- package/dist/src/local-first/Protocol.d.ts.map +1 -1
- package/dist/src/local-first/Protocol.js +36 -13
- package/dist/src/local-first/Query.d.ts +147 -62
- package/dist/src/local-first/Query.d.ts.map +1 -1
- package/dist/src/local-first/Query.js +112 -58
- package/dist/src/local-first/Relay.d.ts +44 -14
- package/dist/src/local-first/Relay.d.ts.map +1 -1
- package/dist/src/local-first/Schema.d.ts +92 -41
- package/dist/src/local-first/Schema.d.ts.map +1 -1
- package/dist/src/local-first/Schema.js +25 -8
- package/dist/src/local-first/Shared.d.ts +23 -21
- package/dist/src/local-first/Shared.d.ts.map +1 -1
- package/dist/src/local-first/Shared.js +100 -57
- package/dist/src/local-first/Storage.d.ts +53 -32
- package/dist/src/local-first/Storage.d.ts.map +1 -1
- package/dist/src/local-first/Storage.js +194 -234
- package/dist/src/local-first/Timestamp.d.ts +21 -21
- package/dist/src/local-first/Timestamp.d.ts.map +1 -1
- package/dist/src/local-first/Timestamp.js +2 -2
- package/dist/src/local-first/index.d.ts +11 -11
- package/package.json +14 -13
- package/src/Array.ts +306 -205
- package/src/Assert.ts +54 -69
- package/src/BigInt.ts +6 -3
- package/src/Brand.ts +27 -40
- package/src/Buffer.ts +28 -12
- package/src/Cache.ts +9 -4
- package/src/Callbacks.ts +30 -19
- package/src/Console.ts +156 -84
- package/src/Crypto.ts +83 -41
- package/src/Eq.ts +95 -22
- package/src/Error.ts +8 -4
- package/src/Function.ts +167 -59
- package/src/Http.ts +549 -0
- package/src/Identicon.ts +16 -7
- package/src/LeakDetector.ts +182 -0
- package/src/LockManager.ts +43 -39
- package/src/Lookup.ts +62 -28
- package/src/Microtask.ts +19 -23
- package/src/Number.ts +64 -12
- package/src/Object.ts +173 -49
- package/src/Option.ts +10 -7
- package/src/Order.ts +23 -21
- package/src/Platform.ts +136 -0
- package/src/Polyfills.ts +6 -12
- package/src/Random.ts +32 -19
- package/src/Redacted.ts +44 -30
- package/src/Ref.ts +14 -6
- package/src/RefCount.ts +38 -80
- package/src/Relation.ts +202 -10
- package/src/Resource.ts +1199 -591
- package/src/Result.ts +930 -271
- package/src/Schedule.ts +859 -343
- package/src/Set.ts +89 -40
- package/src/Sqlite.ts +144 -138
- package/src/StackTrace.ts +230 -0
- package/src/Store.ts +8 -7
- package/src/String.ts +22 -5
- package/src/Task.ts +5101 -2832
- package/src/Test.ts +20 -168
- package/src/Time.ts +293 -90
- package/src/Type.ts +10034 -4117
- package/src/Types.ts +227 -110
- package/src/WebSocket.ts +64 -36
- package/src/Worker.ts +180 -72
- package/src/index.ts +55 -52
- package/src/intl/cs.ts +388 -0
- package/src/intl/index.ts +7 -0
- package/src/local-first/Db.ts +152 -179
- package/src/local-first/Error.ts +4 -4
- package/src/local-first/Evolu.ts +495 -250
- package/src/local-first/LocalAuth.ts +6 -12
- package/src/local-first/Owner.ts +58 -21
- package/src/local-first/Protocol.ts +49 -31
- package/src/local-first/Query.ts +146 -61
- package/src/local-first/Relay.ts +51 -21
- package/src/local-first/Schema.ts +109 -51
- package/src/local-first/Shared.ts +266 -226
- package/src/local-first/Storage.ts +266 -264
- package/src/local-first/Timestamp.ts +25 -18
- package/src/local-first/index.ts +11 -11
- package/dist/src/Skiplist.d.ts +0 -28
- package/dist/src/Skiplist.d.ts.map +0 -1
- package/dist/src/Skiplist.js +0 -64
- package/dist/src/Tracer.d.ts +0 -48
- package/dist/src/Tracer.d.ts.map +0 -1
- package/dist/src/Tracer.js +0 -6
- package/src/Skiplist.ts +0 -108
- package/src/Tracer.ts +0 -54
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JavaScript stack trace parsing utilities.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface StackTraceFrame {
|
|
8
|
+
/** Function or frame label reported by the engine, if available. */
|
|
9
|
+
readonly name: string | undefined;
|
|
10
|
+
/** Basename of the source location without query or hash suffixes. */
|
|
11
|
+
readonly sourceName: string;
|
|
12
|
+
readonly location: string;
|
|
13
|
+
readonly lineNumber: number;
|
|
14
|
+
readonly columnNumber: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface StackTrace {
|
|
18
|
+
readonly frames: ReadonlyArray<StackTraceFrame>;
|
|
19
|
+
readonly names: ReadonlyArray<string>;
|
|
20
|
+
readonly files: ReadonlyArray<string>;
|
|
21
|
+
readonly sites: ReadonlyArray<string>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface StackTraceOptions {
|
|
25
|
+
readonly maxSourceLabelLineOffset?: number;
|
|
26
|
+
readonly sourceLabel?: string;
|
|
27
|
+
readonly sourceLabelsByLine?: Map<number, string>;
|
|
28
|
+
readonly sourceNameAllowlist?: ReadonlySet<string>;
|
|
29
|
+
readonly sourceName?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Parses V8, SpiderMonkey, and JavaScriptCore stack frames for tests.
|
|
34
|
+
*
|
|
35
|
+
* Warning: This is AI-slop containment code for tests, not production stack
|
|
36
|
+
* trace parsing infrastructure.
|
|
37
|
+
*
|
|
38
|
+
* This is intentionally not a complete stack trace parser. It extracts only
|
|
39
|
+
* frame names and source positions needed by async stack trace tests and
|
|
40
|
+
* similar assertions that need stable, cross-engine stack evidence.
|
|
41
|
+
*/
|
|
42
|
+
export function parseStackTrace(
|
|
43
|
+
stack: string | undefined,
|
|
44
|
+
options?: StackTraceOptions,
|
|
45
|
+
): StackTrace;
|
|
46
|
+
export function parseStackTrace(
|
|
47
|
+
run: () => Promise<never>,
|
|
48
|
+
options?: StackTraceOptions,
|
|
49
|
+
): Promise<StackTrace>;
|
|
50
|
+
export function parseStackTrace(
|
|
51
|
+
input: string | undefined | (() => Promise<never>),
|
|
52
|
+
options: StackTraceOptions = {},
|
|
53
|
+
): StackTrace | Promise<StackTrace> {
|
|
54
|
+
if (typeof input === "function")
|
|
55
|
+
return (async () => {
|
|
56
|
+
try {
|
|
57
|
+
if (options.sourceLabel != null)
|
|
58
|
+
parseStackTrace(new Error().stack, options);
|
|
59
|
+
await input();
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (!(error instanceof Error)) throw error;
|
|
62
|
+
|
|
63
|
+
const { sourceLabel: _sourceLabel, ...readOptions } = options;
|
|
64
|
+
return parseStackTrace(error.stack, readOptions);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
throw new Error("Stack trace capture must throw.");
|
|
68
|
+
})();
|
|
69
|
+
|
|
70
|
+
const frames = parseStackTraceFrames(input).filter(
|
|
71
|
+
({ sourceName }) =>
|
|
72
|
+
options.sourceNameAllowlist == null ||
|
|
73
|
+
options.sourceNameAllowlist.has(sourceName),
|
|
74
|
+
);
|
|
75
|
+
recordSourceLabel(frames, options);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
files: frames.map(({ sourceName }) => sourceName),
|
|
79
|
+
frames,
|
|
80
|
+
names: frames
|
|
81
|
+
.map(({ name }) => name)
|
|
82
|
+
.filter((name): name is string => name !== undefined),
|
|
83
|
+
sites: sourceLabels(frames, options),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const parseStackTraceFrames = (
|
|
88
|
+
stack: string | undefined,
|
|
89
|
+
): ReadonlyArray<StackTraceFrame> =>
|
|
90
|
+
(stack ?? "")
|
|
91
|
+
.split("\n")
|
|
92
|
+
.map(parseStackTraceLine)
|
|
93
|
+
.filter((frame): frame is StackTraceFrame => frame !== undefined);
|
|
94
|
+
|
|
95
|
+
const recordSourceLabel = (
|
|
96
|
+
frames: ReadonlyArray<StackTraceFrame>,
|
|
97
|
+
{ sourceLabel, sourceLabelsByLine, sourceName }: StackTraceOptions,
|
|
98
|
+
): void => {
|
|
99
|
+
if (sourceLabel == null || sourceLabelsByLine == null || sourceName == null)
|
|
100
|
+
return;
|
|
101
|
+
|
|
102
|
+
const frame = frames.find((frame) => frame.sourceName === sourceName);
|
|
103
|
+
if (frame == null) return;
|
|
104
|
+
|
|
105
|
+
sourceLabelsByLine.set(frame.lineNumber, sourceLabel);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const sourceLabels = (
|
|
109
|
+
frames: ReadonlyArray<StackTraceFrame>,
|
|
110
|
+
{
|
|
111
|
+
maxSourceLabelLineOffset = 8,
|
|
112
|
+
sourceLabelsByLine,
|
|
113
|
+
sourceName,
|
|
114
|
+
}: StackTraceOptions,
|
|
115
|
+
): ReadonlyArray<string> => {
|
|
116
|
+
if (sourceLabelsByLine == null || sourceName == null) return [];
|
|
117
|
+
|
|
118
|
+
return frames.flatMap((frame) => {
|
|
119
|
+
if (frame.sourceName !== sourceName) return [];
|
|
120
|
+
|
|
121
|
+
for (let offset = 0; offset <= maxSourceLabelLineOffset; offset += 1) {
|
|
122
|
+
const label = sourceLabelsByLine.get(frame.lineNumber - offset);
|
|
123
|
+
if (label != null) return [label];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return [];
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const parseStackTraceLine = (line: string): StackTraceFrame | undefined => {
|
|
131
|
+
const stackLine = parseStackLine(line);
|
|
132
|
+
if (stackLine == null) return undefined;
|
|
133
|
+
|
|
134
|
+
const location = parseStackLocation(stackLine.location);
|
|
135
|
+
if (location == null) return undefined;
|
|
136
|
+
|
|
137
|
+
return { ...location, name: stackLine.name };
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const parseStackLine = (
|
|
141
|
+
line: string,
|
|
142
|
+
):
|
|
143
|
+
| { readonly name: string | undefined; readonly location: string }
|
|
144
|
+
| undefined => {
|
|
145
|
+
let text = line.trim();
|
|
146
|
+
if (text === "") return undefined;
|
|
147
|
+
|
|
148
|
+
if (text.startsWith("at ")) {
|
|
149
|
+
text = text.slice(3);
|
|
150
|
+
if (text.startsWith("async ")) text = text.slice(6);
|
|
151
|
+
|
|
152
|
+
const locationStart = text.lastIndexOf("(");
|
|
153
|
+
if (locationStart >= 0 && text.endsWith(")")) {
|
|
154
|
+
const name = stackFrameName(text.slice(0, locationStart).trim());
|
|
155
|
+
const location = text.slice(locationStart + 1, -1);
|
|
156
|
+
return { name, location };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return { location: text, name: undefined };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (text.startsWith("async*")) text = text.slice(6);
|
|
163
|
+
|
|
164
|
+
const locationStart = text.indexOf("@");
|
|
165
|
+
if (locationStart < 0) return { location: text, name: undefined };
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
location: text.slice(locationStart + 1),
|
|
169
|
+
name: stackFrameName(text.slice(0, locationStart)),
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const parseStackLocation = (
|
|
174
|
+
location: string,
|
|
175
|
+
): Omit<StackTraceFrame, "name"> | undefined => {
|
|
176
|
+
const columnStart = location.lastIndexOf(":");
|
|
177
|
+
if (columnStart < 0) return undefined;
|
|
178
|
+
|
|
179
|
+
const lineStart = location.lastIndexOf(":", columnStart - 1);
|
|
180
|
+
if (lineStart < 0) return undefined;
|
|
181
|
+
|
|
182
|
+
const pathEnd = Math.max(
|
|
183
|
+
location.lastIndexOf("/"),
|
|
184
|
+
location.lastIndexOf("\\"),
|
|
185
|
+
);
|
|
186
|
+
if (lineStart <= pathEnd) return undefined;
|
|
187
|
+
|
|
188
|
+
const lineNumber = parseLeadingInt(location.slice(lineStart + 1));
|
|
189
|
+
const columnNumber = parseLeadingInt(location.slice(columnStart + 1));
|
|
190
|
+
if (lineNumber == null || columnNumber == null) return undefined;
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
columnNumber,
|
|
194
|
+
lineNumber,
|
|
195
|
+
location,
|
|
196
|
+
sourceName: stackTraceSourceName(location.slice(0, lineStart)),
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const stackTraceSourceName = (source: string): string => {
|
|
201
|
+
const queryStart = source.indexOf("?");
|
|
202
|
+
const hashStart = source.indexOf("#");
|
|
203
|
+
const suffixStart =
|
|
204
|
+
queryStart < 0
|
|
205
|
+
? hashStart
|
|
206
|
+
: hashStart < 0
|
|
207
|
+
? queryStart
|
|
208
|
+
: Math.min(queryStart, hashStart);
|
|
209
|
+
const path = suffixStart < 0 ? source : source.slice(0, suffixStart);
|
|
210
|
+
|
|
211
|
+
return path.slice(
|
|
212
|
+
Math.max(path.lastIndexOf("/"), path.lastIndexOf("\\")) + 1,
|
|
213
|
+
);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const parseLeadingInt = (value: string): number | undefined => {
|
|
217
|
+
let end = 0;
|
|
218
|
+
while (end < value.length && isAsciiDigit(value.charCodeAt(end))) end += 1;
|
|
219
|
+
if (end === 0) return undefined;
|
|
220
|
+
|
|
221
|
+
return Number(value.slice(0, end));
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
const isAsciiDigit = (charCode: number): boolean =>
|
|
225
|
+
charCode >= 48 && charCode <= 57;
|
|
226
|
+
|
|
227
|
+
const stackFrameName = (value: string): string | undefined => {
|
|
228
|
+
while (value.endsWith("/<")) value = value.slice(0, -2);
|
|
229
|
+
return value === "" ? undefined : value;
|
|
230
|
+
};
|
package/src/Store.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { Eq } from "./Eq.
|
|
8
|
-
import {
|
|
9
|
-
import type { Ref } from "./Ref.
|
|
10
|
-
import { createRef } from "./Ref.
|
|
7
|
+
import type { Eq } from "./Eq.ts";
|
|
8
|
+
import { eqSameValueZero } from "./Eq.ts";
|
|
9
|
+
import type { Ref } from "./Ref.ts";
|
|
10
|
+
import { createRef } from "./Ref.ts";
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* A store for managing state with change notifications. Like a {@link Ref} with
|
|
@@ -51,11 +51,12 @@ export type Unsubscribe = () => void;
|
|
|
51
51
|
* state, which can be read with `get` and updated with `set` or `update`. All
|
|
52
52
|
* changes are broadcast to subscribers.
|
|
53
53
|
*
|
|
54
|
-
* By default, state changes are detected using
|
|
55
|
-
*
|
|
54
|
+
* By default, state changes are detected using {@link eqSameValueZero}, which
|
|
55
|
+
* considers `NaN` equal to itself and `0` equal to `-0`. You can provide a
|
|
56
|
+
* custom equality function as the second argument.
|
|
56
57
|
*/
|
|
57
58
|
export const createStore = <T>(initialState: T, eq?: Eq<T>): Store<T> => {
|
|
58
|
-
const equality = eq ??
|
|
59
|
+
const equality = eq ?? eqSameValueZero;
|
|
59
60
|
const ref = createRef(initialState);
|
|
60
61
|
const listeners = new Set<Listener>();
|
|
61
62
|
|
package/src/String.ts
CHANGED
|
@@ -1,16 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* String utilities
|
|
2
|
+
* String utilities.
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Escapes regular-expression syntax so a string can be used as a literal
|
|
9
|
+
* pattern.
|
|
10
|
+
*/
|
|
11
|
+
export const escapeRegExp = (value: string): string =>
|
|
12
|
+
value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13
|
+
|
|
14
|
+
/** Converts an unknown value to a compact, human-readable diagnostic string. */
|
|
7
15
|
export const safelyStringifyUnknownValue = (value: unknown): string => {
|
|
8
|
-
if (value ===
|
|
9
|
-
if (value ===
|
|
10
|
-
|
|
16
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
17
|
+
if (value === null || typeof value !== "object")
|
|
18
|
+
return globalThis.String(value);
|
|
19
|
+
|
|
11
20
|
try {
|
|
12
|
-
|
|
21
|
+
// `JSON.stringify` can return `undefined` when `toJSON` does.
|
|
22
|
+
const stringifiedValue: unknown = JSON.stringify(value);
|
|
23
|
+
if (typeof stringifiedValue === "string") return stringifiedValue;
|
|
13
24
|
} catch {
|
|
25
|
+
// Fall through to a simpler representation.
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
try {
|
|
14
29
|
return globalThis.String(value);
|
|
30
|
+
} catch {
|
|
31
|
+
return "[Unserializable value]";
|
|
15
32
|
}
|
|
16
33
|
};
|