@capxul/sdk-react 4.2.0-rc.5 → 4.2.0-rc.7

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.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "source": {
3
- "commit": "72be9c2d5c9b2dcdd27fa5c5acb22163ddec5c44",
4
- "tree": "1529290d3427ecf12fece6ff70fbea35b077b6a9",
3
+ "commit": "8686db25e55ef5d7e7b3b6a4314e077c5e00d54a",
4
+ "tree": "dbde050fc2c894e1eba477c371d19d6999690ee8",
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.5"
10
+ "version": "4.2.0-rc.7"
11
11
  }
@@ -106,23 +106,11 @@ type AccountProgress = Exclude<Readiness, {
106
106
  type AccountFailure = Extract<Readiness, {
107
107
  at: "failed";
108
108
  }>;
109
- /**
110
- * The Organization lane while it still owes an answer. `loading` widens the
111
- * lane's `orgId` to `string | null`: after a reload the SDK asks the backend
112
- * whether a setup is pending, and until that read lands the claimed identity
113
- * holds no Organization id at all. The identity model keeps its own `loading`
114
- * id non-null — only this slot type carries the pre-attach window.
115
- */
116
109
  type OrgProgress = Exclude<OrgLane, {
117
110
  at: "failed";
118
111
  } | {
119
112
  at: "ready";
120
- } | {
121
- at: "loading";
122
- }> | {
123
- readonly at: "loading";
124
- readonly orgId: string | null;
125
- };
113
+ }>;
126
114
  type OrgFailure = Extract<OrgLane, {
127
115
  at: "failed";
128
116
  }>;
