@capxul/sdk-react 1.0.0-alpha.20 → 1.0.0-alpha.22
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.d.mts +195 -23
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +391 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -355,6 +355,7 @@ function actorKey(actor) {
|
|
|
355
355
|
}
|
|
356
356
|
function targetKey(target) {
|
|
357
357
|
if (target === void 0) return "all";
|
|
358
|
+
if ("self" in target) return "self";
|
|
358
359
|
switch (target.kind) {
|
|
359
360
|
case "handle": return `handle:${target.handle}`;
|
|
360
361
|
case "email": return `email:${target.email}`;
|
|
@@ -396,6 +397,12 @@ const capxulKeys = {
|
|
|
396
397
|
root: ["capxul"],
|
|
397
398
|
session: ["capxul", "session"],
|
|
398
399
|
profile: ["capxul", "profile"],
|
|
400
|
+
usernameAvailability: (username) => [
|
|
401
|
+
"capxul",
|
|
402
|
+
"profile",
|
|
403
|
+
"username-availability",
|
|
404
|
+
username
|
|
405
|
+
],
|
|
399
406
|
account: ["capxul", "account"],
|
|
400
407
|
accountLifecycle: ["capxul", "accountLifecycle"],
|
|
401
408
|
provisioning: ["capxul", "provisioning"],
|
|
@@ -575,10 +582,11 @@ function useCapxulSession() {
|
|
|
575
582
|
//#region src/hooks/use-capxul-profile.ts
|
|
576
583
|
function useCapxulProfile() {
|
|
577
584
|
const client = useCapxulClientOrNull();
|
|
585
|
+
const session = useCapxulSession();
|
|
578
586
|
return useQuery({
|
|
579
587
|
queryKey: capxulKeys.profile,
|
|
580
588
|
queryFn: async () => unwrapCapxulResult(await requireBootstrappedClient(client, "identity.loadCurrent").identity.loadCurrent(), client._internal.telemetry),
|
|
581
|
-
enabled: client !== null
|
|
589
|
+
enabled: client !== null && session.data != null
|
|
582
590
|
});
|
|
583
591
|
}
|
|
584
592
|
//#endregion
|
|
@@ -1445,12 +1453,51 @@ function useCapxulCompletePersonalOnboarding() {
|
|
|
1445
1453
|
const bootstrappedClient = requireBootstrappedClient(client, "onboarding.completePersonal");
|
|
1446
1454
|
return unwrapCapxulResult(await bootstrappedClient.onboarding.completePersonal(input), bootstrappedClient._internal.telemetry, "mutation");
|
|
1447
1455
|
},
|
|
1448
|
-
|
|
1456
|
+
onSettled: async () => {
|
|
1449
1457
|
await Promise.all([queryClient.invalidateQueries({ queryKey: capxulKeys.profile }), queryClient.invalidateQueries({ queryKey: capxulKeys.accountLifecycle })]);
|
|
1450
1458
|
}
|
|
1451
1459
|
});
|
|
1452
1460
|
}
|
|
1453
1461
|
//#endregion
|
|
1462
|
+
//#region ../types/src/index.ts
|
|
1463
|
+
const SUPPORTED_CURRENCIES = [
|
|
1464
|
+
{
|
|
1465
|
+
code: "USD",
|
|
1466
|
+
symbol: "$",
|
|
1467
|
+
name: "US Dollar"
|
|
1468
|
+
},
|
|
1469
|
+
{
|
|
1470
|
+
code: "NGN",
|
|
1471
|
+
symbol: "NGN",
|
|
1472
|
+
name: "Nigerian Naira"
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
code: "GHS",
|
|
1476
|
+
symbol: "GHS",
|
|
1477
|
+
name: "Ghanaian Cedi"
|
|
1478
|
+
},
|
|
1479
|
+
{
|
|
1480
|
+
code: "KES",
|
|
1481
|
+
symbol: "KSh",
|
|
1482
|
+
name: "Kenyan Shilling"
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
code: "UGX",
|
|
1486
|
+
symbol: "USh",
|
|
1487
|
+
name: "Ugandan Shilling"
|
|
1488
|
+
}
|
|
1489
|
+
];
|
|
1490
|
+
SUPPORTED_CURRENCIES.map((currency) => currency.code);
|
|
1491
|
+
Object.fromEntries(SUPPORTED_CURRENCIES.map((currency) => [currency.code, currency.symbol]));
|
|
1492
|
+
Math.floor(Number.MAX_SAFE_INTEGER / 1e3);
|
|
1493
|
+
function toOrgId(raw) {
|
|
1494
|
+
return toNonEmptyStringBrand(raw, "orgId");
|
|
1495
|
+
}
|
|
1496
|
+
function toNonEmptyStringBrand(raw, field) {
|
|
1497
|
+
if (typeof raw !== "string" || raw.length === 0) throw Errors.invalidInput(field, "must be a non-empty string");
|
|
1498
|
+
return raw;
|
|
1499
|
+
}
|
|
1500
|
+
//#endregion
|
|
1454
1501
|
//#region src/hooks/use-capxul-complete-organization-onboarding.ts
|
|
1455
1502
|
function useCapxulCompleteOrganizationOnboarding() {
|
|
1456
1503
|
const client = useCapxulClientOrNull();
|
|
@@ -1460,16 +1507,23 @@ function useCapxulCompleteOrganizationOnboarding() {
|
|
|
1460
1507
|
const bootstrappedClient = requireBootstrappedClient(client, "onboarding.completeOrganization");
|
|
1461
1508
|
return unwrapCapxulResult(await bootstrappedClient.onboarding.completeOrganization(input), bootstrappedClient._internal.telemetry, "mutation");
|
|
1462
1509
|
},
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
queryClient.invalidateQueries({ queryKey: capxulKeys.org(orgId) })
|
|
1469
|
-
]);
|
|
1510
|
+
onSettled: async (data, error) => {
|
|
1511
|
+
const invalidations = [queryClient.invalidateQueries({ queryKey: capxulKeys.profile }), queryClient.invalidateQueries({ queryKey: capxulKeys.accountLifecycle })];
|
|
1512
|
+
const orgId = data?.orgId ?? organizationIdFromError(error);
|
|
1513
|
+
if (orgId !== void 0) invalidations.push(queryClient.invalidateQueries({ queryKey: capxulKeys.orgs }), queryClient.invalidateQueries({ queryKey: capxulKeys.org(orgId) }), queryClient.invalidateQueries({ queryKey: capxulKeys.orgLifecycle(orgId) }));
|
|
1514
|
+
await Promise.all(invalidations);
|
|
1470
1515
|
}
|
|
1471
1516
|
});
|
|
1472
1517
|
}
|
|
1518
|
+
function organizationIdFromError(error) {
|
|
1519
|
+
const candidate = error?.details?.orgId;
|
|
1520
|
+
if (typeof candidate !== "string") return void 0;
|
|
1521
|
+
try {
|
|
1522
|
+
return toOrgId(candidate);
|
|
1523
|
+
} catch {
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1473
1527
|
//#endregion
|
|
1474
1528
|
//#region src/hooks/use-capxul-invite-member.ts
|
|
1475
1529
|
function useCapxulInviteMember(orgId) {
|
|
@@ -1632,38 +1686,6 @@ function toQuerySlotState(query) {
|
|
|
1632
1686
|
};
|
|
1633
1687
|
}
|
|
1634
1688
|
//#endregion
|
|
1635
|
-
//#region ../types/src/index.ts
|
|
1636
|
-
const SUPPORTED_CURRENCIES = [
|
|
1637
|
-
{
|
|
1638
|
-
code: "USD",
|
|
1639
|
-
symbol: "$",
|
|
1640
|
-
name: "US Dollar"
|
|
1641
|
-
},
|
|
1642
|
-
{
|
|
1643
|
-
code: "NGN",
|
|
1644
|
-
symbol: "NGN",
|
|
1645
|
-
name: "Nigerian Naira"
|
|
1646
|
-
},
|
|
1647
|
-
{
|
|
1648
|
-
code: "GHS",
|
|
1649
|
-
symbol: "GHS",
|
|
1650
|
-
name: "Ghanaian Cedi"
|
|
1651
|
-
},
|
|
1652
|
-
{
|
|
1653
|
-
code: "KES",
|
|
1654
|
-
symbol: "KSh",
|
|
1655
|
-
name: "Kenyan Shilling"
|
|
1656
|
-
},
|
|
1657
|
-
{
|
|
1658
|
-
code: "UGX",
|
|
1659
|
-
symbol: "USh",
|
|
1660
|
-
name: "Ugandan Shilling"
|
|
1661
|
-
}
|
|
1662
|
-
];
|
|
1663
|
-
SUPPORTED_CURRENCIES.map((currency) => currency.code);
|
|
1664
|
-
Object.fromEntries(SUPPORTED_CURRENCIES.map((currency) => [currency.code, currency.symbol]));
|
|
1665
|
-
Math.floor(Number.MAX_SAFE_INTEGER / 1e3);
|
|
1666
|
-
//#endregion
|
|
1667
1689
|
//#region src/headless/money/SendMoney.tsx
|
|
1668
1690
|
function SendMoney({ initialValue = null, slots, onSent }) {
|
|
1669
1691
|
const pay = useCapxulPay();
|
|
@@ -1781,6 +1803,333 @@ function Destinations({ input, slots }) {
|
|
|
1781
1803
|
return slots.root?.({ children }) ?? children;
|
|
1782
1804
|
}
|
|
1783
1805
|
//#endregion
|
|
1784
|
-
|
|
1806
|
+
//#region src/headless/journey/journey-state.ts
|
|
1807
|
+
const JOURNEY_KEY = "capxul.onboarding.journey.v1";
|
|
1808
|
+
const VALIDATED_OWNER_KEY = "capxul.onboarding.validated-owner.v1";
|
|
1809
|
+
const JOURNEY_VERSION = 1;
|
|
1810
|
+
const MAX_DRAFT_TEXT_LENGTH = 200;
|
|
1811
|
+
const MAX_ID_LENGTH = 160;
|
|
1812
|
+
const MAX_STORED_JOURNEY_LENGTH = 8192;
|
|
1813
|
+
const MAX_PAYOUT_DRAFT_ENTRIES = 10;
|
|
1814
|
+
/**
|
|
1815
|
+
* The owner whose stored journey may currently be attributed to observations.
|
|
1816
|
+
* Persisted in sessionStorage rather than module memory so `currentOnboarding-
|
|
1817
|
+
* JourneyId` is a pure function of durable state — attribution is the same
|
|
1818
|
+
* regardless of the order of renders, reloads, or telemetry emits. Established
|
|
1819
|
+
* only when an authenticated owner is (journey start, or an owner-matched load)
|
|
1820
|
+
* and cleared at every auth boundary or on discard.
|
|
1821
|
+
*/
|
|
1822
|
+
function markOnboardingOwnerValidated(ownerId) {
|
|
1823
|
+
try {
|
|
1824
|
+
sessionStorage.setItem(VALIDATED_OWNER_KEY, ownerId);
|
|
1825
|
+
} catch {}
|
|
1826
|
+
}
|
|
1827
|
+
function clearValidatedOnboardingOwner() {
|
|
1828
|
+
try {
|
|
1829
|
+
sessionStorage.removeItem(VALIDATED_OWNER_KEY);
|
|
1830
|
+
} catch {}
|
|
1831
|
+
}
|
|
1832
|
+
function validatedOnboardingOwner() {
|
|
1833
|
+
try {
|
|
1834
|
+
return sessionStorage.getItem(VALIDATED_OWNER_KEY);
|
|
1835
|
+
} catch {
|
|
1836
|
+
return null;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
function startOnboardingJourney(input) {
|
|
1840
|
+
const journey = {
|
|
1841
|
+
version: JOURNEY_VERSION,
|
|
1842
|
+
ownerId: input.ownerId,
|
|
1843
|
+
journeyId: `journey_${createRandomId()}`,
|
|
1844
|
+
intent: input.intent,
|
|
1845
|
+
entryPoint: input.entryPoint,
|
|
1846
|
+
step: input.step ?? "profile",
|
|
1847
|
+
...input.origin === void 0 ? {} : { origin: input.origin }
|
|
1848
|
+
};
|
|
1849
|
+
markOnboardingOwnerValidated(journey.ownerId);
|
|
1850
|
+
saveOnboardingJourney(journey);
|
|
1851
|
+
return journey;
|
|
1852
|
+
}
|
|
1853
|
+
function loadOnboardingJourney(expectedOwnerId) {
|
|
1854
|
+
try {
|
|
1855
|
+
const raw = sessionStorage.getItem(JOURNEY_KEY);
|
|
1856
|
+
if (raw === null) return null;
|
|
1857
|
+
if (raw.length > MAX_STORED_JOURNEY_LENGTH) return discardInvalidJourney();
|
|
1858
|
+
const value = JSON.parse(raw);
|
|
1859
|
+
if (!isValidJourney(value)) return discardInvalidJourney();
|
|
1860
|
+
if (expectedOwnerId !== void 0 && value.ownerId !== expectedOwnerId) return discardInvalidJourney();
|
|
1861
|
+
if (expectedOwnerId !== void 0) markOnboardingOwnerValidated(expectedOwnerId);
|
|
1862
|
+
return value;
|
|
1863
|
+
} catch {
|
|
1864
|
+
return discardInvalidJourney();
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
function saveOnboardingJourney(journey) {
|
|
1868
|
+
if (!isValidJourney(journey)) {
|
|
1869
|
+
discardInvalidJourney();
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
try {
|
|
1873
|
+
sessionStorage.setItem(JOURNEY_KEY, JSON.stringify(journey));
|
|
1874
|
+
} catch {}
|
|
1875
|
+
}
|
|
1876
|
+
function currentOnboardingJourneyId() {
|
|
1877
|
+
const journey = loadOnboardingJourney();
|
|
1878
|
+
const owner = validatedOnboardingOwner();
|
|
1879
|
+
return journey !== null && owner !== null && journey.ownerId === owner ? journey.journeyId : void 0;
|
|
1880
|
+
}
|
|
1881
|
+
/** Stop observation attribution while no authenticated owner is established. */
|
|
1882
|
+
function invalidateOnboardingJourneyObservation() {
|
|
1883
|
+
clearValidatedOnboardingOwner();
|
|
1884
|
+
}
|
|
1885
|
+
/** Where the journey stands — the pure position apps map to their routes. */
|
|
1886
|
+
function onboardingJourneyPosition(journey) {
|
|
1887
|
+
const proof = journey.origin?.kind === "proof";
|
|
1888
|
+
if (journey.organizationId !== void 0) return {
|
|
1889
|
+
intent: journey.intent,
|
|
1890
|
+
step: "provisioning",
|
|
1891
|
+
organizationId: journey.organizationId,
|
|
1892
|
+
proof
|
|
1893
|
+
};
|
|
1894
|
+
return {
|
|
1895
|
+
intent: journey.intent,
|
|
1896
|
+
step: journey.step,
|
|
1897
|
+
proof
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* The interruption-recovery decision (behavior map §4): a journey that does
|
|
1902
|
+
* not match the ready destination the app just rendered must resume; a
|
|
1903
|
+
* matching one needs no recovery. Returns the journey to resume, or null.
|
|
1904
|
+
*/
|
|
1905
|
+
function activeOnboardingRecovery(ownerId, renderedReadyDestination) {
|
|
1906
|
+
const journey = loadOnboardingJourney(ownerId);
|
|
1907
|
+
if (journey === null) return null;
|
|
1908
|
+
return (renderedReadyDestination?.kind === "personal" ? journey.intent === "personal" && journey.step === "provisioning" && journey.organizationId === void 0 : renderedReadyDestination?.kind === "organization" && journey.intent === "organization" && journey.step === "provisioning" && journey.organizationId === renderedReadyDestination.organizationId) ? null : journey;
|
|
1909
|
+
}
|
|
1910
|
+
function acknowledgeOnboardingDestination(destination, ownerId) {
|
|
1911
|
+
const journey = loadOnboardingJourney(ownerId);
|
|
1912
|
+
if (journey === null) return false;
|
|
1913
|
+
if (!(destination.kind === "personal" ? journey.intent === "personal" && journey.step === "provisioning" : journey.intent === "organization" && journey.step === "provisioning" && journey.organizationId === destination.organizationId)) return false;
|
|
1914
|
+
clearOnboardingJourney();
|
|
1915
|
+
return true;
|
|
1916
|
+
}
|
|
1917
|
+
function clearOnboardingJourney() {
|
|
1918
|
+
clearValidatedOnboardingOwner();
|
|
1919
|
+
try {
|
|
1920
|
+
sessionStorage.removeItem(JOURNEY_KEY);
|
|
1921
|
+
} catch {}
|
|
1922
|
+
}
|
|
1923
|
+
function isValidJourney(value) {
|
|
1924
|
+
if (!isRecord(value) || value.version !== JOURNEY_VERSION) return false;
|
|
1925
|
+
if (!hasOnlyKeys(value, [
|
|
1926
|
+
"version",
|
|
1927
|
+
"ownerId",
|
|
1928
|
+
"journeyId",
|
|
1929
|
+
"intent",
|
|
1930
|
+
"entryPoint",
|
|
1931
|
+
"origin",
|
|
1932
|
+
"step",
|
|
1933
|
+
"profile",
|
|
1934
|
+
"organization",
|
|
1935
|
+
"stableHandle",
|
|
1936
|
+
"organizationId"
|
|
1937
|
+
])) return false;
|
|
1938
|
+
if (!isBoundedId(value.ownerId)) return false;
|
|
1939
|
+
if (!isBoundedId(value.journeyId) || !value.journeyId.startsWith("journey_")) return false;
|
|
1940
|
+
if (value.intent !== "personal" && value.intent !== "organization") return false;
|
|
1941
|
+
if (value.entryPoint !== "signup" && value.entryPoint !== "dashboard") return false;
|
|
1942
|
+
if (value.step !== "profile" && value.step !== "organization" && value.step !== "provisioning") return false;
|
|
1943
|
+
if (value.origin !== void 0 && !isOrigin(value.origin)) return false;
|
|
1944
|
+
if (value.profile !== void 0 && !isProfileDraft(value.profile)) return false;
|
|
1945
|
+
if (value.organization !== void 0 && !isOrganizationDraft(value.organization)) return false;
|
|
1946
|
+
if (value.stableHandle !== void 0 && !isDraftText(value.stableHandle)) return false;
|
|
1947
|
+
if (value.organizationId !== void 0 && !isBoundedId(value.organizationId)) return false;
|
|
1948
|
+
if (value.organization !== void 0 && value.stableHandle !== value.organization.handle) return false;
|
|
1949
|
+
if (value.stableHandle !== void 0 && value.organization === void 0) return false;
|
|
1950
|
+
if (value.intent === "personal" && (value.step === "organization" || value.organization !== void 0 || value.stableHandle !== void 0)) return false;
|
|
1951
|
+
if (value.step === "organization" && value.intent !== "organization") return false;
|
|
1952
|
+
if (value.organizationId !== void 0 && value.intent !== "organization") return false;
|
|
1953
|
+
if (value.organizationId !== void 0 && value.step !== "provisioning") return false;
|
|
1954
|
+
return true;
|
|
1955
|
+
}
|
|
1956
|
+
function isOrigin(value) {
|
|
1957
|
+
if (!isRecord(value)) return false;
|
|
1958
|
+
if (value.kind === "personal") return hasOnlyKeys(value, ["kind"]);
|
|
1959
|
+
if (value.kind === "organization") return hasOnlyKeys(value, ["kind", "organizationId"]) && isBoundedId(value.organizationId);
|
|
1960
|
+
return value.kind === "proof" && hasOnlyKeys(value, ["kind", "organizationId"]) && (value.organizationId === void 0 || isBoundedId(value.organizationId));
|
|
1961
|
+
}
|
|
1962
|
+
function isProfileDraft(value) {
|
|
1963
|
+
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
1964
|
+
"displayName",
|
|
1965
|
+
"country",
|
|
1966
|
+
"withdrawalAddress",
|
|
1967
|
+
"username",
|
|
1968
|
+
"payoutAddresses"
|
|
1969
|
+
]) || !isDraftText(value.displayName) || !isDraftText(value.country) || !isDraftText(value.withdrawalAddress)) return false;
|
|
1970
|
+
if (value.username !== void 0 && !isDraftText(value.username)) return false;
|
|
1971
|
+
if (value.payoutAddresses !== void 0 && !isPayoutDraftList(value.payoutAddresses)) return false;
|
|
1972
|
+
return true;
|
|
1973
|
+
}
|
|
1974
|
+
function isPayoutDraftList(value) {
|
|
1975
|
+
return Array.isArray(value) && value.length <= MAX_PAYOUT_DRAFT_ENTRIES && value.every((entry) => isRecord(entry) && hasOnlyKeys(entry, ["chain", "address"]) && (entry.chain === "evm" || entry.chain === "solana" || entry.chain === "starknet") && isDraftText(entry.address));
|
|
1976
|
+
}
|
|
1977
|
+
function isOrganizationDraft(value) {
|
|
1978
|
+
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
1979
|
+
"name",
|
|
1980
|
+
"handle",
|
|
1981
|
+
"country",
|
|
1982
|
+
"bio",
|
|
1983
|
+
"size"
|
|
1984
|
+
]) || !isDraftText(value.name) || !isDraftText(value.handle) || !isDraftText(value.country)) return false;
|
|
1985
|
+
if (value.bio !== void 0 && !isDraftText(value.bio)) return false;
|
|
1986
|
+
if (value.size !== void 0 && !isDraftText(value.size)) return false;
|
|
1987
|
+
return true;
|
|
1988
|
+
}
|
|
1989
|
+
function isDraftText(value) {
|
|
1990
|
+
return typeof value === "string" && value.length <= MAX_DRAFT_TEXT_LENGTH;
|
|
1991
|
+
}
|
|
1992
|
+
function isBoundedId(value) {
|
|
1993
|
+
return typeof value === "string" && value.length > 0 && value.length <= MAX_ID_LENGTH;
|
|
1994
|
+
}
|
|
1995
|
+
function discardInvalidJourney() {
|
|
1996
|
+
clearValidatedOnboardingOwner();
|
|
1997
|
+
try {
|
|
1998
|
+
sessionStorage.removeItem(JOURNEY_KEY);
|
|
1999
|
+
} catch {}
|
|
2000
|
+
return null;
|
|
2001
|
+
}
|
|
2002
|
+
function createRandomId() {
|
|
2003
|
+
if (typeof globalThis.crypto?.randomUUID === "function") return globalThis.crypto.randomUUID();
|
|
2004
|
+
return Math.random().toString(36).slice(2);
|
|
2005
|
+
}
|
|
2006
|
+
function isRecord(value) {
|
|
2007
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2008
|
+
}
|
|
2009
|
+
function hasOnlyKeys(value, allowed) {
|
|
2010
|
+
return Object.keys(value).every((key) => allowed.includes(key));
|
|
2011
|
+
}
|
|
2012
|
+
//#endregion
|
|
2013
|
+
//#region src/headless/routing/resolve-post-auth-destination.ts
|
|
2014
|
+
function resolvePostAuthDestination(inputs) {
|
|
2015
|
+
if (inputs.journey !== null) return {
|
|
2016
|
+
kind: "journey",
|
|
2017
|
+
position: onboardingJourneyPosition(inputs.journey)
|
|
2018
|
+
};
|
|
2019
|
+
if (!inputs.profileOnboarded) return { kind: "selectUserType" };
|
|
2020
|
+
if (!inputs.accountReady) return { kind: "provisioning" };
|
|
2021
|
+
return {
|
|
2022
|
+
kind: "dashboard",
|
|
2023
|
+
entity: inputs.lastActingEntity ?? { kind: "personal" }
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
//#endregion
|
|
2027
|
+
//#region src/internal/use-debounced-value.ts
|
|
2028
|
+
/** The value as of `delayMs` after its last change (initial value immediate). */
|
|
2029
|
+
function useDebouncedValue(value, delayMs) {
|
|
2030
|
+
const [debounced, setDebounced] = useState(value);
|
|
2031
|
+
useEffect(() => {
|
|
2032
|
+
const timer = setTimeout(() => setDebounced(value), delayMs);
|
|
2033
|
+
return () => clearTimeout(timer);
|
|
2034
|
+
}, [value, delayMs]);
|
|
2035
|
+
return debounced;
|
|
2036
|
+
}
|
|
2037
|
+
//#endregion
|
|
2038
|
+
//#region src/headless/onboarding/use-capxul-username-availability.ts
|
|
2039
|
+
/**
|
|
2040
|
+
* #1062: debounced availability probe for the username the user is typing.
|
|
2041
|
+
* Disabled until the candidate reaches the 3-character floor; a malformed or
|
|
2042
|
+
* reserved candidate surfaces as the query's error (INVALID_INPUT with the
|
|
2043
|
+
* boundary's message), not as `available: false` — only a username someone
|
|
2044
|
+
* else owns is "taken".
|
|
2045
|
+
*/
|
|
2046
|
+
function useCapxulUsernameAvailability(username, options) {
|
|
2047
|
+
const client = useCapxulClientOrNull();
|
|
2048
|
+
const candidate = useDebouncedValue(username.trim(), options?.debounceMs ?? 300);
|
|
2049
|
+
return useQuery({
|
|
2050
|
+
queryKey: capxulKeys.usernameAvailability(candidate),
|
|
2051
|
+
queryFn: async () => {
|
|
2052
|
+
const bootstrappedClient = requireBootstrappedClient(client, "identity.usernameAvailable");
|
|
2053
|
+
return unwrapCapxulResult(await bootstrappedClient.identity.usernameAvailable(candidate), bootstrappedClient._internal.telemetry);
|
|
2054
|
+
},
|
|
2055
|
+
enabled: client !== null && candidate.length >= 3 && (options?.enabled ?? true)
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
//#endregion
|
|
2059
|
+
//#region src/headless/onboarding/use-capxul-persist-payout-entries.ts
|
|
2060
|
+
const CHAIN_TO_NETWORK = {
|
|
2061
|
+
evm: "base-sepolia",
|
|
2062
|
+
solana: "solana-devnet",
|
|
2063
|
+
starknet: "starknet-sepolia"
|
|
2064
|
+
};
|
|
2065
|
+
/**
|
|
2066
|
+
* #1063: persist onboarding payout entries as SELF-owned wallet destinations.
|
|
2067
|
+
* Per-entry failures are collected, never thrown — payout persistence is
|
|
2068
|
+
* additive to the journey (identity creation is the invariant; behavior map
|
|
2069
|
+
* §3 J1), so callers surface `failures` as a non-blocking notice.
|
|
2070
|
+
*/
|
|
2071
|
+
function useCapxulPersistPayoutEntries() {
|
|
2072
|
+
const client = useCapxulClientOrNull();
|
|
2073
|
+
const queryClient = useQueryClient();
|
|
2074
|
+
return useMutation({
|
|
2075
|
+
mutationFn: async (entries) => {
|
|
2076
|
+
const bootstrappedClient = requireBootstrappedClient(client, "destinations.add");
|
|
2077
|
+
const failures = [];
|
|
2078
|
+
let persisted = 0;
|
|
2079
|
+
for (const entry of entries) {
|
|
2080
|
+
const result = await bootstrappedClient.destinations.add({
|
|
2081
|
+
target: { self: true },
|
|
2082
|
+
kind: "external_account",
|
|
2083
|
+
payload: {
|
|
2084
|
+
network: CHAIN_TO_NETWORK[entry.chain],
|
|
2085
|
+
address: entry.address
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
if (result.ok) persisted += 1;
|
|
2089
|
+
else failures.push({
|
|
2090
|
+
entry,
|
|
2091
|
+
error: result.error
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
return {
|
|
2095
|
+
persisted,
|
|
2096
|
+
failures
|
|
2097
|
+
};
|
|
2098
|
+
},
|
|
2099
|
+
onSuccess: async () => {
|
|
2100
|
+
await queryClient.invalidateQueries({ queryKey: capxulKeys.destinationsScope });
|
|
2101
|
+
}
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
//#endregion
|
|
2105
|
+
//#region src/headless/media/use-capxul-image-upload.ts
|
|
2106
|
+
/**
|
|
2107
|
+
* #1061 / ADR-0014: the whole upload→record sequence as one mutation —
|
|
2108
|
+
* upload the blob, then bind the returned storage id to the profile image or
|
|
2109
|
+
* the org logo. The url is the resolved serving URL (re-read from queries,
|
|
2110
|
+
* never persisted by consumers).
|
|
2111
|
+
*/
|
|
2112
|
+
function useCapxulImageUpload() {
|
|
2113
|
+
const client = useCapxulClientOrNull();
|
|
2114
|
+
const queryClient = useQueryClient();
|
|
2115
|
+
return useMutation({
|
|
2116
|
+
mutationFn: async ({ blob, target }) => {
|
|
2117
|
+
const bootstrappedClient = requireBootstrappedClient(client, "media.uploadImage");
|
|
2118
|
+
const media = bootstrappedClient.media;
|
|
2119
|
+
const telemetry = bootstrappedClient._internal.telemetry;
|
|
2120
|
+
const uploaded = unwrapCapxulResult(await media.uploadImage(blob), telemetry);
|
|
2121
|
+
if (target.kind === "profile") return { url: unwrapCapxulResult(await media.setProfileImage({ storageId: uploaded.storageId }), telemetry).imageUrl };
|
|
2122
|
+
return { url: unwrapCapxulResult(await media.setOrgLogo({
|
|
2123
|
+
orgId: target.orgId,
|
|
2124
|
+
storageId: uploaded.storageId
|
|
2125
|
+
}), telemetry).logoUrl };
|
|
2126
|
+
},
|
|
2127
|
+
onSuccess: async (_value, input) => {
|
|
2128
|
+
await queryClient.invalidateQueries({ queryKey: input.target.kind === "profile" ? capxulKeys.profile : capxulKeys.orgs });
|
|
2129
|
+
}
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
//#endregion
|
|
2133
|
+
export { AddressBook, CapxulProvider, Destinations, InsightsSummary, PayrollRoster, RequestInbox, SendMoney, acknowledgeOnboardingDestination, activeOnboardingRecovery, capxulAccountScope, capxulOrgScope, clearOnboardingJourney, currentOnboardingJourneyId, invalidateOnboardingJourneyObservation, loadOnboardingJourney, onboardingJourneyPosition, resolvePostAuthDestination, saveOnboardingJourney, startOnboardingJourney, useCapxul, useCapxulAccountBalance, useCapxulAccountFund, useCapxulAccountLifecycle, useCapxulActivity, useCapxulAddAddressBookEntry, useCapxulAddDestination, useCapxulAddPayrollRosterLine, useCapxulAddressBook, useCapxulAddressBookEntry, useCapxulApproveInboxRequest, useCapxulAssignRole, useCapxulCancelPayment, useCapxulCancelRequest, useCapxulClientOrNull, useCapxulCompleteOrganizationOnboarding, useCapxulCompletePersonalOnboarding, useCapxulCreateOrg, useCapxulCurrentUser, useCapxulDeclineInboxRequest, useCapxulDestinations, useCapxulHideAddressBookEntry, useCapxulImageUpload, useCapxulInbox, useCapxulInsightsHistory, useCapxulInsightsSummary, useCapxulInviteMember, useCapxulIssueRequest, useCapxulLabelAddressBookEntry, useCapxulOfframpQuote, useCapxulOfframpStatus, useCapxulOrg, useCapxulOrgDeployRoles, useCapxulOrgLifecycle, useCapxulOrgMembers, useCapxulOrgRoles, useCapxulOrgTreasury, useCapxulOrganizationAccount, useCapxulOrganizationAuditLog, useCapxulOrgs, useCapxulPay, useCapxulPayment, useCapxulPayments, useCapxulPayout, useCapxulPayrollRoster, useCapxulPersistPayoutEntries, useCapxulProfile, useCapxulReconcileRequests, useCapxulRemoveDestination, useCapxulRemoveMember, useCapxulRemovePayrollRosterLine, useCapxulRequest, useCapxulRequests, useCapxulRunPayroll, useCapxulSession, useCapxulSignIn, useCapxulSignOut, useCapxulSubAccountCreate, useCapxulSubAccountDelete, useCapxulSubAccountRename, useCapxulSubAccountsList, useCapxulSwitchActingEntity, useCapxulTransfer, useCapxulUnhideAddressBookEntry, useCapxulUpdatePayrollRosterLine, useCapxulUsernameAvailability, useCapxulVerifyOtp, useCapxulWithdraw };
|
|
1785
2134
|
|
|
1786
2135
|
//# sourceMappingURL=index.mjs.map
|