CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-refinedev--core

React meta-framework for building enterprise CRUD applications with authentication, data management, and headless UI integration

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities & Helpers

Resource management, loading states, metadata handling, notifications, and various utility functions for enhanced development experience.

Capabilities

Resource & Parameter Management

useResourceParams Hook

Gets resource and parameter information from current context with automatic inference from routes.

/**
 * Gets resource and parameter information from current context
 * @param params - Resource parameter configuration
 * @returns Current resource context and parameter values
 */
function useResourceParams(params?: UseResourceParamsConfig): UseResourceParamsReturnType;

interface UseResourceParamsConfig {
  /** Override resource name */
  resource?: string;
  /** Override record ID */
  id?: BaseKey;
  /** Override action */
  action?: string;
}

interface UseResourceParamsReturnType {
  /** Current resource configuration */
  resource?: IResourceItem;
  /** Resource identifier (name) */
  identifier?: string;
  /** Current record ID */
  id?: BaseKey;
  /** Current action */
  action?: Action;
  /** Function to set ID */
  setId: React.Dispatch<React.SetStateAction<BaseKey | undefined>>;
}

interface IResourceItem {
  /** Resource name */
  name: string;
  /** Display label */
  label?: string;
  /** Resource icon */
  icon?: React.ReactNode;
  /** Whether resource can be deleted */
  canDelete?: boolean;
  /** Parent resource name */
  parentName?: string;
  /** Resource metadata */
  meta?: Record<string, any>;
}

type Action = "list" | "create" | "edit" | "show" | "clone";

Usage Example:

import { useResourceParams } from "@refinedev/core";

function ResourceHeader() {
  const { resource, action, id } = useResourceParams();
  
  const getTitle = () => {
    if (!resource) return "Unknown Resource";
    
    switch (action) {
      case "list":
        return `${resource.label || resource.name} List`;
      case "create":
        return `Create ${resource.label || resource.name}`;
      case "edit":
        return `Edit ${resource.label || resource.name} #${id}`;
      case "show":
        return `${resource.label || resource.name} #${id}`;
      case "clone":
        return `Clone ${resource.label || resource.name} #${id}`;
      default:
        return resource.label || resource.name;
    }
  };
  
  return (
    <header>
      {resource?.icon}
      <h1>{getTitle()}</h1>
    </header>
  );
}

// Dynamic component behavior based on resource
function ResourceActions() {
  const { resource, action, id, setId } = useResourceParams();
  
  const canEdit = resource?.meta?.permissions?.includes("edit");
  const canDelete = resource?.canDelete !== false;
  
  return (
    <div className="resource-actions">
      {action === "show" && canEdit && (
        <button onClick={() => setId(id)}>
          Edit {resource?.label}
        </button>
      )}
      {action === "edit" && canDelete && (
        <button className="danger">
          Delete {resource?.label}
        </button>
      )}
    </div>
  );
}

Loading & Performance

useLoadingOvertime Hook

Tracks loading time for performance monitoring and user experience optimization.

/**
 * Tracks loading time for performance monitoring
 * @param params - Loading overtime configuration
 * @returns Loading time information and callbacks
 */
function useLoadingOvertime(params: UseLoadingOvertimeConfig): UseLoadingOvertimeReturnType;

interface UseLoadingOvertimeConfig {
  /** Whether currently loading */
  isLoading: boolean;
  /** Interval for time updates in milliseconds */
  interval?: number;
  /** Callback fired at each interval */
  onInterval?: (elapsedTime: number) => void;
}

interface UseLoadingOvertimeReturnType {
  /** Elapsed time since loading started in milliseconds */
  elapsedTime?: number;
}

Usage Example:

import { useLoadingOvertime, useList } from "@refinedev/core";

function DataTableWithLoadingIndicator() {
  const { query } = useList({ resource: "posts" });
  
  const { elapsedTime } = useLoadingOvertime({
    isLoading: query.isLoading,
    interval: 1000,
    onInterval: (time) => {
      if (time > 5000) {
        console.warn("Query taking longer than expected:", time);
      }
    }
  });
  
  if (query.isLoading) {
    return (
      <div className="loading-state">
        <div>Loading posts...</div>
        {elapsedTime && elapsedTime > 2000 && (
          <div className="loading-overtime">
            Still loading... ({Math.round(elapsedTime / 1000)}s)
          </div>
        )}
      </div>
    );
  }
  
  return (
    <div>
      {/* Table content */}
    </div>
  );
}

Metadata Management

useMeta Hook

