@objectstack/client-react 4.0.2 → 4.0.3

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,5 +1,5 @@
1
1
 
2
- > @objectstack/client-react@4.0.2 build /home/runner/work/framework/framework/packages/client-react
2
+ > @objectstack/client-react@4.0.3 build /home/runner/work/framework/framework/packages/client-react
3
3
  > tsup src/index.tsx --config ../../tsup.config.ts
4
4
 
5
5
  CLI Building entry: src/index.tsx
@@ -10,13 +10,13 @@
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
12
  CJS Build start
13
- ESM dist/index.mjs 13.30 KB
14
- ESM dist/index.mjs.map 38.08 KB
15
- ESM ⚡️ Build success in 53ms
16
- CJS dist/index.js 16.10 KB
17
- CJS dist/index.js.map 38.11 KB
18
- CJS ⚡️ Build success in 54ms
13
+ CJS dist/index.js 18.71 KB
14
+ CJS dist/index.js.map 45.97 KB
15
+ CJS ⚡️ Build success in 34ms
16
+ ESM dist/index.mjs 15.48 KB
17
+ ESM dist/index.mjs.map 46.02 KB
18
+ ESM ⚡️ Build success in 34ms
19
19
  DTS Build start
20
- DTS ⚡️ Build success in 4192ms
21
- DTS dist/index.d.mts 12.67 KB
22
- DTS dist/index.d.ts 12.67 KB
20
+ DTS ⚡️ Build success in 3244ms
21
+ DTS dist/index.d.mts 16.49 KB
22
+ DTS dist/index.d.ts 16.49 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @objectstack/client-react
2
2
 
3
+ ## 4.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - @objectstack/spec@4.0.3
8
+ - @objectstack/core@4.0.3
9
+ - @objectstack/client@4.0.3
10
+
3
11
  ## 4.0.2
4
12
 
5
13
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -3,6 +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
7
 
7
8
  /**
8
9
  * ObjectStack React Context
@@ -423,4 +424,148 @@ declare function useFields(objectName: string, options?: UseMetadataOptions): Us
423
424
  */
