npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xhub-short/sdk

v0.1.0-beta.5

Published

Main entry point for XHub-short SDK - Short Video Feed for WebView

Readme

@xhub-short/sdk

Glue Layer - Kết nối Core Domain với React UI

📖 SDK là gì?

SDK (Software Development Kit) là package chính mà Host App cài đặt để tích hợp Short Video Feed. Nó đóng vai trò "Glue Layer" - kết nối tất cả các thành phần bên trong SDK thành một API thống nhất, dễ sử dụng.

┌─────────────────────────────────────────────────────────────────────┐
│                         HOST APP (Your App)                          │
│                                                                      │
│   import { ShortVideoProvider, useFeed, usePlayer } from '@xhub-short/sdk';
│   import { VideoFeed, VideoPlayer } from '@xhub-short/ui';          │
│                                                                      │
└──────────────────────────────┬──────────────────────────────────────┘
                               │ uses
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         @xhub-short/ui                               │
│                    (Lego Components - Phase 4)                       │
│                                                                      │
│   VideoFeed, VideoPlayer, InteractionBar, CommentSheet...           │
│                                                                      │
└──────────────────────────────┬──────────────────────────────────────┘
                               │ imports hooks from
                               ▼
┌─────────────────────────────────────────────────────────────────────┐
│                         @xhub-short/sdk                              │
│                       (Glue Layer - Current)                         │
│                                                                      │
│   ┌─────────────┐   ┌─────────────┐   ┌─────────────────────────┐  │
│   │  Provider   │   │   Hooks     │   │    Factory (createSDK)  │  │
│   │  (Context)  │   │  (React)    │   │    (Dependency Inject)  │  │
│   └─────────────┘   └─────────────┘   └─────────────────────────┘  │
│                                                                      │
└──────────────────────────────┬──────────────────────────────────────┘
                               │ orchestrates
          ┌────────────────────┴────────────────────┐
          ▼                                         ▼
   ┌─────────────┐                           ┌─────────────┐
   │   @core     │                           │  @adapters  │
   │ (Domain)    │                           │ (Infra)     │
   └─────────────┘                           └─────────────┘

Lưu ý: @sdk KHÔNG import từ @ui. Mũi tên chỉ hướng dependency (ai import ai).


🎯 Tại sao cần SDK?

| Vấn đề | Giải pháp của SDK | |--------|-------------------| | Host App phải hiểu kiến trúc phức tạp bên trong | SDK expose API đơn giản: hooks + provider | | Khó setup dependency injection cho adapters | createSDK() tự động wire tất cả | | State management phức tạp (Feed, Player, Resource...) | Hooks abstract hết complexity | | SSR compatibility | useSyncExternalStore built-in | | Memory leaks khi unmount | sdk.destroy() cleanup tự động |


📋 Nhiệm vụ chi tiết của SDK

SDK thực hiện 7 nhiệm vụ chính để Host App có thể tích hợp dễ dàng:

1. Dependency Injection & Wiring

SDK là nơi duy nhất thực hiện dependency injection - kết nối các adapters với core managers:

┌─────────────────────────────────────────────────────────────────────┐
│                    DEPENDENCY INJECTION MAP                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   Adapter Interface          ───►    Core Component                 │
│   ─────────────────                  ──────────────                 │
│   IDataSource                ───►    FeedManager                    │
│   IInteraction               ───►    OptimisticManager              │
│   ISessionStorage            ───►    LifecycleManager               │
│   INetworkAdapter            ───►    ResourceGovernor               │
│   IVideoLoader + IPosterLoader ───►  ResourceGovernor               │
│   IAnalytics                 ───►    PlayerEngine (events)          │
│   ILogger                    ───►    All managers (debug)           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

2. Adapter Resolution

SDK tự động resolve adapters theo thứ tự ưu tiên:

