@capxul/sdk-react 4.2.0-rc.2 → 4.2.0-rc.4
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/capxul-source.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": {
|
|
3
|
-
"commit": "
|
|
4
|
-
"tree": "
|
|
3
|
+
"commit": "400e4b861e8c10091ad2d9e71fc0502fe222a801",
|
|
4
|
+
"tree": "c3afb8bb5f3ce69ee8aa1e8fbe811fe213627887",
|
|
5
5
|
"branch": "codex/programme-rc",
|
|
6
6
|
"repository": "https://github.com/Xelmar-tech/infrastructure",
|
|
7
7
|
"lockfileSha256": "5870f53b72706d103220c1bcf733cb4fb71196aea32a9cfbdc277d73cc959264"
|
|
8
8
|
},
|
|
9
9
|
"name": "@capxul/sdk-react",
|
|
10
|
-
"version": "4.2.0-rc.
|
|
10
|
+
"version": "4.2.0-rc.4"
|
|
11
11
|
}
|
|
@@ -151,10 +151,35 @@ const capxulKeys = {
|
|
|
151
151
|
]
|
|
152
152
|
};
|
|
153
153
|
//#endregion
|
|
154
|
-
//#region src/
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
//#region src/internal/invocation-controls.ts
|
|
155
|
+
/**
|
|
156
|
+
* Keep only the five public option fields, and only when they hold the right
|
|
157
|
+
* kind of value. A named action verb takes its attempt as an optional FIRST
|
|
158
|
+
* argument, so a screen that wires one straight to a DOM handler
|
|
159
|
+
* (`onClick={row.hide}`) hands us a React SyntheticEvent. That is not an
|
|
160
|
+
* attempt: it must reach neither the SDK call nor the callback echo.
|
|
161
|
+
*/
|
|
162
|
+
function toInvocationOptions(options) {
|
|
163
|
+
if (typeof options !== "object" || options === null) return void 0;
|
|
164
|
+
const attempt = {};
|
|
165
|
+
if (typeof options.correlationId === "string") attempt.correlationId = options.correlationId;
|
|
166
|
+
if (typeof options.journeyId === "string") attempt.journeyId = options.journeyId;
|
|
167
|
+
if (typeof options.timeoutMs === "number") attempt.timeoutMs = options.timeoutMs;
|
|
168
|
+
if (typeof options.deadlineMs === "number") attempt.deadlineMs = options.deadlineMs;
|
|
169
|
+
if (options.signal instanceof AbortSignal) attempt.signal = options.signal;
|
|
170
|
+
return Object.keys(attempt).length === 0 ? void 0 : attempt;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Map the public camel-case invocation options onto the Core SDK's control
|
|
174
|
+
* spelling. ONE definition, because the identity facade and every headless
|
|
175
|
+
* engine must hand the SDK the same shape: a caller that captured one user
|
|
176
|
+
* attempt before it started gets that attempt's `correlation_id`/`journey_id`
|
|
177
|
+
* on whichever operation it starts (#1960 R02).
|
|
178
|
+
*
|
|
179
|
+
* It creates no identifiers. An absent option stays absent, so an automatic
|
|
180
|
+
* read keeps its own invocation context instead of borrowing an attempt's.
|
|
181
|
+
*/
|
|
182
|
+
function toInvocationControls(options) {
|
|
158
183
|
if (options === void 0) return void 0;
|
|
159
184
|
return {
|
|
160
185
|
...options.signal === void 0 ? {} : { signal: options.signal },
|
|
@@ -164,12 +189,16 @@ function controls(options) {
|
|
|
164
189
|
...options.journeyId === void 0 ? {} : { journey_id: options.journeyId }
|
|
165
190
|
};
|
|
166
191
|
}
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/identity.tsx
|
|
194
|
+
const MISSING_IDENTITY_PROVIDER = Symbol("MISSING_IDENTITY_PROVIDER");
|
|
195
|
+
const IdentityContext = createContext(MISSING_IDENTITY_PROVIDER);
|
|
167
196
|
const failure = (result) => result.ok ? null : {
|
|
168
197
|
ok: false,
|
|
169
198
|
reason: result.refused
|
|
170
199
|
};
|
|
171
200
|
async function guarded(runtime, verb, options, run) {
|
|
172
|
-
const invocation =
|
|
201
|
+
const invocation = toInvocationControls(options);
|
|
173
202
|
try {
|
|
174
203
|
return await (runtime.runFacade?.(verb, invocation, run) ?? run(invocation));
|
|
175
204
|
} catch {
|
|
@@ -215,18 +244,102 @@ function normalizeOrganization(organization) {
|
|
|
215
244
|
return null;
|
|
216
245
|
}
|
|
217
246
|
}
|
|
247
|
+
/** The Organization id when its lane is already running or finished, else null. */
|
|
248
|
+
const runningOrganization = (state) => {
|
|
249
|
+
if (state.phase !== "authenticated" || state.account.at !== "claimed") return null;
|
|
250
|
+
const org = state.account.org;
|
|
251
|
+
return org !== null && (org.at === "loading" || org.at === "settingUp" || org.at === "ready") ? org.orgId : null;
|
|
252
|
+
};
|
|
253
|
+
/** A superseded session read waits at most this long for the winning read. */
|
|
254
|
+
const SESSION_SETTLE_LIMIT_MS = 3e4;
|
|
255
|
+
const accountInFlight = (state) => state.phase === "authenticated" && (state.account.at === "deriving" || state.account.at === "claiming");
|
|
218
256
|
function createAuth(client, clearAuthenticatedQueries) {
|
|
219
257
|
const runtime = client._internal.identity;
|
|
258
|
+
const settledSession = (invocation) => new Promise((resolve) => {
|
|
259
|
+
let done = false;
|
|
260
|
+
let stop = null;
|
|
261
|
+
let timer = null;
|
|
262
|
+
const onAbort = () => finish({
|
|
263
|
+
ok: false,
|
|
264
|
+
reason: "CANCELLED"
|
|
265
|
+
});
|
|
266
|
+
const finish = (result) => {
|
|
267
|
+
if (done) return;
|
|
268
|
+
done = true;
|
|
269
|
+
stop?.();
|
|
270
|
+
if (timer !== null) clearTimeout(timer);
|
|
271
|
+
invocation?.signal?.removeEventListener("abort", onAbort);
|
|
272
|
+
resolve(result);
|
|
273
|
+
};
|
|
274
|
+
if (invocation?.signal?.aborted) {
|
|
275
|
+
onAbort();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
invocation?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
279
|
+
const unsubscribe = runtime.subscribeTransitions((record) => {
|
|
280
|
+
if (record.slot !== "identity:session") return;
|
|
281
|
+
if (record.outcome === "applied" && record.event === "SessionRead") finish({ ok: true });
|
|
282
|
+
else if (record.outcome === "failed" || record.outcome === "cancelled") finish({
|
|
283
|
+
ok: false,
|
|
284
|
+
reason: record.error_code
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
if (done) {
|
|
288
|
+
unsubscribe();
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
stop = unsubscribe;
|
|
292
|
+
timer = setTimeout(() => finish({
|
|
293
|
+
ok: false,
|
|
294
|
+
reason: "UNKNOWN"
|
|
295
|
+
}), SESSION_SETTLE_LIMIT_MS);
|
|
296
|
+
});
|
|
220
297
|
const read = async (invocation) => {
|
|
221
298
|
const result = await runtime.send({ _tag: "ReadSession" }, invocation);
|
|
222
|
-
|
|
299
|
+
const refused = failure(result);
|
|
300
|
+
if (refused === null) return { ok: true };
|
|
301
|
+
return refused.reason === "SUPERSEDED" ? settledSession(invocation) : refused;
|
|
223
302
|
};
|
|
224
303
|
const ensureAccount = async (invocation) => {
|
|
225
304
|
const result = await runtime.send({ _tag: "EnsureAccount" }, invocation);
|
|
226
305
|
return failure(result) ?? { ok: true };
|
|
227
306
|
};
|
|
307
|
+
const settledAccount = (invocation) => new Promise((resolve) => {
|
|
308
|
+
let done = false;
|
|
309
|
+
let stop = null;
|
|
310
|
+
const onAbort = () => finish({
|
|
311
|
+
ok: false,
|
|
312
|
+
reason: "CANCELLED"
|
|
313
|
+
});
|
|
314
|
+
const finish = (result) => {
|
|
315
|
+
if (done) return;
|
|
316
|
+
done = true;
|
|
317
|
+
stop?.();
|
|
318
|
+
invocation?.signal?.removeEventListener("abort", onAbort);
|
|
319
|
+
resolve(result);
|
|
320
|
+
};
|
|
321
|
+
if (invocation?.signal?.aborted) {
|
|
322
|
+
onAbort();
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
invocation?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
326
|
+
const unsubscribe = runtime.subscribe((state) => {
|
|
327
|
+
if (!accountInFlight(state)) finish({ ok: true });
|
|
328
|
+
});
|
|
329
|
+
if (done) {
|
|
330
|
+
unsubscribe();
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
stop = unsubscribe;
|
|
334
|
+
if (!accountInFlight(runtime.snapshot())) finish({ ok: true });
|
|
335
|
+
});
|
|
228
336
|
const reachClaimed = async (invocation) => {
|
|
229
337
|
let state = runtime.snapshot();
|
|
338
|
+
if (accountInFlight(state)) {
|
|
339
|
+
const settled = await settledAccount(invocation);
|
|
340
|
+
if (!settled.ok) return settled;
|
|
341
|
+
state = runtime.snapshot();
|
|
342
|
+
}
|
|
230
343
|
if (state.phase !== "authenticated" || state.account.at === "unknown") {
|
|
231
344
|
const result = await runtime.send({ _tag: "EnsureAccount" }, invocation);
|
|
232
345
|
const refused = failure(result);
|
|
@@ -238,6 +351,16 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
238
351
|
reason: "WRONG_STATE"
|
|
239
352
|
};
|
|
240
353
|
if (state.account.at === "claimed") return { ok: true };
|
|
354
|
+
if (accountInFlight(state)) {
|
|
355
|
+
const settled = await settledAccount(invocation);
|
|
356
|
+
if (!settled.ok) return settled;
|
|
357
|
+
state = runtime.snapshot();
|
|
358
|
+
if (state.phase !== "authenticated") return {
|
|
359
|
+
ok: false,
|
|
360
|
+
reason: "WRONG_STATE"
|
|
361
|
+
};
|
|
362
|
+
if (state.account.at === "claimed") return { ok: true };
|
|
363
|
+
}
|
|
241
364
|
const event = state.account.at === "failed" ? { _tag: "RetryAccount" } : state.account.at === "counterfactual" ? { _tag: "ClaimAccount" } : { _tag: "EnsureAccount" };
|
|
242
365
|
const result = await runtime.send(event, invocation);
|
|
243
366
|
const refused = failure(result);
|
|
@@ -258,13 +381,13 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
258
381
|
ok: false,
|
|
259
382
|
reason: "INVALID_INPUT"
|
|
260
383
|
};
|
|
384
|
+
const refreshed = await read(invocation);
|
|
385
|
+
if (!refreshed.ok) return refreshed;
|
|
261
386
|
const current = runtime.snapshot();
|
|
262
387
|
if (current.phase !== "authenticated" || !current.profileComplete) {
|
|
263
388
|
const completed = await runtime.completeProfile(submission.profileDetails, invocation);
|
|
264
389
|
if (!completed.ok) return completed;
|
|
265
390
|
}
|
|
266
|
-
const refreshed = await read(invocation);
|
|
267
|
-
if (!refreshed.ok) return refreshed;
|
|
268
391
|
const claimed = await reachClaimed(invocation);
|
|
269
392
|
return claimed.ok ? {
|
|
270
393
|
ok: true,
|
|
@@ -341,12 +464,13 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
341
464
|
}),
|
|
342
465
|
createOrganization: (submission, options) => guarded(runtime, "createOrganization", options, async (invocation) => {
|
|
343
466
|
const current = runtime.snapshot();
|
|
467
|
+
const running = runningOrganization(current);
|
|
468
|
+
if (running !== null) return {
|
|
469
|
+
ok: true,
|
|
470
|
+
orgId: running
|
|
471
|
+
};
|
|
344
472
|
if (current.phase === "authenticated" && current.account.at === "claimed") {
|
|
345
473
|
const org = current.account.org;
|
|
346
|
-
if (org !== null && (org.at === "loading" || org.at === "settingUp" || org.at === "ready")) return {
|
|
347
|
-
ok: true,
|
|
348
|
-
orgId: org.orgId
|
|
349
|
-
};
|
|
350
474
|
if (org?.at === "failed" && org.orgId !== null) {
|
|
351
475
|
if (!org.retryable) return {
|
|
352
476
|
ok: false,
|
|
@@ -361,6 +485,11 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
361
485
|
}
|
|
362
486
|
const prepared = await prepareOrganization(submission, invocation);
|
|
363
487
|
if (!prepared.ok) return prepared;
|
|
488
|
+
const opened = runningOrganization(runtime.snapshot());
|
|
489
|
+
if (opened !== null) return {
|
|
490
|
+
ok: true,
|
|
491
|
+
orgId: opened
|
|
492
|
+
};
|
|
364
493
|
const created = await runtime.send({
|
|
365
494
|
_tag: "CreateOrganization",
|
|
366
495
|
draft: prepared.organization
|
|
@@ -442,7 +571,7 @@ function CapxulIdentityProvider({ client, children }) {
|
|
|
442
571
|
}, []);
|
|
443
572
|
const value = useMemo(() => {
|
|
444
573
|
if (client === null || runtime === null) return null;
|
|
445
|
-
const send = (event, options) => runtime.send(event,
|
|
574
|
+
const send = (event, options) => runtime.send(event, toInvocationControls(options));
|
|
446
575
|
const clearAuthenticatedQueries = async () => {
|
|
447
576
|
await queryClient.cancelQueries({ queryKey: capxulKeys.root });
|
|
448
577
|
await queryClient.resetQueries({ queryKey: capxulKeys.root });
|
|
@@ -821,4 +950,4 @@ function organizationForm(props, state, auth, submitted) {
|
|
|
821
950
|
});
|
|
822
951
|
}
|
|
823
952
|
//#endregion
|
|
824
|
-
export { useCapxulAuth as a, useCapxulIdentityOrNull as c,
|
|
953
|
+
export { useCapxulAuth as a, useCapxulIdentityOrNull as c, toInvocationControls as d, toInvocationOptions as f, useCapxul as h, entered as i, useCapxulSend as l, useCapxulClientOrNull as m, CapxulOnboardingController as n, useCapxulDestination as o, capxulKeys as p, CapxulProvider as r, useCapxulIdentity as s, CapxulAuthenticationController as t, useCapxulTransitions as u };
|
package/dist/index.d.mts
CHANGED
|
@@ -383,9 +383,9 @@ interface Contact {
|
|
|
383
383
|
interface ContactRow extends Contact {
|
|
384
384
|
/** Ours: one initials rule, not one copy per screen. */
|
|
385
385
|
readonly initials: string;
|
|
386
|
-
readonly rename: (name: string) => void;
|
|
387
|
-
readonly hide: () => void;
|
|
388
|
-
readonly unhide: () => void;
|
|
386
|
+
readonly rename: (name: string, options?: InvocationOptions) => void;
|
|
387
|
+
readonly hide: (options?: InvocationOptions) => void;
|
|
388
|
+
readonly unhide: (options?: InvocationOptions) => void;
|
|
389
389
|
}
|
|
390
390
|
/** ADR-0023 R1: refusal CODES, never sentences — the app owns the words. */
|
|
391
391
|
type ContactsRefusal = "loading" | "org-unavailable" | "unavailable";
|
|
@@ -421,7 +421,13 @@ interface ContactsListOptions {
|
|
|
421
421
|
interface ContactsAddSlice {
|
|
422
422
|
readonly value: string;
|
|
423
423
|
readonly change: (text: string) => void;
|
|
424
|
-
|
|
424
|
+
/**
|
|
425
|
+
* #1960 R02: hand it the options the screen captured BEFORE the click. The
|
|
426
|
+
* same snapshot reaches the SDK add call and comes back on `onAdded`/
|
|
427
|
+
* `onFailed`, so the UI observation and the operation share one identity even
|
|
428
|
+
* when the reply lands after an account switch. Omitted stays omitted.
|
|
429
|
+
*/
|
|
430
|
+
readonly submit: (options?: InvocationOptions) => void;
|
|
425
431
|
readonly isSubmitting: boolean;
|
|
426
432
|
readonly blocked: boolean;
|
|
427
433
|
readonly blockedReason: ContactsAddBlockedReason | null;
|
|
@@ -431,9 +437,14 @@ interface ContactsAddSlice {
|
|
|
431
437
|
//#region src/headless/contacts/contacts.d.ts
|
|
432
438
|
interface CapxulContactsProps {
|
|
433
439
|
readonly actor: ContactsActor;
|
|
434
|
-
|
|
440
|
+
/**
|
|
441
|
+
* `options` is exactly what the caller handed `.Add.submit` or a row verb, so
|
|
442
|
+
* the screen's own observation of the finished action can reuse the attempt
|
|
443
|
+
* identity the SDK operation ran under (#1960 R02).
|
|
444
|
+
*/
|
|
445
|
+
readonly onAdded: (contact: Contact, options?: InvocationOptions) => void;
|
|
435
446
|
/** ADR-0023 R1: the app maps `error.code` to its own copy; no SDK sentence. */
|
|
436
|
-
readonly onFailed: (error: CapxulError) => void;
|
|
447
|
+
readonly onFailed: (error: CapxulError, options?: InvocationOptions) => void;
|
|
437
448
|
readonly children: ReactNode;
|
|
438
449
|
}
|
|
439
450
|
declare function Root$6({ actor, onAdded, onFailed, children }: CapxulContactsProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -545,7 +556,12 @@ interface ActivityRowsSlice {
|
|
|
545
556
|
readonly rows: readonly ActivityRow[];
|
|
546
557
|
readonly isLoading: boolean;
|
|
547
558
|
readonly error: CapxulError | null;
|
|
548
|
-
|
|
559
|
+
/**
|
|
560
|
+
* #1960 R02: pass the options captured before the retry was selected and the
|
|
561
|
+
* re-read runs under the same attempt identity as the UI observation. Omit
|
|
562
|
+
* them and the read keeps its own invocation context.
|
|
563
|
+
*/
|
|
564
|
+
readonly retry: (options?: InvocationOptions) => void;
|
|
549
565
|
/** Server read time of the newest page, so the app can say which read is older. */
|
|
550
566
|
readonly observedAt: number | null;
|
|
551
567
|
}
|
|
@@ -589,7 +605,8 @@ interface CsvExport {
|
|
|
589
605
|
readonly truncated: boolean;
|
|
590
606
|
}
|
|
591
607
|
interface ActivityExportSlice {
|
|
592
|
-
|
|
608
|
+
/** Same contract as `retry`: the export's pages run under the caller's attempt. */
|
|
609
|
+
readonly toCsv: (options?: InvocationOptions) => Promise<CsvExport>;
|
|
593
610
|
readonly isExporting: boolean;
|
|
594
611
|
}
|
|
595
612
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as
|
|
2
|
+
import { a as useCapxulAuth, c as useCapxulIdentityOrNull, d as toInvocationControls, f as toInvocationOptions, h as useCapxul, i as entered, l as useCapxulSend, m as useCapxulClientOrNull, n as CapxulOnboardingController, o as useCapxulDestination, p as capxulKeys, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-DaT-AGx6.mjs";
|
|
3
3
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
5
5
|
import { CAPXUL_OPERATIONS, CapxulError, EVM_ADDRESS_RE, Errors, HANDLE_RE, PAYMENT_DIRECTIONS, PAYMENT_STATUSES, fingerprintPaymentIntent, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseMoney, paymentPhase, resolveIdentityDestination, toEvmAddress, toPartyId } from "@capxul/sdk";
|
|
@@ -879,6 +879,8 @@ function useCapxulUploadImage() {
|
|
|
879
879
|
}
|
|
880
880
|
//#endregion
|
|
881
881
|
//#region src/headless/contacts/use-contacts.ts
|
|
882
|
+
/** One captured snapshot, or nothing — never a fabricated empty options object. */
|
|
883
|
+
const carry = (options) => options === void 0 ? {} : { options };
|
|
882
884
|
function useContacts(input) {
|
|
883
885
|
const { actor, onAdded, onFailed } = input;
|
|
884
886
|
const client = useCapxulClientOrNull();
|
|
@@ -895,35 +897,40 @@ function useContacts(input) {
|
|
|
895
897
|
const writeMutate = useMutation({
|
|
896
898
|
mutationFn: async (command) => {
|
|
897
899
|
const target = requireBook(book, `addressBook.${command.kind}`);
|
|
900
|
+
const controls = toInvocationControls(command.options);
|
|
898
901
|
return unwrapCapxulResult(command.kind === "rename" ? await target.label({
|
|
899
902
|
entryId: command.id,
|
|
900
903
|
label: command.name
|
|
901
|
-
}) : command.kind === "hide" ? await target.hide(command.id) : await target.unhide(command.id));
|
|
904
|
+
}, controls) : command.kind === "hide" ? await target.hide(command.id, controls) : await target.unhide(command.id, controls));
|
|
902
905
|
},
|
|
903
906
|
onSettled: invalidate,
|
|
904
|
-
onError: onFailed
|
|
907
|
+
onError: (error, command) => onFailed(error, command.options)
|
|
905
908
|
}).mutate;
|
|
906
909
|
const [value, setValue] = useState("");
|
|
907
910
|
const [addError, setAddError] = useState(null);
|
|
908
911
|
const addContact = useMutation({
|
|
909
|
-
mutationFn: async (
|
|
912
|
+
mutationFn: async (command) => unwrapCapxulResult(await requireBook(book, CAPXUL_OPERATIONS.addressBook.add).add({ ref: command.ref }, toInvocationControls(command.options))),
|
|
910
913
|
onSettled: invalidate
|
|
911
914
|
});
|
|
912
915
|
const addMutate = addContact.mutate;
|
|
913
916
|
const blockedReason = refusal !== null ? "org-unavailable" : value.trim() === "" ? "empty" : null;
|
|
914
917
|
const submitGate = useRef(false);
|
|
915
|
-
const submit = useCallback(() => {
|
|
918
|
+
const submit = useCallback((options) => {
|
|
916
919
|
if (blockedReason !== null || submitGate.current) return;
|
|
920
|
+
const attempt = toInvocationOptions(options);
|
|
917
921
|
submitGate.current = true;
|
|
918
922
|
setAddError(null);
|
|
919
|
-
addMutate(
|
|
923
|
+
addMutate({
|
|
924
|
+
ref: refFromTypedText(value),
|
|
925
|
+
...carry(attempt)
|
|
926
|
+
}, {
|
|
920
927
|
onSuccess: (entry) => {
|
|
921
928
|
setValue("");
|
|
922
|
-
onAdded(toContact(entry));
|
|
929
|
+
onAdded(toContact(entry), attempt);
|
|
923
930
|
},
|
|
924
931
|
onError: (error) => {
|
|
925
932
|
setAddError(error.code === "INVALID_INPUT" ? "unresolved" : "failed");
|
|
926
|
-
onFailed(error);
|
|
933
|
+
onFailed(error, attempt);
|
|
927
934
|
},
|
|
928
935
|
onSettled: () => {
|
|
929
936
|
submitGate.current = false;
|
|
@@ -944,18 +951,21 @@ function useContacts(input) {
|
|
|
944
951
|
book,
|
|
945
952
|
scope,
|
|
946
953
|
refusal,
|
|
947
|
-
rename: useCallback((id, name) => writeMutate({
|
|
954
|
+
rename: useCallback((id, name, options) => writeMutate({
|
|
948
955
|
kind: "rename",
|
|
949
956
|
id,
|
|
950
|
-
name
|
|
957
|
+
name,
|
|
958
|
+
...carry(toInvocationOptions(options))
|
|
951
959
|
}), [writeMutate]),
|
|
952
|
-
hide: useCallback((id) => writeMutate({
|
|
960
|
+
hide: useCallback((id, options) => writeMutate({
|
|
953
961
|
kind: "hide",
|
|
954
|
-
id
|
|
962
|
+
id,
|
|
963
|
+
...carry(toInvocationOptions(options))
|
|
955
964
|
}), [writeMutate]),
|
|
956
|
-
unhide: useCallback((id) => writeMutate({
|
|
965
|
+
unhide: useCallback((id, options) => writeMutate({
|
|
957
966
|
kind: "unhide",
|
|
958
|
-
id
|
|
967
|
+
id,
|
|
968
|
+
...carry(toInvocationOptions(options))
|
|
959
969
|
}), [writeMutate]),
|
|
960
970
|
add: {
|
|
961
971
|
value,
|
|
@@ -989,9 +999,9 @@ function useContactsList(engine, options) {
|
|
|
989
999
|
if (entries === void 0) return [];
|
|
990
1000
|
return (limit === void 0 ? entries : entries.slice(0, limit)).map((entry) => Object.assign(toContact(entry), {
|
|
991
1001
|
initials: initialsOf(entry.label),
|
|
992
|
-
rename: (name) => rename(entry.id, name),
|
|
993
|
-
hide: () => hide(entry.id),
|
|
994
|
-
unhide: () => unhide(entry.id)
|
|
1002
|
+
rename: (name, attempt) => rename(entry.id, name, attempt),
|
|
1003
|
+
hide: (attempt) => hide(entry.id, attempt),
|
|
1004
|
+
unhide: (attempt) => unhide(entry.id, attempt)
|
|
995
1005
|
}));
|
|
996
1006
|
}, [
|
|
997
1007
|
entries,
|
|
@@ -1567,6 +1577,12 @@ function useActivity(input) {
|
|
|
1567
1577
|
if (filter !== void 0) params.filter = filter;
|
|
1568
1578
|
return params;
|
|
1569
1579
|
}, [actor, filter]);
|
|
1580
|
+
const selectedRetry = useRef(void 0);
|
|
1581
|
+
const takeSelectedRetry = useCallback(() => {
|
|
1582
|
+
const attempt = selectedRetry.current;
|
|
1583
|
+
selectedRetry.current = void 0;
|
|
1584
|
+
return toInvocationControls(attempt);
|
|
1585
|
+
}, []);
|
|
1570
1586
|
const query = useInfiniteQuery({
|
|
1571
1587
|
queryKey: [
|
|
1572
1588
|
...capxulKeys.activity,
|
|
@@ -1576,7 +1592,7 @@ function useActivity(input) {
|
|
|
1576
1592
|
filter ?? "none"
|
|
1577
1593
|
],
|
|
1578
1594
|
queryFn: async ({ pageParam }) => {
|
|
1579
|
-
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.activity.list).activity.list(listParams(pageParam, limit)));
|
|
1595
|
+
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.activity.list).activity.list(listParams(pageParam, limit), takeSelectedRetry()));
|
|
1580
1596
|
},
|
|
1581
1597
|
initialPageParam: void 0,
|
|
1582
1598
|
getNextPageParam: (last) => last.cursor ?? void 0,
|
|
@@ -1624,14 +1640,15 @@ function useActivity(input) {
|
|
|
1624
1640
|
observerRef.current = observer;
|
|
1625
1641
|
}, [loadMore]);
|
|
1626
1642
|
const [isExporting, setIsExporting] = useState(false);
|
|
1627
|
-
const toCsv = useCallback(async () => {
|
|
1643
|
+
const toCsv = useCallback(async (options) => {
|
|
1628
1644
|
setIsExporting(true);
|
|
1645
|
+
const controls = toInvocationControls(toInvocationOptions(options));
|
|
1629
1646
|
try {
|
|
1630
1647
|
const bootstrapped = requireBootstrappedClient(client, CAPXUL_OPERATIONS.activity.list);
|
|
1631
1648
|
const items = [];
|
|
1632
1649
|
let cursor;
|
|
1633
1650
|
for (let page = 0; page < EXPORT_PAGE_CEILING; page += 1) {
|
|
1634
|
-
const result = unwrapCapxulResult(await bootstrapped.activity.list(listParams(cursor, EXPORT_PAGE_SIZE)));
|
|
1651
|
+
const result = unwrapCapxulResult(await bootstrapped.activity.list(listParams(cursor, EXPORT_PAGE_SIZE), controls));
|
|
1635
1652
|
items.push(...result.items);
|
|
1636
1653
|
cursor = result.cursor ?? void 0;
|
|
1637
1654
|
if (cursor === void 0) break;
|
|
@@ -1654,7 +1671,8 @@ function useActivity(input) {
|
|
|
1654
1671
|
setDirection(void 0);
|
|
1655
1672
|
setStatus([]);
|
|
1656
1673
|
}, []);
|
|
1657
|
-
const retry = useCallback(() => {
|
|
1674
|
+
const retry = useCallback((options) => {
|
|
1675
|
+
selectedRetry.current = toInvocationOptions(options);
|
|
1658
1676
|
refetch();
|
|
1659
1677
|
}, [refetch]);
|
|
1660
1678
|
return {
|
package/dist/testing/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-
|
|
1
|
+
import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-DaT-AGx6.mjs";
|
|
2
2
|
import "react";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { createCapxulTestClient } from "@capxul/sdk/testing";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capxul/sdk-react",
|
|
3
|
-
"version": "4.2.0-rc.
|
|
3
|
+
"version": "4.2.0-rc.4",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/Xelmar-tech/infrastructure.git",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@capxul/sdk": "4.2.0-rc.
|
|
29
|
+
"@capxul/sdk": "4.2.0-rc.4"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@tanstack/react-query": "^5.66.9",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
|
|
44
44
|
"vite-plus": "0.3.0",
|
|
45
45
|
"vitest": "4.1.11",
|
|
46
|
-
"@capxul/errors": "0.3.0",
|
|
47
46
|
"@capxul/typescript-config": "0.0.0",
|
|
48
|
-
"@capxul/types": "0.3.0"
|
|
47
|
+
"@capxul/types": "0.3.0",
|
|
48
|
+
"@capxul/errors": "0.3.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@tanstack/react-query": "^5.66.9",
|