Manages metadata for resources and operations with context-aware defaults.

/**
 * Manages metadata for resources and operations
 * @param params - Meta configuration
 * @returns Current metadata and update functions
 */
function useMeta(params?: UseMetaConfig): UseMetaReturnType;

interface UseMetaConfig {
  /** Initial metadata */
  meta?: MetaQuery;
  /** Resource name for context */
  resource?: string;
}

interface UseMetaReturnType {
  /** Current metadata */
  meta: MetaQuery;
  /** Function to update metadata */
  setMeta: (meta: MetaQuery) => void;
  /** Function to merge metadata */
  mergeMeta: (meta: MetaQuery) => void;
}

interface MetaQuery {
  [key: string]: any;
}

useMetaContext Hook

Access to the meta context provider for global metadata management.

/**
 * Access to meta context provider
 * @returns Meta context value and functions
 */
function useMetaContext(): MetaContextValue;

interface MetaContextValue {
  /** Global metadata */
  meta: MetaQuery;
  /** Function to set global metadata */
  setMeta: (meta: MetaQuery) => void;
}

Notification System

useNotification Hook

Shows notifications with different types, positions, and auto-dismiss functionality.

/**
 * Shows notifications with customizable options
 * @returns Notification functions for different types
 */
function useNotification(): UseNotificationReturnType;

interface UseNotificationReturnType {
  /** Show success notification */
  open: (params: OpenNotificationParams) => void;
  /** Close specific notification */
  close: (key: string) => void;
}

interface OpenNotificationParams {
  /** Notification type */
  type: "success" | "error" | "progress" | "warning" | "info";
  /** Notification message */
  message: string;
  /** Additional description */
  description?: string;
  /** Unique key for the notification */
  key?: string;
  /** Whether notification should not auto-dismiss */
  undoableTimeout?: number;
  /** Whether to show undo button */
  cancelMutation?: () => void;
  /** Custom duration before auto-dismiss */
  duration?: number;
}

Usage Example:

import { useNotification, useCreate } from "@refinedev/core";

function CreatePostForm() {
  const notification = useNotification();
  const { mutate: createPost } = useCreate();
  
  const handleCreate = (values: any) => {
    createPost({
      resource: "posts",
      values
    }, {
      onSuccess: (data) => {
        notification.open({
          type: "success",
          message: "Post Created",
          description: `Post "${data.data.title}" has been created successfully.`,
          duration: 4000
        });
      },
      onError: (error) => {
        notification.open({
          type: "error",
          message: "Creation Failed",
          description: error.message || "Failed to create post."
        });
      }
    });
  };
  
  return (
    <form onSubmit={handleCreate}>
      {/* Form fields */}
    </form>
  );
}

// Undoable notifications
function DeleteWithUndo({ postId }: { postId: string }) {
  const notification = useNotification();
  const { mutate: deletePost } = useDelete();
  
  const handleDelete = () => {
    let cancelMutation: (() => void) | undefined;
    
    notification.open({
      type: "success",
      message: "Post Deleted",
      description: "Post has been deleted.",
      undoableTimeout: 5000,
      cancelMutation: () => {
        if (cancelMutation) {
          cancelMutation();
          notification.open({
            type: "success",
            message: "Deletion Cancelled",
            description: "Post deletion has been cancelled."
          });
        }
      }
    });
    
    // Set timeout for actual deletion
    const timeoutId = setTimeout(() => {
      deletePost({
        resource: "posts",
        id: postId
      });
    }, 5000);
    
    cancelMutation = () => {
      clearTimeout(timeoutId);
    };
  };
  
  return <button onClick={handleDelete}>Delete Post</button>;
}

Modal Management

useModal Hook

Manages modal state with multiple modal support and proper cleanup.

/**
 * Manages modal state with multiple modal support
 * @returns Modal state and control functions
 */
function useModal(): UseModalReturnType;

interface UseModalReturnType {
  /** Whether modal is visible */
  visible: boolean;
  /** Show the modal */
  show: () => void;
  /** Hide the modal */
  close: () => void;
  /** Toggle modal visibility */
  toggle: () => void;
}

Usage Example:

import { useModal, useOne } from "@refinedev/core";