424
425
  declare function useMetadata<T = any>(fetcher: (client: ReturnType<typeof useClient>) => Promise<T>, options?: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'>): UseMetadataResult<T>;
425
426
 
426
- export { ObjectStackContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useClient, useFields, useInfiniteQuery, useMetadata, useMutation, useObject, usePagination, useQuery, useView };
427
+ /**
428
+ * Hook to subscribe to metadata events
429
+ *
430
+ * @param type - Metadata type to subscribe to (e.g., 'object', 'view', 'agent')
431
+ * @param options - Optional filters (packageId)
432
+ * @returns Latest metadata event or null
433
+ *
434
+ * @example
435
+ * ```tsx
436
+ * function ObjectList() {
437
+ * const event = useMetadataSubscription('object');
438
+ *
439
+ * useEffect(() => {
440
+ * if (event?.type === 'metadata.object.created') {
441
+ * console.log('New object:', event.name);
442
+ * // Refresh list
443
+ * }
444
+ * }, [event]);
445
+ *
446
+ * return <div>...</div>;
447
+ * }
448
+ * ```
449
+ */
450
+ declare function useMetadataSubscription(type: string, options?: {
451
+ packageId?: string;
452
+ }): MetadataEvent | null;
453
+ /**
454
+ * Hook to subscribe to data record events
455
+ *
456
+ * @param object - Object name to subscribe to
457
+ * @param options - Optional filters (recordId for specific record)
458
+ * @returns Latest data event or null
459
+ *
460
+ * @example
461
+ * ```tsx
462
+ * function TaskDetail({ taskId }: { taskId: string }) {
463
+ * const event = useDataSubscription('project_task', { recordId: taskId });
464
+ *
465
+ * useEffect(() => {
466
+ * if (event?.type === 'data.record.updated') {
467
+ * console.log('Task updated:', event.changes);
468
+ * // Refresh task data
469
+ * }
470
+ * }, [event]);
471
+ *
472
+ * return <div>...</div>;
473
+ * }
474
+ * ```
475
+ */
476
+ declare function useDataSubscription(object: string, options?: {
477
+ recordId?: string;
478
+ }): DataEvent | null;
479
+ /**
480
+ * Hook to subscribe to metadata events with a callback
481
+ *
482
+ * This variant doesn't store events in state, it just triggers a callback.
483
+ * Useful for triggering refetches or side effects without re-renders.
484
+ *
485
+ * @param type - Metadata type to subscribe to
486
+ * @param callback - Callback to invoke on events
487
+ * @param options - Optional filters
488
+ *
489
+ * @example
490
+ * ```tsx
491
+ * function ObjectList() {
492
+ * const { refetch } = useQuery(...);
493
+ *
494
+ * useMetadataSubscriptionCallback('object', () => {
495
+ * refetch(); // Refetch list when objects change
496
+ * });
497
+ *
498
+ * return <div>...</div>;
499
+ * }
500
+ * ```
501
+ */
502
+ declare function useMetadataSubscriptionCallback(type: string, callback: (event: MetadataEvent) => void, options?: {
503
+ packageId?: string;
504
+ }): void;
505
+ /**
506
+ * Hook to subscribe to data events with a callback
507
+ *
508
+ * @param object - Object name to subscribe to
509
+ * @param callback - Callback to invoke on events
510
+ * @param options - Optional filters
511
+ *
512
+ * @example
513
+ * ```tsx
514
+ * function TaskList() {
515
+ * const { refetch } = useQuery(...);
516
+ *
517
+ * useDataSubscriptionCallback('project_task', () => {
518
+ * refetch(); // Refetch list when tasks change
519
+ * });
520
+ *
521
+ * return <div>...</div>;
522
+ * }
523
+ * ```
524
+ */
525
+ declare function useDataSubscriptionCallback(object: string, callback: (event: DataEvent) => void, options?: {
526
+ recordId?: string;
527
+ }): void;
528
+ /**
529
+ * Hook to get connection status of realtime events
530
+ *
531
+ * @returns Whether realtime is connected
532
+ *
533
+ * @example
534
+ * ```tsx
535
+ * function ConnectionIndicator() {
536
+ * const connected = useRealtimeConnection();
537
+ *
538
+ * return (
539
+ * <div>
540
+ * {connected ? '🟢 Connected' : '🔴 Disconnected'}
541
+ * </div>
542
+ * );
543
+ * }
544
+ * ```
545
+ */
546
+ declare function useRealtimeConnection(): boolean;
547
+ /**
548
+ * Hook for auto-refreshing queries when data changes
549
+ *
550
+ * Combines data subscription with query refetch.
551
+ *
552
+ * @param object - Object name to watch
553
+ * @param refetch - Refetch function from useQuery
554
+ * @param options - Optional filters
555
+ *
556
+ * @example
557
+ * ```tsx
558
+ * function TaskList() {
559
+ * const { data, refetch } = useQuery('project_task', {});
560
+ *
561
+ * useAutoRefresh('project_task', refetch);
562
+ *
563
+ * return <div>{data.map(...)}</div>;
564
+ * }
565
+ * ```
566
+ */
567
+ declare function useAutoRefresh(object: string, refetch: () => void, options?: {
568
+ recordId?: string;
569
+ }): void;
570
+
571
+ export { ObjectStackContext, 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, usePagination, useQuery, useRealtimeConnection, useView };
package/dist/index.d.ts CHANGED
@@ -3,6 +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
7
 
7
8
  /**
8
9
  * ObjectStack React Context
@@ -423,4 +424,148 @@ declare function useFields(objectName: string, options?: UseMetadataOptions): Us
423
424
  */
424
425
  declare function useMetadata<T = any>(fetcher: (client: ReturnType<typeof useClient>) => Promise<T>, options?: Omit<UseMetadataOptions, 'useCache' | 'ifNoneMatch' | 'ifModifiedSince'>): UseMetadataResult<T>;
425
426
 
426
- export { ObjectStackContext, ObjectStackProvider, type ObjectStackProviderProps, type UseInfiniteQueryOptions, type UseInfiniteQueryResult, type UseMetadataOptions, type UseMetadataResult, type UseMutationOptions, type UseMutationResult, type UsePaginationOptions, type UsePaginationResult, type UseQueryOptions, type UseQueryResult, useClient, useFields, useInfiniteQuery, useMetadata, useMutation, useObject, usePagination, useQuery, useView };
427
+ /**
428
+ * Hook to subscribe to metadata events
429
+ *
430
+ * @param type - Metadata type to subscribe to (e.g., 'object', 'view', 'agent')
431
+ * @param options - Optional filters (packageId)
432
+ * @returns Latest metadata event or null
433
+ *
434
+ * @example
435
+ * ```tsx
436
+ * function ObjectList() {
437
+ * const event = useMetadataSubscription('object');
438
+ *
439
+ * useEffect(() => {
440
+ * if (event?.type === 'metadata.object.created') {
441
+ * console.log('New object:', event.name);
442
+ * // Refresh list
443
+ * }
444
+ * }, [event]);
445
+ *
446
+ * return <div>...</div>;
447
+ * }
448
+ * ```
449
+ */
450
+ declare function useMetadataSubscription(type: string, options?: {
451
+ packageId?: string;
452
+ }): MetadataEvent | null;
453
+ /**
454
+ * Hook to subscribe to data record events
455
+ *
456
+ * @param object - Object name to subscribe to
457
+ * @param options - Optional filters (recordId for specific record)
458
+ * @returns Latest data event or null
459
+ *
460
+ * @example
461
+ * ```tsx
462
+ * function TaskDetail({ taskId }: { taskId: string }) {
463
+ * const event = useDataSubscription('project_task', { recordId: taskId });
464
+ *
465
+ * useEffect(() => {
466
+ * if (event?.type === 'data.record.updated') {
467
+ * console.log('Task updated:', event.changes);
468
+ * // Refresh task data
469
+ * }
470
+ * }, [event]);
471
+ *
472
+ * return <div>...</div>;
473
+ * }
474
+ * ```
475
+ */
476
+ declare function useDataSubscription(object: string, options?: {
477
+ recordId?: string;
478
+ }): DataEvent | null;
479
+ /**
480
+ * Hook to subscribe to metadata events with a callback
481
+ *
482
+ * This variant doesn't store events in state, it just triggers a callback.
483
+ * Useful for triggering refetches or side effects without re-renders.
484
+ *
485
+ * @param type - Metadata type to subscribe to
486
+ * @param callback - Callback to invoke on events
487
+ * @param options - Optional filters
488
+ *
489
+ * @example
490
+ * ```tsx
491
+ * function ObjectList() {
492
+ * const { refetch } = useQuery(...);
493
+ *
494
+ * useMetadataSubscriptionCallback('object', () => {
495
+ * refetch(); // Refetch list when objects change
496
+ * });
497
+ *
498
+ * return <div>...</div>;
499
+ * }
500
+ * ```
501
+ */
502
+ declare function useMetadataSubscriptionCallback(type: string, callback: (event: MetadataEvent) => void, options?: {
503
+ packageId?: string;
504
+ }): void;
505
+ /**
506
+ * Hook to subscribe to data events with a callback
507
+ *
508
+ * @param object - Object name to subscribe to
509
+ * @param callback - Callback to invoke on events
510
+ * @param options - Optional filters
511
+ *
512
+ * @example
513
+ * ```tsx
514
+ * function TaskList() {
515
+ * const { refetch } = useQuery(...);
516
+ *
517
+ * useDataSubscriptionCallback('project_task', () => {
518
+ * refetch(); // Refetch list when tasks change
519
+ * });
520
+ *
521
+ * return <div>...</div>;
522
+ * }
523
+ * ```
524
+ */
525
+ declare function useDataSubscriptionCallback(object: string, callback: (event: DataEvent) => void, options?: {
526
+ recordId?: string;
527
+ }): void;
528
+ /**
529
+ * Hook to get connection status of realtime events
530
+ *
531
+ * @returns Whether realtime is connected
532
+ *
533
+ * @example
534
+ * ```tsx
535
+ * function ConnectionIndicator() {
536
+ * const connected = useRealtimeConnection();
537
+ *
538
+ * return (
539
+ * <div>
540
+ * {connected ? '🟢 Connected' : '🔴 Disconnected'}
541
+ * </div>
542
+ * );
543
+ * }
544
+ * ```
545
+ */
546
+ declare function useRealtimeConnection(): boolean;
547
+ /**
548
+ * Hook for auto-refreshing queries when data changes
549
+ *
550
+ * Combines data subscription with query refetch.
551
+ *
552
+ * @param object - Object name to watch
553
+ * @param refetch - Refetch function from useQuery
554
+ * @param options - Optional filters
555
+ *
556
+ * @example
557
+ * ```tsx
558
+ * function TaskList() {
559
+ * const { data, refetch } = useQuery('project_task', {});
560
+ *
561
+ * useAutoRefresh('project_task', refetch);
562
+ *
563
+ * return <div>{data.map(...)}</div>;
564
+ * }
565
+ * ```
566
+ */
567
+ declare function useAutoRefresh(object: string, refetch: () => void, options?: {
568
+ recordId?: string;
569
+ }): void;
570
+
571
+ export { ObjectStackContext, 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, usePagination, useQuery, useRealtimeConnection, useView };
package/dist/index.js CHANGED
@@ -33,14 +33,20 @@ __export(index_exports, {
33
33
  ObjectStackClient: () => import_client.ObjectStackClient,
34
34
  ObjectStackContext: () => ObjectStackContext,
35
35
  ObjectStackProvider: () => ObjectStackProvider,
36
+ useAutoRefresh: () => useAutoRefresh,
36
37
  useClient: () => useClient,
38
+ useDataSubscription: () => useDataSubscription,
39
+ useDataSubscriptionCallback: () => useDataSubscriptionCallback,
37
40
  useFields: () => useFields,
38
41
  useInfiniteQuery: () => useInfiniteQuery,
39
42
  useMetadata: () => useMetadata,
43
+ useMetadataSubscription: () => useMetadataSubscription,
44
+ useMetadataSubscriptionCallback: () => useMetadataSubscriptionCallback,
40
45
  useMutation: () => useMutation,
41
46
  useObject: () => useObject,
42
47
  usePagination: () => usePagination,
43
48
  useQuery: () => useQuery,
49
+ useRealtimeConnection: () => useRealtimeConnection,
44
50
  useView: () => useView
45
51
  });
46
52
  module.exports = __toCommonJS(index_exports);
@@ -506,6 +512,87 @@ function useMetadata(fetcher, options = {}) {
506
512
  };
507
513
  }