Config Priority:
┌──────────────────────────────────────────────────────────────┐
│                                                               │
│   1. config.adapters.dataSource    ◄── Highest (User-defined)│
│              │                                                │
│              ▼ fallback                                       │
│   2. config.preset → createBrowserAdapters()                 │
│              │                                                │
│              ▼ fallback                                       │
│   3. MockAdapter                   ◄── Lowest (Development)  │
│                                                               │
└──────────────────────────────────────────────────────────────┘

Điều này cho phép:

  • Development: Không cần config → Mock adapters tự động
  • Production với Preset: Chỉ cần baseUrl + auth + endpoints
  • Full Custom: Override bất kỳ adapter nào

3. State Synchronization (Core ↔ React)

Core Domain sử dụng vanilla stores (không React). SDK bridge chúng sang React:

┌─────────────────┐         ┌─────────────────┐         ┌─────────────────┐
│  Core Store     │         │     SDK Hook    │         │   React UI      │
│  (Vanilla)      │   ───►  │ (useSyncExternal│   ───►  │  (Re-render)    │
│                 │         │     Store)      │         │                 │
└─────────────────┘         └─────────────────┘         └─────────────────┘
     │                              │
     │ store.subscribe()           │ getSnapshot()
     │ store.setState()            │
     ▼                              ▼
  Framework-agnostic           SSR-safe subscription

Tại sao không dùng Zustand trực tiếp trong Core?

  • Core phải framework-agnostic (có thể dùng với Vue, Svelte...)
  • Giảm bundle size cho Core package
  • Tách biệt concerns rõ ràng

4. Event Orchestration

SDK wire các events giữa managers để chúng phối hợp:

┌──────────────────────────────────────────────────────────────────────┐
│                        EVENT WIRING                                   │
├──────────────────────────────────────────────────────────────────────┤
│                                                                       │
│   PlayerEngine                                                        │
│       │                                                               │
│       ├── on('videoChange') ──────► Analytics.flush()                │
│       │                              (Flush trước khi đổi video)     │
│       │                                                               │
│       └── on('timeUpdate') ───────► LifecycleManager.setPendingSave()│
│                                      (Auto-save playback position)   │
│                                                                       │
│   LifecycleManager                                                    │
│       │                                                               │
│       └── on('visibilityChange') ─► Analytics.flush()                │
│           (state === 'hidden')       (Flush khi app background)      │
│                                                                       │
│   ResourceGovernor                                                    │
│       │                                                               │
│       └── on('focusChange') ──────► PlayerEngine.load(video)         │
│                                      (Load video khi swipe)          │
│                                                                       │
└──────────────────────────────────────────────────────────────────────┘

5. Lifecycle Management

SDK quản lý toàn bộ vòng đời của các managers:

| Phase | SDK Actions | |-------|-------------| | Init | Tạo managers, inject adapters, wire events, restore session | | Active | Managers hoạt động độc lập, SDK chỉ expose hooks | | Background | Auto-save session, flush analytics | | Destroy | Cleanup timers, unsubscribe events, clear cache |

// Tự động trong Provider:
useEffect(() => {
  const sdk = createSDK(config);
  return () => sdk.destroy(); // Cleanup khi unmount
}, []);

6. Public API Surface

SDK expose API đơn giản, ẩn đi complexity bên trong:

| Exposed to Host App | Hidden from Host App | |---------------------|----------------------| | useFeed() - videos, loadMore | FeedManager internals | | usePlayer() - play, pause, seek | PlayerEngine state machine | | useOptimistic() - like, follow | Rollback queue, pending states | | useSwipeGesture() - onSwipe | DOM allocation logic | | Config với preset | Adapter creation |

7. SSR Support

SDK đảm bảo hoạt động với Server-Side Rendering:

