@kontsedal/olas-core 0.0.3 → 0.0.5
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/index.cjs +4 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{root-Cnkb3I--.mjs → root-DqWolle_.mjs} +163 -6
- package/dist/root-DqWolle_.mjs.map +1 -0
- package/dist/{root-D_xAdcom.cjs → root-lBp7qziQ.cjs} +180 -5
- package/dist/root-lBp7qziQ.cjs.map +1 -0
- package/dist/testing.cjs +22 -11
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -1
- package/dist/testing.d.cts.map +1 -1
- package/dist/testing.d.mts +2 -1
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +22 -11
- package/dist/testing.mjs.map +1 -1
- package/dist/{types-CRn4UoLn.d.mts → types-BH1o6nYa.d.mts} +139 -7
- package/dist/types-BH1o6nYa.d.mts.map +1 -0
- package/dist/{types-r_TVaRkD.d.cts → types-C4Vtkxbn.d.cts} +139 -7
- package/dist/types-C4Vtkxbn.d.cts.map +1 -0
- package/package.json +1 -1
- package/src/controller/instance.ts +11 -1
- package/src/controller/types.ts +13 -9
- package/src/index.ts +11 -2
- package/src/query/client.ts +36 -0
- package/src/query/local.ts +1 -0
- package/src/query/mutation.ts +178 -1
- package/src/query/plugin.ts +91 -1
- package/src/query/types.ts +7 -0
- package/src/query/use.ts +6 -0
- package/src/testing.ts +3 -0
- package/dist/root-Cnkb3I--.mjs.map +0 -1
- package/dist/root-D_xAdcom.cjs.map +0 -1
- package/dist/types-CRn4UoLn.d.mts.map +0 -1
- package/dist/types-r_TVaRkD.d.cts.map +0 -1
package/src/query/plugin.ts
CHANGED
|
@@ -118,6 +118,36 @@ export type GcEvent = {
|
|
|
118
118
|
kind: 'data' | 'infinite'
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Emitted when a persistable mutation (`spec.persist === true`) starts
|
|
123
|
+
* executing — before the user's `mutate` is invoked. Plugins use this to
|
|
124
|
+
* persist the variables to durable storage; if the page reloads mid-run,
|
|
125
|
+
* the queue replays from these entries.
|
|
126
|
+
*
|
|
127
|
+
* `runId` is unique per execution (a single `mutation.run(...)` call OR a
|
|
128
|
+
* replay attempt). `attempt` counts retry passes within a single runId.
|
|
129
|
+
*/
|
|
130
|
+
export type MutationEnqueueEvent = {
|
|
131
|
+
mutationId: string
|
|
132
|
+
runId: string
|
|
133
|
+
variables: unknown
|
|
134
|
+
attempt: number
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Emitted after a persistable mutation settles. Plugins use this to drop
|
|
139
|
+
* the run from the durable queue (on `'success'` or `'error'` after retries
|
|
140
|
+
* exhaust), or to leave it pending (on `'cancelled'` — e.g. parent dispose
|
|
141
|
+
* mid-flight).
|
|
142
|
+
*/
|
|
143
|
+
export type MutationSettleEvent = {
|
|
144
|
+
mutationId: string
|
|
145
|
+
runId: string
|
|
146
|
+
outcome: 'success' | 'error' | 'cancelled'
|
|
147
|
+
/** Only present on `'error'` — the final thrown value after retries. */
|
|
148
|
+
error?: unknown
|
|
149
|
+
}
|
|
150
|
+
|
|
121
151
|
/**
|
|
122
152
|
* Plugin contract. Every hook is optional. Hooks are wrapped in try/catch
|
|
123
153
|
* by `QueryClient`; thrown exceptions are routed through the root's
|
|
@@ -126,12 +156,24 @@ export type GcEvent = {
|
|
|
126
156
|
export type QueryClientPlugin = {
|
|
127
157
|
/**
|
|
128
158
|
* Called once after the `QueryClient` is constructed. Use it to wire up
|
|
129
|
-
* transport listeners and capture the `QueryClientPluginApi`.
|
|
159
|
+
* transport listeners and capture the `QueryClientPluginApi`. SPEC §13.2.
|
|
160
|
+
*
|
|
161
|
+
* Persistable-mutation replay typically happens HERE — module-scope
|
|
162
|
+
* `defineMutation(...)` calls have already registered their handlers by
|
|
163
|
+
* the time `createRoot(...)` runs, so `init` can walk durable storage
|
|
164
|
+
* and re-invoke registered mutates for any pending entries.
|
|
130
165
|
*/
|
|
131
166
|
init?(api: QueryClientPluginApi): void
|
|
132
167
|
onSetData?(event: SetDataEvent): void
|
|
133
168
|
onInvalidate?(event: InvalidateEvent): void
|
|
134
169
|
onGc?(event: GcEvent): void
|
|
170
|
+
/**
|
|
171
|
+
* Fired when a persistable mutation (`spec.persist === true`) starts
|
|
172
|
+
* executing. SPEC §13.3.
|
|
173
|
+
*/
|
|
174
|
+
onMutationEnqueue?(event: MutationEnqueueEvent): void
|
|
175
|
+
/** Fired after a persistable mutation settles. SPEC §13.3. */
|
|
176
|
+
onMutationSettle?(event: MutationSettleEvent): void
|
|
135
177
|
/** Called from `QueryClient.dispose`. Tear down transports / listeners here. */
|
|
136
178
|
dispose?(): void
|
|
137
179
|
}
|
|
@@ -183,3 +225,51 @@ export function lookupRegisteredQuery(queryId: string): RegisteredQuery | undefi
|
|
|
183
225
|
export function _unregisterQueryById(queryId: string): void {
|
|
184
226
|
queryRegistry.delete(queryId)
|
|
185
227
|
}
|
|
228
|
+
|
|
229
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
230
|
+
// Mutation registry — parallel to query registry. Persistable mutations
|
|
231
|
+
// (`spec.persist === true`) register themselves at module-import time via
|
|
232
|
+
// `defineMutation(...)` so the mutation-queue plugin can replay pending
|
|
233
|
+
// runs at `init` time, BEFORE controllers reconstruct.
|
|
234
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Shape stored in the `mutationId → handler` registry. Only the `mutate`
|
|
238
|
+
* function and the id are needed for replay — lifecycle hooks like
|
|
239
|
+
* `onSuccess` / `onError` are per-controller and can't be safely replayed
|
|
240
|
+
* across page reloads (the controller doesn't exist yet).
|
|
241
|
+
*/
|
|
242
|
+
export type RegisteredMutation = {
|
|
243
|
+
readonly mutationId: string
|
|
244
|
+
/**
|
|
245
|
+
* Replay-safe `mutate`. Matches `MutationSpec.mutate` 1:1 — receives the
|
|
246
|
+
* variables and an `AbortSignal`. The mutation-queue plugin invokes this
|
|
247
|
+
* directly on replay, so the implementation MUST NOT close over
|
|
248
|
+
* controller-instance state. Module-level deps (a shared `api` client,
|
|
249
|
+
* etc.) are fine.
|
|
250
|
+
*/
|
|
251
|
+
readonly mutate: (vars: unknown, signal: AbortSignal) => Promise<unknown>
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const mutationRegistry = new Map<string, RegisteredMutation>()
|
|
255
|
+
|
|
256
|
+
/** Register a mutation by its `mutationId`. Internal — called from `defineMutation`. */
|
|
257
|
+
export function registerMutationById(mutationId: string, entry: RegisteredMutation): void {
|
|
258
|
+
mutationRegistry.set(mutationId, entry)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Look up a registered mutation by id. Returns `undefined` when no
|
|
263
|
+
* mutation with that id has been defined — typical when a queue entry
|
|
264
|
+
* references a mutation whose module hasn't been imported (e.g. a
|
|
265
|
+
* code-split route boundary). The plugin should leave such entries in
|
|
266
|
+
* place and retry once the module loads.
|
|
267
|
+
*/
|
|
268
|
+
export function lookupRegisteredMutation(mutationId: string): RegisteredMutation | undefined {
|
|
269
|
+
return mutationRegistry.get(mutationId)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** Test-only — drop a registered mutation. Not exported from the package. */
|
|
273
|
+
export function _unregisterMutationById(mutationId: string): void {
|
|
274
|
+
mutationRegistry.delete(mutationId)
|
|
275
|
+
}
|
package/src/query/types.ts
CHANGED
|
@@ -32,6 +32,13 @@ export type AsyncState<T> = {
|
|
|
32
32
|
refetch: () => Promise<T>
|
|
33
33
|
reset: () => void
|
|
34
34
|
firstValue: () => Promise<T>
|
|
35
|
+
/**
|
|
36
|
+
* Alias of `firstValue()` — clearer name for Suspense / `React.use(...)`
|
|
37
|
+
* use cases. Resolves with `data` on first success (short-circuits if
|
|
38
|
+
* already settled), rejects with `error` on the first failure. Use this
|
|
39
|
+
* to suspend a React tree until the query lands its first value.
|
|
40
|
+
*/
|
|
41
|
+
promise: () => Promise<T>
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
/**
|
package/src/query/use.ts
CHANGED
|
@@ -98,6 +98,9 @@ class SubscriptionImpl<T, U = T> implements QuerySubscription<U> {
|
|
|
98
98
|
return cur.entry.firstValue().then((v) => this.project(v))
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
// Alias surfaced on `AsyncState` for Suspense / React 19 `use(...)`.
|
|
102
|
+
promise = (): Promise<U> => this.firstValue()
|
|
103
|
+
|
|
101
104
|
private project(v: T): U {
|
|
102
105
|
return this.select === undefined ? (v as unknown as U) : this.select(v)
|
|
103
106
|
}
|
|
@@ -325,6 +328,9 @@ class InfiniteSubscriptionImpl<TPage, TItem> implements InfiniteQuerySubscriptio
|
|
|
325
328
|
return cur.entry.firstValue()
|
|
326
329
|
}
|
|
327
330
|
|
|
331
|
+
// Alias of firstValue() for Suspense / React 19 `use(...)` ergonomics.
|
|
332
|
+
promise = (): Promise<TPage[]> => this.firstValue()
|
|
333
|
+
|
|
328
334
|
fetchNextPage = (): Promise<void> => {
|
|
329
335
|
const cur = this.current$.peek()
|
|
330
336
|
if (!cur) return Promise.resolve()
|
package/src/testing.ts
CHANGED
|
@@ -111,6 +111,7 @@ export function fakeAsyncState<T>(
|
|
|
111
111
|
refetch: () => Promise<T>
|
|
112
112
|
reset: () => void
|
|
113
113
|
firstValue: () => Promise<T>
|
|
114
|
+
promise: () => Promise<T>
|
|
114
115
|
}>,
|
|
115
116
|
): AsyncState<T> {
|
|
116
117
|
const data$: ReadSignal<T | undefined> = signal(overrides?.data)
|
|
@@ -127,6 +128,7 @@ export function fakeAsyncState<T>(
|
|
|
127
128
|
const refetch = overrides?.refetch ?? (async () => data$.peek() as T)
|
|
128
129
|
const reset = overrides?.reset ?? (() => {})
|
|
129
130
|
const firstValue = overrides?.firstValue ?? (async () => data$.peek() as T)
|
|
131
|
+
const promise = overrides?.promise ?? firstValue
|
|
130
132
|
|
|
131
133
|
return {
|
|
132
134
|
data: data$,
|
|
@@ -140,5 +142,6 @@ export function fakeAsyncState<T>(
|
|
|
140
142
|
refetch,
|
|
141
143
|
reset,
|
|
142
144
|
firstValue,
|
|
145
|
+
promise,
|
|
143
146
|
}
|
|
144
147
|
}
|