cloudsignal-websocket

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CloudSignal WebSocket — React MQTT Context Generator

CloudSignal WebSocket — React MQTT上下文生成器

Generate a production-grade React context provider for real-time messaging over CloudSignal's MQTT broker using WebSocket. The generated code handles the full connection lifecycle: authentication via external auth providers, reconnection, proactive token refresh, message routing, and cleanup.
生成一个生产级React上下文提供者,用于通过WebSocket连接CloudSignal的MQTT代理进行实时消息传递。生成的代码处理完整的连接生命周期:通过外部身份验证提供商进行认证、重连、主动令牌刷新、消息路由以及资源清理。

What You Generate

生成内容

  1. mqtt-context.tsx
    — React context provider with:
    • Auth-provider token exchange (Clerk, Supabase, Auth0, Firebase, or custom OIDC)
    • WebSocket connection to CloudSignal MQTT broker
    • Auth error circuit-breaker (max 3 retries, 10s delay)
    • Proactive token refresh at 50 minutes (before 60-min TTL expiry)
    • Exact topic routing with safe JSON parsing
    • React StrictMode double-mount protection
    • Tab visibility reconnection
    • Typed subscription hooks (jobs, notifications, transactions, or custom)
  2. cloudsignal.d.ts
    — TypeScript declarations for
    @cloudsignal/mqtt-client
    (the npm package does not ship types)
  1. mqtt-context.tsx
    — 包含以下功能的React上下文提供者:
    • 身份验证提供商令牌交换(Clerk、Supabase、Auth0、Firebase或自定义OIDC)
    • 连接到CloudSignal MQTT代理的WebSocket连接
    • 认证错误熔断机制(最多3次重试,10秒延迟)
    • 主动令牌刷新(在60分钟令牌过期前的第50分钟执行)
    • 精确主题路由与安全JSON解析
    • React StrictMode双挂载保护
    • 标签页可见性触发重连
    • 类型化订阅钩子(任务、通知、交易或自定义类型)
  2. cloudsignal.d.ts
    @cloudsignal/mqtt-client
    的TypeScript声明文件(该npm包未自带类型文件)

Before You Start

开始之前

Ask the user for these inputs (use defaults if not provided):
InputExampleDefault
Auth providerClerk, Supabase, Auth0, FirebaseAsk (required)
Organization ID
org_k7xm4pqr2n5t
Ask (required)
Topic namespace
myapp
App name from package.json
Message types needednotifications, jobs, transactionsAll three
Target directory
src/lib/
or
src/contexts/
src/lib/
向用户询问以下输入信息(未提供时使用默认值):
输入项示例默认值
身份验证提供商Clerk, Supabase, Auth0, Firebase必须询问(必填)
组织ID
org_k7xm4pqr2n5t
必须询问(必填)
主题命名空间
myapp
来自package.json的应用名称
需要的消息类型notifications, jobs, transactions全部三种
目标目录
src/lib/
src/contexts/
src/lib/

Generation Steps

生成步骤

Step 1: Read the Reference Implementation

步骤1:阅读参考实现

Read
references/mqtt-context.tsx
in this skill's directory. This is the canonical reference — a production-tested context provider extracted from a live SaaS. Use it as the base for all generated code.
阅读本skill目录下的
references/mqtt-context.tsx
文件。这是标准参考实现——一个从上线SaaS系统中提取的经过生产环境测试的上下文提供者。以此作为所有生成代码的基础。

Step 2: Adapt the Auth Provider Hooks

步骤2:适配身份验证提供者钩子