┌──────────────────────────────────────────────────────────────┐
│                      SSR STRATEGY                             │
├──────────────────────────────────────────────────────────────┤
│                                                               │
│   Server:                                                     │
│   ├─ ShortVideoProvider renders với empty state              │
│   ├─ Hooks return initial/fallback values                    │
│   └─ Không tạo SDK instance                                  │
│                                                               │
│   Client (Hydration):                                         │
│   ├─ useEffect tạo SDK instance                              │
│   ├─ Restore session từ localStorage                         │
│   └─ useSyncExternalStore subscribe to stores                │
│                                                               │
└──────────────────────────────────────────────────────────────┘

🏗️ Kiến trúc

Vị trí trong hệ thống

┌─────────────────────────────────────────────────────────────────────┐
│                      HEXAGONAL ARCHITECTURE                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   ┌─────────────────────────────────────────────────────────────┐   │
│   │                    @xhub-short/sdk                           │   │
│   │                    ════════════════                          │   │
│   │                                                              │   │
│   │   ShortVideoProvider ──────┬──────── createSDK()            │   │
│   │          │                 │              │                  │   │
│   │          │          Dependency Injection  │                  │   │
│   │          │                 │              │                  │   │
│   │          ▼                 ▼              ▼                  │   │
│   │   ┌──────────┐      ┌──────────┐   ┌──────────┐             │   │
│   │   │  Hooks   │      │  Core    │   │ Adapters │             │   │
│   │   │ (React)  │◀────▶│ Managers │◀──│ (Inject) │             │   │
│   │   └──────────┘      └──────────┘   └──────────┘             │   │
│   │                                                              │   │
│   └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
│   ┌──────────────┐  ┌──────────────┐  ┌──────────────────────────┐  │
│   │ @contracts   │  │   @core      │  │      @adapters           │  │
│   │ (Interfaces) │  │ (Domain)     │  │   (Infrastructure)       │  │
│   └──────────────┘  └──────────────┘  └──────────────────────────┘  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Package Dependencies

@xhub-short/sdk
├── @xhub-short/contracts  (types, interfaces)
├── @xhub-short/core       (domain logic)
├── @xhub-short/adapters   (mock + preset adapters)
├── @xhub-short/ui         (headless components)
├── react (peer dependency)
└── zustand (peer dependency)

Host App Installation

npm install @xhub-short/sdk

That's it! No other dependencies needed.

Bundled internally:

  • zustand - state management (bundled in @xhub-short/core)
  • clsx - class names utility (bundled in @xhub-short/ui)
  • Custom useTouchDrag hook - gesture handling (bundled in @xhub-short/sdk)

✨ Chức năng chính

1. Provider - Context cho toàn bộ SDK

<ShortVideoProvider config={{ preset: {...} }}>
  <YourApp />
</ShortVideoProvider>

2. Hooks - React API để truy cập SDK

| Hook | Mục đích | |------|----------| | useFeed() | Video list, pagination, loading states | | usePlayer() | Playback control, time, volume, handlers | | useResource() | DOM allocations, prefetch queue | | useOptimistic() | Like/Follow với instant UI + rollback | | useSwipeGesture() | Vertical swipe navigation |

3. Wired Components - Pre-connected UI Components

SDK exports pre-wired versions of UI components with SDK hooks already injected:

| Component | Description | |-----------|-------------| | VideoFeed | Wired VideoFeedHeadless with useFeed + useSwipeGesture | | VideoSlot | Wired VideoSlotHeadless with useResourceAllocation + usePlayer | | VideoPlayer | Wired VideoPlayerHeadless with usePlayer (auto-load, sync) | | ProgressBar | Wired progress bar with Direct DOM Update (60fps smooth) |

VideoPlayer (Wired)

Pre-wired video player that auto-connects to SDK PlayerEngine.

import { VideoSlot, VideoPlayer } from '@xhub-short/sdk';
import { VideoSlotPoster, VideoSlotOverlay } from '@xhub-short/ui';

function FeedItem({ video }) {
  return (
    <VideoSlot video={video}>
      <VideoPlayer 
        resetOnInactive={true}  // TikTok-like: restart from beginning
      />
      <VideoSlotPoster />
      <VideoSlotOverlay>...</VideoSlotOverlay>
    </VideoSlot>
  );
}