@@ -169,8 +157,11 @@ type ProfileSlotProps = {
169
157
  interface OnboardingControllerProps {
170
158
  readonly intent: "personal" | "organization" | null;
171
159
  readonly organizationProfile: ProfileDetails | null;
160
+ readonly submittedOrganization: CreateOrganizationSubmission | null;
161
+ readonly recoveryOptions?: () => InvocationOptions;
172
162
  readonly onIntent: (intent: "personal" | "organization") => void;
173
163
  readonly onOrganizationProfile: (profile: ProfileDetails | null) => void;
164
+ readonly onSubmittedOrganization: (submission: CreateOrganizationSubmission | null) => void;
174
165
  readonly navigation: {
175
166
  readonly selectorBack: NavigationAction;
176
167
  readonly profileCancel: NavigationAction;
@@ -187,6 +178,8 @@ interface OnboardingControllerProps {
187
178
  readonly organization: Slot<{
188
179
  state: AuthenticatedState;
189
180
  profileDetails: ProfileDetails;
181
+ submitted: CreateOrganizationSubmission | null;
182
+ pinnedHandle: string | null;
190
183
  submit: (organization: OrganizationDetails, options: InvocationOptions) => ReturnType<CapxulAuth["createOrganization"]>;
191
184
  back: NavigationAction;
192
185
  cancel: NavigationAction;
@@ -519,6 +519,13 @@ function createAuth(client, clearAuthenticatedQueries) {
519
519
  const event = state.phase === "authenticated" && state.account.at === "claimed" ? { _tag: "RetryOrganization" } : { _tag: "RetryAccount" };
520
520
  const result = await runtime.send(event, invocation);
521
521
  return failure(result) ?? { ok: true };
522
+ }),
523
+ resumeSubmittedOrganization: (submission, options) => guarded(runtime, "createOrganization", options, async (invocation) => {
524
+ const prepared = await prepareOrganization(submission, invocation);
525
+ return prepared.ok ? { ok: true } : {
526
+ ok: false,
527
+ reason: prepared.reason
528
+ };
522
529
  })
523
530
  };
524
531
  }
@@ -569,10 +576,12 @@ function CapxulIdentityProvider({ client, children }) {
569
576
  await queryClient.cancelQueries({ queryKey: capxulKeys.root });
570
577
  await queryClient.resetQueries({ queryKey: capxulKeys.root });
571
578
  };
579
+ const auth = createAuth(client, clearAuthenticatedQueries);
572
580
  return {
573
581
  runtime,
574
582
  send,
575
- auth: createAuth(client, clearAuthenticatedQueries),
583
+ auth,
584
+ resumeSubmittedOrganization: auth.resumeSubmittedOrganization,
576
585
  addTransitionListener
577
586
  };
578
587
  }, [
@@ -610,6 +619,9 @@ function useCapxulSend() {
610
619
  function useCapxulAuth() {
611
620
  return useIdentityContext().auth;
612
621
  }
622
+ function useResumeSubmittedOrganization() {
623
+ return useIdentityContext().resumeSubmittedOrganization;
624
+ }
613
625
  function useCapxulDestination() {
614
626
  const state = useCapxulIdentity();
615
627
  const next = resolveIdentityDestination(state);
@@ -820,24 +832,29 @@ function CapxulAuthenticationController({ slots }) {
820
832
  function ready(destination) {
821
833
  return destination?.to === "dashboardPersonal" || destination?.to === "dashboardOrganization";
822
834
  }
823
- /**
824
- * The pre-attach window: a claimed identity holding no Organization while the
825
- * SDK asks the backend whether one is pending. The controller reports progress
826
- * only when no form step is left to render. An app that still holds an
827
- * Organization profile and has not submitted through this mount is entering
828
- * the form, not resuming it — a member who starts an Organization from the
829
- * dashboard is claimed with a complete Profile before they ever see the form,
830
- * so reporting progress on the claim alone would hide the form for good.
831
- */
832
- const ATTACHING = {
833
- at: "loading",
834
- orgId: null
835
- };
836
835
  function CapxulOnboardingController(props) {
837
836
  const state = useCapxulIdentity();
838
837
  const destination = useCapxulDestination();
839
838
  const auth = useCapxulAuth();
840
- const submitted = useRef(false);
839
+ const resumeSubmittedOrganization = useResumeSubmittedOrganization();
840
+ const resumedSubmission = useRef(null);
841
+ const [failedRecovery, setFailedRecovery] = useState(null);
842
+ const submission = props.submittedOrganization;
843
+ const accountAt = state.phase === "authenticated" ? state.account.at : null;
844
+ useEffect(() => {
845
+ if (props.intent !== "organization" || submission === null || props.recoveryOptions === void 0 || accountAt !== "unknown" && accountAt !== "counterfactual" || resumedSubmission.current === submission) return;
846
+ resumedSubmission.current = submission;
847
+ setFailedRecovery(null);
848
+ resumeSubmittedOrganization(submission, props.recoveryOptions()).then((result) => {
849
+ if (!result.ok) setFailedRecovery(submission);
850
+ });
851
+ }, [
852
+ accountAt,
853
+ props.intent,
854
+ props.recoveryOptions,
855
+ resumeSubmittedOrganization,
856
+ submission
857
+ ]);
841
858
  if (state.phase !== "authenticated") return null;
842
859
  const { slots, navigation } = props;
843
860
  if (props.intent === null) return slots.intent({
@@ -851,24 +868,37 @@ function CapxulOnboardingController(props) {
851
868
  completePersonal: auth.completePersonal,
852
869
  cancel: navigation.profileCancel
853
870
  });
854
- if (props.intent === "organization" && !state.profileComplete) return props.organizationProfile === null ? slots.profile({
871
+ if (props.intent === "organization" && props.organizationProfile === null && submission === null) return slots.profile({
855
872
  intent: "organization",
856
873
  state,
857
874
  continueOrganization: props.onOrganizationProfile,
858
875
  cancel: navigation.profileCancel
859
- }) : organizationForm(props, state, auth, submitted);
860
- if (props.intent === "organization" && state.account.at === "claimed") {
861
- const org = state.account.org;
862
- if (org === null) return props.organizationProfile === null || submitted.current ? slots.organizationProgress({
876
+ });
877
+ if (props.intent === "organization" && props.organizationProfile !== null && submission === null) return organizationForm(props, state, auth, null);
878
+ if (submission !== null && failedRecovery === submission && state.account.at !== "claimed") return organizationForm(props, state, auth, submission);
879
+ if (submission !== null && state.account.at !== "claimed") {
880
+ if (state.account.at === "failed") {
881
+ const retry = state.account.retryable ? (options) => auth.createOrganization(submission, options) : void 0;
882
+ return slots.accountFailure({
883
+ state,
884
+ account: state.account,
885
+ ...retry === void 0 ? {} : { retry }
886
+ });
887
+ }
888
+ return slots.accountProgress({
863
889
  state,
864
- org: ATTACHING
865
- }) : organizationForm(props, state, auth, submitted);
890
+ account: state.account
891
+ });
892
+ }
893
+ if (submission !== null && state.account.at === "claimed") {
894
+ const org = state.account.org;
895
+ if (org === null) return organizationForm(props, state, auth, submission);
866
896
  if (org.at === "failed") {
867
- const retryable = org.retryable && org.orgId !== null;
897
+ const retry = org.retryable ? org.orgId === null ? (options) => auth.createOrganization(submission, options) : auth.retry : void 0;
868
898
  return slots.organizationFailure({
869
899
  state,
870
900
  org,
871
- ...retryable ? { retry: auth.retry } : {}
901
+ ...retry === void 0 ? {} : { retry }
872
902
  });
873
903
  }
874
904
  if (org.at !== "ready") return slots.organizationProgress({
@@ -891,20 +921,26 @@ function CapxulOnboardingController(props) {
891
921
  }) : null;
892
922
  }
893
923
  function organizationForm(props, state, auth, submitted) {
894
- const profileDetails = props.organizationProfile;
924
+ const profileDetails = submitted?.profileDetails ?? props.organizationProfile;
895
925
  if (profileDetails === null) return null;
896
926
  return props.slots.organization({
897
927
  state,
898
928
  profileDetails,
929
+ submitted,
930
+ pinnedHandle: submitted?.organization.handle ?? null,
899
931
  submit: (organization, options) => {
900
- submitted.current = true;
901
- return auth.createOrganization({
932
+ if (submitted !== null) return auth.createOrganization(submitted, options);
933
+ const normalized = normalizeOrganization(organization);
934
+ if (normalized === null) return auth.createOrganization({
902
935
  profileDetails,
903
936
  organization
904
- }, options).then((result) => {
905
- if (!result.ok) submitted.current = false;
906
- return result;
907
- });
937
+ }, options);
938
+ const next = {
939
+ profileDetails,
940
+ organization: normalized
941
+ };
942
+ props.onSubmittedOrganization(next);
943
+ return auth.createOrganization(next, options);
908
944
  },
909
945
  back: () => {
910
946
  props.onOrganizationProfile(null);
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
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-COGAAS-c.mjs";
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-BWmKRFy6.mjs";
2
2
  import { ReactNode, RefCallback } from "react";
3
3
  import { QueryClient, UseMutationResult, UseQueryResult } from "@tanstack/react-query";
4
4
  import { Account, AccountRequirement, ActivityAnnotation, ActivityAnnotationInput, ActivityDetail, ActivityKind, ActivityListParams, ActivityPage, ActivityPhase, ActivityRange, ActivityReference, ActorReference, AddressBookEntry, BudgetId, CapxulClient, CapxulError, CapxulResult, CapxulSigner, CreateOrgInput, CurrentHoldings, HostObservability, IdentityDestination, InviteMemberInput, MemberView, Money, MoneyParseErrorReason, OrgId, OrgView, OrganizationPaymentBatchInput, OrganizationPaymentInput, PartyId, Payment, PaymentDirection, PaymentDocumentRef, PaymentDocumentRender, PaymentStatus, PaymentTiming, PaymentType, PaymentsPayInput, PayrollGroupId, PayrollGroupInput, PayrollRunId, PayrollRunStatus, Permission, PermissionMethods, PermissionReadResult, Profile, RoleView, SubmittedPermissionExecution, isClaimed, isRestoring } from "@capxul/sdk";
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use client";
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-DHXq3gJY.mjs";
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";
@@ -1,4 +1,4 @@
1
- import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-COGAAS-c.mjs";
1
+ import { a as AuthenticationSlots, d as OnboardingControllerProps } from "../controllers-BWmKRFy6.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";
@@ -1,4 +1,4 @@
1
- import { n as CapxulOnboardingController, r as CapxulProvider, t as CapxulAuthenticationController } from "../controllers-DHXq3gJY.mjs";
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.5",
3
+ "version": "4.2.0-rc.7",
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.5"
29
+ "@capxul/sdk": "4.2.0-rc.7"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",
@@ -44,8 +44,8 @@
44
44
  "vite-plus": "0.3.0",
45
45
  "vitest": "4.1.11",
46
46
  "@capxul/errors": "0.3.0",
47
- "@capxul/typescript-config": "0.0.0",
48
- "@capxul/types": "0.3.0"
47
+ "@capxul/types": "0.3.0",
48
+ "@capxul/typescript-config": "0.0.0"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "@tanstack/react-query": "^5.66.9",