function PostDetailsModal({ postId }: { postId?: string }) {
  const modal = useModal();
  const { data: post } = useOne({
    resource: "posts",
    id: postId!,
    queryOptions: {
      enabled: !!postId && modal.visible
    }
  });
  
  return (
    <>
      <button onClick={modal.show}>View Details</button>
      
      {modal.visible && (
        <div className="modal-overlay" onClick={modal.close}>
          <div className="modal-content" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <h2>{post?.data.title}</h2>
              <button onClick={modal.close}>×</button>
            </div>
            <div className="modal-body">
              <p>{post?.data.content}</p>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// Multiple modals
function MultiModalExample() {
  const editModal = useModal();
  const deleteModal = useModal();
  const viewModal = useModal();
  
  return (
    <div>
      <button onClick={editModal.show}>Edit</button>
      <button onClick={deleteModal.show}>Delete</button>
      <button onClick={viewModal.show}>View</button>
      
      {/* Multiple modal components */}
    </div>
  );
}

Cache Management

useInvalidate Hook

Invalidates React Query cache with fine-grained control over cache keys.

/**
 * Invalidates React Query cache with fine-grained control
 * @returns Cache invalidation functions
 */
function useInvalidate(): UseInvalidateReturnType;

interface UseInvalidateReturnType {
  /** Invalidate specific cache entries */
  invalidate: (params: InvalidateParams) => Promise<void>;
  /** Invalidate all cache entries for a resource */
  invalidateAll: (resource: string) => Promise<void>;
}

interface InvalidateParams {
  /** Resource name */
  resource: string;
  /** Specific record ID */
  id?: BaseKey;
  /** Data provider name */
  dataProviderName?: string;
  /** Whether to invalidate exact match only */
  exact?: boolean;
}

Usage Example:

import { useInvalidate, useUpdate } from "@refinedev/core";

function RefreshablePostList() {
  const invalidate = useInvalidate();
  const { mutate: updatePost } = useUpdate();
  
  const handleRefresh = async () => {
    // Invalidate all posts data
    await invalidate.invalidateAll("posts");
  };
  
  const handleUpdatePost = (id: string, values: any) => {
    updatePost({
      resource: "posts",
      id,
      values
    }, {
      onSuccess: async () => {
        // Invalidate specific post and list
        await invalidate.invalidate({ resource: "posts", id });
        await invalidate.invalidate({ resource: "posts" });
      }
    });
  };
  
  return (
    <div>
      <button onClick={handleRefresh}>Refresh All</button>
      {/* Post list */}
    </div>
  );
}

Import/Export Utilities

File Processing Utilities

Utilities for handling file uploads, downloads, and format conversion.

/**
 * Convert file to base64 string
 * @param file - File to convert
 * @returns Promise resolving to base64 string
 */
function file2Base64(file: File): Promise<string>;

/**
 * CSV import data mapper
 * @param data - Raw CSV data
 * @param mapping - Field mapping configuration
 * @returns Mapped data array
 */
function importCSVMapper(
  data: any[],
  mapping: Record<string, string>
): any[];

interface FileProcessingOptions {
  /** Maximum file size in bytes */
  maxSize?: number;
  /** Allowed file types */
  allowedTypes?: string[];
  /** Custom validation function */
  validate?: (file: File) => boolean | string;
}

Usage Example:

import { file2Base64, importCSVMapper } from "@refinedev/core";

function FileUploadComponent() {
  const handleFileUpload = async (file: File) => {
    try {
      // Convert to base64 for API upload
      const base64 = await file2Base64(file);
      
      // Upload to server
      await fetch("/api/upload", {
        method: "POST",
        body: JSON.stringify({ file: base64 }),
        headers: { "Content-Type": "application/json" }
      });
    } catch (error) {
      console.error("Upload failed:", error);
    }
  };
  
  const handleCSVImport = (csvData: any[]) => {
    // Map CSV columns to database fields
    const mappedData = importCSVMapper(csvData, {
      "Full Name": "name",
      "Email Address": "email",
      "Phone Number": "phone"
    });
    
    // Process mapped data
    console.log("Imported data:", mappedData);
  };
  
  return (
    <div>
      <input
        type="file"
        accept=".csv,.xlsx"
        onChange={(e) => {
          const file = e.target.files?.[0];
          if (file) handleFileUpload(file);
        }}
      />
    </div>
  );
}

Helper Functions

Query Key Management

Standardized query key generation for consistent React Query caching.

/**
 * Query key utilities for React Query
 */
interface QueryKeys {
  /** Generate keys for list queries */
  list: (resource: string, params?: any) => string[];
  /** Generate keys for single record queries */
  one: (resource: string, id: BaseKey, params?: any) => string[];
  /** Generate keys for many records queries */
  many: (resource: string, ids: BaseKey[], params?: any) => string[];
  /** Generate keys for custom queries */
  custom: (resource: string, params?: any) => string[];
}

/**
 * Query key builder for advanced cache management
 */
class KeyBuilder {
  /** Set resource name */
  resource(name: string): KeyBuilder;
  /** Set action type */
  action(action: string): KeyBuilder;
  /** Set parameters */
  params(params: any): KeyBuilder;
  /** Build the key array */
  get(): string[];
}

URL & Route Utilities

Utilities for URL generation and route matching.

/**
 * Generate user-friendly names from resource identifiers
 * @param name - Resource name or identifier
 * @returns User-friendly display name
 */
function useUserFriendlyName(): (name: string) => string;

/**
 * Match resource from current route
 * @param route - Current route path
 * @param resources - Available resources
 * @returns Matched resource configuration
 */
function matchResourceFromRoute(
  route: string,
  resources: IResourceItem[]
): IResourceItem | undefined;

/**
 * Generate default document title
 * @param params - Title generation parameters
 * @returns Generated document title
 */
function generateDefaultDocumentTitle(params: {
  resource?: string;
  action?: string;
  id?: BaseKey;
}): string;

Object Utilities

Utilities for object manipulation and property access.

/**
 * Flatten nested object keys with dot notation
 * @param obj - Object to flatten
 * @param prefix - Key prefix for nested properties
 * @returns Flattened object
 */
function flattenObjectKeys(
  obj: Record<string, any>,
  prefix?: string
): Record<string, any>;

/**
 * Convert property path string to array
 * @param path - Property path (e.g., "user.profile.name")
 * @returns Path array (e.g., ["user", "profile", "name"])
 */
function propertyPathToArray(path: string): string[];

Usage Example:

import { 
  flattenObjectKeys, 
  propertyPathToArray,
  useUserFriendlyName 
} from "@refinedev/core";

function ObjectUtilsExample() {
  const getUserFriendlyName = useUserFriendlyName();
  
  // Flatten nested object
  const nestedData = {
    user: {
      profile: {
        name: "John Doe",
        address: {
          city: "New York",
          country: "USA"
        }
      }
    }
  };
  
  const flatData = flattenObjectKeys(nestedData);
  // Result: { "user.profile.name": "John Doe", "user.profile.address.city": "New York", ... }
  
  // Convert path to array
  const pathArray = propertyPathToArray("user.profile.name");
  // Result: ["user", "profile", "name"]
  
  // Generate friendly names
  const friendlyName = getUserFriendlyName("user_profiles");
  // Result: "User Profiles"
  
  return (
    <div>
      <h2>{friendlyName}</h2>
      <pre>{JSON.stringify(flatData, null, 2)}</pre>
    </div>
  );
}

Types

interface UtilityConfig {
  /** Default configuration values */
  defaults?: Record<string, any>;
  /** Feature flags */
  features?: Record<string, boolean>;
  /** Custom settings */
  settings?: Record<string, any>;
}

interface ProcessingResult<T> {
  /** Processing success status */
  success: boolean;
  /** Processed data */
  data?: T;
  /** Processing errors */
  errors?: string[];
  /** Warning messages */
  warnings?: string[];
}

interface CacheOptions {
  /** Cache expiry time in milliseconds */
  expiry?: number;
  /** Whether to use stale data while revalidating */
  staleWhileRevalidate?: boolean;
  /** Custom cache key */
  key?: string;
}

interface ErrorBoundaryProps {
  /** Fallback component for errors */
  fallback?: React.ComponentType<{ error: Error }>;
  /** Error callback */
  onError?: (error: Error, errorInfo: any) => void;
  /** Children to wrap */
  children: React.ReactNode;
}

Real-time & Live Data

usePublish Hook

Publishes real-time events to subscribed clients for live data synchronization.

/**
 * Publishes real-time events to subscribed clients
 * @returns Publish function from the live provider
 */
function usePublish(): ((event: LiveEvent) => void) | undefined;

interface LiveEvent {
  /** Channel name for the event */
  channel: string;
  /** Event type */
  type: "created" | "updated" | "deleted" | string;
  /** Event payload */
  payload: {
    /** IDs of affected records */
    ids?: BaseKey[];
    /** Additional event data */
    [key: string]: any;
  };
  /** Timestamp of the event */
  date: Date;
}

Usage Example:

import { usePublish } from "@refinedev/core";

function ProductForm() {
  const publish = usePublish();
  
  const handleProductUpdate = (product) => {
    // Update product logic...
    
    // Notify other clients about the update
    publish?.({
      channel: "products",
      type: "updated",
      payload: {
        ids: [product.id]
      },
      date: new Date()
    });
  };
  
  return (
    <form onSubmit={handleProductUpdate}>
      {/* Form fields */}
    </form>
  );
}

useSubscription Hook

Subscribes to real-time events for live data synchronization and automatic updates.

/**
 * Subscribes to real-time events for live data updates
 * @param params - Subscription configuration
 */
function useSubscription(params: UseSubscriptionConfig): void;

interface UseSubscriptionConfig {
  /** Channel name to subscribe to */
  channel: string;
  /** Callback function when live events are received */
  onLiveEvent: (event: LiveEvent) => void;
  /** Types of events to subscribe to */
  types?: Array<"created" | "updated" | "deleted" | "*" | string>;
  /** Whether subscription is enabled */
  enabled?: boolean;
  /** Additional parameters for the subscription */
  params?: {
    ids?: BaseKey[];
    id?: BaseKey;
    sorters?: CrudSort[];
    filters?: CrudFilter[];
    subscriptionType?: "useList" | "useOne" | "useMany";
    resource?: string;
    [key: string]: any;
  };
  /** Metadata for the subscription */
  meta?: MetaQuery & { dataProviderName?: string };
}

Usage Example:

import { useSubscription, useList } from "@refinedev/core";

function ProductsList() {
  const { data, refetch } = useList({ resource: "products" });
  
  // Subscribe to product updates
  useSubscription({
    channel: "products",
    onLiveEvent: (event) => {
      if (event.type === "created" || event.type === "updated" || event.type === "deleted") {
        // Refetch the list when products are modified
        refetch();
      }
    },
    types: ["created", "updated", "deleted"],
    enabled: true
  });
  
  return (
    <div>
      {data?.data.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}

useLiveMode Hook

Manages live mode state and automatic real-time updates for data operations.

/**
 * Manages live mode state for automatic real-time updates
 * @returns Live mode configuration and state
 */
function useLiveMode(): UseLiveModeReturnType;

interface UseLiveModeReturnType {
  /** Current live mode setting */
  liveMode?: "auto" | "manual" | "off";
}

Usage Example:

import { useLiveMode, useList } from "@refinedev/core";

function ProductsList() {
  const { liveMode } = useLiveMode();
  
  const { data } = useList({
    resource: "products",
    liveMode: liveMode, // Use global live mode setting
  });
  
  return (
    <div>
      <p>Live mode: {liveMode}</p>
      {data?.data.map(product => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}

Menu & Navigation

useMenu Hook

Generates menu items for navigation based on available resources, with hierarchical structure support and customizable visibility.

/**
 * Generates menu items for navigation sidebars and menus
 * @param params - Menu configuration options
 * @returns Menu items with navigation structure
 */
function useMenu(params?: UseMenuConfig): UseMenuReturnType;

interface UseMenuConfig {
  /** Additional metadata for menu generation */
  meta?: Record<string, any>;
  /** Hide menu items that have missing route parameters */
  hideOnMissingParameter?: boolean;
}

interface UseMenuReturnType {
  /** Keys of menu items that should be open by default */
  defaultOpenKeys: string[];
  /** Currently selected menu item key */
  selectedKey: string;
  /** Hierarchical menu items structure */
  menuItems: TreeMenuItem[];
}

interface TreeMenuItem {
  /** Menu item key/identifier */
  key: string;
  /** Display label for the menu item */
  label?: string;
  /** Icon component for the menu item */
  icon?: React.ReactNode;
  /** Route path for navigation */
  route?: string;
  /** Child menu items */
  children: TreeMenuItem[];
  /** Resource metadata */
  resource?: IResourceItem;
  /** Parent resource reference */
  parentName?: string;
}

Usage Example:

import { useMenu } from "@refinedev/core";

function Sidebar() {
  const { menuItems, selectedKey, defaultOpenKeys } = useMenu({
    hideOnMissingParameter: true
  });
  
  const renderMenuItem = (item: TreeMenuItem) => (
    <div key={item.key} className={selectedKey === item.key ? "active" : ""}>
      {item.icon}
      <span>{item.label}</span>
      {item.children.length > 0 && (
        <div>
          {item.children.map(renderMenuItem)}
        </div>
      )}
    </div>
  );
  
  return (
    <nav>
      {menuItems.map(renderMenuItem)}
    </nav>
  );
}

Install with Tessl CLI

npx tessl i tessl/npm-refinedev--core

docs

application-setup.md

authentication.md

data-operations.md

forms.md

index.md

navigation.md

tables-lists.md

utilities.md

tile.json