| Prop | Type | Default | Description | |------|------|---------|-------------| | video | VideoItem | from context | Video to play (optional if inside VideoSlot) | | autoLoad | boolean | true | Auto-load video into PlayerEngine | | autoPlay | boolean | true | Auto-play when slot becomes active | | resetOnInactive | boolean | true | Reset video to 0:00 when slot becomes inactive | | loop | boolean | true | Loop video playback | | muted | boolean | true | Start muted (required for autoplay) |

resetOnInactive behavior:

  • true (default): TikTok-like - swiping back restarts video from beginning
  • false: YouTube-like - video continues from where user left off

ProgressBar (Wired) - P11 Re-render Optimization

Pre-wired progress bar that uses Direct DOM Update for 60fps smooth animation.

import { VideoSlot, VideoPlayer, ProgressBar } from '@xhub-short/sdk';
import { VideoSlotOverlay } from '@xhub-short/ui';

function FeedItem({ video }) {
  return (
    <VideoSlot video={video}>
      <VideoPlayer />
      <VideoSlotOverlay>
        <ProgressBar seekable={true} />  {/* 60fps smooth! */}
      </VideoSlotOverlay>
    </VideoSlot>
  );
}

| Prop | Type | Default | Description | |------|------|---------|-------------| | seekable | boolean | true | Enable click/drag to seek | | showTime | boolean | false | Show current/duration text | | showTooltip | boolean | true | Show tooltip on hover | | minimal | boolean | false | Thin bar without handle |

Performance Architecture:

PlayerEngine.store ───── subscribe() ───── fillRef.style.transform
                                           (scaleX, GPU accelerated)
                         NOT React re-render!

This component demonstrates ADR 005: Direct DOM Manipulation for high-frequency updates. See docs/issues/RE_RENDER_ANALYSIS.md for detailed optimization rationale.

4. Factory - Dependency Injection

const sdk = createSDK({
  preset: { baseUrl, auth, endpoints },  // Auto-generate adapters
  adapters: { dataSource, interaction }, // Or custom adapters
  feed: { pageSize: 20 },
  player: { autoplay: true },
});

🔄 Cách hoạt động

Flow: Từ Config đến UI

┌──────────────────────────────────────────────────────────────────────┐
│                          INITIALIZATION                               │
├──────────────────────────────────────────────────────────────────────┤
│                                                                       │
│   1. Host App mount <ShortVideoProvider config={...}>                │
│                           │                                           │
│                           ▼                                           │
│   2. createSDK(config)                                               │
│      ├─ Resolve adapters (preset → browser adapters)                 │
│      ├─ Create Core managers:                                        │
│      │   ├─ FeedManager      (video list, deduplication, GC)        │
│      │   ├─ PlayerEngine     (playback state machine)               │
│      │   ├─ ResourceGovernor (DOM allocation, prefetch)             │
│      │   ├─ OptimisticManager (like/follow with rollback)           │
│      │   └─ LifecycleManager (session persistence)                  │
│      └─ Wire analytics flush events                                  │
│                           │                                           │
│                           ▼                                           │
│   3. SDKContext.Provider value={sdk}                                 │
│                           │                                           │
│                           ▼                                           │
│   4. Hooks subscribe to managers via useSyncExternalStore            │
│                                                                       │
└──────────────────────────────────────────────────────────────────────┘

Flow: User Interaction

User swipes down
       │
       ▼
useSwipeGesture() ─────────► ResourceGovernor.setFocusedIndex(n+1)
                                    │
                   ┌────────────────┼────────────────┐
                   ▼                ▼                ▼
            Deallocate         Allocate         Preload
            video[n-1]         video[n+1]       video[n+2]
                                    │
                                    ▼
                            PlayerEngine.load(video)
                                    │
                                    ▼
                            Analytics.track('video_view')

