@nexushub/client 0.8.9 → 1.1.0
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.
- package/README.md +36 -1078
- package/dist/chunk-CBSACQXV.js +116 -0
- package/dist/chunk-Z7UZC7IK.cjs +116 -0
- package/dist/cli.cjs +222 -146
- package/dist/content/local-cache-server.cjs +34 -13
- package/dist/content/local-cache-server.d.cts +2 -5
- package/dist/content/local-cache-server.d.ts +2 -5
- package/dist/content/local-cache-server.js +34 -13
- package/dist/index.cjs +660 -339
- package/dist/index.d.cts +225 -36
- package/dist/index.d.ts +225 -36
- package/dist/index.js +650 -339
- package/dist/{local-cache-server-S5KIABVH.cjs → local-cache-server-AMGC6BOZ.cjs} +16 -8
- package/dist/{local-cache-server-667T23JJ.js → local-cache-server-SD3K7MZG.js} +15 -7
- package/dist/react.cjs +971 -374
- package/dist/react.d.cts +193 -76
- package/dist/react.d.ts +193 -76
- package/dist/react.js +1013 -416
- package/package.json +29 -27
- package/dist/chunk-HUABKET6.js +0 -53
- package/dist/chunk-WZ47UVA2.cjs +0 -53
package/README.md
CHANGED
|
@@ -1,1105 +1,63 @@
|
|
|
1
|
-
#
|
|
1
|
+
# GN-Apex SDK 1.1.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The GN-Apex SDK is the runtime layer for GN-Apex-generated sites. It is deliberately **zero developer configuration**: site developers focus on content, components and UI/UX while GN-Apex owns platform behavior.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://bundlephobia.com/package/@nexushub/client)
|
|
7
|
-
[](https://www.typescriptlang.org/)
|
|
8
|
-
[](https://reactjs.org/)
|
|
9
|
-
[](LICENSE)
|
|
5
|
+
## Zero-config by design
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
```ts
|
|
8
|
+
import { nexus } from "@nexushub/client";
|
|
12
9
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## ✨ Features
|
|
16
|
-
|
|
17
|
-
### 🚀 **Performance First**
|
|
18
|
-
|
|
19
|
-
- **Multi-layer caching**: Memory → LocalStorage → Remote with LRU eviction
|
|
20
|
-
- **Request optimization**: Batching, deduplication, exponential backoff
|
|
21
|
-
- **Smart preloading**: Automatic content prediction and prefetching
|
|
22
|
-
- **< 5ms** cache hits, **< 100ms** cold starts
|
|
23
|
-
|
|
24
|
-
### 📊 **Built-in Analytics Engine**
|
|
25
|
-
|
|
26
|
-
- **Real-time tracking**: Page views, clicks, form submissions
|
|
27
|
-
- **Web Vitals**: Core Web Vitals with RUM (Real User Monitoring)
|
|
28
|
-
- **Session management**: 30-minute sessions with automatic renewal
|
|
29
|
-
- **User identification**: Anonymous → Known user handshake
|
|
30
|
-
- **E-commerce ready**: Track purchases, cart events, conversions
|
|
31
|
-
|
|
32
|
-
### 🔐 **Authentication System**
|
|
33
|
-
|
|
34
|
-
- **Full auth flow**: Register, login, logout, social login (Google)
|
|
35
|
-
- **Protected routes**: React hooks for auth state
|
|
36
|
-
- **Session persistence**: HttpOnly cookies for security
|
|
37
|
-
- **Role-based access**: User roles and permissions
|
|
38
|
-
|
|
39
|
-
### 📁 **Content Engine**
|
|
40
|
-
|
|
41
|
-
- **Type-safe content**: Full TypeScript support with generics
|
|
42
|
-
- **Advanced querying**: Filter, sort, paginate, search, include
|
|
43
|
-
- **Real-time updates**: WebSocket/SSE subscriptions
|
|
44
|
-
- **Collection support**: Dynamic content with rich relationships
|
|
45
|
-
- **Singleton pages**: Static content with smart caching
|
|
46
|
-
|
|
47
|
-
### 🛠 **Developer Experience**
|
|
48
|
-
|
|
49
|
-
- **Zero-config setup**: Auto-detects environment variables
|
|
50
|
-
- **Local development**: Offline mode with local cache
|
|
51
|
-
- **CLI tool**: Pull, seed, deploy, and manage content
|
|
52
|
-
- **Debug mode**: Detailed logs and performance metrics
|
|
53
|
-
- **Hot reload**: Instant updates during development
|
|
54
|
-
|
|
55
|
-
## 🚀 Quick Start
|
|
56
|
-
|
|
57
|
-
### 1. Installation
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npm install @nexushub/client
|
|
61
|
-
# or
|
|
62
|
-
yarn add @nexushub/client
|
|
63
|
-
# or
|
|
64
|
-
pnpm add @nexushub/client
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### 2. Environment Setup
|
|
68
|
-
|
|
69
|
-
Create `.env.local` in your project root:
|
|
70
|
-
|
|
71
|
-
```env
|
|
72
|
-
# Required
|
|
73
|
-
NEXT_PUBLIC_NEXUS_ID=your_project_id_here
|
|
74
|
-
NEXT_PUBLIC_NEXUS_KEY=your_api_key_here
|
|
75
|
-
|
|
76
|
-
# Optional (defaults to https://api.nexushub.com/v1)
|
|
77
|
-
NEXT_PUBLIC_NEXUS_API_URL=https://api.nexushub.com/v1
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 3. Wrap Your App (Next.js/React)
|
|
81
|
-
|
|
82
|
-
```tsx
|
|
83
|
-
// app/layout.tsx (Next.js App Router)
|
|
84
|
-
import { NexusProvider } from '@nexushub/client'
|
|
85
|
-
|
|
86
|
-
export default function RootLayout({
|
|
87
|
-
children,
|
|
88
|
-
}: {
|
|
89
|
-
children: React.ReactNode
|
|
90
|
-
}) {
|
|
91
|
-
return (
|
|
92
|
-
<html lang="en">
|
|
93
|
-
<body>
|
|
94
|
-
<NexusProvider>
|
|
95
|
-
{children}
|
|
96
|
-
</NexusProvider>
|
|
97
|
-
</body>
|
|
98
|
-
</html>
|
|
99
|
-
)
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### 4. Use Content Anywhere
|
|
104
|
-
|
|
105
|
-
```tsx
|
|
106
|
-
// app/page.tsx
|
|
107
|
-
import { nexus } from '@nexushub/client'
|
|
108
|
-
|
|
109
|
-
export default async function HomePage() {
|
|
110
|
-
const homePage = await nexus.getPage('home')
|
|
111
|
-
const blogPosts = await nexus.content.getCollection('blog_posts', {
|
|
112
|
-
page: 1,
|
|
113
|
-
limit: 10,
|
|
114
|
-
sort: 'createdAt',
|
|
115
|
-
order: 'desc',
|
|
116
|
-
filter: { published: true }
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
return (
|
|
120
|
-
<main>
|
|
121
|
-
<h1>{homePage.title}</h1>
|
|
122
|
-
<p>{homePage.content}</p>
|
|
123
|
-
|
|
124
|
-
<h2>Latest Posts</h2>
|
|
125
|
-
<ul>
|
|
126
|
-
{blogPosts.items.map(post => (
|
|
127
|
-
<li key={post.id}>
|
|
128
|
-
<h3>{post.title}</h3>
|
|
129
|
-
<p>{post.excerpt}</p>
|
|
130
|
-
</li>
|
|
131
|
-
))}
|
|
132
|
-
</ul>
|
|
133
|
-
</main>
|
|
134
|
-
)
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## 📖 Documentation
|
|
139
|
-
|
|
140
|
-
### Table of Contents
|
|
141
|
-
|
|
142
|
-
1. [Configuration](#configuration)
|
|
143
|
-
2. [Content Fetching](#content-fetching)
|
|
144
|
-
3. [Authentication](#authentication)
|
|
145
|
-
4. [Analytics](#analytics)
|
|
146
|
-
5. [Caching](#caching)
|
|
147
|
-
6. [CLI Tool](#cli-tool)
|
|
148
|
-
7. [API Reference](#api-reference)
|
|
149
|
-
8. [Examples](#examples)
|
|
150
|
-
9. [Troubleshooting](#troubleshooting)
|
|
151
|
-
|
|
152
|
-
## 🔧 Configuration
|
|
153
|
-
|
|
154
|
-
### Auto Configuration (Recommended)
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
// Uses environment variables automatically
|
|
158
|
-
const client = nexus // Singleton instance
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
### Manual Configuration
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
import { createNexusClient } from '@nexushub/client'
|
|
165
|
-
|
|
166
|
-
const client = createNexusClient({
|
|
167
|
-
projectId: 'your-project-id',
|
|
168
|
-
apiKey: 'your-api-key',
|
|
169
|
-
apiUrl: 'https://api.nexushub.com/v1', // Optional
|
|
170
|
-
debug: true, // Enable debug logging
|
|
171
|
-
cacheStrategy: 'memory', // 'memory' | 'localStorage' | 'none'
|
|
172
|
-
revalidateTime: 60, // Cache revalidation in seconds
|
|
173
|
-
timeout: 10000, // Request timeout in ms
|
|
174
|
-
retries: 3, // Number of retry attempts
|
|
175
|
-
})
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### React Configuration
|
|
179
|
-
|
|
180
|
-
```tsx
|
|
181
|
-
// app/NexusWrapper.tsx
|
|
182
|
-
'use client'
|
|
183
|
-
|
|
184
|
-
import { NexusProvider } from '@nexushub/client'
|
|
185
|
-
|
|
186
|
-
export function NexusWrapper({ children }: { children: React.ReactNode }) {
|
|
187
|
-
return (
|
|
188
|
-
<NexusProvider projectId="optional-override-id">
|
|
189
|
-
{children}
|
|
190
|
-
</NexusProvider>
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## 📁 Content Fetching
|
|
196
|
-
|
|
197
|
-
### Get a Single Page
|
|
198
|
-
|
|
199
|
-
```typescript
|
|
200
|
-
// Basic usage
|
|
201
|
-
const page = await nexus.getPage('home')
|
|
202
|
-
|
|
203
|
-
// With options
|
|
204
|
-
const page = await nexus.getPage('about', {
|
|
205
|
-
revalidate: 300, // Revalidate every 5 minutes
|
|
206
|
-
tags: ['page:about'], // Cache tags for invalidation
|
|
207
|
-
forceRefresh: false, // Bypass cache
|
|
208
|
-
includeMetadata: true, // Include cache metadata
|
|
209
|
-
})
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### Get Collections
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
// Get all items from a collection
|
|
216
|
-
const posts = await nexus.content.getCollection('blog_posts')
|
|
217
|
-
|
|
218
|
-
// Advanced querying
|
|
219
|
-
const products = await nexus.content.getCollection('products', {
|
|
220
|
-
page: 1,
|
|
221
|
-
limit: 20,
|
|
222
|
-
sort: 'price',
|
|
223
|
-
order: 'asc',
|
|
224
|
-
filter: {
|
|
225
|
-
category: 'electronics',
|
|
226
|
-
price: { $lt: 1000 },
|
|
227
|
-
inStock: true
|
|
228
|
-
},
|
|
229
|
-
search: 'wireless headphones',
|
|
230
|
-
fields: ['id', 'name', 'price', 'image'],
|
|
231
|
-
include: ['category', 'reviews'],
|
|
232
|
-
})
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Get a Single Item
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
const product = await nexus.content.getItem('products', 'prod_12345', {
|
|
239
|
-
include: ['category', 'reviews', 'variants'],
|
|
240
|
-
tags: ['product:prod_12345'],
|
|
241
|
-
})
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Search Across Collections
|
|
245
|
-
|
|
246
|
-
```typescript
|
|
247
|
-
const results = await nexus.content.search('wireless', {
|
|
248
|
-
collections: ['products', 'articles'],
|
|
249
|
-
fields: ['title', 'description', 'content'],
|
|
250
|
-
limit: 50,
|
|
251
|
-
})
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### Get Global Settings
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
const globals = await nexus.content.getGlobals({
|
|
258
|
-
include: ['navigation', 'footer', 'social_links'],
|
|
259
|
-
revalidate: 3600, // Cache for 1 hour
|
|
260
|
-
})
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
## 🔐 Authentication
|
|
264
|
-
|
|
265
|
-
### Setup Auth Provider
|
|
266
|
-
|
|
267
|
-
```tsx
|
|
268
|
-
// app/auth/layout.tsx
|
|
269
|
-
'use client'
|
|
270
|
-
|
|
271
|
-
import { useNexusAuth } from '@nexushub/client'
|
|
272
|
-
|
|
273
|
-
export default function AuthLayout({ children }) {
|
|
274
|
-
const { user, isLoading, isAuthenticated } = useNexusAuth()
|
|
275
|
-
|
|
276
|
-
if (isLoading) return <div>Loading...</div>
|
|
277
|
-
|
|
278
|
-
return (
|
|
279
|
-
<div>
|
|
280
|
-
{isAuthenticated ? (
|
|
281
|
-
<div>
|
|
282
|
-
<p>Welcome, {user.name}!</p>
|
|
283
|
-
{children}
|
|
284
|
-
</div>
|
|
285
|
-
) : (
|
|
286
|
-
<LoginForm />
|
|
287
|
-
)}
|
|
288
|
-
</div>
|
|
289
|
-
)
|
|
290
|
-
}
|
|
10
|
+
const page = await nexus.getPage("home");
|
|
291
11
|
```
|
|
292
12
|
|
|
293
|
-
|
|
13
|
+
A GN-Apex deployment can inject runtime configuration through `window.__GNAPEX__` or meta tags. Environment variables remain supported as an escape hatch for Node/CI.
|
|
294
14
|
|
|
295
|
-
|
|
296
|
-
'use client'
|
|
15
|
+
## Automatic runtime behavior
|
|
297
16
|
|
|
298
|
-
|
|
299
|
-
import { useState } from 'react'
|
|
17
|
+
By default the browser runtime automatically handles:
|
|
300
18
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
const handleGoogleLogin = () => {
|
|
316
|
-
loginWithGoogle()
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return (
|
|
320
|
-
<div>
|
|
321
|
-
<input
|
|
322
|
-
type="email"
|
|
323
|
-
value={email}
|
|
324
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
325
|
-
placeholder="Email"
|
|
326
|
-
/>
|
|
327
|
-
<input
|
|
328
|
-
type="password"
|
|
329
|
-
value={password}
|
|
330
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
331
|
-
placeholder="Password"
|
|
332
|
-
/>
|
|
333
|
-
<button onClick={handleLogin}>Login</button>
|
|
334
|
-
<button onClick={handleGoogleLogin}>Login with Google</button>
|
|
335
|
-
</div>
|
|
336
|
-
)
|
|
337
|
-
}
|
|
338
|
-
```
|
|
19
|
+
- page views and SPA navigation
|
|
20
|
+
- clicks, links, buttons, outbound links
|
|
21
|
+
- dead/rage clicks
|
|
22
|
+
- forms without collecting field values
|
|
23
|
+
- video lifecycle + 25/50/75/90/100% milestones
|
|
24
|
+
- scroll depth
|
|
25
|
+
- Web Vitals
|
|
26
|
+
- uncaught errors and unhandled rejections
|
|
27
|
+
- session/visitor identity
|
|
28
|
+
- offline IndexedDB event queue
|
|
29
|
+
- retry, batching, deduplication IDs and circuit breaking
|
|
30
|
+
- authentication synchronization
|
|
31
|
+
- push subscription synchronization (permission prompting remains platform/UX controlled)
|
|
32
|
+
- realtime content updates and cache invalidation
|
|
339
33
|
|
|
340
|
-
|
|
34
|
+
Custom analytics calls are available as an escape hatch, not a requirement.
|
|
341
35
|
|
|
342
|
-
|
|
343
|
-
'use client'
|
|
344
|
-
|
|
345
|
-
import { useNexusAuth } from '@nexushub/client'
|
|
346
|
-
import { useRouter } from 'next/navigation'
|
|
347
|
-
import { useEffect } from 'react'
|
|
348
|
-
|
|
349
|
-
export function useRequireAuth(redirectTo = '/login') {
|
|
350
|
-
const { user, isLoading, isAuthenticated } = useNexusAuth()
|
|
351
|
-
const router = useRouter()
|
|
352
|
-
|
|
353
|
-
useEffect(() => {
|
|
354
|
-
if (!isLoading && !isAuthenticated) {
|
|
355
|
-
router.push(redirectTo)
|
|
356
|
-
}
|
|
357
|
-
}, [isLoading, isAuthenticated, router, redirectTo])
|
|
358
|
-
|
|
359
|
-
return { user, isLoading }
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Usage
|
|
363
|
-
export default function DashboardPage() {
|
|
364
|
-
const { user, isLoading } = useRequireAuth('/login')
|
|
365
|
-
|
|
366
|
-
if (isLoading) return <div>Loading...</div>
|
|
367
|
-
|
|
368
|
-
return (
|
|
369
|
-
<div>
|
|
370
|
-
<h1>Dashboard</h1>
|
|
371
|
-
<p>Welcome, {user.name}!</p>
|
|
372
|
-
</div>
|
|
373
|
-
)
|
|
374
|
-
}
|
|
375
|
-
```
|
|
36
|
+
## Cache model
|
|
376
37
|
|
|
377
|
-
|
|
38
|
+
GN-Apex intentionally defaults content revalidation to `false`. This is **not** a short-lived SDK cache. GN-Apex/Cloudflare owns invalidation and purge. Content can therefore be cached effectively forever until the platform purges affected resources.
|
|
378
39
|
|
|
379
|
-
|
|
40
|
+
The SDK still supports per-call revalidation for exceptional integrations, but production GN-Apex sites should normally leave the platform default untouched.
|
|
380
41
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
- Page views and route changes
|
|
384
|
-
- Click events (links, buttons)
|
|
385
|
-
- Form submissions
|
|
386
|
-
- Web Vitals (CLS, LCP, FID, INP)
|
|
387
|
-
- Performance metrics
|
|
388
|
-
- Error tracking
|
|
389
|
-
|
|
390
|
-
### Manual Event Tracking
|
|
391
|
-
|
|
392
|
-
```typescript
|
|
393
|
-
import { nexus } from '@nexushub/client'
|
|
394
|
-
|
|
395
|
-
// Get analytics instance (automatically initialized)
|
|
396
|
-
const analytics = nexus['analytics'] // Internal access
|
|
397
|
-
|
|
398
|
-
// Or track custom events
|
|
399
|
-
analytics.track('button_clicked', {
|
|
400
|
-
button_id: 'cta-primary',
|
|
401
|
-
page: '/home',
|
|
402
|
-
timestamp: new Date().toISOString()
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
// Track purchases
|
|
406
|
-
analytics.trackPurchase({
|
|
407
|
-
order_id: 'ORD_12345',
|
|
408
|
-
total: 99.99,
|
|
409
|
-
currency: 'USD',
|
|
410
|
-
items: [
|
|
411
|
-
{ id: 'prod_1', name: 'Product 1', price: 49.99, quantity: 2 }
|
|
412
|
-
]
|
|
413
|
-
})
|
|
414
|
-
|
|
415
|
-
// Identify users (link anonymous to known)
|
|
416
|
-
await analytics.identify('user_123', {
|
|
417
|
-
name: 'John Doe',
|
|
418
|
-
email: 'john@example.com',
|
|
419
|
-
plan: 'premium'
|
|
420
|
-
})
|
|
421
|
-
```
|
|
42
|
+
## Reliability
|
|
422
43
|
|
|
423
|
-
|
|
44
|
+
The internal request pipeline provides request IDs, normalized errors, timeout handling, retry/backoff with jitter, rate limiting and circuit breaking. The request coalescer prevents duplicate concurrent reads for the same resource without incorrectly resolving unrelated requests with the same response.
|
|
424
45
|
|
|
425
|
-
|
|
46
|
+
## Platform features
|
|
426
47
|
|
|
427
|
-
|
|
428
|
-
// You can access vitals data through the analytics engine
|
|
429
|
-
const sessionId = analytics.getSessionId()
|
|
430
|
-
console.log('Session:', sessionId)
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
### Disable Analytics
|
|
434
|
-
|
|
435
|
-
```tsx
|
|
436
|
-
// If you need to disable analytics (GDPR compliance)
|
|
437
|
-
<NexusProvider disableAnalytics>
|
|
438
|
-
{children}
|
|
439
|
-
</NexusProvider>
|
|
440
|
-
```
|
|
441
|
-
|
|
442
|
-
## 💾 Caching System
|
|
443
|
-
|
|
444
|
-
### Cache Strategies
|
|
445
|
-
|
|
446
|
-
```typescript
|
|
447
|
-
// 1. Memory Cache (Default - Fastest)
|
|
448
|
-
const client = createNexusClient({
|
|
449
|
-
cacheStrategy: 'memory', // In-memory cache, cleared on page refresh
|
|
450
|
-
revalidateTime: 60 // Seconds
|
|
451
|
-
})
|
|
452
|
-
|
|
453
|
-
// 2. LocalStorage Cache (Persistent)
|
|
454
|
-
const client = createNexusClient({
|
|
455
|
-
cacheStrategy: 'localStorage', // Persists across sessions
|
|
456
|
-
revalidateTime: 300 // 5 minutes
|
|
457
|
-
})
|
|
458
|
-
|
|
459
|
-
// 3. No Cache (Always Fresh)
|
|
460
|
-
const client = createNexusClient({
|
|
461
|
-
cacheStrategy: 'none' // Always fetch from network
|
|
462
|
-
})
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Cache Invalidation
|
|
466
|
-
|
|
467
|
-
```typescript
|
|
468
|
-
// Invalidate by tags
|
|
469
|
-
nexus.content.invalidateCache(['page:home', 'collection:blog_posts'])
|
|
470
|
-
|
|
471
|
-
// Clear all cache
|
|
472
|
-
nexus.content.clearCache()
|
|
473
|
-
|
|
474
|
-
// Manual cache control
|
|
475
|
-
const page = await nexus.getPage('home', {
|
|
476
|
-
forceRefresh: true, // Skip cache
|
|
477
|
-
revalidate: 0 // No revalidation
|
|
478
|
-
})
|
|
479
|
-
|
|
480
|
-
// Get cache statistics
|
|
481
|
-
const stats = nexus.content.getCacheStats()
|
|
482
|
-
console.log(stats)
|
|
483
|
-
/*
|
|
484
|
-
{
|
|
485
|
-
memory: {
|
|
486
|
-
size: 15,
|
|
487
|
-
hits: 124,
|
|
488
|
-
misses: 12,
|
|
489
|
-
hitRate: 0.91,
|
|
490
|
-
evictions: 3
|
|
491
|
-
},
|
|
492
|
-
browser: { size: 24567 },
|
|
493
|
-
local: { loaded: true }
|
|
494
|
-
}
|
|
495
|
-
*/
|
|
496
|
-
```
|
|
48
|
+
The runtime exposes feature flags, remote configuration, diagnostics and a typed event bus for internal/platform integrations.
|
|
497
49
|
|
|
498
|
-
|
|
50
|
+
## Security
|
|
499
51
|
|
|
500
|
-
|
|
52
|
+
Never expose a privileged server secret in browser configuration. Browser deployments should use the public GN-Apex credential model enforced by the platform. Analytics payloads redact common credential/secret fields when privacy redaction is enabled.
|
|
501
53
|
|
|
502
|
-
|
|
503
|
-
// Content gets tagged automatically:
|
|
504
|
-
// - `nexus_project_${projectId}`
|
|
505
|
-
// - `content_${slug}`
|
|
506
|
-
// - `collection_${collectionId}`
|
|
507
|
-
// - `item_${itemId}`
|
|
508
|
-
// - `nexus_global_config`
|
|
509
|
-
|
|
510
|
-
// You can add custom tags:
|
|
511
|
-
const page = await nexus.getPage('home', {
|
|
512
|
-
tags: ['homepage', 'featured']
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
// Later, invalidate all homepage content:
|
|
516
|
-
nexus.content.invalidateCache(['homepage'])
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
## 🛠️ CLI Tool
|
|
520
|
-
|
|
521
|
-
### Installation
|
|
522
|
-
|
|
523
|
-
```bash
|
|
524
|
-
# If installed globally
|
|
525
|
-
npm install -g @nexushub/client
|
|
526
|
-
|
|
527
|
-
# Or use npx
|
|
528
|
-
npx @nexushub/client <command>
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
### Available Commands
|
|
532
|
-
|
|
533
|
-
```bash
|
|
534
|
-
# Initialize project structure
|
|
535
|
-
npx nexus init
|
|
536
|
-
|
|
537
|
-
# Pull content from NexusHub to local cache
|
|
538
|
-
npx nexus pull --api-key YOUR_KEY --project-id YOUR_ID
|
|
539
|
-
|
|
540
|
-
# Seed content from local files to NexusHub
|
|
541
|
-
npx nexus seed --input .nexus/seed
|
|
542
|
-
|
|
543
|
-
# Trigger deployment
|
|
544
|
-
npx nexus deploy --environment production
|
|
545
|
-
|
|
546
|
-
# Check project status
|
|
547
|
-
npx nexus status
|
|
548
|
-
|
|
549
|
-
# Force overwrite local cache
|
|
550
|
-
npx nexus pull --force
|
|
551
|
-
```
|
|
552
|
-
|
|
553
|
-
### Project Structure
|
|
554
|
-
|
|
555
|
-
```
|
|
556
|
-
.nexus/
|
|
557
|
-
├── cache.json # Local cache (gitignored)
|
|
558
|
-
├── seed/ # Seed data for content
|
|
559
|
-
│ ├── pages.json # Static pages
|
|
560
|
-
│ ├── collections/ # Dynamic collections
|
|
561
|
-
│ │ ├── blog_posts.json
|
|
562
|
-
│ │ └── products.json
|
|
563
|
-
│ └── globals.json # Global settings
|
|
564
|
-
└── README.md
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
### Environment Variables for CLI
|
|
568
|
-
|
|
569
|
-
```bash
|
|
570
|
-
# .env.local (for CLI)
|
|
571
|
-
NEXUS_API_KEY=your_api_key_here
|
|
572
|
-
NEXUS_PROJECT_ID=your_project_id_here
|
|
573
|
-
NEXUS_API_URL=https://api.nexushub.com/v1
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
## 📚 API Reference
|
|
577
|
-
|
|
578
|
-
### `NexusClient`
|
|
579
|
-
|
|
580
|
-
#### Constructor
|
|
581
|
-
|
|
582
|
-
```typescript
|
|
583
|
-
new NexusClient(config?: Partial<NexusConfig>)
|
|
584
|
-
```
|
|
585
|
-
|
|
586
|
-
#### Methods
|
|
587
|
-
|
|
588
|
-
- `getPage<T>(slug: string, options?)`: Get singleton page
|
|
589
|
-
- `getConfig()`: Get current config
|
|
590
|
-
- `content`: ContentEngine instance
|
|
591
|
-
- `analytics`: AnalyticsEngine instance (internal)
|
|
592
|
-
|
|
593
|
-
### `ContentEngine`
|
|
594
|
-
|
|
595
|
-
#### Core Methods
|
|
596
|
-
|
|
597
|
-
```typescript
|
|
598
|
-
// Content fetching
|
|
599
|
-
getPage<T>(slug: string, options?): Promise<T>
|
|
600
|
-
getCollection<T>(collectionId: string, query?, options?): Promise<CollectionResponse<T>>
|
|
601
|
-
getItem<T>(collectionId: string, itemId: string, options?): Promise<T>
|
|
602
|
-
getGlobals<T>(options?): Promise<T>
|
|
603
|
-
|
|
604
|
-
// Search
|
|
605
|
-
search<T>(query: string, options?): Promise<{ results: T[], total: number }>
|
|
606
|
-
|
|
607
|
-
// Cache management
|
|
608
|
-
invalidateCache(tags: string[]): void
|
|
609
|
-
clearCache(): void
|
|
610
|
-
getCacheStats(): CacheStats
|
|
611
|
-
|
|
612
|
-
// Real-time
|
|
613
|
-
subscribeToUpdates(callback): () => void
|
|
614
|
-
prefetch(urls: string[]): Promise<void>
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
### `useNexusAuth()` Hook
|
|
618
|
-
|
|
619
|
-
#### Returns
|
|
620
|
-
|
|
621
|
-
```typescript
|
|
622
|
-
{
|
|
623
|
-
user: SiteUser | null,
|
|
624
|
-
isLoading: boolean,
|
|
625
|
-
error: Error | null,
|
|
626
|
-
isAuthenticated: boolean,
|
|
627
|
-
|
|
628
|
-
// Methods
|
|
629
|
-
login: (credentials: LoginCredentials) => Promise<void>,
|
|
630
|
-
register: (credentials: RegisterCredentials) => Promise<void>,
|
|
631
|
-
logout: () => Promise<void>,
|
|
632
|
-
loginWithGoogle: () => void,
|
|
633
|
-
updateProfile: (data: Partial<SiteUser>) => Promise<void>
|
|
634
|
-
}
|
|
635
|
-
```
|
|
636
|
-
|
|
637
|
-
### Types
|
|
638
|
-
|
|
639
|
-
```typescript
|
|
640
|
-
interface NexusConfig {
|
|
641
|
-
projectId: string;
|
|
642
|
-
apiUrl: string;
|
|
643
|
-
apiKey?: string;
|
|
644
|
-
debug?: boolean;
|
|
645
|
-
cacheStrategy?: 'memory' | 'localStorage' | 'none';
|
|
646
|
-
revalidateTime?: number;
|
|
647
|
-
timeout?: number;
|
|
648
|
-
retries?: number;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
interface ContentResponse<T = any> {
|
|
652
|
-
id: string;
|
|
653
|
-
type: string;
|
|
654
|
-
data: T;
|
|
655
|
-
meta: {
|
|
656
|
-
version: number;
|
|
657
|
-
updatedAt: string;
|
|
658
|
-
locale?: string;
|
|
659
|
-
cacheStatus: 'hit' | 'miss' | 'stale';
|
|
660
|
-
};
|
|
661
|
-
}
|
|
662
|
-
|
|
663
|
-
interface CollectionResponse<T = any> {
|
|
664
|
-
items: T[];
|
|
665
|
-
total: number;
|
|
666
|
-
page: number;
|
|
667
|
-
limit: number;
|
|
668
|
-
totalPages: number;
|
|
669
|
-
hasNext: boolean;
|
|
670
|
-
hasPrev: boolean;
|
|
671
|
-
meta?: {
|
|
672
|
-
fetchedAt: string;
|
|
673
|
-
cacheStatus: string;
|
|
674
|
-
filters?: Record<string, any>;
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
## 🚦 Examples
|
|
680
|
-
|
|
681
|
-
### Next.js App Router
|
|
682
|
-
|
|
683
|
-
```tsx
|
|
684
|
-
// app/layout.tsx
|
|
685
|
-
import { NexusProvider } from '@nexushub/client'
|
|
686
|
-
|
|
687
|
-
export default function RootLayout({ children }) {
|
|
688
|
-
return (
|
|
689
|
-
<html lang="en">
|
|
690
|
-
<body>
|
|
691
|
-
<NexusProvider>
|
|
692
|
-
{children}
|
|
693
|
-
</NexusProvider>
|
|
694
|
-
</body>
|
|
695
|
-
</html>
|
|
696
|
-
)
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
// app/blog/page.tsx
|
|
700
|
-
import { nexus } from '@nexushub/client'
|
|
701
|
-
|
|
702
|
-
export default async function BlogPage() {
|
|
703
|
-
const posts = await nexus.content.getCollection('blog_posts', {
|
|
704
|
-
page: 1,
|
|
705
|
-
limit: 10,
|
|
706
|
-
sort: 'publishedAt',
|
|
707
|
-
order: 'desc',
|
|
708
|
-
filter: { status: 'published' }
|
|
709
|
-
})
|
|
710
|
-
|
|
711
|
-
return (
|
|
712
|
-
<div>
|
|
713
|
-
<h1>Blog</h1>
|
|
714
|
-
{posts.items.map(post => (
|
|
715
|
-
<article key={post.id}>
|
|
716
|
-
<h2>{post.title}</h2>
|
|
717
|
-
<p>{post.excerpt}</p>
|
|
718
|
-
</article>
|
|
719
|
-
))}
|
|
720
|
-
</div>
|
|
721
|
-
)
|
|
722
|
-
}
|
|
723
|
-
```
|
|
724
|
-
|
|
725
|
-
### Next.js Pages Router
|
|
726
|
-
|
|
727
|
-
```tsx
|
|
728
|
-
// pages/_app.tsx
|
|
729
|
-
import { NexusProvider } from '@nexushub/client'
|
|
730
|
-
|
|
731
|
-
function MyApp({ Component, pageProps }) {
|
|
732
|
-
return (
|
|
733
|
-
<NexusProvider>
|
|
734
|
-
<Component {...pageProps} />
|
|
735
|
-
</NexusProvider>
|
|
736
|
-
)
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// pages/index.tsx
|
|
740
|
-
import { nexus } from '@nexushub/client'
|
|
741
|
-
|
|
742
|
-
export async function getServerSideProps() {
|
|
743
|
-
const page = await nexus.getPage('home')
|
|
744
|
-
return { props: { page } }
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
export default function Home({ page }) {
|
|
748
|
-
return (
|
|
749
|
-
<div>
|
|
750
|
-
<h1>{page.title}</h1>
|
|
751
|
-
<div dangerouslySetInnerHTML={{ __html: page.content }} />
|
|
752
|
-
</div>
|
|
753
|
-
)
|
|
754
|
-
}
|
|
755
|
-
```
|
|
756
|
-
|
|
757
|
-
### React (No Framework)
|
|
758
|
-
|
|
759
|
-
```tsx
|
|
760
|
-
// index.tsx
|
|
761
|
-
import React from 'react'
|
|
762
|
-
import ReactDOM from 'react-dom/client'
|
|
763
|
-
import { NexusProvider } from '@nexushub/client'
|
|
764
|
-
import App from './App'
|
|
765
|
-
|
|
766
|
-
const root = ReactDOM.createRoot(document.getElementById('root'))
|
|
767
|
-
root.render(
|
|
768
|
-
<React.StrictMode>
|
|
769
|
-
<NexusProvider projectId="your-project-id">
|
|
770
|
-
<App />
|
|
771
|
-
</NexusProvider>
|
|
772
|
-
</React.StrictMode>
|
|
773
|
-
)
|
|
774
|
-
|
|
775
|
-
// App.tsx
|
|
776
|
-
import { nexus, useNexusAuth } from '@nexushub/client'
|
|
777
|
-
import { useEffect, useState } from 'react'
|
|
778
|
-
|
|
779
|
-
function App() {
|
|
780
|
-
const [page, setPage] = useState(null)
|
|
781
|
-
const { user, login } = useNexusAuth()
|
|
782
|
-
|
|
783
|
-
useEffect(() => {
|
|
784
|
-
nexus.getPage('home').then(setPage)
|
|
785
|
-
}, [])
|
|
786
|
-
|
|
787
|
-
if (!page) return <div>Loading...</div>
|
|
788
|
-
|
|
789
|
-
return (
|
|
790
|
-
<div>
|
|
791
|
-
<h1>{page.title}</h1>
|
|
792
|
-
<p>{page.content}</p>
|
|
793
|
-
</div>
|
|
794
|
-
)
|
|
795
|
-
}
|
|
796
|
-
```
|
|
797
|
-
|
|
798
|
-
### E-commerce Example
|
|
799
|
-
|
|
800
|
-
```tsx
|
|
801
|
-
// components/ProductList.tsx
|
|
802
|
-
import { nexus } from '@nexushub/client'
|
|
803
|
-
|
|
804
|
-
export async function ProductList({ category }) {
|
|
805
|
-
const products = await nexus.content.getCollection('products', {
|
|
806
|
-
filter: { category },
|
|
807
|
-
sort: 'createdAt',
|
|
808
|
-
order: 'desc',
|
|
809
|
-
include: ['variants', 'reviews']
|
|
810
|
-
})
|
|
811
|
-
|
|
812
|
-
const handlePurchase = (product) => {
|
|
813
|
-
// Track purchase in analytics
|
|
814
|
-
nexus['analytics'].trackPurchase({
|
|
815
|
-
order_id: `temp_${Date.now()}`,
|
|
816
|
-
total: product.price,
|
|
817
|
-
currency: 'USD',
|
|
818
|
-
items: [{
|
|
819
|
-
id: product.id,
|
|
820
|
-
name: product.name,
|
|
821
|
-
price: product.price,
|
|
822
|
-
quantity: 1
|
|
823
|
-
}]
|
|
824
|
-
})
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
return (
|
|
828
|
-
<div className="grid grid-cols-4 gap-4">
|
|
829
|
-
{products.items.map(product => (
|
|
830
|
-
<div key={product.id} className="border p-4">
|
|
831
|
-
<img src={product.image} alt={product.name} />
|
|
832
|
-
<h3>{product.name}</h3>
|
|
833
|
-
<p>${product.price}</p>
|
|
834
|
-
<button
|
|
835
|
-
onClick={() => handlePurchase(product)}
|
|
836
|
-
className="bg-blue-500 text-white px-4 py-2"
|
|
837
|
-
>
|
|
838
|
-
Add to Cart
|
|
839
|
-
</button>
|
|
840
|
-
</div>
|
|
841
|
-
))}
|
|
842
|
-
</div>
|
|
843
|
-
)
|
|
844
|
-
}
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
## 🐛 Troubleshooting
|
|
848
|
-
|
|
849
|
-
### Common Issues
|
|
850
|
-
|
|
851
|
-
#### 1. "Missing projectId" Error
|
|
852
|
-
|
|
853
|
-
```bash
|
|
854
|
-
# Check your environment variables
|
|
855
|
-
echo $NEXT_PUBLIC_NEXUS_ID
|
|
856
|
-
|
|
857
|
-
# Ensure .env.local exists
|
|
858
|
-
ls -la .env.local
|
|
859
|
-
|
|
860
|
-
# Restart dev server after changing env vars
|
|
861
|
-
npm run dev
|
|
862
|
-
```
|
|
863
|
-
|
|
864
|
-
#### 2. Cache Not Updating
|
|
865
|
-
|
|
866
|
-
```typescript
|
|
867
|
-
// Force refresh
|
|
868
|
-
await nexus.getPage('home', { forceRefresh: true })
|
|
869
|
-
|
|
870
|
-
// Clear all cache
|
|
871
|
-
nexus.content.clearCache()
|
|
872
|
-
|
|
873
|
-
// Check cache stats
|
|
874
|
-
console.log(nexus.content.getCacheStats())
|
|
875
|
-
```
|
|
876
|
-
|
|
877
|
-
#### 3. Analytics Not Tracking
|
|
878
|
-
|
|
879
|
-
```typescript
|
|
880
|
-
// Check if analytics is enabled
|
|
881
|
-
const client = createNexusClient({ debug: true })
|
|
882
|
-
|
|
883
|
-
// Verify in console logs
|
|
884
|
-
// Should see: "[NexusHub] Analytics started"
|
|
885
|
-
```
|
|
886
|
-
|
|
887
|
-
#### 4. Authentication Issues
|
|
888
|
-
|
|
889
|
-
```typescript
|
|
890
|
-
// Check CORS settings in NexusHub dashboard
|
|
891
|
-
// Ensure your domain is whitelisted
|
|
892
|
-
|
|
893
|
-
// Verify HttpOnly cookies are supported
|
|
894
|
-
// Some ad blockers may interfere
|
|
895
|
-
```
|
|
896
|
-
|
|
897
|
-
#### 5. TypeScript Errors
|
|
898
|
-
|
|
899
|
-
```typescript
|
|
900
|
-
// If you get "Property 'content' does not exist"
|
|
901
|
-
// Make sure you're using the correct import:
|
|
902
|
-
import { nexus } from '@nexushub/client' // Correct
|
|
903
|
-
import nexus from '@nexushub/client' // Wrong
|
|
904
|
-
```
|
|
905
|
-
|
|
906
|
-
### Debug Mode
|
|
907
|
-
|
|
908
|
-
Enable debug logging to see detailed information:
|
|
909
|
-
|
|
910
|
-
```typescript
|
|
911
|
-
const client = createNexusClient({
|
|
912
|
-
debug: true,
|
|
913
|
-
cacheStrategy: 'memory'
|
|
914
|
-
})
|
|
915
|
-
|
|
916
|
-
// Check console for:
|
|
917
|
-
// - Cache hits/misses
|
|
918
|
-
// - Network requests
|
|
919
|
-
// - Performance metrics
|
|
920
|
-
// - Analytics events
|
|
921
|
-
```
|
|
922
|
-
|
|
923
|
-
### Performance Monitoring
|
|
924
|
-
|
|
925
|
-
```typescript
|
|
926
|
-
// Get performance metrics
|
|
927
|
-
const stats = nexus.content.getCacheStats()
|
|
928
|
-
console.log('Cache Hit Rate:', stats.memory.hitRate)
|
|
929
|
-
|
|
930
|
-
// Monitor Web Vitals in analytics dashboard
|
|
931
|
-
// Visit: https://dashboard.nexushub.com/analytics
|
|
932
|
-
```
|
|
933
|
-
|
|
934
|
-
## 🔧 Advanced Configuration
|
|
935
|
-
|
|
936
|
-
### Custom Cache Implementation
|
|
937
|
-
|
|
938
|
-
```typescript
|
|
939
|
-
import { MemoryCache, BrowserCache } from '@nexushub/client'
|
|
940
|
-
|
|
941
|
-
// Extend existing cache
|
|
942
|
-
class CustomMemoryCache extends MemoryCache {
|
|
943
|
-
constructor(options) {
|
|
944
|
-
super({ ...options, maxSize: 2000 })
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
set(key, data, options) {
|
|
948
|
-
// Add custom logic
|
|
949
|
-
console.log(`Caching: ${key}`)
|
|
950
|
-
super.set(key, data, options)
|
|
951
|
-
}
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
// Use in your app
|
|
955
|
-
const customCache = new CustomMemoryCache({ ttl: 60000 })
|
|
956
|
-
```
|
|
957
|
-
|
|
958
|
-
### Middleware & Interceptors
|
|
959
|
-
|
|
960
|
-
```typescript
|
|
961
|
-
// Request/Response interceptors
|
|
962
|
-
const client = createNexusClient({
|
|
963
|
-
interceptors: {
|
|
964
|
-
request: (config) => {
|
|
965
|
-
// Add custom headers
|
|
966
|
-
config.headers['X-Custom-Header'] = 'value'
|
|
967
|
-
return config
|
|
968
|
-
},
|
|
969
|
-
response: (response) => {
|
|
970
|
-
// Transform response
|
|
971
|
-
return response.data
|
|
972
|
-
},
|
|
973
|
-
error: (error) => {
|
|
974
|
-
// Custom error handling
|
|
975
|
-
console.error('Request failed:', error)
|
|
976
|
-
throw error
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
})
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### Multiple Projects
|
|
983
|
-
|
|
984
|
-
```typescript
|
|
985
|
-
import { createNexusClient } from '@nexushub/client'
|
|
986
|
-
|
|
987
|
-
const mainClient = createNexusClient({
|
|
988
|
-
projectId: 'main-project',
|
|
989
|
-
apiKey: 'main-key'
|
|
990
|
-
})
|
|
991
|
-
|
|
992
|
-
const secondaryClient = createNexusClient({
|
|
993
|
-
projectId: 'secondary-project',
|
|
994
|
-
apiKey: 'secondary-key',
|
|
995
|
-
apiUrl: 'https://api-2.nexushub.com/v1'
|
|
996
|
-
})
|
|
997
|
-
|
|
998
|
-
// Use both clients in your app
|
|
999
|
-
const [mainPage, secondaryPage] = await Promise.all([
|
|
1000
|
-
mainClient.getPage('home'),
|
|
1001
|
-
secondaryClient.getPage('home')
|
|
1002
|
-
])
|
|
1003
|
-
```
|
|
1004
|
-
|
|
1005
|
-
## 📈 Performance Benchmarks
|
|
1006
|
-
|
|
1007
|
-
```
|
|
1008
|
-
Cache Performance:
|
|
1009
|
-
├── Memory Cache: 0.1ms - 1ms
|
|
1010
|
-
├── LocalStorage: 1ms - 5ms
|
|
1011
|
-
└── Network: 50ms - 300ms
|
|
1012
|
-
|
|
1013
|
-
Bundle Size:
|
|
1014
|
-
├── Core SDK: 15kb gzipped
|
|
1015
|
-
├── With Analytics: 28kb gzipped
|
|
1016
|
-
└── Full Package: 35kb gzipped
|
|
1017
|
-
|
|
1018
|
-
Memory Usage:
|
|
1019
|
-
├── Memory Cache: ~5MB max
|
|
1020
|
-
├── LocalStorage: ~5MB max
|
|
1021
|
-
└── Browser Memory: ~10MB typical
|
|
1022
|
-
```
|
|
1023
|
-
|
|
1024
|
-
## 🤝 Contributing
|
|
1025
|
-
|
|
1026
|
-
We welcome contributions! Here's how to get started:
|
|
1027
|
-
|
|
1028
|
-
1. **Fork the repository**
|
|
1029
|
-
2. **Clone your fork**
|
|
1030
|
-
|
|
1031
|
-
```bash
|
|
1032
|
-
git clone https://github.com/your-username/nexushub-client-sdk.git
|
|
1033
|
-
cd nexushub-client-sdk/packages/client-sdk
|
|
1034
|
-
```
|
|
1035
|
-
|
|
1036
|
-
1. **Install dependencies**
|
|
54
|
+
## Build
|
|
1037
55
|
|
|
1038
56
|
```bash
|
|
1039
57
|
npm install
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
1. **Run tests**
|
|
1043
|
-
|
|
1044
|
-
```bash
|
|
58
|
+
npm run type-check
|
|
1045
59
|
npm test
|
|
1046
|
-
npm run test:coverage
|
|
1047
|
-
```
|
|
1048
|
-
|
|
1049
|
-
1. **Make changes and test**
|
|
1050
|
-
|
|
1051
|
-
```bash
|
|
1052
|
-
npm run dev # Watch mode
|
|
1053
|
-
npm run build
|
|
1054
|
-
```
|
|
1055
|
-
|
|
1056
|
-
1. **Submit a Pull Request**
|
|
1057
|
-
|
|
1058
|
-
### Development Scripts
|
|
1059
|
-
|
|
1060
|
-
```bash
|
|
1061
|
-
# Build
|
|
1062
60
|
npm run build
|
|
1063
|
-
|
|
1064
|
-
# Development (watch mode)
|
|
1065
|
-
npm run dev
|
|
1066
|
-
|
|
1067
|
-
# Type checking
|
|
1068
|
-
npm run type-check
|
|
1069
|
-
|
|
1070
|
-
# Linting
|
|
1071
|
-
npm run lint
|
|
1072
|
-
|
|
1073
|
-
# Testing
|
|
1074
|
-
npm test # Run all tests
|
|
1075
|
-
npm run test:watch # Watch mode
|
|
1076
|
-
npm run test:coverage # Coverage report
|
|
1077
|
-
npm run test:debug # Verbose output
|
|
1078
61
|
```
|
|
1079
62
|
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
MIT License - see [LICENSE](LICENSE) file for details.
|
|
1083
|
-
|
|
1084
|
-
## 🔗 Links
|
|
1085
|
-
|
|
1086
|
-
- [NexusHub Dashboard](https://dashboard.nexushub.com)
|
|
1087
|
-
- [Documentation](https://docs.nexushub.com)
|
|
1088
|
-
- [API Reference](https://docs.nexushub.com/api)
|
|
1089
|
-
- [GitHub Issues](https://github.com/nexushub/client-sdk/issues)
|
|
1090
|
-
- [Discord Community](https://discord.gg/nexushub)
|
|
1091
|
-
|
|
1092
|
-
## 🏆 Support
|
|
1093
|
-
|
|
1094
|
-
- **Community Support**: [GitHub Discussions](https://github.com/nexushub/client-sdk/discussions)
|
|
1095
|
-
- **Priority Support**: Available for enterprise plans
|
|
1096
|
-
- **Bug Reports**: [GitHub Issues](https://github.com/nexushub/client-sdk/issues)
|
|
1097
|
-
- **Feature Requests**: Submit via GitHub Issues
|
|
1098
|
-
|
|
1099
|
-
---
|
|
1100
|
-
|
|
1101
|
-
<div align="center">
|
|
1102
|
-
Made with ❤️ by the NexusHub Team
|
|
1103
|
-
<br/>
|
|
1104
|
-
<a href="https://nexushub.com">nexushub.com</a>
|
|
1105
|
-
</div>
|
|
63
|
+
Before publishing, run the complete test/build pipeline in the target CI environment.
|