on-zero 0.6.2 → 0.6.3
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/cjs/helpers/recoverZeroClient.cjs +64 -7
- package/dist/cjs/helpers/recoverZeroClient.native.js +72 -9
- package/dist/cjs/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/cjs/helpers/recoverZeroClient.test.cjs +60 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js +60 -0
- package/dist/cjs/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.native.js +1 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.mjs +64 -8
- package/dist/esm/helpers/recoverZeroClient.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.native.js +72 -10
- package/dist/esm/helpers/recoverZeroClient.native.js.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs +61 -1
- package/dist/esm/helpers/recoverZeroClient.test.mjs.map +1 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js +61 -1
- package/dist/esm/helpers/recoverZeroClient.test.native.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -2
- package/dist/esm/index.native.js.map +1 -1
- package/package.json +2 -2
- package/src/helpers/recoverZeroClient.test.ts +66 -0
- package/src/helpers/recoverZeroClient.ts +91 -15
- package/src/index.ts +3 -0
- package/types/helpers/recoverZeroClient.d.ts +9 -1
- package/types/helpers/recoverZeroClient.d.ts.map +1 -1
- package/types/index.d.ts +1 -1
- package/types/index.d.ts.map +1 -1
|
@@ -4,6 +4,7 @@ import { UpdateNeededReasonType } from '@rocicorp/zero'
|
|
|
4
4
|
import { beforeEach, describe, expect, test, vi } from 'vitest'
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
+
classifyZeroRecoveryLog,
|
|
7
8
|
composeRecoveryLogSink,
|
|
8
9
|
makeZeroRecovery,
|
|
9
10
|
resetRecoveryStateForTests,
|
|
@@ -131,6 +132,38 @@ describe('zero recovery', () => {
|
|
|
131
132
|
expect(reload).toHaveBeenCalledTimes(1)
|
|
132
133
|
})
|
|
133
134
|
|
|
135
|
+
test('logSink recovers on native sqlite finalized-statement local-store loss', async () => {
|
|
136
|
+
const { deps, deleteLocalState, reload } = setup()
|
|
137
|
+
const sqliteError = new Error('This statement has been finalized')
|
|
138
|
+
sqliteError.name = 'SqliteError'
|
|
139
|
+
const sink = composeRecoveryLogSink(deps)
|
|
140
|
+
sink.log('error', { bgIntervalProcess: 'Heartbeat' }, 'Error running.', sqliteError)
|
|
141
|
+
await flush()
|
|
142
|
+
expect(deleteLocalState).toHaveBeenCalledTimes(1)
|
|
143
|
+
expect(reload).toHaveBeenCalledTimes(1)
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
test('logSink recovers on repeated store-closed local-store loss', async () => {
|
|
147
|
+
const nowSpy = vi.spyOn(Date, 'now')
|
|
148
|
+
const { deps, deleteLocalState, reload } = setup()
|
|
149
|
+
try {
|
|
150
|
+
const sink = composeRecoveryLogSink(deps)
|
|
151
|
+
nowSpy.mockReturnValue(10_000)
|
|
152
|
+
sink.log('error', undefined, 'Failed to connect.', new Error('Store is closed'))
|
|
153
|
+
await flush()
|
|
154
|
+
expect(deleteLocalState).not.toHaveBeenCalled()
|
|
155
|
+
expect(reload).not.toHaveBeenCalled()
|
|
156
|
+
|
|
157
|
+
nowSpy.mockReturnValue(13_000)
|
|
158
|
+
sink.log('error', undefined, 'Failed to connect.', new Error('Store is closed'))
|
|
159
|
+
await flush()
|
|
160
|
+
expect(deleteLocalState).toHaveBeenCalledTimes(1)
|
|
161
|
+
expect(reload).toHaveBeenCalledTimes(1)
|
|
162
|
+
} finally {
|
|
163
|
+
nowSpy.mockRestore()
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
|
|
134
167
|
test('logSink with no consumer preserves console output and still watches', async () => {
|
|
135
168
|
const { deps, deleteLocalState, reload } = setup()
|
|
136
169
|
const infoSpy = vi.spyOn(console, 'info').mockImplementation(() => {})
|
|
@@ -170,6 +203,39 @@ describe('zero recovery', () => {
|
|
|
170
203
|
expect(reload).not.toHaveBeenCalled()
|
|
171
204
|
})
|
|
172
205
|
|
|
206
|
+
test('recovery log classification is narrow', () => {
|
|
207
|
+
const sqliteError = new Error('This statement has been finalized')
|
|
208
|
+
sqliteError.name = 'SqliteError'
|
|
209
|
+
expect(
|
|
210
|
+
classifyZeroRecoveryLog('error', ['Error running.', sqliteError]),
|
|
211
|
+
).toMatchObject({
|
|
212
|
+
reason: 'sqlite-statement-finalized',
|
|
213
|
+
dropLocalState: true,
|
|
214
|
+
})
|
|
215
|
+
expect(
|
|
216
|
+
classifyZeroRecoveryLog('error', [
|
|
217
|
+
{ name: 'SqliteError', message: 'database is locked' },
|
|
218
|
+
]),
|
|
219
|
+
).toBeUndefined()
|
|
220
|
+
expect(
|
|
221
|
+
classifyZeroRecoveryLog('warn', ['Expected IndexedDB not found']),
|
|
222
|
+
).toBeUndefined()
|
|
223
|
+
expect(classifyZeroRecoveryLog('error', ['Store is closed'], 10_000)).toBeUndefined()
|
|
224
|
+
expect(classifyZeroRecoveryLog('error', ['Store is closed'], 11_000)).toBeUndefined()
|
|
225
|
+
expect(classifyZeroRecoveryLog('error', ['Store is closed'], 14_000)).toMatchObject({
|
|
226
|
+
reason: 'store-closed-repeat',
|
|
227
|
+
dropLocalState: true,
|
|
228
|
+
})
|
|
229
|
+
resetRecoveryStateForTests()
|
|
230
|
+
expect(
|
|
231
|
+
classifyZeroRecoveryLog(
|
|
232
|
+
'error',
|
|
233
|
+
['Mutator "send" error on server', 'Store is closed'],
|
|
234
|
+
20_000,
|
|
235
|
+
),
|
|
236
|
+
).toBeUndefined()
|
|
237
|
+
})
|
|
238
|
+
|
|
173
239
|
// a host with a `window` shim but no real `location` — the sootsim tenant
|
|
174
240
|
// render-worker, which hides `location` for isolation. the DEFAULT reload
|
|
175
241
|
// path (no injected `deps.reload`) must still drop stale IDB and not throw
|
|
@@ -10,6 +10,23 @@ const RECOVER_GUARD_MS = 60_000
|
|
|
10
10
|
// the fatal local-store-loss signature Zero logs when the IndexedDB it expects
|
|
11
11
|
// is gone (evicted, or deleted by another tab).
|
|
12
12
|
const LOCAL_STORE_LOST = 'Expected IndexedDB not found'
|
|
13
|
+
const SQLITE_ERROR_NAME = 'SqliteError'
|
|
14
|
+
const SQLITE_STATEMENT_FINALIZED = 'This statement has been finalized'
|
|
15
|
+
const STORE_CLOSED = 'Store is closed'
|
|
16
|
+
const STORE_CLOSED_REPEAT_MIN_MS = 2_000
|
|
17
|
+
const STORE_CLOSED_REPEAT_MAX_MS = 60_000
|
|
18
|
+
|
|
19
|
+
export type ZeroRecoveryLogReason =
|
|
20
|
+
| 'indexeddb-not-found'
|
|
21
|
+
| 'sqlite-statement-finalized'
|
|
22
|
+
| 'store-closed-repeat'
|
|
23
|
+
|
|
24
|
+
export type ZeroRecoveryLogClassification = {
|
|
25
|
+
reason: ZeroRecoveryLogReason
|
|
26
|
+
reasonKey: string
|
|
27
|
+
message: string
|
|
28
|
+
dropLocalState: boolean
|
|
29
|
+
}
|
|
13
30
|
|
|
14
31
|
export type ZeroRecoveryDeps = {
|
|
15
32
|
// delete THIS client's local persistent state (its own scoped IDB). pass the
|
|
@@ -38,15 +55,22 @@ const pendingDeletes: Array<Promise<unknown>> = []
|
|
|
38
55
|
function recoveryGuardOpen(reasonKey: string): boolean {
|
|
39
56
|
try {
|
|
40
57
|
const key = `on-zero-recover-${reasonKey}`
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
const rawLast = window.sessionStorage.getItem(key)
|
|
59
|
+
const now = Date.now()
|
|
60
|
+
const last = rawLast ? Number(rawLast) : 0
|
|
61
|
+
if (last > 0 && now - last < RECOVER_GUARD_MS) return false
|
|
62
|
+
window.sessionStorage.setItem(key, String(now))
|
|
44
63
|
} catch {
|
|
45
64
|
// no sessionStorage (private mode) — fall back to the in-memory latch.
|
|
46
65
|
}
|
|
47
66
|
return true
|
|
48
67
|
}
|
|
49
68
|
|
|
69
|
+
// "Store is closed" is noisy during intentional instance replacement. One log is
|
|
70
|
+
// teardown noise; repeated logs seconds apart mean a live client is stuck using a
|
|
71
|
+
// closed local store and needs fresh local state.
|
|
72
|
+
let lastStoreClosedAtMs = 0
|
|
73
|
+
|
|
50
74
|
function recover(
|
|
51
75
|
deps: ZeroRecoveryDeps,
|
|
52
76
|
reasonKey: string,
|
|
@@ -137,6 +161,66 @@ function logToConsole(
|
|
|
137
161
|
console[method](...(prefix ? [prefix] : []), ...args)
|
|
138
162
|
}
|
|
139
163
|
|
|
164
|
+
function logArgText(arg: unknown): string {
|
|
165
|
+
if (typeof arg === 'string') return arg
|
|
166
|
+
if (arg instanceof Error) return `${arg.name} ${arg.message} ${arg.stack || ''}`
|
|
167
|
+
if (arg && typeof arg === 'object') {
|
|
168
|
+
const message = 'message' in arg ? (arg as { message?: unknown }).message : undefined
|
|
169
|
+
const name = 'name' in arg ? (arg as { name?: unknown }).name : undefined
|
|
170
|
+
if (typeof message === 'string')
|
|
171
|
+
return `${typeof name === 'string' ? name : ''} ${message}`
|
|
172
|
+
}
|
|
173
|
+
return ''
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isBenignStoreClosedLog(text: string): boolean {
|
|
177
|
+
if (/Mutator\s+".*"\s+error on server/i.test(text)) return true
|
|
178
|
+
if (/Mutator\s+".*"\s+app error on client/i.test(text)) return true
|
|
179
|
+
return false
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function classifyZeroRecoveryLog(
|
|
183
|
+
level: LogLevel | string,
|
|
184
|
+
args: readonly unknown[],
|
|
185
|
+
nowMs = Date.now(),
|
|
186
|
+
): ZeroRecoveryLogClassification | undefined {
|
|
187
|
+
if (level !== 'error') return undefined
|
|
188
|
+
const text = args.map(logArgText).join(' ')
|
|
189
|
+
if (text.includes(LOCAL_STORE_LOST)) {
|
|
190
|
+
return {
|
|
191
|
+
reason: 'indexeddb-not-found',
|
|
192
|
+
reasonKey: 'local-store',
|
|
193
|
+
message: 'local store lost',
|
|
194
|
+
dropLocalState: true,
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (text.includes(SQLITE_ERROR_NAME) && text.includes(SQLITE_STATEMENT_FINALIZED)) {
|
|
198
|
+
return {
|
|
199
|
+
reason: 'sqlite-statement-finalized',
|
|
200
|
+
reasonKey: 'sqlite-statement-finalized',
|
|
201
|
+
message: 'sqlite statement finalized',
|
|
202
|
+
dropLocalState: true,
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (text.includes(STORE_CLOSED) && !isBenignStoreClosedLog(text)) {
|
|
206
|
+
const prevMs = lastStoreClosedAtMs
|
|
207
|
+
lastStoreClosedAtMs = nowMs
|
|
208
|
+
if (
|
|
209
|
+
prevMs > 0 &&
|
|
210
|
+
nowMs - prevMs >= STORE_CLOSED_REPEAT_MIN_MS &&
|
|
211
|
+
nowMs - prevMs <= STORE_CLOSED_REPEAT_MAX_MS
|
|
212
|
+
) {
|
|
213
|
+
return {
|
|
214
|
+
reason: 'store-closed-repeat',
|
|
215
|
+
reasonKey: 'store-closed-repeat',
|
|
216
|
+
message: 'local store closed repeatedly',
|
|
217
|
+
dropLocalState: true,
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return undefined
|
|
222
|
+
}
|
|
223
|
+
|
|
140
224
|
// watch error-level logs for the local-store-lost signature (the one fatal Zero
|
|
141
225
|
// surfaces only through the log, not the structured callbacks) and trigger the
|
|
142
226
|
// same recovery. forwards to the consumer sink, or to the console when there is
|
|
@@ -151,18 +235,9 @@ export function composeRecoveryLogSink(
|
|
|
151
235
|
log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {
|
|
152
236
|
if (consumerLogSink) consumerLogSink.log(level, context, ...args)
|
|
153
237
|
else logToConsole(level, context, ...args)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
.
|
|
157
|
-
typeof arg === 'string'
|
|
158
|
-
? arg
|
|
159
|
-
: arg && typeof arg === 'object' && 'message' in arg
|
|
160
|
-
? String((arg as { message: unknown }).message)
|
|
161
|
-
: '',
|
|
162
|
-
)
|
|
163
|
-
.join(' ')
|
|
164
|
-
if (text.includes(LOCAL_STORE_LOST)) {
|
|
165
|
-
recover(deps, 'local-store', 'local store lost', true)
|
|
238
|
+
const recovery = classifyZeroRecoveryLog(level, args)
|
|
239
|
+
if (recovery) {
|
|
240
|
+
recover(deps, recovery.reasonKey, recovery.message, recovery.dropLocalState)
|
|
166
241
|
}
|
|
167
242
|
},
|
|
168
243
|
// call through the consumer sink so a class-based sink keeps its `this`,
|
|
@@ -176,4 +251,5 @@ export function composeRecoveryLogSink(
|
|
|
176
251
|
export function resetRecoveryStateForTests() {
|
|
177
252
|
reloadScheduled = false
|
|
178
253
|
pendingDeletes.length = 0
|
|
254
|
+
lastStoreClosedAtMs = 0
|
|
179
255
|
}
|
package/src/index.ts
CHANGED
|
@@ -42,7 +42,10 @@ export {
|
|
|
42
42
|
type ZeroClientErrorInfo,
|
|
43
43
|
} from './helpers/showZeroClientError'
|
|
44
44
|
export {
|
|
45
|
+
classifyZeroRecoveryLog,
|
|
45
46
|
makeZeroRecovery,
|
|
46
47
|
composeRecoveryLogSink,
|
|
48
|
+
type ZeroRecoveryLogClassification,
|
|
49
|
+
type ZeroRecoveryLogReason,
|
|
47
50
|
type ZeroRecoveryDeps,
|
|
48
51
|
} from './helpers/recoverZeroClient'
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { Emitter } from '@take-out/helpers';
|
|
2
2
|
import type { ZeroEvent } from '../types';
|
|
3
3
|
import type { UpdateNeededReason } from '@rocicorp/zero';
|
|
4
|
-
import type { LogSink } from '@rocicorp/logger';
|
|
4
|
+
import type { LogLevel, LogSink } from '@rocicorp/logger';
|
|
5
|
+
export type ZeroRecoveryLogReason = 'indexeddb-not-found' | 'sqlite-statement-finalized' | 'store-closed-repeat';
|
|
6
|
+
export type ZeroRecoveryLogClassification = {
|
|
7
|
+
reason: ZeroRecoveryLogReason;
|
|
8
|
+
reasonKey: string;
|
|
9
|
+
message: string;
|
|
10
|
+
dropLocalState: boolean;
|
|
11
|
+
};
|
|
5
12
|
export type ZeroRecoveryDeps = {
|
|
6
13
|
deleteLocalState: () => Promise<unknown>;
|
|
7
14
|
zeroEvents: Emitter<ZeroEvent | null>;
|
|
@@ -12,6 +19,7 @@ export declare function makeZeroRecovery(deps: ZeroRecoveryDeps): {
|
|
|
12
19
|
onUpdateNeeded(reason: UpdateNeededReason): void;
|
|
13
20
|
onClientStateNotFound(): void;
|
|
14
21
|
};
|
|
22
|
+
export declare function classifyZeroRecoveryLog(level: LogLevel | string, args: readonly unknown[], nowMs?: number): ZeroRecoveryLogClassification | undefined;
|
|
15
23
|
export declare function composeRecoveryLogSink(deps: ZeroRecoveryDeps, consumerLogSink?: LogSink): LogSink;
|
|
16
24
|
export declare function resetRecoveryStateForTests(): void;
|
|
17
25
|
//# sourceMappingURL=recoverZeroClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recoverZeroClient.d.ts","sourceRoot":"","sources":["../../src/helpers/recoverZeroClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"recoverZeroClient.d.ts","sourceRoot":"","sources":["../../src/helpers/recoverZeroClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,KAAK,EAAW,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAelE,MAAM,MAAM,qBAAqB,GAC7B,qBAAqB,GACrB,4BAA4B,GAC5B,qBAAqB,CAAA;AAEzB,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,qBAAqB,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAI7B,gBAAgB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAExC,UAAU,EAAE,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAA;IAGrC,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAElC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AA6ED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB;2BAE5B,kBAAkB;;EAsB5C;AAsCD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,QAAQ,GAAG,MAAM,EACxB,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,KAAK,SAAa,GACjB,6BAA6B,GAAG,SAAS,CAoC3C;AAOD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,gBAAgB,EACtB,eAAe,CAAC,EAAE,OAAO,GACxB,OAAO,CAeT;AAID,wBAAgB,0BAA0B,SAIzC"}
|
package/types/index.d.ts
CHANGED
|
@@ -21,5 +21,5 @@ export { defineQuery, defineQueries } from '@rocicorp/zero';
|
|
|
21
21
|
export type * from './types';
|
|
22
22
|
export { clearZeroClientData, type ClearZeroClientDataOptions, } from './helpers/clearZeroClientData';
|
|
23
23
|
export { showZeroClientErrorOnce, resetShownZeroClientError, type ShowZeroClientErrorOptions, type ZeroClientErrorInfo, } from './helpers/showZeroClientError';
|
|
24
|
-
export { makeZeroRecovery, composeRecoveryLogSink, type ZeroRecoveryDeps, } from './helpers/recoverZeroClient';
|
|
24
|
+
export { classifyZeroRecoveryLog, makeZeroRecovery, composeRecoveryLogSink, type ZeroRecoveryLogClassification, type ZeroRecoveryLogReason, type ZeroRecoveryDeps, } from './helpers/recoverZeroClient';
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,OAAO,CAAA;AACrB,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AACzD,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,OAAO,CAAA;AACrB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAM3D,mBAAmB,SAAS,CAAA;AAE5B,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,GACzB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,sBAAsB,CAAA;AACpC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAErD,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,kBAAkB,GACxB,MAAM,oBAAoB,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,OAAO,CAAA;AACrB,OAAO,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AACzD,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,OAAO,CAAA;AACrB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAM3D,mBAAmB,SAAS,CAAA;AAE5B,OAAO,EACL,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,GACzB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAA"}
|