@capxul/sdk-react 4.20.0-beta.10 → 4.20.0-beta.12
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 +7 -7
- package/dist/{controllers-BWmKRFy6.d.mts → controllers-BMAU2kKH.d.mts} +2 -8
- package/dist/{controllers-L1UqwWS1.mjs → controllers-BV3e8WD3.mjs} +39 -37
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +129 -29
- package/dist/testing/index.d.mts +1 -1
- package/dist/testing/index.mjs +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -27,13 +27,13 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
27
27
|
- The provider restores Account readiness after a complete authenticated
|
|
28
28
|
session. Account and Organization readiness transitions refresh active
|
|
29
29
|
authenticated queries.
|
|
30
|
-
-
|
|
31
|
-
app-owned slots and render no SDK-owned DOM.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
- CapxulAuthenticationController and CapxulOnboardingController select
|
|
31
|
+
app-owned slots and render no SDK-owned DOM. Organization create begins a
|
|
32
|
+
backend setup and returns its exact ID. The Core SDK actor subscribes to
|
|
33
|
+
that setup. Awaiting authorization, attention, and failure reach actionable
|
|
34
|
+
slots; processing and rechecking reach a finite progress slot.
|
|
35
|
+
- CapxulDashboardAccess combines current setup with current org.me authority.
|
|
36
|
+
A historical ready setup does not grant access after authority is revoked.
|
|
37
37
|
- Rich-data hooks such as `useCapxulProfile`, `useCapxulOrgs`, members, roles,
|
|
38
38
|
treasury, and money hooks remain TanStack Query projections. Personal
|
|
39
39
|
holdings and activity reads start only after the Account is claimed.
|
|
@@ -106,14 +106,8 @@ type AccountProgress = Exclude<Readiness, {
|
|
|
106
106
|
type AccountFailure = Extract<Readiness, {
|
|
107
107
|
at: "failed";
|
|
108
108
|
}>;
|
|
109
|
-
type OrgProgress =
|
|
110
|
-
|
|
111
|
-
} | {
|
|
112
|
-
at: "ready";
|
|
113
|
-
}>;
|
|
114
|
-
type OrgFailure = Extract<OrgLane, {
|
|
115
|
-
at: "failed";
|
|
116
|
-
}>;
|
|
109
|
+
type OrgProgress = OrgLane;
|
|
110
|
+
type OrgFailure = OrgLane;
|
|
117
111
|
type ReadyDestination = Extract<IdentityDestination, {
|
|
118
112
|
to: "dashboardPersonal" | "dashboardOrganization";
|
|
119
113
|
}>;
|
|
@@ -228,7 +228,7 @@ async function guarded(runtime, verb, options, run) {
|
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
230
|
function organizationFailure(reason, state) {
|
|
231
|
-
const stateFailure = state.phase === "faulted" ? state.failure : state.phase === "authenticated" && state.account.at === "failed" ? state.account.failure : state.phase === "authenticated" && state.account.at === "claimed"
|
|
231
|
+
const stateFailure = state.phase === "faulted" ? state.failure : state.phase === "authenticated" && state.account.at === "failed" ? state.account.failure : state.phase === "authenticated" && state.account.at === "claimed" ? state.account.org?.failure : void 0;
|
|
232
232
|
if (stateFailure?.code === reason) return {
|
|
233
233
|
ok: false,
|
|
234
234
|
reason,
|
|
@@ -266,8 +266,7 @@ function normalizeOrganization(organization) {
|
|
|
266
266
|
/** The Organization id when its lane is already running or finished, else null. */
|
|
267
267
|
const runningOrganization = (state) => {
|
|
268
268
|
if (state.phase !== "authenticated" || state.account.at !== "claimed") return null;
|
|
269
|
-
|
|
270
|
-
return org !== null && (org.at === "loading" || org.at === "settingUp" || org.at === "ready") ? org.orgId : null;
|
|
269
|
+
return state.account.org?.orgId ?? null;
|
|
271
270
|
};
|
|
272
271
|
/** A superseded session read waits at most this long for the winning read. */
|
|
273
272
|
const SESSION_SETTLE_LIMIT_MS = 3e4;
|
|
@@ -488,20 +487,6 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
488
487
|
ok: true,
|
|
489
488
|
orgId: running
|
|
490
489
|
};
|
|
491
|
-
if (current.phase === "authenticated" && current.account.at === "claimed") {
|
|
492
|
-
const org = current.account.org;
|
|
493
|
-
if (org?.at === "failed" && org.orgId !== null) {
|
|
494
|
-
if (!org.retryable) return {
|
|
495
|
-
ok: false,
|
|
496
|
-
reason: org.failure.code
|
|
497
|
-
};
|
|
498
|
-
const retried = await runtime.send({ _tag: "RetryOrganization" }, invocation);
|
|
499
|
-
return failure(retried) ?? {
|
|
500
|
-
ok: true,
|
|
501
|
-
orgId: org.orgId
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
490
|
const prepared = await prepareOrganization(submission, invocation);
|
|
506
491
|
if (!prepared.ok) return prepared;
|
|
507
492
|
const opened = runningOrganization(runtime.snapshot());
|
|
@@ -509,20 +494,24 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
509
494
|
ok: true,
|
|
510
495
|
orgId: opened
|
|
511
496
|
};
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
draft: prepared.organization
|
|
515
|
-
}, invocation);
|
|
516
|
-
const refused = failure(created);
|
|
517
|
-
if (refused !== null) return refused;
|
|
518
|
-
const state = created.state;
|
|
519
|
-
const org = state.phase === "authenticated" && state.account.at === "claimed" ? state.account.org : null;
|
|
520
|
-
return org?.at === "ready" && org.orgId !== null ? {
|
|
521
|
-
ok: true,
|
|
522
|
-
orgId: org.orgId
|
|
523
|
-
} : {
|
|
497
|
+
const begun = await client.onboarding.beginOrganization(prepared.organization, invocation);
|
|
498
|
+
if (!begun.ok) return {
|
|
524
499
|
ok: false,
|
|
525
|
-
reason:
|
|
500
|
+
reason: begun.error.code,
|
|
501
|
+
error: begun.error
|
|
502
|
+
};
|
|
503
|
+
const { orgId, setup } = begun.value;
|
|
504
|
+
if (setup.status === "awaitingAuthorization") {
|
|
505
|
+
const authorized = await client.org(orgId).setup.authorize(invocation);
|
|
506
|
+
if (!authorized.ok) return {
|
|
507
|
+
ok: false,
|
|
508
|
+
reason: authorized.error.code,
|
|
509
|
+
error: authorized.error
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
return {
|
|
513
|
+
ok: true,
|
|
514
|
+
orgId: String(orgId)
|
|
526
515
|
};
|
|
527
516
|
}).then((result) => {
|
|
528
517
|
if (result.ok) return result;
|
|
@@ -535,8 +524,21 @@ function createAuth(client, clearAuthenticatedQueries) {
|
|
|
535
524
|
}),
|
|
536
525
|
retry: (options) => guarded(runtime, "retry", options, async (invocation) => {
|
|
537
526
|
const state = runtime.snapshot();
|
|
538
|
-
const
|
|
539
|
-
|
|
527
|
+
const orgId = runningOrganization(state);
|
|
528
|
+
if (orgId !== null) {
|
|
529
|
+
const scoped = client.org(orgId);
|
|
530
|
+
const current = await scoped.setup.get(invocation);
|
|
531
|
+
if (!current.ok) return {
|
|
532
|
+
ok: false,
|
|
533
|
+
reason: current.error.code
|
|
534
|
+
};
|
|
535
|
+
const result = current.value.status === "awaitingAuthorization" ? await scoped.setup.authorize(invocation) : await scoped.setup.resume(invocation);
|
|
536
|
+
return result.ok ? { ok: true } : {
|
|
537
|
+
ok: false,
|
|
538
|
+
reason: result.error.code
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
const result = await runtime.send({ _tag: "RetryAccount" }, invocation);
|
|
540
542
|
return failure(result) ?? { ok: true };
|
|
541
543
|
}),
|
|
542
544
|
resumeSubmittedOrganization: (submission, options) => guarded(runtime, "createOrganization", options, async (invocation) => {
|
|
@@ -580,7 +582,7 @@ function CapxulIdentityProvider({ client, children }) {
|
|
|
580
582
|
const account = actingAccount(state);
|
|
581
583
|
const accountChanged = previousAccount !== void 0 && account !== void 0 && account !== previousAccount;
|
|
582
584
|
previousAccount = account;
|
|
583
|
-
if (record.outcome === "applied" && (record.from !== record.to || accountChanged) && (record.to === "authenticated:claimed" || record.to === "authenticated:claimed:
|
|
585
|
+
if (record.outcome === "applied" && (record.from !== record.to || accountChanged) && (record.to === "authenticated:claimed" || record.to === "authenticated:claimed:organization")) queryClient.invalidateQueries({
|
|
584
586
|
queryKey: capxulKeys.root,
|
|
585
587
|
...accountChanged ? { refetchType: "none" } : {}
|
|
586
588
|
});
|
|
@@ -922,15 +924,15 @@ function CapxulOnboardingController(props) {
|
|
|
922
924
|
if (submission !== null && state.account.at === "claimed") {
|
|
923
925
|
const org = state.account.org;
|
|
924
926
|
if (org === null) return organizationForm(props, state, auth, submission);
|
|
925
|
-
if (org.
|
|
926
|
-
const retry = org.
|
|
927
|
+
if (org.observation === "error" || org.setup?.status === "failed" || org.setup?.status === "needsAttention" || org.setup?.status === "awaitingAuthorization") {
|
|
928
|
+
const retry = org.orgId === null ? (options) => auth.createOrganization(submission, options) : auth.retry;
|
|
927
929
|
return slots.organizationFailure({
|
|
928
930
|
state,
|
|
929
931
|
org,
|
|
930
|
-
|
|
932
|
+
retry
|
|
931
933
|
});
|
|
932
934
|
}
|
|
933
|
-
if (org.
|
|
935
|
+
if (org.setup?.status !== "ready" || org.observation !== "connected") return slots.organizationProgress({
|
|
934
936
|
state,
|
|
935
937
|
org
|
|
936
938
|
});
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { A as entered, C as CreateOrganizationFailure, D as OrganizationDetails, E as InvocationOptions, F as useCapxulTransitions, M as useCapxulDestination, N as useCapxulIdentity, O as ProfileDetails, P as useCapxulSend, S as CapxulSend, T as Destination, _ as ReadyDestination, a as AuthenticationSlots, b as Slot, c as ControllerAction, d as OnboardingControllerProps, f as OrgFailure, g as ProfileSlotProps, h as PendingAuthState, i as AuthenticatedState, j as useCapxulAuth, k as SendResult, l as FaultedState, m as OtpPendingState, n as AccountProgress, o as CapxulAuthenticationController, p as OrgProgress, r as ActionResult, s as CapxulOnboardingController, t as AccountFailure, u as NavigationAction, v as RetryAction, w as CreateOrganizationSubmission, x as CapxulAuth, y as SignedOutState } from "./controllers-
|
|
1
|
+
import { A as entered, C as CreateOrganizationFailure, D as OrganizationDetails, E as InvocationOptions, F as useCapxulTransitions, M as useCapxulDestination, N as useCapxulIdentity, O as ProfileDetails, P as useCapxulSend, S as CapxulSend, T as Destination, _ as ReadyDestination, a as AuthenticationSlots, b as Slot, c as ControllerAction, d as OnboardingControllerProps, f as OrgFailure, g as ProfileSlotProps, h as PendingAuthState, i as AuthenticatedState, j as useCapxulAuth, k as SendResult, l as FaultedState, m as OtpPendingState, n as AccountProgress, o as CapxulAuthenticationController, p as OrgProgress, r as ActionResult, s as CapxulOnboardingController, t as AccountFailure, u as NavigationAction, v as RetryAction, w as CreateOrganizationSubmission, x as CapxulAuth, y as SignedOutState } from "./controllers-BMAU2kKH.mjs";
|
|
2
2
|
import { ReactNode, RefCallback } from "react";
|
|
3
3
|
import { QueryClient, UseMutationResult, UseQueryResult } from "@tanstack/react-query";
|
|
4
|
-
import { Account, AccountRequirement, ActivityAnnotation, ActivityAnnotationInput, ActivityDetail, ActivityKind, ActivityListParams, ActivityPage, ActivityPhase, ActivityRange, ActivityReference, ActivitySummaryTotal, ActorReference, AddressBookEntry, AssetAmount, AssetId, BudgetId, CapxulClient, CapxulError, CapxulResult, CapxulSigner,
|
|
4
|
+
import { Account, AccountRequirement, ActivityAnnotation, ActivityAnnotationInput, ActivityDetail, ActivityKind, ActivityListParams, ActivityPage, ActivityPhase, ActivityRange, ActivityReference, ActivitySummaryTotal, ActorReference, AddressBookEntry, AssetAmount, AssetId, BudgetId, CapxulClient, CapxulError, CapxulResult, CapxulSigner, CurrentHoldings, HostObservability, IdentityDestination, IdentityState, MemberView, Money, MoneyParseErrorReason, OrgId, OrganizationAccess, OrganizationOnboarding, OrganizationOnboardingInput, OrganizationPaymentBatchInput, OrganizationPaymentInput, PartyId, Payment, PaymentDirection, PaymentDocumentDownload, PaymentDocumentReadRef, PaymentDocumentRef, PaymentDocumentRender, PaymentStatus, PaymentTiming, PaymentType, PaymentsPayInput, PayrollGroupId, PayrollGroupInput, PayrollRunId, PayrollRunStatus, Permission, PermissionMethods, PermissionReadResult, Profile, RoleView, SubmittedPermissionExecution, isClaimed, isRestoring } from "@capxul/sdk";
|
|
5
5
|
//#region src/provider.d.ts
|
|
6
6
|
type CapxulProviderSharedProps = {
|
|
7
7
|
/** Bring your own QueryClient; otherwise the provider creates one. */
|
|
@@ -199,9 +199,9 @@ declare function useCapxulOrgTreasury(orgId: OrgId | undefined, options?: UseCap
|
|
|
199
199
|
//#region src/hooks/use-capxul-create-org.d.ts
|
|
200
200
|
/**
|
|
201
201
|
* Create an Organization. Binds directly to the
|
|
202
|
-
* `
|
|
202
|
+
* `onboarding.completeOrganization(input)` SDK method. On success, invalidates the org list.
|
|
203
203
|
*/
|
|
204
|
-
type UseCapxulCreateOrgReturn = UseMutationResult<
|
|
204
|
+
type UseCapxulCreateOrgReturn = UseMutationResult<OrganizationOnboarding, CapxulError, OrganizationOnboardingInput>;
|
|
205
205
|
declare function useCapxulCreateOrg(): UseCapxulCreateOrgReturn;
|
|
206
206
|
//#endregion
|
|
207
207
|
//#region src/headless/journey/journey-state.d.ts
|
|
@@ -840,14 +840,14 @@ type DashboardScope = {
|
|
|
840
840
|
};
|
|
841
841
|
type DashboardAccessPhase = "checking" | "error" | "redirect" | "granted";
|
|
842
842
|
/**
|
|
843
|
-
* Which
|
|
843
|
+
* Which probe produced the error the screen is showing. The
|
|
844
844
|
* error code alone cannot say: a provider failure reads the same whether the
|
|
845
845
|
* session read, the membership list or the lifecycle read raised it, and a
|
|
846
846
|
* consumer that reports a displayed gate error has to keep those apart
|
|
847
847
|
* (#1963 R05-2). It names the SOURCE only; `retry` still re-runs every failed
|
|
848
848
|
* probe, exactly as before.
|
|
849
849
|
*/
|
|
850
|
-
type DashboardAccessProbe = "session" | "membership" | "lifecycle";
|
|
850
|
+
type DashboardAccessProbe = "session" | "membership" | "lifecycle" | "authority";
|
|
851
851
|
interface DashboardAccessErrorSlice {
|
|
852
852
|
readonly error: CapxulError;
|
|
853
853
|
/** The probe the surfaced error came from, in the frozen precedence order. */
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { _ as useCapxul, a as useCapxulAuth, c as useCapxulIdentityOrNull, d as toInvocationControls, f as toInvocationOptions, g as useCapxulClientOrNull, h as capxulKeys, i as entered, l as useCapxulSend, m as actingAccount, n as CapxulOnboardingController, o as useCapxulDestination, p as accountKey, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-
|
|
2
|
+
import { _ as useCapxul, a as useCapxulAuth, c as useCapxulIdentityOrNull, d as toInvocationControls, f as toInvocationOptions, g as useCapxulClientOrNull, h as capxulKeys, i as entered, l as useCapxulSend, m as actingAccount, n as CapxulOnboardingController, o as useCapxulDestination, p as accountKey, r as CapxulProvider, s as useCapxulIdentity, t as CapxulAuthenticationController, u as useCapxulTransitions } from "./controllers-BV3e8WD3.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, assetSymbolFor, fingerprintPaymentIntent, formatAssetAmount, formatMoney, isCapxulError, isClaimed, isClaimed as isClaimed$1, isMoneyParseError, isRestoring, isRestoring as isRestoring$1, parseAssetAmount, parseMoney, paymentPhase, requireAsset, resolveIdentityDestination, toEvmAddress, toPartyId, toRaw, valueActivitySummary } from "@capxul/sdk";
|
|
@@ -538,7 +538,7 @@ function useCapxulCreateOrg() {
|
|
|
538
538
|
const queryClient = useQueryClient();
|
|
539
539
|
return useMutation({
|
|
540
540
|
mutationFn: async (input) => {
|
|
541
|
-
return unwrapCapxulResult(await requireBootstrappedClient(client,
|
|
541
|
+
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.onboarding.completeOrganization).onboarding.completeOrganization(input));
|
|
542
542
|
},
|
|
543
543
|
onSuccess: async () => {
|
|
544
544
|
await queryClient.invalidateQueries({ queryKey: capxulKeys.orgs });
|
|
@@ -2342,18 +2342,14 @@ function isOrgLaneSettled(identity) {
|
|
|
2342
2342
|
if (identity.phase !== "authenticated" || identity.account.at !== "claimed") return true;
|
|
2343
2343
|
const org = identity.account.org;
|
|
2344
2344
|
if (org === null) return true;
|
|
2345
|
-
|
|
2346
|
-
case "ready":
|
|
2347
|
-
case "failed": return true;
|
|
2348
|
-
default: return false;
|
|
2349
|
-
}
|
|
2345
|
+
return org.observation === "connected" && org.setup !== null;
|
|
2350
2346
|
}
|
|
2351
2347
|
/** Exactly the Organization asked for, and ready to be used. */
|
|
2352
2348
|
function isExactOrgReady(lifecycle, orgId) {
|
|
2353
2349
|
return lifecycle?.status === "ready" && String(lifecycle.orgId) === orgId;
|
|
2354
2350
|
}
|
|
2355
2351
|
function isLifecycleSettled(lifecycle) {
|
|
2356
|
-
return lifecycle
|
|
2352
|
+
return lifecycle !== void 0;
|
|
2357
2353
|
}
|
|
2358
2354
|
function destinationOrNull(identity) {
|
|
2359
2355
|
return identity === null ? null : resolveIdentityDestination(identity);
|
|
@@ -2381,19 +2377,27 @@ function decidePhase(input) {
|
|
|
2381
2377
|
* Which probe produced the surfaced error — the SAME precedence `error` itself
|
|
2382
2378
|
* is chosen by, written once so the code and its source can never disagree.
|
|
2383
2379
|
*/
|
|
2384
|
-
function probeOf(session, membership, lifecycle) {
|
|
2380
|
+
function probeOf(session, membership, lifecycle, authority) {
|
|
2385
2381
|
if (session !== null) return "session";
|
|
2386
2382
|
if (membership !== null) return "membership";
|
|
2387
2383
|
if (lifecycle !== null) return "lifecycle";
|
|
2384
|
+
if (authority !== null) return "authority";
|
|
2388
2385
|
return null;
|
|
2389
2386
|
}
|
|
2390
2387
|
/** The engine — all the logic. NOT exported from the package barrel. */
|
|
2391
2388
|
function useDashboardAccess(scope) {
|
|
2392
2389
|
const client = useCapxulClientOrNull();
|
|
2390
|
+
const queryClient = useQueryClient();
|
|
2393
2391
|
const identity = useCapxulIdentityOrNull();
|
|
2394
2392
|
const destination = useMemo(() => destinationOrNull(identity), [identity]);
|
|
2395
2393
|
const orgId = scope.kind === "organization" ? scope.orgId : void 0;
|
|
2396
2394
|
const claimed = isClaimedOrFalse(identity);
|
|
2395
|
+
const scopeKey = `${orgId ?? ""}:${identity?.phase === "authenticated" ? identity.session.authUserId : ""}:${actingAccount(identity) ?? ""}`;
|
|
2396
|
+
const [observation, setObservation] = useState({
|
|
2397
|
+
scopeKey,
|
|
2398
|
+
status: "loading"
|
|
2399
|
+
});
|
|
2400
|
+
const [subscriptionRetry, setSubscriptionRetry] = useState(0);
|
|
2397
2401
|
const sessionError = useMemo(() => identity?.phase === "faulted" ? identityError(identity) : null, [identity]);
|
|
2398
2402
|
const wantsMemberships = orgId !== void 0 && claimed;
|
|
2399
2403
|
const memberships = useCapxulOrgs({ enabled: wantsMemberships });
|
|
@@ -2401,33 +2405,125 @@ function useDashboardAccess(scope) {
|
|
|
2401
2405
|
const membershipsSettled = !wantsMemberships || memberships.data !== void 0 || membershipError !== null;
|
|
2402
2406
|
const hasMembership = orgId !== void 0 && (memberships.data ?? []).some((organization) => String(organization.id) === orgId);
|
|
2403
2407
|
const wantsLifecycle = wantsMemberships && membershipsSettled && hasMembership;
|
|
2408
|
+
const setupKey = accountKey(capxulKeys.orgLifecycle(orgId), identity);
|
|
2404
2409
|
const lifecycle = useQuery({
|
|
2405
|
-
queryKey:
|
|
2410
|
+
queryKey: setupKey,
|
|
2406
2411
|
queryFn: async () => {
|
|
2407
|
-
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.
|
|
2412
|
+
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.organization.setup).org(orgId).setup.get());
|
|
2408
2413
|
},
|
|
2409
2414
|
enabled: wantsLifecycle && client !== null
|
|
2410
2415
|
});
|
|
2411
|
-
const
|
|
2412
|
-
|
|
2416
|
+
const meKey = capxulKeys.orgMe(orgId, actingAccount(identity));
|
|
2417
|
+
useEffect(() => {
|
|
2418
|
+
if (!wantsLifecycle || client === null || orgId === void 0) return;
|
|
2419
|
+
const controller = new AbortController();
|
|
2420
|
+
let closed = false;
|
|
2421
|
+
let stop = null;
|
|
2422
|
+
setObservation({
|
|
2423
|
+
scopeKey,
|
|
2424
|
+
status: "loading"
|
|
2425
|
+
});
|
|
2426
|
+
client.org(orgId).setup.subscribe((snapshot) => {
|
|
2427
|
+
if (closed) return;
|
|
2428
|
+
if (snapshot.status === "value") {
|
|
2429
|
+
setObservation({
|
|
2430
|
+
scopeKey,
|
|
2431
|
+
status: "value",
|
|
2432
|
+
value: snapshot.value
|
|
2433
|
+
});
|
|
2434
|
+
queryClient.setQueryData(setupKey, snapshot.value);
|
|
2435
|
+
} else if (snapshot.status === "error") setObservation({
|
|
2436
|
+
scopeKey,
|
|
2437
|
+
status: "error",
|
|
2438
|
+
error: snapshot.error
|
|
2439
|
+
});
|
|
2440
|
+
}, { signal: controller.signal }).then((result) => {
|
|
2441
|
+
if (!result.ok) {
|
|
2442
|
+
if (!closed) setObservation({
|
|
2443
|
+
scopeKey,
|
|
2444
|
+
status: "error",
|
|
2445
|
+
error: result.error
|
|
2446
|
+
});
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2449
|
+
stop = result.value;
|
|
2450
|
+
if (closed) stop();
|
|
2451
|
+
}).catch(() => {
|
|
2452
|
+
if (!closed) setObservation({
|
|
2453
|
+
scopeKey,
|
|
2454
|
+
status: "error",
|
|
2455
|
+
error: new CapxulError("UNKNOWN", "Organization setup subscription failed")
|
|
2456
|
+
});
|
|
2457
|
+
});
|
|
2458
|
+
return () => {
|
|
2459
|
+
closed = true;
|
|
2460
|
+
controller.abort();
|
|
2461
|
+
stop?.();
|
|
2462
|
+
};
|
|
2463
|
+
}, [
|
|
2464
|
+
client,
|
|
2465
|
+
orgId,
|
|
2466
|
+
wantsLifecycle,
|
|
2467
|
+
queryClient,
|
|
2468
|
+
scopeKey,
|
|
2469
|
+
subscriptionRetry
|
|
2470
|
+
]);
|
|
2471
|
+
const currentSetup = observation.scopeKey === scopeKey && observation.status === "value" ? observation.value : void 0;
|
|
2472
|
+
const wantsAuthority = wantsLifecycle && currentSetup?.status === "ready";
|
|
2473
|
+
const authority = useQuery({
|
|
2474
|
+
queryKey: meKey,
|
|
2475
|
+
queryFn: async () => {
|
|
2476
|
+
return unwrapCapxulResult(await requireBootstrappedClient(client, CAPXUL_OPERATIONS.org.me).org(orgId).me());
|
|
2477
|
+
},
|
|
2478
|
+
enabled: wantsAuthority && client !== null
|
|
2479
|
+
});
|
|
2480
|
+
const [checkedAuthority, setCheckedAuthority] = useState(null);
|
|
2481
|
+
useEffect(() => {
|
|
2482
|
+
if (!wantsAuthority || currentSetup === void 0) return;
|
|
2483
|
+
let active = true;
|
|
2484
|
+
authority.refetch().then((result) => {
|
|
2485
|
+
if (active && result.isSuccess) setCheckedAuthority({
|
|
2486
|
+
scopeKey,
|
|
2487
|
+
setup: currentSetup
|
|
2488
|
+
});
|
|
2489
|
+
});
|
|
2490
|
+
return () => {
|
|
2491
|
+
active = false;
|
|
2492
|
+
};
|
|
2493
|
+
}, [
|
|
2494
|
+
scopeKey,
|
|
2495
|
+
currentSetup,
|
|
2496
|
+
wantsAuthority,
|
|
2497
|
+
authority.refetch
|
|
2498
|
+
]);
|
|
2499
|
+
const authorityCurrent = checkedAuthority?.scopeKey === scopeKey && checkedAuthority.setup === currentSetup && authority.data !== void 0;
|
|
2500
|
+
const observationError = observation.scopeKey === scopeKey && observation.status === "error" ? observation.error : void 0;
|
|
2501
|
+
const lifecycleError = wantsLifecycle ? observationError ?? lifecycle.error : null;
|
|
2502
|
+
const authorityError = wantsAuthority ? authority.error : null;
|
|
2503
|
+
const lifecycleSettled = !wantsLifecycle || lifecycleError !== null || authorityError !== null || isLifecycleSettled(currentSetup) && (!wantsAuthority || authorityCurrent);
|
|
2413
2504
|
const retry = useCallback(() => {
|
|
2414
2505
|
if (sessionError !== null && client !== null) client.auth.getSession();
|
|
2415
2506
|
if (membershipError !== null) memberships.refetch();
|
|
2507
|
+
if (observationError !== void 0) setSubscriptionRetry((attempt) => attempt + 1);
|
|
2416
2508
|
if (lifecycleError !== null) lifecycle.refetch();
|
|
2509
|
+
if (authorityError !== null) authority.refetch();
|
|
2417
2510
|
}, [
|
|
2418
2511
|
client,
|
|
2419
2512
|
sessionError,
|
|
2420
2513
|
membershipError,
|
|
2514
|
+
observationError,
|
|
2421
2515
|
lifecycleError,
|
|
2422
2516
|
memberships.refetch,
|
|
2423
|
-
lifecycle.refetch
|
|
2517
|
+
lifecycle.refetch,
|
|
2518
|
+
authorityError,
|
|
2519
|
+
authority.refetch
|
|
2424
2520
|
]);
|
|
2425
|
-
const error = sessionError ?? membershipError ?? lifecycleError;
|
|
2426
|
-
const probe = probeOf(sessionError, membershipError, lifecycleError);
|
|
2521
|
+
const error = sessionError ?? membershipError ?? lifecycleError ?? authorityError;
|
|
2522
|
+
const probe = probeOf(sessionError, membershipError, lifecycleError, authorityError);
|
|
2427
2523
|
const phase = decidePhase({
|
|
2428
2524
|
error,
|
|
2429
2525
|
settled: client !== null && identity !== null && !isRestoring$1(identity) && membershipsSettled && lifecycleSettled,
|
|
2430
|
-
granted: scope.kind === "personal" ? claimed : claimed && orgId !== void 0 && hasMembership && isExactOrgReady(
|
|
2526
|
+
granted: scope.kind === "personal" ? claimed : claimed && orgId !== void 0 && hasMembership && isExactOrgReady(currentSetup, orgId) && authorityCurrent,
|
|
2431
2527
|
orgLaneSettled: identity !== null && isOrgLaneSettled(identity),
|
|
2432
2528
|
destination
|
|
2433
2529
|
});
|
|
@@ -2867,28 +2963,33 @@ function decodeDraft(value, scope) {
|
|
|
2867
2963
|
const to = record(item.to);
|
|
2868
2964
|
const amount = record(item.amount);
|
|
2869
2965
|
const partyId = toPartyId(identifier(item.partyId));
|
|
2870
|
-
if (to.kind !== "party" || to.partyId !== partyId || item.gross !== item.net || typeof amount.asset !== "string" || typeof amount.value !== "string" ||
|
|
2966
|
+
if (to.kind !== "party" || to.partyId !== partyId || item.gross !== item.net || typeof amount.asset !== "string" || typeof amount.value !== "string" || "currency" in item || "decimals" in item || !Array.isArray(item.adjustments) || item.adjustments.length !== 0) throw Errors.invalidInput("payrollDraft", "Invalid draft recipient");
|
|
2871
2967
|
const net = minorAmount(item.net);
|
|
2968
|
+
const selectedAsset = requireAsset(identifier(amount.asset));
|
|
2969
|
+
const selectedAmount = {
|
|
2970
|
+
asset: selectedAsset.assetId,
|
|
2971
|
+
value: amount.value
|
|
2972
|
+
};
|
|
2973
|
+
try {
|
|
2974
|
+
if (toRaw(selectedAmount, selectedAsset).toString() !== net) throw Errors.invalidInput("payrollDraft", "Draft payout units differ from net");
|
|
2975
|
+
} catch {
|
|
2976
|
+
throw Errors.invalidInput("payrollDraft", "Invalid draft payout amount");
|
|
2977
|
+
}
|
|
2872
2978
|
return {
|
|
2873
2979
|
to: {
|
|
2874
2980
|
kind: "party",
|
|
2875
2981
|
partyId
|
|
2876
2982
|
},
|
|
2877
2983
|
partyId,
|
|
2878
|
-
amount:
|
|
2879
|
-
asset: requireAsset(amount.asset).assetId,
|
|
2880
|
-
value: amount.value
|
|
2881
|
-
},
|
|
2984
|
+
amount: selectedAmount,
|
|
2882
2985
|
gross: net,
|
|
2883
2986
|
net,
|
|
2884
|
-
currency: item.currency,
|
|
2885
|
-
decimals: item.decimals,
|
|
2886
2987
|
adjustments: []
|
|
2887
2988
|
};
|
|
2888
2989
|
});
|
|
2889
2990
|
if (new Set(items.map((item) => item.partyId)).size !== items.length) throw Errors.invalidInput("payrollDraft", "Duplicate draft recipient");
|
|
2890
2991
|
const exactAsset = requireAsset(identifier(asset.id));
|
|
2891
|
-
if (items.some((item) => item.amount.asset !== exactAsset.assetId)) throw Errors.invalidInput("payrollDraft", "Draft item asset does not match the run asset");
|
|
2992
|
+
if (input.asset !== exactAsset.assetId || items.some((item) => item.amount.asset !== exactAsset.assetId)) throw Errors.invalidInput("payrollDraft", "Draft item asset does not match the run asset");
|
|
2892
2993
|
return {
|
|
2893
2994
|
version: 1,
|
|
2894
2995
|
scope,
|
|
@@ -3133,6 +3234,7 @@ function freshRunItems(input) {
|
|
|
3133
3234
|
const amount = input.amounts[index];
|
|
3134
3235
|
const terms = input.compensationTerms.get(recipientId);
|
|
3135
3236
|
if (to === void 0 || amount === void 0 || terms === void 0) throw Errors.unknown();
|
|
3237
|
+
const rawAmount = toRaw(amount, requireAsset(amount.asset)).toString();
|
|
3136
3238
|
items.push({
|
|
3137
3239
|
to: {
|
|
3138
3240
|
kind: "party",
|
|
@@ -3140,10 +3242,8 @@ function freshRunItems(input) {
|
|
|
3140
3242
|
},
|
|
3141
3243
|
partyId: recipientId,
|
|
3142
3244
|
amount,
|
|
3143
|
-
gross:
|
|
3144
|
-
net:
|
|
3145
|
-
currency: terms.currency,
|
|
3146
|
-
decimals: terms.decimals,
|
|
3245
|
+
gross: rawAmount,
|
|
3246
|
+
net: rawAmount,
|
|
3147
3247
|
adjustments: []
|
|
3148
3248
|
});
|
|
3149
3249
|
}
|
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-
|
|
1
|
+
import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-BMAU2kKH.mjs";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { ReactNode } from "react";
|
|
4
4
|
import { CapxulTestClient, CapxulTestClock, CapxulTestObservation, CreateCapxulTestClientOptions, SeedTestIdentityInput, createCapxulTestClient } from "@capxul/sdk/testing";
|
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-BV3e8WD3.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.20.0-beta.
|
|
3
|
+
"version": "4.20.0-beta.12",
|
|
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.20.0-beta.
|
|
29
|
+
"@capxul/sdk": "4.20.0-beta.12"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@tanstack/react-query": "^5.66.9",
|
|
@@ -43,7 +43,7 @@
|
|
|
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/config": "0.4.0-beta.
|
|
46
|
+
"@capxul/config": "0.4.0-beta.1",
|
|
47
47
|
"@capxul/errors": "0.3.0",
|
|
48
48
|
"@capxul/types": "0.3.0",
|
|
49
49
|
"@capxul/typescript-config": "0.0.0"
|