508
514
 
515
+ // src/realtime-hooks.tsx
516
+ var import_react4 = require("react");
517
+ function useMetadataSubscription(type, options) {
518
+ const client = useClient();
519
+ const [event, setEvent] = (0, import_react4.useState)(null);
520
+ (0, import_react4.useEffect)(() => {
521
+ if (!client) return;
522
+ const unsubscribe = client.events.subscribeMetadata(
523
+ type,
524
+ (e) => setEvent(e),
525
+ options
526
+ );
527
+ return () => {
528
+ unsubscribe();
529
+ };
530
+ }, [client, type, options?.packageId]);
531
+ return event;
532
+ }
533
+ function useDataSubscription(object, options) {
534
+ const client = useClient();
535
+ const [event, setEvent] = (0, import_react4.useState)(null);
536
+ (0, import_react4.useEffect)(() => {
537
+ if (!client) return;
538
+ const unsubscribe = client.events.subscribeData(
539
+ object,
540
+ (e) => setEvent(e),
541
+ options
542
+ );
543
+ return () => {
544
+ unsubscribe();
545
+ };
546
+ }, [client, object, options?.recordId]);
547
+ return event;
548
+ }
549
+ function useMetadataSubscriptionCallback(type, callback, options) {
550
+ const client = useClient();
551
+ (0, import_react4.useEffect)(() => {
552
+ if (!client) return;
553
+ const unsubscribe = client.events.subscribeMetadata(
554
+ type,
555
+ callback,
556
+ options
557
+ );
558
+ return () => {
559
+ unsubscribe();
560
+ };
561
+ }, [client, type, callback, options?.packageId]);
562
+ }
563
+ function useDataSubscriptionCallback(object, callback, options) {
564
+ const client = useClient();
565
+ (0, import_react4.useEffect)(() => {
566
+ if (!client) return;
567
+ const unsubscribe = client.events.subscribeData(
568
+ object,
569
+ callback,
570
+ options
571
+ );
572
+ return () => {
573
+ unsubscribe();
574
+ };
575
+ }, [client, object, callback, options?.recordId]);
576
+ }
577
+ function useRealtimeConnection() {
578
+ const client = useClient();
579
+ const [connected, setConnected] = (0, import_react4.useState)(true);
580
+ (0, import_react4.useEffect)(() => {
581
+ if (!client) {
582
+ setConnected(false);
583
+ return;
584
+ }
585
+ setConnected(true);
586
+ }, [client]);
587
+ return connected;
588
+ }
589
+ function useAutoRefresh(object, refetch, options) {
590
+ const handleEvent = (0, import_react4.useCallback)((_event) => {
591
+ refetch();
592
+ }, [refetch]);
593
+ useDataSubscriptionCallback(object, handleEvent, options);
594
+ }
595
+
509
596
  // src/index.tsx
510
597
  var import_client = require("@objectstack/client");
511
598
  // Annotate the CommonJS export names for ESM import in node:
@@ -513,14 +600,20 @@ var import_client = require("@objectstack/client");
513
600
  ObjectStackClient,
514
601
  ObjectStackContext,
515
602
  ObjectStackProvider,
603
+ useAutoRefresh,
516
604
  useClient,
605
+ useDataSubscription,
606
+ useDataSubscriptionCallback,
517
607
  useFields,
518
608
  useInfiniteQuery,
519
609
  useMetadata,
610
+ useMetadataSubscription,
611
+ useMetadataSubscriptionCallback,
520
612
  useMutation,
521
613
  useObject,
522
614
  usePagination,
523
615
  useQuery,
616
+ useRealtimeConnection,
524
617
  useView
525
618
  });
526
619
  //# sourceMappingURL=index.js.map