📦 Exports

Provider

export { ShortVideoProvider } from './provider';
export type { ShortVideoProviderProps, SDKConfig } from './provider';

Hooks

// Feed management
export { useFeed, useFeedSelector } from './hooks';

// Player control
export { usePlayer, usePlayerSelector, usePlayerForVideo } from './hooks';

// Resource management (DOM allocation)
export { useResource, useResourceSelector, useResourceAllocation } from './hooks';

// Optimistic UI (like/follow)
export { useOptimistic, useOptimisticSelector } from './hooks';

// Swipe navigation
export { useSwipeGesture } from './hooks';

// SDK context access
export { useSDK } from './hooks';

Factory

export { createSDK } from './store';
export type { SDKInstance } from './store';

Types (Re-exported)

// From @xhub-short/contracts
export type { VideoItem, FeedResponse, IDataSource, ... } from '@xhub-short/contracts';

// From @xhub-short/core
export type { FeedState, PlayerState, ResourceState, ... } from '@xhub-short/core';

🚀 Quick Start

Simplest Usage (Recommended)

import { ShortVideoRoot, VideoFeed, DefaultSlot } from '@xhub-short/sdk';

function App() {
  return (
    <ShortVideoRoot
      config={{
        preset: {
          baseUrl: 'https://api.example.com/v1',
          auth: { getAccessToken: () => localStorage.getItem('token') },
          endpoints: {
            feed: { list: '/videos', detail: '/videos/:id' },
            interaction: { like: '/videos/:id/like' },
          },
        },
      }}
      errorMode="auto-skip-with-toast"
    >
      <VideoFeed renderSlot={(video, index) => (
        <DefaultSlot 
          video={video} 
          index={index}
          showBookmark={true}
          onOpenComments={(videoId) => openSheet(videoId)}
          onShare={(video) => shareVideo(video)}
        />
      )} />
    </ShortVideoRoot>
  );
}

That's it! The SDK handles everything: video loading, HLS playback, swipe navigation, like/follow actions, error handling, and more.

DefaultSlot Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | video | VideoItem | required | Video data | | index | number | required | Index in feed | | showPoster | boolean | true | Show poster | | showLikeAnimation | boolean | true | Double-tap hearts | | showAuthorInfo | boolean | true | Avatar + follow | | showActionBar | boolean | true | Like, comment, share | | showVideoInfo | boolean | true | Caption, hashtags | | showProgressBar | boolean | true | Progress bar | | showBookmark | boolean | false | Bookmark button | | onOpenComments | (videoId) => void | - | Comment click | | onShare | (video) => void | - | Share click | | onOpenProfile | (author) => void | - | Author click | | onHashtagClick | (tag) => void | - | Hashtag click |

Custom Usage (Advanced)

For full control, use individual components:

import { 
  ShortVideoRoot, VideoFeed, VideoSlot, VideoPlayer,
  ActionBar, AuthorInfo, VideoInfo, ProgressBar 
} from '@xhub-short/sdk';
import { VideoSlotOverlay, VideoSlotPoster } from '@xhub-short/ui';

<VideoFeed renderSlot={(video, index) => (
  <VideoSlot video={video} index={index}>
    <VideoPlayer />
    <VideoSlotPoster />
    <VideoSlotOverlay>
      <VideoSlotOverlay.Actions>
        <AuthorInfo video={video} variant="avatar-badge" />
        <ActionBar video={video} />
      </VideoSlotOverlay.Actions>
      <VideoSlotOverlay.Bottom>
        <VideoInfo video={video} />
        <ProgressBar showTime />
      </VideoSlotOverlay.Bottom>
    </VideoSlotOverlay>
  </VideoSlot>
)} />

### With Custom Adapters

