@objectstack/client-react 17.0.0-rc.0 → 17.0.0-rc.2

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 CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { ObjectStackClient, PaginatedResult } from '@objectstack/client';
4
4
  export { ClientConfig, ObjectStackClient } from '@objectstack/client';
5
5
  import { QueryAST, FilterCondition } from '@objectstack/spec/data';
6
- import { DataEvent, MetadataEvent } from '@objectstack/spec/api';
6
+ import { BulkDataEvent, DataEvent, MetadataEvent } from '@objectstack/spec/api';
7
7
 
8
8
  /**
9
9
  * ObjectStack React Context
@@ -527,6 +527,64 @@ declare function useMetadataSubscriptionCallback(type: string, callback: (event:
527
527
  declare function useDataSubscriptionCallback(object: string, callback: (event: DataEvent) => void, options?: {
528
528
  recordId?: string;
529
529
  }): void;
530
+ /**
531
+ * Hook to subscribe to bulk (predicate-write) data events
532
+ *
533
+ * A `multi: true` update/delete reaches the driver's `updateMany`/`deleteMany`,
534
+ * which report an affected COUNT and name no rows — so it publishes
535
+ * `data.records.updated` / `data.records.deleted` rather than the per-record
536
+ * events {@link useDataSubscription} delivers (#4639).
537
+ *
538
+ * The event carries `object` and `matched` — there is no `recordId` and no
539
+ * record body, which is why this is a separate hook rather than more types
540
+ * flowing through `useDataSubscription`: a `DataEvent` callback receiving one
541
+ * of these would read `undefined` for every field it expects.
542
+ *
543
+ * Use it to invalidate a list, show "40 records changed", or trigger a
544
+ * refetch — not to patch a per-record cache, which a count cannot drive.
545
+ *
546
+ * @param object - Object name to subscribe to
547
+ * @returns Latest bulk data event or null
548
+ *
549
+ * @example
550
+ * ```tsx
551
+ * function TaskList() {
552
+ * const bulk = useBulkDataSubscription('project_task');
553
+ *
554
+ * useEffect(() => {
555
+ * if (bulk) {
556
+ * console.log(`${bulk.matched} tasks changed in one write`);
557
+ * }
558
+ * }, [bulk]);
559
+ *
560
+ * return <div>...</div>;
561
+ * }
562
+ * ```
563
+ */
564
+ declare function useBulkDataSubscription(object: string): BulkDataEvent | null;
565
+ /**
566
+ * Hook to subscribe to bulk data events with a callback
567
+ *
568
+ * The callback variant of {@link useBulkDataSubscription} — no state, no
569
+ * re-render, for triggering refetches and side effects.
570
+ *
571
+ * @param object - Object name to subscribe to
572
+ * @param callback - Callback to invoke on events
573
+ *
574
+ * @example
575
+ * ```tsx
576
+ * function TaskList() {
577
+ * const { refetch } = useQuery(...);
578
+ *
579
+ * useBulkDataSubscriptionCallback('project_task', () => {
580
+ * refetch(); // a predicate write touched an unknown set of rows
581
+ * });
582
+ *
583
+ * return <div>...</div>;
584
+ * }
585
+ * ```
586
+ */
587
+ declare function useBulkDataSubscriptionCallback(object: string, callback: (event: BulkDataEvent) => void): void;
530
588
  /**
531
589
  * Hook to get connection status of realtime events
532
590
  *
@@ -551,6 +609,18 @@ declare function useRealtimeConnection(): boolean;
551
609
  *
552
610
  * Combines data subscription with query refetch.
553
611
  *
612
+ * Watches BOTH event streams (#4678): per-record `data.record.*` writes and
613
+ * the aggregate `data.records.*` a predicate (`multi: true`) write publishes.
614
+ * A bulk write is the case that dirties a list hardest — one statement can
615
+ * change or delete every row on screen — so a refresh hook that ignored it
616
+ * would sit still exactly when it matters most, while still refreshing for a
617
+ * single-row edit.
618
+ *
619
+ * Mixing the two streams is safe here in a way it is not for
620
+ * {@link useDataSubscription}: this hook's output is a refetch signal, not an
621
+ * event body, so the shape difference that keeps the two contracts apart
622
+ * (no `recordId`, no record) never reaches the caller.
623
+ *
554
624
  * @param object - Object name to watch
555
625
  * @param refetch - Refetch function from useQuery
556
626
  * @param options - Optional filters
@@ -570,4 +640,4 @@ declare function useAutoRefresh(object: string, refetch: () => void, options?: {
570
640
  recordId?: string;
571
641
  }): void;
572
642
 
573
- export { ObjectStackContext, ObjectStackLocaleContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useAutoRefresh, useClient, useDataSubscription, useDataSubscriptionCallback, useFields, useInfiniteQuery, useMetadata, useMetadataSubscription, useMetadataSubscriptionCallback, useMutation, useObject, useObjectStackLocale, usePagination, useQuery, useRealtimeConnection, useView };
643
+ export { ObjectStackContext, ObjectStackLocaleContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useAutoRefresh, useBulkDataSubscription, useBulkDataSubscriptionCallback, useClient, useDataSubscription, useDataSubscriptionCallback, useFields, useInfiniteQuery, useMetadata, useMetadataSubscription, useMetadataSubscriptionCallback, useMutation, useObject, useObjectStackLocale, usePagination, useQuery, useRealtimeConnection, useView };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { ObjectStackClient, PaginatedResult } from '@objectstack/client';
4
4
  export { ClientConfig, ObjectStackClient } from '@objectstack/client';
5
5
  import { QueryAST, FilterCondition } from '@objectstack/spec/data';
6
- import { DataEvent, MetadataEvent } from '@objectstack/spec/api';
6
+ import { BulkDataEvent, DataEvent, MetadataEvent } from '@objectstack/spec/api';
7
7
 
8
8
  /**
9
9
  * ObjectStack React Context
@@ -527,6 +527,64 @@ declare function useMetadataSubscriptionCallback(type: string, callback: (event:
527
527
  declare function useDataSubscriptionCallback(object: string, callback: (event: DataEvent) => void, options?: {
528
528
  recordId?: string;
529
529
  }): void;
530
+ /**
531
+ * Hook to subscribe to bulk (predicate-write) data events
532
+ *
533
+ * A `multi: true` update/delete reaches the driver's `updateMany`/`deleteMany`,
534
+ * which report an affected COUNT and name no rows — so it publishes
535
+ * `data.records.updated` / `data.records.deleted` rather than the per-record
536
+ * events {@link useDataSubscription} delivers (#4639).
537
+ *
538
+ * The event carries `object` and `matched` — there is no `recordId` and no
539
+ * record body, which is why this is a separate hook rather than more types
540
+ * flowing through `useDataSubscription`: a `DataEvent` callback receiving one
541
+ * of these would read `undefined` for every field it expects.
542
+ *
543
+ * Use it to invalidate a list, show "40 records changed", or trigger a
544
+ * refetch — not to patch a per-record cache, which a count cannot drive.
545
+ *
546
+ * @param object - Object name to subscribe to
547
+ * @returns Latest bulk data event or null
548
+ *
549
+ * @example
550
+ * ```tsx
551
+ * function TaskList() {
552
+ * const bulk = useBulkDataSubscription('project_task');
553
+ *
554
+ * useEffect(() => {
555
+ * if (bulk) {
556
+ * console.log(`${bulk.matched} tasks changed in one write`);
557
+ * }
558
+ * }, [bulk]);
559
+ *
560
+ * return <div>...</div>;
561
+ * }
562
+ * ```
563
+ */
564
+ declare function useBulkDataSubscription(object: string): BulkDataEvent | null;
565
+ /**
566
+ * Hook to subscribe to bulk data events with a callback
567
+ *
568
+ * The callback variant of {@link useBulkDataSubscription} — no state, no
569
+ * re-render, for triggering refetches and side effects.
570
+ *
571
+ * @param object - Object name to subscribe to
572
+ * @param callback - Callback to invoke on events
573
+ *
574
+ * @example
575
+ * ```tsx
576
+ * function TaskList() {
577
+ * const { refetch } = useQuery(...);
578
+ *
579
+ * useBulkDataSubscriptionCallback('project_task', () => {
580
+ * refetch(); // a predicate write touched an unknown set of rows
581
+ * });
582
+ *
583
+ * return <div>...</div>;
584
+ * }
585
+ * ```
586
+ */
587
+ declare function useBulkDataSubscriptionCallback(object: string, callback: (event: BulkDataEvent) => void): void;
530
588
  /**
531
589
  * Hook to get connection status of realtime events
532
590
  *
@@ -551,6 +609,18 @@ declare function useRealtimeConnection(): boolean;
551
609
  *
552
610
  * Combines data subscription with query refetch.
553
611
  *
612
+ * Watches BOTH event streams (#4678): per-record `data.record.*` writes and
613
+ * the aggregate `data.records.*` a predicate (`multi: true`) write publishes.
614
+ * A bulk write is the case that dirties a list hardest — one statement can
615
+ * change or delete every row on screen — so a refresh hook that ignored it
616
+ * would sit still exactly when it matters most, while still refreshing for a
617
+ * single-row edit.
618
+ *
619
+ * Mixing the two streams is safe here in a way it is not for
620
+ * {@link useDataSubscription}: this hook's output is a refetch signal, not an
621
+ * event body, so the shape difference that keeps the two contracts apart
622
+ * (no `recordId`, no record) never reaches the caller.
623
+ *
554
624
  * @param object - Object name to watch
555
625
  * @param refetch - Refetch function from useQuery
556
626
  * @param options - Optional filters
@@ -570,4 +640,4 @@ declare function useAutoRefresh(object: string, refetch: () => void, options?: {
570
640
  recordId?: string;
571
641
  }): void;
572
642
 
573
- export { ObjectStackContext, ObjectStackLocaleContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useAutoRefresh, useClient, useDataSubscription, useDataSubscriptionCallback, useFields, useInfiniteQuery, useMetadata, useMetadataSubscription, useMetadataSubscriptionCallback, useMutation, useObject, useObjectStackLocale, usePagination, useQuery, useRealtimeConnection, useView };
643
+ export { ObjectStackContext, ObjectStackLocaleContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useAutoRefresh, useBulkDataSubscription, useBulkDataSubscriptionCallback, useClient, useDataSubscription, useDataSubscriptionCallback, useFields, useInfiniteQuery, useMetadata, useMetadataSubscription, useMetadataSubscriptionCallback, useMutation, useObject, useObjectStackLocale, usePagination, useQuery, useRealtimeConnection, useView };