The reference contains two placeholder functions that MUST be replaced based on the user's auth provider:
useCurrentUser()
— must return
{ id: string } | null
:
ProviderImplementation
Clerk
import { useUser } from "@clerk/nextjs"; const { user } = useUser(); return user ? { id: user.id } : null;
Supabase
import { useSession } from "@supabase/auth-helpers-react"; const session = useSession(); return session ? { id: session.user.id } : null;
Auth0
import { useAuth0 } from "@auth0/auth0-react"; const { user, isAuthenticated } = useAuth0(); return isAuthenticated && user ? { id: user.sub! } : null;
Firebase
import { useAuthState } from "react-firebase-hooks/auth"; import { auth } from "@/lib/firebase"; const [user] = useAuthState(auth); return user ? { id: user.uid } : null;
useGetToken()
— must return
() => Promise<string | null>
:
ProviderImplementation
Clerk
import { useAuth } from "@clerk/nextjs"; const { getToken } = useAuth(); return getToken;
Supabase
import { useSupabaseClient } from "@supabase/auth-helpers-react"; const supabase = useSupabaseClient(); return async () => { const { data } = await supabase.auth.getSession(); return data.session?.access_token ?? null; };
Auth0
import { useAuth0 } from "@auth0/auth0-react"; const { getAccessTokenSilently } = useAuth0(); return async () => { try { return await getAccessTokenSilently(); } catch { return null; } };
Firebase
import { auth } from "@/lib/firebase"; return async () => auth.currentUser?.getIdToken() ?? null;
参考实现中包含两个占位函数,必须根据用户的身份验证提供者进行替换:
useCurrentUser()
— 必须返回
{ id: string } | null
提供者实现代码
Clerk
import { useUser } from "@clerk/nextjs"; const { user } = useUser(); return user ? { id: user.id } : null;
Supabase
import { useSession } from "@supabase/auth-helpers-react"; const session = useSession(); return session ? { id: session.user.id } : null;
Auth0
import { useAuth0 } from "@auth0/auth0-react"; const { user, isAuthenticated } = useAuth0(); return isAuthenticated && user ? { id: user.sub! } : null;
Firebase
import { useAuthState } from "react-firebase-hooks/auth"; import { auth } from "@/lib/firebase"; const [user] = useAuthState(auth); return user ? { id: user.uid } : null;
useGetToken()
— 必须返回
() => Promise<string | null>
提供者实现代码
Clerk
import { useAuth } from "@clerk/nextjs"; const { getToken } = useAuth(); return getToken;
Supabase
import { useSupabaseClient } from "@supabase/auth-helpers-react"; const supabase = useSupabaseClient(); return async () => { const { data } = await supabase.auth.getSession(); return data.session?.access_token ?? null; };
Auth0
import { useAuth0 } from "@auth0/auth0-react"; const { getAccessTokenSilently } = useAuth0(); return async () => { try { return await getAccessTokenSilently(); } catch { return null; } };
Firebase
import { auth } from "@/lib/firebase"; return async () => auth.currentUser?.getIdToken() ?? null;

Step 3: Customize Message Types

步骤3:自定义消息类型

Replace the reference message interfaces with the user's domain. Keep the structure (interface + handler type + registry pattern) but adapt field names and types.
Default message types from reference:
ProgressMessage
,
StatusMessage
,
TransactionMessage
,
NotificationMessage
.
将参考实现中的消息接口替换为用户业务域的接口。保留结构(接口+处理程序类型+注册模式),但调整字段名称和类型。
参考实现中的默认消息类型:
ProgressMessage
StatusMessage
TransactionMessage
NotificationMessage

Step 4: Set Configuration Constants

步骤4:设置配置常量

tsx
const CLOUDSIGNAL_ORG_ID = process.env.NEXT_PUBLIC_CLOUDSIGNAL_ORG_ID;
const CLOUDSIGNAL_HOST = process.env.NEXT_PUBLIC_CLOUDSIGNAL_HOST || "wss://connect.cloudsignal.app:18885/";
const TOPIC_ROOT = "{user's namespace}";
tsx
const CLOUDSIGNAL_ORG_ID = process.env.NEXT_PUBLIC_CLOUDSIGNAL_ORG_ID;
const CLOUDSIGNAL_HOST = process.env.NEXT_PUBLIC_CLOUDSIGNAL_HOST || "wss://connect.cloudsignal.app:18885/";
const TOPIC_ROOT = "{user's namespace}";

Step 5: Write the Type Declarations

步骤5:编写类型声明文件

Read
references/cloudsignal.d.ts
and write it to the user's
types/
directory (or wherever their project keeps type declarations). This file is required because
@cloudsignal/mqtt-client
does not ship
.d.ts
files.
阅读
references/cloudsignal.d.ts
并将其写入用户的
types/
目录(或项目存放类型声明的其他位置)。该文件是必需的,因为
@cloudsignal/mqtt-client
未提供
.d.ts
文件。

Step 6: Write the Context Provider

步骤6:编写上下文提供者

Combine the adapted auth hooks, customized message types, and the full provider logic from the reference into the final
mqtt-context.tsx
. Preserve ALL of these production patterns:
  • Stable ref pattern:
    connectRef
    updated every render, used by timers
  • Auth error circuit-breaker:
    authErrorCountRef
    with
    MAX_AUTH_ERRORS = 3
  • Proactive token refresh:
    scheduleTokenRefresh()
    at 50 minutes
  • StrictMode guard:
    connectingRef
    +
    mountedRef
    prevent double connections
  • Exact topic matching:
    topic === \
    ${prefix}/notifications`
    not
    .includes()`
  • Safe JSON parsing: try/catch around
    JSON.parse
    in message handler
  • Client destruction on auth error: Stops SDK's stale-token reconnect loop
  • Tab visibility reconnect:
    visibilitychange
    event listener
