nexus-platform-sdk 0.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 ADDED
@@ -0,0 +1,329 @@
1
+ # Nexus Platform SDK
2
+
3
+ The Nexus Platform SDK provides a JavaScript/TypeScript interface for building apps on the Nexus Platform. When Nexus generates your app via Code Studio, the generated code uses this SDK to authenticate users, manage your app's data, and execute serverless functions. You can use the same SDK to modify and extend your app.
4
+
5
+ ## Modules
6
+
7
+ The SDK provides access to Nexus Platform's functionality through the following modules:
8
+
9
+ - **`auth`**: Manage user authentication, registration, and session handling.
10
+ - **`entities`**: Work with your app's data entities using CRUD operations.
11
+ - **`functions`**: Execute serverless backend functions.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install nexus-platform-sdk
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { createClient } from 'nexus-platform-sdk';
23
+
24
+ const nexus = createClient({
25
+ appId: 'your-app-id',
26
+ tenantId: 'your-tenant-id',
27
+ dataSourceId: 'your-datasource-id',
28
+ apiUrl: 'https://api.nexus.io',
29
+ });
30
+ ```
31
+
32
+ ## Example
33
+
34
+ Here's a quick look at working with data in the SDK, using the `entities` module to create, update, and list records. In this example, we're working with a custom `Task` entity:
35
+
36
+ ```typescript
37
+ import { nexus } from '@/api/nexusClient';
38
+
39
+ // Create a new task
40
+ const newTask = await nexus.entities.Task.create({
41
+ title: 'Complete project documentation',
42
+ status: 'pending',
43
+ dueDate: '2025-12-31',
44
+ });
45
+
46
+ // Update the task
47
+ await nexus.entities.Task.update(newTask.id, {
48
+ status: 'in-progress',
49
+ });
50
+
51
+ // List all tasks sorted by creation date
52
+ const tasks = await nexus.entities.Task.list('-created_at', 10);
53
+
54
+ // Filter tasks by status
55
+ const pendingTasks = await nexus.entities.Task.filter({ status: 'pending' });
56
+ ```
57
+
58
+ ## Authentication
59
+
60
+ The SDK manages authentication state automatically, persisting tokens in localStorage.
61
+
62
+ ```typescript
63
+ // Sign up a new user (auto-logs in after registration)
64
+ const user = await nexus.auth.signUp({
65
+ email: 'user@example.com',
66
+ password: 'password123',
67
+ name: 'John Doe',
68
+ });
69
+
70
+ // Sign in existing user
71
+ await nexus.auth.signIn({
72
+ email: 'user@example.com',
73
+ password: 'password123',
74
+ });
75
+
76
+ // Check authentication state
77
+ if (nexus.auth.isAuthenticated) {
78
+ console.log('Logged in as:', nexus.auth.currentUser?.email);
79
+ }
80
+
81
+ // Get fresh user data from server
82
+ const currentUser = await nexus.auth.me();
83
+
84
+ // Validate token with server
85
+ const isValid = await nexus.auth.checkAuth();
86
+
87
+ // Listen for auth state changes
88
+ const unsubscribe = nexus.auth.onAuthStateChange((user) => {
89
+ console.log(user ? 'Logged in' : 'Logged out');
90
+ });
91
+
92
+ // Sign out
93
+ nexus.auth.signOut();
94
+
95
+ // Or sign out with redirect
96
+ nexus.auth.logout('/goodbye');
97
+
98
+ // Redirect unauthenticated users to login
99
+ nexus.auth.redirectToLogin('/dashboard');
100
+ // Redirects to: /login?returnUrl=%2Fdashboard
101
+ ```
102
+
103
+ ## Entities
104
+
105
+ The `entities` module provides dynamic access to your database tables with full CRUD support.
106
+
107
+ ### Listing and Filtering
108
+
109
+ ```typescript
110
+ // Simple list
111
+ const tasks = await nexus.entities.Task.list();
112
+
113
+ // With positional parameters: sort, limit, skip, fields
114
+ const tasks = await nexus.entities.Task.list('-created_at', 10, 0);
115
+
116
+ // Or with options object
117
+ const tasks = await nexus.entities.Task.list({
118
+ sort: '-created_at', // prefix with '-' for descending
119
+ limit: 10,
120
+ skip: 0,
121
+ fields: ['id', 'title', 'status'],
122
+ });
123
+
124
+ // Filter by criteria
125
+ const doneTasks = await nexus.entities.Task.filter({ status: 'done' });
126
+
127
+ // Filter with sorting and pagination
128
+ const tasks = await nexus.entities.Task.filter(
129
+ { status: 'pending' },
130
+ '-priority', // sort
131
+ 10, // limit
132
+ 0 // skip
133
+ );
134
+ ```
135
+
136
+ ### CRUD Operations
137
+
138
+ ```typescript
139
+ // Get single record by ID
140
+ const task = await nexus.entities.Task.get('task-id');
141
+
142
+ // Create new record
143
+ const newTask = await nexus.entities.Task.create({
144
+ title: 'New Task',
145
+ status: 'pending',
146
+ });
147
+
148
+ // Update existing record
149
+ const updated = await nexus.entities.Task.update(newTask.id, {
150
+ status: 'completed',
151
+ });
152
+
153
+ // Delete single record
154
+ await nexus.entities.Task.delete(newTask.id);
155
+
156
+ // Delete multiple records matching criteria
157
+ const result = await nexus.entities.Task.deleteMany({ status: 'archived' });
158
+ console.log(`Deleted ${result.deleted} records`);
159
+
160
+ // Bulk create multiple records
161
+ const tasks = await nexus.entities.Task.bulkCreate([
162
+ { title: 'Task 1', status: 'pending' },
163
+ { title: 'Task 2', status: 'pending' },
164
+ { title: 'Task 3', status: 'pending' },
165
+ ]);
166
+ ```
167
+
168
+ ### TypeScript Support
169
+
170
+ Define interfaces for type-safe entity access:
171
+
172
+ ```typescript
173
+ interface Task {
174
+ id: string;
175
+ title: string;
176
+ status: 'pending' | 'in_progress' | 'completed';
177
+ priority: number;
178
+ created_at: string;
179
+ }
180
+
181
+ // Get typed table accessor
182
+ const tasks = nexus.entities.getTable<Task>('Task');
183
+
184
+ // Now all operations are fully typed
185
+ const pending = await tasks.filter({ status: 'pending' });
186
+ pending.forEach((task) => {
187
+ console.log(task.title); // TypeScript knows this is a string
188
+ console.log(task.priority); // TypeScript knows this is a number
189
+ });
190
+ ```
191
+
192
+ ## Functions
193
+
194
+ The `functions` module allows you to execute serverless backend functions.
195
+
196
+ ```typescript
197
+ // Invoke a function
198
+ const result = await nexus.functions.invoke('sendEmail', {
199
+ to: 'user@example.com',
200
+ subject: 'Hello from Nexus',
201
+ body: 'Welcome to the platform!',
202
+ });
203
+
204
+ // With full type safety
205
+ interface EmailInput {
206
+ to: string;
207
+ subject: string;
208
+ body: string;
209
+ }
210
+
211
+ interface EmailOutput {
212
+ messageId: string;
213
+ status: 'sent' | 'queued';
214
+ }
215
+
216
+ const result = await nexus.functions.invoke<EmailInput, EmailOutput>('sendEmail', {
217
+ to: 'user@example.com',
218
+ subject: 'Hello',
219
+ body: 'Welcome!',
220
+ });
221
+
222
+ console.log(result.messageId); // Fully typed
223
+
224
+ // List available functions
225
+ const functions = await nexus.functions.list();
226
+ functions.forEach((fn) => {
227
+ console.log(`${fn.name}: ${fn.description}`);
228
+ });
229
+ ```
230
+
231
+ ## Error Handling
232
+
233
+ The SDK throws `NexusApiError` for all API errors, providing structured error information:
234
+
235
+ ```typescript
236
+ import { NexusApiError } from 'nexus-platform-sdk';
237
+
238
+ try {
239
+ await nexus.entities.Task.get('non-existent-id');
240
+ } catch (error) {
241
+ if (error instanceof NexusApiError) {
242
+ console.error('Status:', error.status); // HTTP status code
243
+ console.error('Message:', error.message); // Error message
244
+ console.error('Code:', error.code); // Application error code
245
+ console.error('Details:', error.details); // Additional error details
246
+ }
247
+ }
248
+ ```
249
+
250
+ ## React Integration
251
+
252
+ Here's a recommended pattern for integrating the SDK with React applications:
253
+
254
+ ```typescript
255
+ // src/api/nexusClient.ts
256
+ import { createClient } from 'nexus-platform-sdk';
257
+
258
+ export const nexus = createClient({
259
+ appId: import.meta.env.VITE_NEXUS_APP_ID,
260
+ tenantId: import.meta.env.VITE_NEXUS_TENANT_ID,
261
+ dataSourceId: import.meta.env.VITE_NEXUS_DATASOURCE_ID,
262
+ apiUrl: import.meta.env.VITE_NEXUS_API_URL,
263
+ });
264
+
265
+ // src/hooks/useAuth.ts
266
+ import { useEffect, useState } from 'react';
267
+ import { nexus } from '../api/nexusClient';
268
+ import type { User } from 'nexus-platform-sdk';
269
+
270
+ export function useAuth() {
271
+ const [user, setUser] = useState<User | null>(nexus.auth.currentUser);
272
+ const [loading, setLoading] = useState(true);
273
+
274
+ useEffect(() => {
275
+ // Validate token on mount
276
+ nexus.auth.checkAuth().finally(() => setLoading(false));
277
+
278
+ // Subscribe to auth state changes
279
+ return nexus.auth.onAuthStateChange(setUser);
280
+ }, []);
281
+
282
+ return {
283
+ user,
284
+ loading,
285
+ isAuthenticated: !!user,
286
+ signIn: nexus.auth.signIn.bind(nexus.auth),
287
+ signUp: nexus.auth.signUp.bind(nexus.auth),
288
+ signOut: nexus.auth.signOut.bind(nexus.auth),
289
+ };
290
+ }
291
+
292
+ // src/components/ProtectedRoute.tsx
293
+ import { Navigate, useLocation } from 'react-router-dom';
294
+ import { useAuth } from '../hooks/useAuth';
295
+
296
+ export function ProtectedRoute({ children }: { children: React.ReactNode }) {
297
+ const { isAuthenticated, loading } = useAuth();
298
+ const location = useLocation();
299
+
300
+ if (loading) {
301
+ return <div>Loading...</div>;
302
+ }
303
+
304
+ if (!isAuthenticated) {
305
+ return <Navigate to={`/login?returnUrl=${location.pathname}`} replace />;
306
+ }
307
+
308
+ return <>{children}</>;
309
+ }
310
+ ```
311
+
312
+ ## Development
313
+
314
+ ### Build the SDK
315
+
316
+ ```bash
317
+ npm install
318
+ npm run build
319
+ ```
320
+
321
+ ### Run tests
322
+
323
+ ```bash
324
+ npm test
325
+ ```
326
+
327
+ ## License
328
+
329
+ MIT