@capxul/sdk-react 4.2.0-rc.10 → 4.2.0-rc.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.
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "source": {
3
- "commit": "a7e55e5f1c2af5567a8b285a4ef70b8b5a3289f6",
4
- "tree": "91bf1b080c0006fe30131711c13c843afd627158",
3
+ "commit": "fd5b4d0f124c75f609e469b8673c61f84253c0dc",
4
+ "tree": "d61f0f6b0c83dfc2d405ffc6b55eecf2e9d80f2d",
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"
10
+ "version": "4.2.0-rc.12"
11
11
  }
package/dist/index.d.mts CHANGED
@@ -891,8 +891,14 @@ interface PayrollSummarySlice {
891
891
  }
892
892
  interface PayrollGroupsSlice {
893
893
  readonly groups: readonly PayrollGroupRow[];
894
- readonly save: (input: PayrollGroupInput) => Promise<CapxulResult<PayrollGroupRow>>;
895
- readonly remove: (id: PayrollGroupId) => Promise<CapxulResult<void>>;
894
+ /**
895
+ * R13 (#1968): `options` is the browser attempt the caller captured before the
896
+ * employer pressed the button. It reaches the SDK operation unchanged, so the
897
+ * group's `ui_payroll_action_completed` and the durable `payroll_group_changed`
898
+ * share one correlation. Absent, the write keeps its own invocation context.
899
+ */
900
+ readonly save: (input: PayrollGroupInput, options?: InvocationOptions) => Promise<CapxulResult<PayrollGroupRow>>;
901
+ readonly remove: (id: PayrollGroupId, options?: InvocationOptions) => Promise<CapxulResult<void>>;
896
902
  readonly isSaving: boolean;
897
903
  readonly isLoading: boolean;
898
904
  readonly error: CapxulError | null;
@@ -984,7 +990,14 @@ interface PayrollRunSummarySlice {
984
990
  interface PayrollRunActionsSlice {
985
991
  readonly recovery: "none" | "restoring" | "required" | "unavailable";
986
992
  readonly recoveryError: CapxulError | null;
987
- readonly submit: () => void;
993
+ /**
994
+ * R13 (#1968): `options` is the browser attempt captured before the employer
995
+ * confirmed. It reaches `authorizeRun` unchanged, so the sheet's own
996
+ * `ui_payroll_action_completed` and the durable `payroll_run_transitioned`
997
+ * rows share one correlation. It is NEVER written into the persisted draft —
998
+ * a restored run keeps its own identity, not a stale attempt's.
999
+ */
1000
+ readonly submit: (options?: InvocationOptions) => void;
988
1001
  readonly isSubmitting: boolean;
989
1002
  readonly blocked: boolean;
990
1003
  readonly blockedReason: CapxulPayrollRunBlockedReason | null;
package/dist/index.mjs CHANGED
@@ -880,7 +880,7 @@ function useCapxulUploadImage() {
880
880
  //#endregion
881
881
  //#region src/headless/contacts/use-contacts.ts
882
882
  /** One captured snapshot, or nothing — never a fabricated empty options object. */
883
- const carry = (options) => options === void 0 ? {} : { options };
883
+ const carry$1 = (options) => options === void 0 ? {} : { options };
884
884
  function useContacts(input) {
885
885
  const { actor, onAdded, onFailed } = input;
886
886
  const client = useCapxulClientOrNull();
@@ -922,7 +922,7 @@ function useContacts(input) {
922
922
  setAddError(null);
923
923
  addMutate({
924
924
  ref: refFromTypedText(value),
925
- ...carry(attempt)
925
+ ...carry$1(attempt)
926
926
  }, {
927
927
  onSuccess: (entry) => {
928
928
  setValue("");
@@ -955,17 +955,17 @@ function useContacts(input) {
955
955
  kind: "rename",
956
956
  id,
957
957
  name,
958
- ...carry(toInvocationOptions(options))
958
+ ...carry$1(toInvocationOptions(options))
959
959
  }), [writeMutate]),
960
960
  hide: useCallback((id, options) => writeMutate({
961
961
  kind: "hide",
962
962
  id,
963
- ...carry(toInvocationOptions(options))
963
+ ...carry$1(toInvocationOptions(options))
964
964
  }), [writeMutate]),
965
965
  unhide: useCallback((id, options) => writeMutate({
966
966
  kind: "unhide",
967
967
  id,
968
- ...carry(toInvocationOptions(options))
968
+ ...carry$1(toInvocationOptions(options))
969
969
  }), [writeMutate]),
970
970
  add: {
971
971
  value,
@@ -1598,6 +1598,28 @@ function useActivity(input) {
1598
1598
  getNextPageParam: (last) => last.cursor ?? void 0,
1599
1599
  enabled
1600
1600
  });
1601
+ const queryClient = useQueryClient();
1602
+ useEffect(() => {
1603
+ if (!enabled || client === null) return;
1604
+ let stop;
1605
+ let cancelled = false;
1606
+ client.activity.subscribe(() => {
1607
+ queryClient.invalidateQueries({ queryKey: capxulKeys.activity });
1608
+ }, actor === void 0 ? void 0 : { actor }).then((result) => {
1609
+ if (!result.ok) return;
1610
+ if (cancelled) result.value();
1611
+ else stop = result.value;
1612
+ });
1613
+ return () => {
1614
+ cancelled = true;
1615
+ stop?.();
1616
+ };
1617
+ }, [
1618
+ actor,
1619
+ client,
1620
+ enabled,
1621
+ queryClient
1622
+ ]);
1601
1623
  const pages = query.data?.pages;
1602
1624
  const rows = useMemo(() => {
1603
1625
  return (pages?.flatMap((page) => page.items) ?? []).map((item) => toActivityRow(item, actor)).filter((row) => matchesSearch(row, searchText));
@@ -2557,6 +2579,14 @@ function scopedClient(client, method, orgId) {
2557
2579
  //#region src/headless/payroll/use-payroll.ts
2558
2580
  /** Money reads the same way everywhere on this screen: amount then code. */
2559
2581
  const GRAMMAR$1 = { grammar: "code" };
2582
+ /**
2583
+ * One captured snapshot, or nothing — never a fabricated empty options object,
2584
+ * and never a DOM event a screen wired straight to `onClick`.
2585
+ */
2586
+ function carry(options) {
2587
+ const attempt = toInvocationOptions(options);
2588
+ return attempt === void 0 ? {} : { options: attempt };
2589
+ }
2560
2590
  function toPayrollGroupRow(group) {
2561
2591
  const currency = new Set(group.members.map((member) => member.currency)).size === 1 ? group.members[0]?.currency : void 0;
2562
2592
  return {
@@ -2596,16 +2626,17 @@ function usePayroll(orgId) {
2596
2626
  const write = useMutation({
2597
2627
  mutationFn: async (command) => {
2598
2628
  const payroll = scopedClient(client, CAPXUL_OPERATIONS.org.payroll.groups[command.kind], orgId).payroll;
2629
+ const controls = toInvocationControls(command.options);
2599
2630
  if (command.kind === "remove") {
2600
- unwrapCapxulResult(await payroll.groups.remove(command.id));
2631
+ unwrapCapxulResult(await payroll.groups.remove(command.id, controls));
2601
2632
  return null;
2602
2633
  }
2603
- return unwrapCapxulResult(await payroll.groups.save(command.input));
2634
+ return unwrapCapxulResult(await payroll.groups.save(command.input, controls));
2604
2635
  },
2605
2636
  onSettled: invalidate
2606
2637
  });
2607
2638
  const mutateAsync = write.mutateAsync;
2608
- const save = useCallback(async (input) => {
2639
+ const save = useCallback(async (input, options) => {
2609
2640
  const refusal = invalidGroup(input);
2610
2641
  if (refusal !== null) return {
2611
2642
  ok: false,
@@ -2614,7 +2645,8 @@ function usePayroll(orgId) {
2614
2645
  try {
2615
2646
  const saved = await mutateAsync({
2616
2647
  kind: "save",
2617
- input
2648
+ input,
2649
+ ...carry(options)
2618
2650
  });
2619
2651
  return saved === null ? {
2620
2652
  ok: false,
@@ -2630,11 +2662,12 @@ function usePayroll(orgId) {
2630
2662
  };
2631
2663
  }
2632
2664
  }, [mutateAsync]);
2633
- const remove = useCallback(async (id) => {
2665
+ const remove = useCallback(async (id, options) => {
2634
2666
  try {
2635
2667
  await mutateAsync({
2636
2668
  kind: "remove",
2637
- id
2669
+ id,
2670
+ ...carry(options)
2638
2671
  });
2639
2672
  return {
2640
2673
  ok: true,
@@ -3152,11 +3185,12 @@ function usePayrollRun(input) {
3152
3185
  amountsParse: total !== null
3153
3186
  });
3154
3187
  const authorize = useMutation({
3155
- mutationFn: async (candidate) => {
3188
+ mutationFn: async ({ candidate, options }) => {
3156
3189
  if (candidate.scope !== currentScope.current) throw Errors.notAuthenticated();
3157
3190
  return executeRunDraft(candidate, async (persisted, onRequestKey, onResolved) => {
3158
3191
  if (candidate.scope === currentScope.current) setDraft(persisted);
3159
3192
  return unwrapCapxulResult(await scopedClient(client, CAPXUL_OPERATIONS.org.payroll.authorizeRun, orgId).payroll.authorizeRun(persisted.input, {
3193
+ ...toInvocationControls(options),
3160
3194
  onResolved,
3161
3195
  onRequestKey: (key) => {
3162
3196
  if (candidate.scope !== currentScope.current) throw Errors.notAuthenticated();
@@ -3165,14 +3199,15 @@ function usePayrollRun(input) {
3165
3199
  }));
3166
3200
  });
3167
3201
  },
3168
- onSettled: (_run, _error, candidate) => {
3202
+ onSettled: (_run, _error, { candidate }) => {
3169
3203
  queryClient.invalidateQueries({ queryKey: capxulKeys.payrollRuns(orgId) });
3170
3204
  if (candidate.scope === currentScope.current) restoreDraft(candidate.scope);
3171
3205
  }
3172
3206
  });
3173
3207
  const totalDisplay = total === null ? null : formatMoney(total, GRAMMAR);
3174
3208
  const authorizeMutate = authorize.mutate;
3175
- const submit = useCallback(() => {
3209
+ const submit = useCallback((options) => {
3210
+ const attempt = toInvocationOptions(options);
3176
3211
  const permissionId = budgets[0]?.id;
3177
3212
  if (blockedReason !== null || submitGate.current || draftBlocked || draftScope === null || assetMoney === null || selectedAsset === null) return;
3178
3213
  if (permissionId === void 0 || totalDisplay === null || parsedAmounts === null) return;
@@ -3214,7 +3249,10 @@ function usePayrollRun(input) {
3214
3249
  }
3215
3250
  };
3216
3251
  submitGate.current = true;
3217
- authorizeMutate(candidate, {
3252
+ authorizeMutate({
3253
+ candidate,
3254
+ ...attempt === void 0 ? {} : { options: attempt }
3255
+ }, {
3218
3256
  onSuccess: (run) => {
3219
3257
  if (candidate.scope === currentScope.current) onRun({
3220
3258
  id: run.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capxul/sdk-react",
3
- "version": "4.2.0-rc.10",
3
+ "version": "4.2.0-rc.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.2.0-rc.10"
29
+ "@capxul/sdk": "4.2.0-rc.12"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tanstack/react-query": "^5.66.9",
@@ -43,8 +43,8 @@
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",
47
+ "@capxul/errors": "0.3.0",
48
48
  "@capxul/types": "0.3.0"
49
49
  },
50
50
  "peerDependencies": {