@livestore/livestore 0.0.46-dev.4 → 0.0.47-dev.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 +10 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/__tests__/react/fixture.d.ts +28 -12
- package/dist/__tests__/react/fixture.d.ts.map +1 -1
- package/dist/__tests__/react/fixture.js +27 -3
- package/dist/__tests__/react/fixture.js.map +1 -1
- package/dist/__tests__/react/utils/otel.d.ts +10 -0
- package/dist/__tests__/react/utils/otel.d.ts.map +1 -0
- package/dist/__tests__/react/utils/otel.js +42 -0
- package/dist/__tests__/react/utils/otel.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/LiveStoreProvider.js +39 -6
- package/dist/react/LiveStoreProvider.js.map +1 -1
- package/dist/react/LiveStoreProvider.test.d.ts +2 -0
- package/dist/react/LiveStoreProvider.test.d.ts.map +1 -0
- package/dist/react/LiveStoreProvider.test.js +40 -0
- package/dist/react/LiveStoreProvider.test.js.map +1 -0
- package/dist/react/components/LiveList.d.ts +21 -0
- package/dist/react/components/LiveList.d.ts.map +1 -0
- package/dist/react/components/LiveList.js +31 -0
- package/dist/react/components/LiveList.js.map +1 -0
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/useAtom.d.ts +1 -1
- package/dist/react/useAtom.d.ts.map +1 -1
- package/dist/react/useAtom.js +6 -1
- package/dist/react/useAtom.js.map +1 -1
- package/dist/react/useQuery.d.ts +4 -1
- package/dist/react/useQuery.d.ts.map +1 -1
- package/dist/react/useQuery.js +24 -19
- package/dist/react/useQuery.js.map +1 -1
- package/dist/react/useQuery.test.js +11 -11
- package/dist/react/useQuery.test.js.map +1 -1
- package/dist/react/useRow.d.ts.map +1 -1
- package/dist/react/useRow.js +14 -69
- package/dist/react/useRow.js.map +1 -1
- package/dist/react/useRow.test.js +440 -28
- package/dist/react/useRow.test.js.map +1 -1
- package/dist/react/useTemporaryQuery.d.ts +15 -3
- package/dist/react/useTemporaryQuery.d.ts.map +1 -1
- package/dist/react/useTemporaryQuery.js +60 -27
- package/dist/react/useTemporaryQuery.js.map +1 -1
- package/dist/react/useTemporaryQuery.test.js +10 -9
- package/dist/react/useTemporaryQuery.test.js.map +1 -1
- package/dist/reactive.d.ts +23 -5
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +44 -11
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +1 -1
- package/dist/reactive.test.js.map +1 -1
- package/dist/reactiveQueries/base-class.d.ts +1 -1
- package/dist/reactiveQueries/base-class.d.ts.map +1 -1
- package/dist/reactiveQueries/base-class.js.map +1 -1
- package/dist/reactiveQueries/graphql.d.ts +2 -2
- package/dist/reactiveQueries/graphql.d.ts.map +1 -1
- package/dist/reactiveQueries/graphql.js +21 -11
- package/dist/reactiveQueries/graphql.js.map +1 -1
- package/dist/reactiveQueries/sql.d.ts +1 -1
- package/dist/reactiveQueries/sql.d.ts.map +1 -1
- package/dist/reactiveQueries/sql.js +15 -11
- package/dist/reactiveQueries/sql.js.map +1 -1
- package/dist/reactiveQueries/sql.test.js +1 -40
- package/dist/reactiveQueries/sql.test.js.map +1 -1
- package/dist/row-query.d.ts.map +1 -1
- package/dist/row-query.js +3 -1
- package/dist/row-query.js.map +1 -1
- package/dist/store.d.ts +7 -5
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +50 -38
- package/dist/store.js.map +1 -1
- package/package.json +11 -13
- package/src/__tests__/react/fixture.tsx +35 -2
- package/src/__tests__/react/utils/otel.ts +61 -0
- package/src/index.ts +12 -1
- package/src/react/LiveStoreProvider.test.tsx +63 -0
- package/src/react/LiveStoreProvider.tsx +42 -7
- package/src/react/components/LiveList.tsx +84 -0
- package/src/react/index.ts +1 -1
- package/src/react/useAtom.ts +6 -2
- package/src/react/useQuery.test.tsx +11 -11
- package/src/react/useQuery.ts +29 -22
- package/src/react/useRow.test.tsx +502 -30
- package/src/react/useRow.ts +19 -107
- package/src/react/useTemporaryQuery.test.tsx +17 -16
- package/src/react/useTemporaryQuery.ts +96 -28
- package/src/reactive.test.ts +1 -1
- package/src/reactive.ts +76 -15
- package/src/reactiveQueries/base-class.ts +2 -1
- package/src/reactiveQueries/graphql.ts +26 -16
- package/src/reactiveQueries/sql.test.ts +1 -54
- package/src/reactiveQueries/sql.ts +20 -14
- package/src/row-query.ts +3 -1
- package/src/store.ts +71 -49
- package/tsconfig.json +0 -1
- package/dist/react/components/DiffableList.d.ts +0 -20
- package/dist/react/components/DiffableList.d.ts.map +0 -1
- package/dist/react/components/DiffableList.js +0 -113
- package/dist/react/components/DiffableList.js.map +0 -1
- package/dist/react/utils/useCleanup.d.ts +0 -7
- package/dist/react/utils/useCleanup.d.ts.map +0 -1
- package/dist/react/utils/useCleanup.js +0 -19
- package/dist/react/utils/useCleanup.js.map +0 -1
- package/src/react/components/DiffableList.tsx +0 -192
- package/src/react/utils/useCleanup.ts +0 -25
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as otel from '@opentelemetry/api'
|
|
2
|
-
import type { ReadableSpan } from '@opentelemetry/sdk-trace-base'
|
|
3
2
|
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
|
|
4
3
|
import { describe, expect, it } from 'vitest'
|
|
5
4
|
|
|
6
5
|
import { makeTodoMvc, todos } from '../__tests__/react/fixture.js'
|
|
6
|
+
import { getSimplifiedRootSpan } from '../__tests__/react/utils/otel.js'
|
|
7
7
|
import { computed, ParseUtils, querySQL, rawSqlMutation, sql } from '../index.js'
|
|
8
8
|
|
|
9
9
|
/*
|
|
@@ -299,56 +299,3 @@ describe('otel', () => {
|
|
|
299
299
|
`)
|
|
300
300
|
})
|
|
301
301
|
})
|
|
302
|
-
|
|
303
|
-
const compareHrTime = (a: [number, number], b: [number, number]) => {
|
|
304
|
-
if (a[0] !== b[0]) return a[0] - b[0]
|
|
305
|
-
return a[1] - b[1]
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const omitEmpty = (obj: any) => {
|
|
309
|
-
const result: any = {}
|
|
310
|
-
for (const key in obj) {
|
|
311
|
-
if (
|
|
312
|
-
obj[key] !== undefined &&
|
|
313
|
-
!(Array.isArray(obj[key]) && obj[key].length === 0) &&
|
|
314
|
-
Object.keys(obj[key]).length > 0
|
|
315
|
-
) {
|
|
316
|
-
result[key] = obj[key]
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return result
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
const getSimplifiedRootSpan = (exporter: InMemorySpanExporter) => {
|
|
323
|
-
const spans = exporter.getFinishedSpans()
|
|
324
|
-
const spansMap = new Map<string, NestedSpan>(spans.map((span) => [span.spanContext().spanId, { span, children: [] }]))
|
|
325
|
-
|
|
326
|
-
spansMap.forEach((nestedSpan) => {
|
|
327
|
-
const parentSpan = nestedSpan.span.parentSpanId ? spansMap.get(nestedSpan.span.parentSpanId) : undefined
|
|
328
|
-
if (parentSpan) {
|
|
329
|
-
parentSpan.children.push(nestedSpan)
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
|
|
333
|
-
type NestedSpan = { span: ReadableSpan; children: NestedSpan[] }
|
|
334
|
-
const rootSpan = spansMap.get(spans.find((_) => _.name === 'test')!.spanContext().spanId)!
|
|
335
|
-
|
|
336
|
-
type SimplifiedNestedSpan = { _name: string; attributes: any; children: SimplifiedNestedSpan[] }
|
|
337
|
-
|
|
338
|
-
const simplifySpan = (span: NestedSpan): SimplifiedNestedSpan =>
|
|
339
|
-
omitEmpty({
|
|
340
|
-
_name: span.span.name,
|
|
341
|
-
attributes: span.span.attributes,
|
|
342
|
-
children: span.children
|
|
343
|
-
.filter((_) => _.span.name !== 'createStore')
|
|
344
|
-
.sort((a, b) => compareHrTime(a.span.startTime, b.span.startTime))
|
|
345
|
-
.map(simplifySpan),
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
// console.dir(
|
|
349
|
-
// spans.map((_) => [_.spanContext().spanId, _.name, _.attributes, _.parentSpanId]),
|
|
350
|
-
// { depth: 10 },
|
|
351
|
-
// )
|
|
352
|
-
|
|
353
|
-
return simplifySpan(rootSpan)
|
|
354
|
-
}
|
|
@@ -49,7 +49,7 @@ export class LiveStoreSQLQuery<TResult, TQueryInfo extends QueryInfo = QueryInfo
|
|
|
49
49
|
_tag: 'sql' = 'sql'
|
|
50
50
|
|
|
51
51
|
/** A reactive thunk representing the query text */
|
|
52
|
-
queryString$: Thunk<string, DbContext, RefreshReason>
|
|
52
|
+
queryString$: Thunk<string, DbContext, RefreshReason> | undefined
|
|
53
53
|
|
|
54
54
|
/** A reactive thunk representing the query results */
|
|
55
55
|
results$: Thunk<TResult, DbContext, RefreshReason>
|
|
@@ -126,23 +126,23 @@ Result:`,
|
|
|
126
126
|
? map
|
|
127
127
|
: shouldNeverHappen(`Invalid map function ${map}`)
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
let queryString$OrQueryString: string | Thunk<string, DbContext, RefreshReason>
|
|
130
|
+
if (typeof genQueryString === 'function') {
|
|
131
|
+
queryString$OrQueryString = this.dbGraph.makeThunk(
|
|
132
|
+
(get, setDebugInfo, { rootOtelContext }, otelContext) => {
|
|
133
133
|
const startMs = performance.now()
|
|
134
134
|
const queryString = genQueryString(makeGetAtomResult(get, otelContext ?? rootOtelContext))
|
|
135
135
|
const durationMs = performance.now() - startMs
|
|
136
136
|
setDebugInfo({ _tag: 'js', label: `${label}:queryString`, query: queryString, durationMs })
|
|
137
137
|
return queryString
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
},
|
|
142
|
-
{ label: `${label}:queryString`, meta: { liveStoreThunkType: 'sqlQueryString' } },
|
|
143
|
-
)
|
|
138
|
+
},
|
|
139
|
+
{ label: `${label}:queryString`, meta: { liveStoreThunkType: 'sqlQueryString' } },
|
|
140
|
+
)
|
|
144
141
|
|
|
145
|
-
|
|
142
|
+
this.queryString$ = queryString$OrQueryString
|
|
143
|
+
} else {
|
|
144
|
+
queryString$OrQueryString = genQueryString
|
|
145
|
+
}
|
|
146
146
|
|
|
147
147
|
const queryLabel = `${label}:results`
|
|
148
148
|
|
|
@@ -162,7 +162,10 @@ Result:`,
|
|
|
162
162
|
this.execBeforeFirstRun = undefined
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
const sqlString =
|
|
165
|
+
const sqlString =
|
|
166
|
+
typeof queryString$OrQueryString === 'string'
|
|
167
|
+
? queryString$OrQueryString
|
|
168
|
+
: get(queryString$OrQueryString, otelContext)
|
|
166
169
|
|
|
167
170
|
if (queriedTablesRef.current === undefined) {
|
|
168
171
|
queriedTablesRef.current = store.mainDbWrapper.getTablesUsed(sqlString)
|
|
@@ -238,7 +241,10 @@ Result:`,
|
|
|
238
241
|
// })
|
|
239
242
|
|
|
240
243
|
destroy = () => {
|
|
241
|
-
|
|
244
|
+
if (this.queryString$ !== undefined) {
|
|
245
|
+
this.dbGraph.destroyNode(this.queryString$)
|
|
246
|
+
}
|
|
247
|
+
|
|
242
248
|
this.dbGraph.destroyNode(this.results$)
|
|
243
249
|
}
|
|
244
250
|
}
|
package/src/row-query.ts
CHANGED
|
@@ -78,6 +78,9 @@ export const rowQuery: MakeRowQuery = <TTableDef extends DbSchema.TableDef>(
|
|
|
78
78
|
genQueryString: queryStr,
|
|
79
79
|
queriedTables: new Set([componentTableName]),
|
|
80
80
|
dbGraph: options?.dbGraph,
|
|
81
|
+
// TODO remove this once the LiveStore Devtools are no longer relying on it
|
|
82
|
+
// as the defaults rows are now already being inserted during store initialization
|
|
83
|
+
// and the tables need to be registered during initialization
|
|
81
84
|
execBeforeFirstRun: makeExecBeforeFirstRun({
|
|
82
85
|
otelContext: options?.otelContext,
|
|
83
86
|
table,
|
|
@@ -201,7 +204,6 @@ const makeExecBeforeFirstRun =
|
|
|
201
204
|
}
|
|
202
205
|
|
|
203
206
|
if (skipInsertDefaultRow !== true) {
|
|
204
|
-
// TODO find a way to only do this if necessary
|
|
205
207
|
insertRowWithDefaultValuesOrIgnore({
|
|
206
208
|
store,
|
|
207
209
|
id: id ?? 'singleton',
|
package/src/store.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
type DatabaseFactory,
|
|
3
|
+
type DatabaseImpl,
|
|
4
|
+
getExecArgsFromMutation,
|
|
5
|
+
type PreparedBindValues,
|
|
6
|
+
} from '@livestore/common'
|
|
7
|
+
import type { LiveStoreSchema, MutationEvent, MutationEventSchema } from '@livestore/common/schema'
|
|
8
|
+
import { makeMutationEventSchema } from '@livestore/common/schema'
|
|
3
9
|
import { assertNever, isPromise, makeNoopTracer, shouldNeverHappen } from '@livestore/utils'
|
|
4
10
|
import { Schema } from '@livestore/utils/effect'
|
|
5
11
|
import * as otel from '@opentelemetry/api'
|
|
@@ -7,7 +13,6 @@ import type { GraphQLSchema } from 'graphql'
|
|
|
7
13
|
|
|
8
14
|
import { globalDbGraph } from './global-state.js'
|
|
9
15
|
import { MainDatabaseWrapper } from './MainDatabaseWrapper.js'
|
|
10
|
-
import { migrateDb } from './migrations.js'
|
|
11
16
|
import type { StackInfo } from './react/utils/stack-info.js'
|
|
12
17
|
import type { DebugRefreshReasonBase, ReactiveGraph, Ref } from './reactive.js'
|
|
13
18
|
import type { DbContext, DbGraph, LiveQuery } from './reactiveQueries/base-class.js'
|
|
@@ -39,6 +44,7 @@ export type StoreOptions<
|
|
|
39
44
|
otelTracer: otel.Tracer
|
|
40
45
|
otelRootSpanContext: otel.Context
|
|
41
46
|
dbGraph: DbGraph
|
|
47
|
+
mutationEventSchema: MutationEventSchema<any>
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
export type RefreshReason =
|
|
@@ -77,6 +83,7 @@ const uniqueStoreId = () => `store-${++storeCount}`
|
|
|
77
83
|
|
|
78
84
|
export type BootDb = {
|
|
79
85
|
execute(queryStr: string, bindValues?: ParamsObject): void
|
|
86
|
+
mutate: <const TMutationArg extends ReadonlyArray<MutationEvent.Any>>(...list: TMutationArg) => void
|
|
80
87
|
select<T>(queryStr: string, bindValues?: ParamsObject): ReadonlyArray<T>
|
|
81
88
|
txn(callback: () => void): void
|
|
82
89
|
}
|
|
@@ -105,7 +112,7 @@ export class Store<
|
|
|
105
112
|
/** RC-based set to see which queries are currently subscribed to */
|
|
106
113
|
activeQueries: ReferenceCountedSet<LiveQuery<any>>
|
|
107
114
|
|
|
108
|
-
private
|
|
115
|
+
private mutationEventSchema
|
|
109
116
|
|
|
110
117
|
private constructor({
|
|
111
118
|
db,
|
|
@@ -115,6 +122,7 @@ export class Store<
|
|
|
115
122
|
dbGraph,
|
|
116
123
|
otelTracer,
|
|
117
124
|
otelRootSpanContext,
|
|
125
|
+
mutationEventSchema,
|
|
118
126
|
}: StoreOptions<TGraphQLContext, TSchema>) {
|
|
119
127
|
this.mainDbWrapper = new MainDatabaseWrapper({ otelTracer, otelRootSpanContext, db: db.mainDb })
|
|
120
128
|
this.db = db
|
|
@@ -122,7 +130,8 @@ export class Store<
|
|
|
122
130
|
this.schema = schema
|
|
123
131
|
|
|
124
132
|
// TODO refactor
|
|
125
|
-
this.
|
|
133
|
+
this.mutationEventSchema = mutationEventSchema
|
|
134
|
+
// this.mutationEventSchema = makeMutationEventSchema(Object.fromEntries(schema.mutations.entries()) as any)
|
|
126
135
|
|
|
127
136
|
// TODO generalize the `tableRefs` concept to allow finer-grained refs
|
|
128
137
|
this.tableRefs = {}
|
|
@@ -184,22 +193,23 @@ export class Store<
|
|
|
184
193
|
* Returns a function to cancel the subscription.
|
|
185
194
|
*/
|
|
186
195
|
subscribe = <TResult>(
|
|
187
|
-
query
|
|
196
|
+
query$: LiveQuery<TResult, any>,
|
|
188
197
|
onNewValue: (value: TResult) => void,
|
|
189
198
|
onUnsubsubscribe?: () => void,
|
|
190
199
|
options?: { label?: string; otelContext?: otel.Context; skipInitialRun?: boolean } | undefined,
|
|
191
200
|
): (() => void) =>
|
|
192
201
|
this.otel.tracer.startActiveSpan(
|
|
193
202
|
`LiveStore.subscribe`,
|
|
194
|
-
{ attributes: { label: options?.label, queryLabel: query
|
|
203
|
+
{ attributes: { label: options?.label, queryLabel: query$.label } },
|
|
195
204
|
options?.otelContext ?? this.otel.queriesSpanContext,
|
|
196
205
|
(span) => {
|
|
206
|
+
// console.log('store sub', query$.label)
|
|
197
207
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
198
208
|
|
|
199
209
|
const label = `subscribe:${options?.label}`
|
|
200
|
-
const effect = this.graph.makeEffect((get) => onNewValue(get(query
|
|
210
|
+
const effect = this.graph.makeEffect((get) => onNewValue(get(query$.results$)), { label })
|
|
201
211
|
|
|
202
|
-
this.activeQueries.add(query as LiveQuery<TResult>)
|
|
212
|
+
this.activeQueries.add(query$ as LiveQuery<TResult>)
|
|
203
213
|
|
|
204
214
|
// Running effect right away to get initial value (unless `skipInitialRun` is set)
|
|
205
215
|
if (options?.skipInitialRun !== true) {
|
|
@@ -207,9 +217,10 @@ export class Store<
|
|
|
207
217
|
}
|
|
208
218
|
|
|
209
219
|
const unsubscribe = () => {
|
|
220
|
+
// console.log('store unsub', query$.label)
|
|
210
221
|
try {
|
|
211
222
|
this.graph.destroyNode(effect)
|
|
212
|
-
this.activeQueries.remove(query as LiveQuery<TResult>)
|
|
223
|
+
this.activeQueries.remove(query$ as LiveQuery<TResult>)
|
|
213
224
|
onUnsubsubscribe?.()
|
|
214
225
|
} finally {
|
|
215
226
|
span.end()
|
|
@@ -225,7 +236,7 @@ export class Store<
|
|
|
225
236
|
*
|
|
226
237
|
* Currently only used when shutting down the app for debugging purposes (e.g. to close Otel spans).
|
|
227
238
|
*/
|
|
228
|
-
destroy = () => {
|
|
239
|
+
destroy = async () => {
|
|
229
240
|
for (const tableRef of Object.values(this.tableRefs)) {
|
|
230
241
|
for (const superComp of tableRef.super) {
|
|
231
242
|
this.graph.removeEdge(superComp, tableRef)
|
|
@@ -234,6 +245,8 @@ export class Store<
|
|
|
234
245
|
|
|
235
246
|
otel.trace.getSpan(this.otel.mutationsSpanContext)!.end()
|
|
236
247
|
otel.trace.getSpan(this.otel.queriesSpanContext)!.end()
|
|
248
|
+
|
|
249
|
+
await this.db.storageDb.shutdown()
|
|
237
250
|
}
|
|
238
251
|
|
|
239
252
|
mutate: {
|
|
@@ -371,48 +384,43 @@ export class Store<
|
|
|
371
384
|
* the caller must refresh queries after calling this method.
|
|
372
385
|
*/
|
|
373
386
|
private mutateWithoutRefresh = (
|
|
374
|
-
|
|
387
|
+
mutationEventDecoded: MutationEvent.ForSchema<TSchema>,
|
|
375
388
|
otelContext: otel.Context,
|
|
376
389
|
): { writeTables: ReadonlySet<string>; durationMs: number } => {
|
|
377
390
|
return this.otel.tracer.startActiveSpan(
|
|
378
391
|
'LiveStore:mutatetWithoutRefresh',
|
|
379
392
|
{
|
|
380
393
|
attributes: {
|
|
381
|
-
'livestore.mutation':
|
|
382
|
-
'livestore.args': JSON.stringify(
|
|
394
|
+
'livestore.mutation': mutationEventDecoded.mutation,
|
|
395
|
+
'livestore.args': JSON.stringify(mutationEventDecoded.args, null, 2),
|
|
383
396
|
},
|
|
384
397
|
},
|
|
385
398
|
otelContext,
|
|
386
399
|
(span) => {
|
|
387
400
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
388
401
|
|
|
389
|
-
const
|
|
390
|
-
|
|
391
|
-
shouldNeverHappen(`Unknown mutation type: ${mutationEvent.mutation}`)
|
|
392
|
-
|
|
393
|
-
const statementRes =
|
|
394
|
-
typeof mutationDef.sql === 'function' ? mutationDef.sql(mutationEvent.args) : mutationDef.sql
|
|
402
|
+
const allWriteTables = new Set<string>()
|
|
403
|
+
let durationMsTotal = 0
|
|
395
404
|
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
? this.mainDbWrapper.getTablesUsed(statementSql)
|
|
400
|
-
: statementRes.writeTables ?? this.mainDbWrapper.getTablesUsed(statementSql)
|
|
405
|
+
const mutationDef =
|
|
406
|
+
this.schema.mutations.get(mutationEventDecoded.mutation) ??
|
|
407
|
+
shouldNeverHappen(`Unknown mutation type: ${mutationEventDecoded.mutation}`)
|
|
401
408
|
|
|
402
|
-
const
|
|
403
|
-
typeof statementRes === 'string'
|
|
404
|
-
? Schema.encodeUnknownSync(mutationDef.schema)(mutationEvent.args)
|
|
405
|
-
: statementRes.bindValues
|
|
409
|
+
const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
|
|
406
410
|
|
|
407
|
-
const {
|
|
411
|
+
for (const {
|
|
408
412
|
statementSql,
|
|
409
|
-
|
|
410
|
-
writeTables,
|
|
411
|
-
|
|
412
|
-
|
|
413
|
+
bindValues,
|
|
414
|
+
writeTables = this.mainDbWrapper.getTablesUsed(statementSql),
|
|
415
|
+
} of execArgsArr) {
|
|
416
|
+
const { durationMs } = this.mainDbWrapper.execute(statementSql, bindValues, writeTables, { otelContext })
|
|
417
|
+
|
|
418
|
+
durationMsTotal += durationMs
|
|
419
|
+
writeTables.forEach((table) => allWriteTables.add(table))
|
|
420
|
+
}
|
|
413
421
|
|
|
414
422
|
// Asynchronously apply mutation to a persistent storage (we're not awaiting this promise here)
|
|
415
|
-
const mutationEventEncoded = Schema.encodeUnknownSync(this.
|
|
423
|
+
const mutationEventEncoded = Schema.encodeUnknownSync(this.mutationEventSchema)(mutationEventDecoded)
|
|
416
424
|
this.db.storageDb.mutate(mutationEventEncoded, span)
|
|
417
425
|
|
|
418
426
|
// Uncomment to print a list of queries currently registered on the store
|
|
@@ -420,7 +428,7 @@ export class Store<
|
|
|
420
428
|
|
|
421
429
|
span.end()
|
|
422
430
|
|
|
423
|
-
return { writeTables, durationMs }
|
|
431
|
+
return { writeTables: allWriteTables, durationMs: durationMsTotal }
|
|
424
432
|
},
|
|
425
433
|
)
|
|
426
434
|
}
|
|
@@ -492,24 +500,21 @@ export const createStore = async <
|
|
|
492
500
|
}): Promise<Store<TGraphQLContext, TSchema>> => {
|
|
493
501
|
return otelTracer.startActiveSpan('createStore', {}, otelRootSpanContext, async (span) => {
|
|
494
502
|
try {
|
|
503
|
+
performance.mark('livestore:db-creating')
|
|
495
504
|
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
496
505
|
|
|
497
|
-
const dbPromise = makeDb({ otelTracer, otelContext })
|
|
506
|
+
const dbPromise = makeDb({ otelTracer, otelContext, schema })
|
|
498
507
|
const db = dbPromise instanceof Promise ? await dbPromise : dbPromise
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
try {
|
|
502
|
-
const otelContext = otel.trace.setSpan(otel.context.active(), span)
|
|
503
|
-
migrateDb({ db, schema, otelContext })
|
|
504
|
-
} finally {
|
|
505
|
-
span.end()
|
|
506
|
-
}
|
|
507
|
-
})
|
|
508
|
+
performance.mark('livestore:db-created')
|
|
509
|
+
performance.measure('livestore:db-create', 'livestore:db-creating', 'livestore:db-created')
|
|
508
510
|
|
|
509
511
|
if (batchUpdates !== undefined) {
|
|
510
512
|
dbGraph.effectsWrapper = batchUpdates
|
|
511
513
|
}
|
|
512
514
|
|
|
515
|
+
const mutationEventSchema = makeMutationEventSchema(Object.fromEntries(schema.mutations.entries()) as any)
|
|
516
|
+
|
|
517
|
+
// TODO consider moving booting into the storage backend
|
|
513
518
|
if (boot !== undefined) {
|
|
514
519
|
let isInTxn = false
|
|
515
520
|
let txnExecuteStmnts: [string, PreparedBindValues | undefined][] = []
|
|
@@ -526,6 +531,23 @@ export const createStore = async <
|
|
|
526
531
|
void db.storageDb.execute(queryStr, preparedBindValues, undefined)
|
|
527
532
|
}
|
|
528
533
|
},
|
|
534
|
+
mutate: (...list) => {
|
|
535
|
+
for (const mutationEventDecoded of list) {
|
|
536
|
+
const mutationDef =
|
|
537
|
+
schema.mutations.get(mutationEventDecoded.mutation) ??
|
|
538
|
+
shouldNeverHappen(`Unknown mutation type: ${mutationEventDecoded.mutation}`)
|
|
539
|
+
|
|
540
|
+
const execArgsArr = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
|
|
541
|
+
// const { bindValues, statementSql } = getExecArgsFromMutation({ mutationDef, mutationEventDecoded })
|
|
542
|
+
|
|
543
|
+
for (const { statementSql, bindValues } of execArgsArr) {
|
|
544
|
+
db.mainDb.execute(statementSql, bindValues)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const mutationEventEncoded = Schema.encodeUnknownSync(mutationEventSchema)(mutationEventDecoded)
|
|
548
|
+
void db.storageDb.mutate(mutationEventEncoded, span)
|
|
549
|
+
}
|
|
550
|
+
},
|
|
529
551
|
select: (queryStr, bindValues) => {
|
|
530
552
|
const stmt = db.mainDb.prepare(queryStr)
|
|
531
553
|
const preparedBindValues = bindValues ? prepareBindValues(bindValues, queryStr) : undefined
|
|
@@ -540,11 +562,11 @@ export const createStore = async <
|
|
|
540
562
|
|
|
541
563
|
db.mainDb.execute('COMMIT', undefined)
|
|
542
564
|
|
|
543
|
-
db.storageDb.execute('BEGIN', undefined, undefined)
|
|
565
|
+
// db.storageDb.execute('BEGIN', undefined, undefined)
|
|
544
566
|
for (const [queryStr, bindValues] of txnExecuteStmnts) {
|
|
545
567
|
db.storageDb.execute(queryStr, bindValues, undefined)
|
|
546
568
|
}
|
|
547
|
-
db.storageDb.execute('COMMIT', undefined, undefined)
|
|
569
|
+
// db.storageDb.execute('COMMIT', undefined, undefined)
|
|
548
570
|
} catch (e: any) {
|
|
549
571
|
db.mainDb.execute('ROLLBACK', undefined)
|
|
550
572
|
throw e
|
|
@@ -566,7 +588,7 @@ export const createStore = async <
|
|
|
566
588
|
// Think about what to do about this case.
|
|
567
589
|
// await applySchema(db, schema)
|
|
568
590
|
return Store.createStore<TGraphQLContext, TSchema>(
|
|
569
|
-
{ db, schema, graphQLOptions, otelTracer, otelRootSpanContext, dbGraph },
|
|
591
|
+
{ db, schema, graphQLOptions, otelTracer, otelRootSpanContext, dbGraph, mutationEventSchema },
|
|
570
592
|
span,
|
|
571
593
|
)
|
|
572
594
|
} finally {
|
package/tsconfig.json
CHANGED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { LiveQuery } from '../../reactiveQueries/base-class.js';
|
|
3
|
-
export type Props<TItem> = {
|
|
4
|
-
items$: LiveQuery<ReadonlyArray<TItem>>;
|
|
5
|
-
/**
|
|
6
|
-
* @example
|
|
7
|
-
* ```tsx
|
|
8
|
-
* renderContainer={(children) => <ul>{children}</ul>}
|
|
9
|
-
* ```
|
|
10
|
-
*/
|
|
11
|
-
renderContainer: (ref: React.LegacyRef<any>) => React.ReactNode;
|
|
12
|
-
renderItem: (item: TItem, opts: {
|
|
13
|
-
index: number;
|
|
14
|
-
isInitialListRender: boolean;
|
|
15
|
-
}) => React.ReactNode;
|
|
16
|
-
getKey: (item: TItem, index: number) => string | number;
|
|
17
|
-
};
|
|
18
|
-
export declare const DiffableList_: <TItem>({ items$, renderContainer, renderItem, getKey, }: Props<TItem>) => React.ReactNode;
|
|
19
|
-
export declare const DiffableList: <TItem>({ items$, renderContainer, renderItem, getKey, }: Props<TItem>) => React.ReactNode;
|
|
20
|
-
//# sourceMappingURL=DiffableList.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiffableList.d.ts","sourceRoot":"","sources":["../../../src/react/components/DiffableList.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAIpE,MAAM,MAAM,KAAK,CAAC,KAAK,IAAI;IACzB,MAAM,EAAE,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAA;IACvC;;;;;OAKG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,SAAS,CAAA;IAE/D,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,OAAO,CAAA;KAAE,KAAK,KAAK,CAAC,SAAS,CAAA;IACnG,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAA;CACxD,CAAA;AAED,eAAO,MAAM,aAAa,4DAKvB,MAAM,KAAK,CAAC,KAAG,MAAM,SAyIvB,CAAA;AAED,eAAO,MAAM,YAAY,4DAKtB,MAAM,KAAK,CAAC,KAAG,MAAM,SAIvB,CAAA"}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { FI } from '@livestore/fractional-index';
|
|
2
|
-
import { casesHandled } from '@livestore/utils';
|
|
3
|
-
import * as itsFine from 'its-fine';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
import ReactDOM from 'react-dom/client';
|
|
6
|
-
import { computed } from '../../reactiveQueries/js.js';
|
|
7
|
-
import { useQuery } from '../useQuery.js';
|
|
8
|
-
export const DiffableList_ = ({ items$, renderContainer, renderItem, getKey, }) => {
|
|
9
|
-
const ref = React.useRef(null);
|
|
10
|
-
const container = renderContainer(ref);
|
|
11
|
-
const [hasMounted, setHasMounted] = React.useState(false);
|
|
12
|
-
React.useEffect(() => setHasMounted(true), []);
|
|
13
|
-
const keys$ = computed((get) => get(items$).map(getKey));
|
|
14
|
-
const elsRef = React.useRef([]);
|
|
15
|
-
const ContextBridge = itsFine.useContextBridge();
|
|
16
|
-
const renderListEl = React.useCallback((parentEl, index, item$) => {
|
|
17
|
-
const root = ReactDOM.createRoot(parentEl);
|
|
18
|
-
root.render(React.createElement(ContextBridge, null,
|
|
19
|
-
React.createElement(ItemWrapper, { "item$": item$, renderItem: renderItem, opts: { index, isInitialListRender: !hasMounted } })));
|
|
20
|
-
return root;
|
|
21
|
-
}, [ContextBridge, hasMounted, renderItem]);
|
|
22
|
-
React.useLayoutEffect(() => {
|
|
23
|
-
if (ref.current === null) {
|
|
24
|
-
throw new Error('ref.current is null');
|
|
25
|
-
}
|
|
26
|
-
const keys = keys$.run();
|
|
27
|
-
for (let index = 0; index < keys.length; index++) {
|
|
28
|
-
const parentEl = document.createElement('div');
|
|
29
|
-
ref.current.append(parentEl);
|
|
30
|
-
const item$ = computed((get) => get(items$)[index]);
|
|
31
|
-
const root = renderListEl(parentEl, index, item$);
|
|
32
|
-
elsRef.current.push({ el: parentEl, item$, root, id: keys[index] });
|
|
33
|
-
}
|
|
34
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
35
|
-
}, []);
|
|
36
|
-
React.useEffect(() => () => keys$.destroy(), [keys$]);
|
|
37
|
-
React.useEffect(() => {
|
|
38
|
-
// const keys = keys$.run()
|
|
39
|
-
return keys$.subscribe((keys) => {
|
|
40
|
-
const prevKeys = elsRef.current.map((el) => el.id);
|
|
41
|
-
let arrayIsEqual = true;
|
|
42
|
-
for (let i = 0; i < keys.length; i++) {
|
|
43
|
-
if (keys[i] !== prevKeys[i]) {
|
|
44
|
-
arrayIsEqual = false;
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (arrayIsEqual)
|
|
49
|
-
return;
|
|
50
|
-
const previousAgg = FI.aggregateMake(prevKeys, FI.fractionalIndexImplNumber);
|
|
51
|
-
const { newEvents } = FI.getNewEvents(previousAgg, keys, FI.fractionalIndexImplNumber);
|
|
52
|
-
console.log('newEvents', newEvents);
|
|
53
|
-
for (const event of newEvents) {
|
|
54
|
-
switch (event.op) {
|
|
55
|
-
case 'remove': {
|
|
56
|
-
const { index } = event;
|
|
57
|
-
const el = elsRef.current[index];
|
|
58
|
-
el.root.unmount();
|
|
59
|
-
el.el.remove();
|
|
60
|
-
el.item$.destroy();
|
|
61
|
-
elsRef.current.splice(index, 1);
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
case 'add': {
|
|
65
|
-
const { index } = event;
|
|
66
|
-
const parentEl = document.createElement('div');
|
|
67
|
-
ref.current.append(parentEl);
|
|
68
|
-
const item$ = computed((get) => get(items$)[index]);
|
|
69
|
-
const root = renderListEl(parentEl, index, item$);
|
|
70
|
-
elsRef.current.splice(index, 0, { el: parentEl, item$, root, id: keys[index] });
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
case 'move': {
|
|
74
|
-
// const { newIndex, previousIndex } = event
|
|
75
|
-
// const el = elsRef.current[previousIndex]!
|
|
76
|
-
// const item$ = el.item$
|
|
77
|
-
// const root = el.root
|
|
78
|
-
// const elEl = el.el
|
|
79
|
-
// elsRef.current.splice(previousIndex, 1)
|
|
80
|
-
// elsRef.current.splice(newIndex, 0, { el: elEl, item$, root })
|
|
81
|
-
// ref.current!.insertBefore(elEl, elsRef.current[newIndex + 1]?.el)
|
|
82
|
-
// // move dom element
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
default: {
|
|
86
|
-
casesHandled(event);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
// for (let index = 0; index < keys.length; index++) {
|
|
92
|
-
// if (prevKeys[index] === keys[index]) continue
|
|
93
|
-
// // check if `keys[index]` === `prevKeys[index + 1]`
|
|
94
|
-
// // which probably means that
|
|
95
|
-
// if (keys[index] === prevKeys[index + 1]) {
|
|
96
|
-
// // sp
|
|
97
|
-
// }
|
|
98
|
-
// prevKeys[index] = keys[index] as any
|
|
99
|
-
// }
|
|
100
|
-
// TODO in the future use a more efficient diffing algorithm that re-uses elements more optimally
|
|
101
|
-
// right now we're only looking one step ahead
|
|
102
|
-
// reconcile until `keys` and `prevKeys` are equal
|
|
103
|
-
// prevKeys = keys
|
|
104
|
-
}, [items$, keys$, renderListEl]);
|
|
105
|
-
return React.createElement(React.Fragment, null, container);
|
|
106
|
-
};
|
|
107
|
-
export const DiffableList = ({ items$, renderContainer, renderItem, getKey, }) => (React.createElement(itsFine.FiberProvider, null,
|
|
108
|
-
React.createElement(DiffableList_, { "items$": items$, renderContainer: renderContainer, renderItem: renderItem, getKey: getKey })));
|
|
109
|
-
const ItemWrapper = ({ item$, opts, renderItem, }) => {
|
|
110
|
-
const item = useQuery(item$);
|
|
111
|
-
return React.createElement(React.Fragment, null, renderItem(item, opts));
|
|
112
|
-
};
|
|
113
|
-
//# sourceMappingURL=DiffableList.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DiffableList.js","sourceRoot":"","sources":["../../../src/react/components/DiffableList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,UAAU,CAAA;AACnC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,QAAQ,MAAM,kBAAkB,CAAA;AAGvC,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAgBzC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAS,EACpC,MAAM,EACN,eAAe,EACf,UAAU,EACV,MAAM,GACO,EAAmB,EAAE;IAClC,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAc,IAAI,CAAC,CAAA;IAC3C,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;IAEtC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEzD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;IAE9C,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;IAOxD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAU,EAAE,CAAC,CAAA;IAExC,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAA;IAEhD,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CACpC,CAAC,QAAqB,EAAE,KAAa,EAAE,KAAuB,EAAE,EAAE;QAChE,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QAC1C,IAAI,CAAC,MAAM,CACT,oBAAC,aAAa;YACZ,oBAAC,WAAW,aAAQ,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,UAAU,EAAE,GAAI,CAC1F,CACjB,CAAA;QAED,OAAO,IAAI,CAAA;IACb,CAAC,EACD,CAAC,aAAa,EAAE,UAAU,EAAE,UAAU,CAAC,CACxC,CAAA;IAED,KAAK,CAAC,eAAe,CAAC,GAAG,EAAE;QACzB,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QACxC,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAA;QAExB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;YAC9C,GAAG,CAAC,OAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;YAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,CAAE,CAAqB,CAAA;YACxE,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;YACjD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAE,EAAE,CAAC,CAAA;QACtE,CAAC;QACD,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAErD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,2BAA2B;QAE3B,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;YAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;YAElD,IAAI,YAAY,GAAG,IAAI,CAAA;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5B,YAAY,GAAG,KAAK,CAAA;oBACpB,MAAK;gBACP,CAAC;YACH,CAAC;YACD,IAAI,YAAY;gBAAE,OAAM;YAExB,MAAM,WAAW,GAAG,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,yBAAyB,CAAC,CAAA;YAC5E,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,EAAE,EAAE,CAAC,yBAAyB,CAAC,CAAA;YAEtF,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YAEnC,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;gBAC9B,QAAQ,KAAK,CAAC,EAAE,EAAE,CAAC;oBACjB,KAAK,QAAQ,CAAC,CAAC,CAAC;wBACd,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;wBACvB,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAE,CAAA;wBACjC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAA;wBACjB,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAA;wBACd,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;wBAClB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;wBAC/B,MAAK;oBACP,CAAC;oBACD,KAAK,KAAK,CAAC,CAAC,CAAC;wBACX,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;wBACvB,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;wBAC9C,GAAG,CAAC,OAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;wBAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,CAAE,CAAqB,CAAA;wBACxE,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;wBACjD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAE,EAAE,CAAC,CAAA;wBAChF,MAAK;oBACP,CAAC;oBACD,KAAK,MAAM,CAAC,CAAC,CAAC;wBACZ,4CAA4C;wBAE5C,4CAA4C;wBAC5C,yBAAyB;wBACzB,uBAAuB;wBACvB,qBAAqB;wBAErB,0CAA0C;wBAC1C,gEAAgE;wBAEhE,oEAAoE;wBAEpE,sBAAsB;wBAEtB,MAAK;oBACP,CAAC;oBACD,OAAO,CAAC,CAAC,CAAC;wBACR,YAAY,CAAC,KAAK,CAAC,CAAA;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,sDAAsD;QACtD,kDAAkD;QAElD,sDAAsD;QACtD,+BAA+B;QAC/B,6CAA6C;QAC7C,SAAS;QACT,IAAI;QAEJ,uCAAuC;QACvC,IAAI;QAEJ,iGAAiG;QACjG,8CAA8C;QAE9C,kDAAkD;QAElD,kBAAkB;IACpB,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC,CAAA;IAEjC,OAAO,0CAAG,SAAS,CAAI,CAAA;AACzB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAS,EACnC,MAAM,EACN,eAAe,EACf,UAAU,EACV,MAAM,GACO,EAAmB,EAAE,CAAC,CACnC,oBAAC,OAAO,CAAC,aAAa;IACpB,oBAAC,aAAa,cAAS,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAI,CACrF,CACzB,CAAA;AAED,MAAM,WAAW,GAAG,CAAS,EAC3B,KAAK,EACL,IAAI,EACJ,UAAU,GAKX,EAAE,EAAE;IACH,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE5B,OAAO,0CAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAI,CAAA;AACtC,CAAC,CAAA"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Like cleanup callback of `React.useEffect` but running as part of the render loop.
|
|
3
|
-
*
|
|
4
|
-
* NOTE: This hook should not be used with React strict mode.
|
|
5
|
-
*/
|
|
6
|
-
export declare const useCleanup: (cleanupCallback: () => void) => void;
|
|
7
|
-
//# sourceMappingURL=useCleanup.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useCleanup.d.ts","sourceRoot":"","sources":["../../../src/react/utils/useCleanup.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,UAAU,oBAEJ,MAAM,IAAI,SAe5B,CAAA"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Like cleanup callback of `React.useEffect` but running as part of the render loop.
|
|
4
|
-
*
|
|
5
|
-
* NOTE: This hook should not be used with React strict mode.
|
|
6
|
-
*/
|
|
7
|
-
export const useCleanup = (
|
|
8
|
-
/** Needs to be a `React.useCallback` value */
|
|
9
|
-
cleanupCallback) => {
|
|
10
|
-
const callbackRef = React.useRef(cleanupCallback);
|
|
11
|
-
if (callbackRef.current !== cleanupCallback) {
|
|
12
|
-
callbackRef.current();
|
|
13
|
-
callbackRef.current = cleanupCallback;
|
|
14
|
-
}
|
|
15
|
-
React.useEffect(() => () => {
|
|
16
|
-
callbackRef.current();
|
|
17
|
-
}, []);
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=useCleanup.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useCleanup.js","sourceRoot":"","sources":["../../../src/react/utils/useCleanup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;AACxB,8CAA8C;AAC9C,eAA2B,EAC3B,EAAE;IACF,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,CAAA;IAEjD,IAAI,WAAW,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;QAC5C,WAAW,CAAC,OAAO,EAAE,CAAA;QACrB,WAAW,CAAC,OAAO,GAAG,eAAe,CAAA;IACvC,CAAC;IAED,KAAK,CAAC,SAAS,CACb,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,WAAW,CAAC,OAAO,EAAE,CAAA;IACvB,CAAC,EACD,EAAE,CACH,CAAA;AACH,CAAC,CAAA"}
|