@zhmdff/uc-client
v1.0.8
Published
Fail-open client for zhmdffUC control-plane
Readme
@zhmdff/uc-client
A fail-open TypeScript/JavaScript SDK for the zhmdffUC control-plane. Provides Next.js Middleware, a React provider + hook, server-side log transport, and a core polling client — all with zero impact on your app if the control-plane is offline.
Features
- Next.js Middleware: intercepts routes on
Paused/Disabledstatus and returns a maintenance response - React Provider + Hook: exposes
status,metadata,updateMetadata, andprofilein React context - Disabled Overlay: built-in full-screen UI block when project status is
Disabled - Auto-Fetch Logging: automatically intercepts
fetchcalls to log slow requests (>2s) or network errors - Log Transport: ships
console.*output server-side to/api/logs/ingestrespecting per-project enabled levels - Core Client: singleton polling client with in-memory cache and fail-open guarantee
- Metadata Sync: read and write project-specific private metadata directly from the SDK
- SDK Registration: one-time startup ping to annotate the instance in the control-plane dashboard
Package Structure
src/
index.ts — Public exports
types.ts — ProjectStatus, LogLevel, profile/status types
client.ts — MasterControlClient (singleton, polling, cache)
middleware.ts — createMasterControlMiddleware() for Next.js
withMasterControl.ts — next.config.js wrapper
react/
MasterControlProvider.tsx
useMasterControl.ts
logging/
LogBuffer.ts — In-memory queue (server only)
LogTransport.ts — setInterval flush to /api/logs/ingest
levels.ts — Level filtering helpers
patch.ts — initMasterControlLogging() console patcherInstallation
npm install @zhmdff/uc-clientEnvironment Variables
MASTER_CONTROL_BASE_URL=https://uc.zhmdff.dev
MASTER_CONTROL_PROJECT_ID=your-project-guid
MASTER_CONTROL_API_KEY=your-project-api-key
MASTER_CONTROL_POLL_INTERVAL=30000
MASTER_CONTROL_LOG_FLUSH_INTERVAL=45000Usage
Next.js Middleware (full-page block)
Create middleware.ts at the project root:
import { createMasterControlMiddleware } from '@zhmdff/uc-client/middleware';
export const middleware = createMasterControlMiddleware({
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
});When Paused or Disabled, matched routes return the project's StatusCode with a maintenance response. Active (or fail-open) passes through.
next.config.js Wrapper
import { withMasterControl } from '@zhmdff/uc-client';
export default withMasterControl({ /* your config */ });React Provider + Hook
// app/layout.tsx
import { MasterControlProvider, ZhmdffUcClient } from '@zhmdff/uc-client';
const client = new ZhmdffUcClient({
baseUrl: process.env.NEXT_PUBLIC_MASTER_CONTROL_BASE_URL,
projectId: process.env.NEXT_PUBLIC_MASTER_CONTROL_PROJECT_ID,
apiKey: process.env.MASTER_CONTROL_API_KEY,
autoLogFetch: true // Enable automatic fetch error/slow-log tracking
});
export default function Layout({ children }) {
return (
<MasterControlProvider client={client}>
{children}
</MasterControlProvider>
);
}
// Any component
import { useMasterControl } from '@zhmdff/uc-client';
const { status, metadata, updateMetadata, isLoading } = useMasterControl();
// Use metadata for feature flags
const isNewFeatureEnabled = metadata['enable_beta'] === 'true';
// Update private project metadata
await updateMetadata('last_login', new Date().toISOString());status is one of 'Active' | 'Paused' | 'Disabled'. The provider handles the Disabled Overlay automatically.
Log Transport
Opt-in, server-side only (Node.js runtime):
// instrumentation.ts
import { initMasterControlLogging } from '@zhmdff/uc-client';
export async function register() {
initMasterControlLogging(); // patches console.error/warn/log/debug
}Only log levels enabled in the project's LogLevelConfiguration on the control-plane are enqueued. The LogBuffer (max 1,000 entries, drop-oldest) flushes via setInterval.
Core Client (manual)
import { MasterControlClient } from '@zhmdff/uc-client';
const client = new MasterControlClient({
baseUrl: process.env.MASTER_CONTROL_BASE_URL!,
projectId: process.env.MASTER_CONTROL_PROJECT_ID!,
apiKey: process.env.MASTER_CONTROL_API_KEY,
});
await client.start(); // starts background polling
const state = client.getCurrentState();
// state.status: 'Active' | 'Paused' | 'Disabled'
// state.statusCode: number
// state.statusMessage: string | null
// state.scheduledResumeAt: string | null
// state.enabledLogLevels: string[]Status Model
type ProjectStatus = 'Active' | 'Paused' | 'Disabled';| Status | Client Behavior |
| :--- | :--- |
| Active | Pass through |
| Paused | Return statusCode + statusMessage (middleware) or surface via hook |
| Disabled | Same as Paused |
Resilience Guarantees
| Scenario | Behavior |
| :--- | :--- |
| Backend offline | Last cached status served; requests pass through (fail-open) |
| Poll failure | Error swallowed silently; cache unchanged |
| First boot, unreachable | Status treated as Active until first successful poll |
| Log flush failure | Buffer retained; retry on next flush interval |
| Log buffer overflow | Oldest entries dropped (max 1,000) |
Build & Type-check
cd Packages/npm
npm run build # compile TypeScript
npx tsc --noEmit # type-check onlyPart of the zhmdffUC ecosystem. See usage.md for full integration guide.