将适配后的身份验证钩子、自定义消息类型以及参考实现中的完整提供者逻辑组合成最终的
mqtt-context.tsx
。保留所有以下生产环境模式:
  • 稳定引用模式
    connectRef
    在每次渲染时更新,供定时器使用
  • 认证错误熔断机制:带有
    MAX_AUTH_ERRORS = 3
    authErrorCountRef
  • 主动令牌刷新:在第50分钟执行
    scheduleTokenRefresh()
  • StrictMode防护
    connectingRef
    +
    mountedRef
    防止重复连接
  • 精确主题匹配:使用
    topic === 
    ${prefix}/notifications``而非
    .includes()
  • 安全JSON解析:消息处理程序中
    JSON.parse
    包裹try/catch
  • 认证错误时销毁客户端:停止SDK的过期令牌重连循环
  • 标签页可见性重连
    visibilitychange
    事件监听器

Step 7: Show Usage

步骤7:展示使用示例

Provide a usage example showing:
  1. Provider wrapping in
    app/providers.tsx
    (nested inside the auth provider)
  2. A consumer component using
    useMQTT()
    hook
  3. Environment variable setup (
    .env.local
    )
提供使用示例,包括:
  1. app/providers.tsx
    中包裹提供者(嵌套在身份验证提供者内部)
  2. 使用
    useMQTT()
    钩子的消费者组件
  3. 环境变量设置(
    .env.local

Critical SDK Pitfalls

SDK关键陷阱

Read
references/sdk-pitfalls.md
for the full list. These MUST be handled in generated code:
  1. Token expiry reconnect loop: Destroy client on
    onAuthError
    , don't rely on SDK reconnect
  2. externalToken
    not
    idToken
    : Use
    externalToken
    in
    connectWithToken()
  3. No TypeScript declarations: Always generate
    cloudsignal.d.ts
  4. React StrictMode double-mount: Use
    connectingRef
    +
    mountedRef
    guards
  5. Token service version: SDK v2.x expects
    /v2/tokens/exchange
阅读
references/sdk-pitfalls.md
获取完整列表。生成的代码必须处理以下问题:
  1. 令牌过期重连循环:在
    onAuthError
    时销毁客户端,不要依赖SDK重连
  2. 使用
    externalToken
    而非
    idToken
    :在
    connectWithToken()
    中使用
    externalToken
  3. 无TypeScript声明:始终生成
    cloudsignal.d.ts
  4. React StrictMode双挂载:使用
    connectingRef
    +
    mountedRef
    防护
  5. 令牌服务版本:SDK v2.x期望使用
    /v2/tokens/exchange

Environment Variables

环境变量

Tell the user to add these to
.env.local
:
bash
NEXT_PUBLIC_CLOUDSIGNAL_ORG_ID=org_xxxxxxxxxxxxx    # From CloudSignal dashboard
NEXT_PUBLIC_CLOUDSIGNAL_HOST=wss://connect.cloudsignal.app:18885/  # Optional, this is default
告知用户将以下内容添加到
.env.local
bash
NEXT_PUBLIC_CLOUDSIGNAL_ORG_ID=org_xxxxxxxxxxxxx    # 来自CloudSignal控制台
NEXT_PUBLIC_CLOUDSIGNAL_HOST=wss://connect.cloudsignal.app:18885/  # 可选,此为默认值

CloudSignal Dashboard Setup

CloudSignal控制台设置

Remind the user they need to configure their CloudSignal organization:
  1. Create an organization at https://dashboard.cloudsignal.app
  2. Configure an External Auth Provider integration (select their provider, enter JWKS URL)
  3. Note the
    org_xxx
    ID for the environment variable
提醒用户需要配置他们的CloudSignal组织:
  1. https://dashboard.cloudsignal.app创建组织
  2. 配置外部身份验证提供商集成(选择对应的提供商,输入JWKS URL)
  3. 记录
    org_xxx
    ID用于环境变量

npm Dependency

npm依赖项

The user needs to install the CloudSignal MQTT client:
bash
npm install @cloudsignal/mqtt-client
用户需要安装CloudSignal MQTT客户端:
bash
npm install @cloudsignal/mqtt-client