```tsx
<ShortVideoProvider
  config={{
    adapters: {
      dataSource: new MyGraphQLAdapter(),
      interaction: new MyFlutterBridgeAdapter(),
    },
  }}
>
  <App />
</ShortVideoProvider>

👤 Guest Mode (Chế độ khách)

SDK hỗ trợ chế độ khách cho phép người dùng chưa đăng nhập xem video và bình luận (read-only). Các tương tác (Like, Comment, Follow) sẽ bị chặn và trigger callback để Host App xử lý (ví dụ: hiện modal đăng nhập).

Cấu hình

<ShortVideoRoot
  config={{
    // ...
    guest: {
      /**
       * 'auto': Tự động detect dựa trên auth token (default)
       * true: Force guest mode
       * false: Disable guest mode
       */
      mode: 'auto',

      /**
       * Callback khi guest thực hiện hành động cần auth (Like, Comment, Follow...)
       */
      onAction: (action, context) => {
        console.log('Guest Action:', action, context); 
        // VD: showLoginModal();
      }
    }
  }}
>
  <VideoFeed />
</ShortVideoRoot>

Các hành động được chặn

  • Like / Bookmark: Trigger onAction
  • Follow: Trigger onAction
  • Comment Input: Hiển thị nút "Login to comment". Khi click triggers onAction (action='comment').

⚡ Prefetch Data (Tải trước dữ liệu)

Cho phép Host App tải trước dữ liệu Feed (Reels) để trải nghiệm hiển thị tức thì (instant loading).

Cách sử dụng

Gọi hàm prefetchFeed trước khi mount SDK components (ví dụ: khi hover vào menu Reels hoặc trong route loader).

import { prefetchFeed } from '@xhub-short/sdk';

// 1. Prefetch data (lưu vào bộ nhớ tạm)
// Có thể gọi ở bất kỳ đâu trong Host App
await prefetchFeed(sdkConfig, { ttl: 5 * 60 * 1000 });

// ... Sau đó ...

// 2. Khi User vào trang Reels, SDK sẽ tự động dùng data đã fetch
<ShortVideoRoot config={sdkConfig}>
  <VideoFeed />
</ShortVideoRoot>

Đặc điểm

  • In-Memory Cache: Dữ liệu chỉ lưu tạm trong RAM, mất khi refresh trang (đảm bảo fresh data).
  • Auto-Consume: ShortVideoRoot tự động tiêu thụ cache và xóa sau khi dùng.
  • Performance: Giúp giảm thời gian chờ đợi (LCP) xuống gần bằng 0 khi user chuyển trang.

🔗 Liên kết với các Packages

| Package | Quan hệ với SDK | |---------|-----------------| | @xhub-short/contracts | SDK re-export types/interfaces | | @xhub-short/core | SDK wraps core managers với React hooks | | @xhub-short/adapters | SDK inject adapters vào core managers | | @xhub-short/ui | UI components sử dụng SDK hooks (Phase 4) | | @xhub-short/bridge | Optional Flutter integration |

Dependency Flow

contracts ◀─────────────────────────────────────────┐
    ▲                                               │
    │                                               │
core ◀──────────────────────────┐                  │
    ▲                           │                  │
    │                           │                  │
adapters ◀──────────┐          │                  │
    ▲               │          │                  │
    │               │          │                  │
    └───────────────┴──────────┴────────── sdk ───┘
                                             │
                                             ▼
                                        Host App

⚠️ Lưu ý quan trọng

SSR Safety

  • Tất cả hooks sử dụng useSyncExternalStore
  • Provider render fallback trên server
  • SDK instance chỉ tạo trên client

Memory Management

  • sdk.destroy() được gọi tự động khi Provider unmount
  • Max 3 video DOM nodes (via ResourceGovernor)
  • LRU cache eviction trong FeedManager

Deprecated APIs

// ❌ DEPRECATED - Singleton gây issues với SSR/testing
const sdk = getSDK(config);

// ✅ RECOMMENDED - Sử dụng Provider
<ShortVideoProvider config={config}>
  <App />
</ShortVideoProvider>

📚 Tài liệu liên quan