@centrali-io/centrali-sdk 2.4.0 → 2.4.3

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 CHANGED
@@ -4,6 +4,8 @@ Official Node.js SDK for Centrali - Build modern web applications without managi
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/%40centrali-io%2Fcentrali-sdk.svg)](https://www.npmjs.com/package/@centrali-io/centrali-sdk)
6
6
 
7
+ > **Try it now!** Explore the SDK in our [Live Playground on StackBlitz](https://stackblitz.com/~/github.com/centrali-demo/sdk-playground) - no setup required.
8
+
7
9
  ## Installation
8
10
 
9
11
  ```bash
package/dist/index.js CHANGED
@@ -183,6 +183,16 @@ class RealtimeManager {
183
183
  if (options.filter) {
184
184
  url.searchParams.set('filter', options.filter);
185
185
  }
186
+ // Add compute function filters
187
+ if (options.jobId) {
188
+ url.searchParams.set('jobId', options.jobId);
189
+ }
190
+ if (options.triggerType) {
191
+ url.searchParams.set('triggerType', options.triggerType);
192
+ }
193
+ if (options.functionId) {
194
+ url.searchParams.set('functionId', options.functionId);
195
+ }
186
196
  // Create EventSource (uses polyfill in Node.js)
187
197
  eventSource = new EventSourceImpl(url.toString());
188
198
  // Handle connection open
@@ -1467,6 +1477,52 @@ class CentraliSDK {
1467
1477
  const path = getRecordApiPath(this.options.workspaceId, recordSlug, id) + '/restore';
1468
1478
  return this.request('POST', path);
1469
1479
  }
1480
+ // ------------------ Secrets API Methods ------------------
1481
+ /**
1482
+ * Reveal plaintext values of secret fields for a record.
1483
+ * Requires secrets:reveal permission.
1484
+ *
1485
+ * @param recordSlug - The structure's record slug
1486
+ * @param id - The record ID
1487
+ * @param fields - Optional array of specific secret field names to reveal
1488
+ * @returns Object with field names as keys and plaintext secret values
1489
+ *
1490
+ * @example
1491
+ * ```ts
1492
+ * // Reveal all secrets
1493
+ * const result = await client.revealSecrets('users', 'record-123');
1494
+ * console.log(result.data.revealed.apiKey); // "sk_live_..."
1495
+ *
1496
+ * // Reveal specific fields
1497
+ * const result = await client.revealSecrets('users', 'record-123', ['apiKey']);
1498
+ * ```
1499
+ */
1500
+ revealSecrets(recordSlug, id, fields) {
1501
+ const path = getRecordApiPath(this.options.workspaceId, recordSlug, id) + '/secrets/reveal';
1502
+ return this.request('POST', path, fields ? { fields } : {});
1503
+ }
1504
+ /**
1505
+ * Compare a candidate value against a secret field without revealing the stored secret.
1506
+ * Requires secrets:compare permission.
1507
+ *
1508
+ * @param recordSlug - The structure's record slug
1509
+ * @param id - The record ID
1510
+ * @param field - The secret field name to compare against
1511
+ * @param value - The candidate value to compare
1512
+ * @returns Boolean indicating if the values match
1513
+ *
1514
+ * @example
1515
+ * ```ts
1516
+ * const result = await client.compareSecret('users', 'record-123', 'apiKey', 'sk_live_test');
1517
+ * if (result.data.matches) {
1518
+ * console.log('API key is valid');
1519
+ * }
1520
+ * ```
1521
+ */
1522
+ compareSecret(recordSlug, id, field, value) {
1523
+ const path = getRecordApiPath(this.options.workspaceId, recordSlug, id) + '/secrets/compare';
1524
+ return this.request('POST', path, { field, value });
1525
+ }
1470
1526
  // ------------------ Storage API Methods ------------------
1471
1527
  /** Upload a file to the storage service. */
1472
1528
  uploadFile(file_1, location_1) {
package/index.ts CHANGED
@@ -33,11 +33,16 @@ export type ValidationEventType = 'validation_suggestion_created' | 'validation_
33
33
  */
34
34
  export type AnomalyEventType = 'anomaly_insight_created' | 'anomaly_detection_completed';
35
35
 
36
+ /**
37
+ * Compute function event types emitted by the realtime service.
38
+ */
39
+ export type ComputeEventType = 'function_run_completed' | 'function_run_failed';
40
+
36
41
  /**
37
42
  * All event types emitted by the realtime service.
38
43
  * Matches: services/backend/realtime/internal/redis/message.go
39
44
  */
40
- export type RealtimeEventType = RecordEventType | ValidationEventType | AnomalyEventType;
45
+ export type RealtimeEventType = RecordEventType | ValidationEventType | AnomalyEventType | ComputeEventType;
41
46
 
42
47
  /**
43
48
  * Record event payload from the realtime service.
@@ -242,6 +247,63 @@ export interface RealtimeAnomalyDetectionEvent {
242
247
  data: AnomalyDetectionData;
243
248
  }
244
249
 
250
+ /**
251
+ * Function run error details.
252
+ */
253
+ export interface FunctionRunError {
254
+ /** Error message */
255
+ message: string;
256
+ /** Error code */
257
+ code?: string;
258
+ /** Stack trace */
259
+ stack?: string;
260
+ }
261
+
262
+ /**
263
+ * Memory usage metrics from function execution.
264
+ */
265
+ export interface FunctionMemoryUsage {
266
+ /** Heap memory used in bytes */
267
+ heapUsed: number;
268
+ /** Resident set size in bytes */
269
+ rss: number;
270
+ }
271
+
272
+ /**
273
+ * Compute function run event payload.
274
+ * Matches the format published by handle_function_run_events.ts
275
+ */
276
+ export interface RealtimeFunctionRunEvent {
277
+ /** Event type */
278
+ event: ComputeEventType;
279
+ /** Workspace slug */
280
+ workspaceSlug: string;
281
+ /** Unique job identifier (returned from execute call) */
282
+ jobId: string;
283
+ /** Function run record ID */
284
+ runId: string;
285
+ /** Trigger that initiated the run */
286
+ triggerId: string;
287
+ /** Function that was executed */
288
+ functionId: string;
289
+ /** Trigger type: on-demand, event-driven, scheduled, http-trigger */
290
+ triggerType: 'on-demand' | 'event-driven' | 'scheduled' | 'http-trigger';
291
+ /** Execution status */
292
+ status: 'completed' | 'failure';
293
+ /** Function return value (if completed) */
294
+ outputs?: unknown;
295
+ /** Error details (if failed) */
296
+ error?: FunctionRunError;
297
+ /** Execution time in milliseconds */
298
+ duration: number;
299
+ /** Memory usage metrics */
300
+ memoryUsage?: FunctionMemoryUsage;
301
+ /** User who triggered the run */
302
+ userId: string;
303
+ /** ISO timestamp when the function completed */
304
+ timestamp: string;
305
+ }
306
+
245
307
  /**
246
308
  * Close event payload from the realtime service.
247
309
  */
@@ -255,7 +317,7 @@ export interface RealtimeCloseEvent {
255
317
  /**
256
318
  * Union type of all realtime events.
257
319
  */
258
- export type RealtimeEvent = RealtimeRecordEvent | RealtimeValidationSuggestionEvent | RealtimeValidationBatchEvent | RealtimeAnomalyInsightEvent | RealtimeAnomalyDetectionEvent;
320
+ export type RealtimeEvent = RealtimeRecordEvent | RealtimeValidationSuggestionEvent | RealtimeValidationBatchEvent | RealtimeAnomalyInsightEvent | RealtimeAnomalyDetectionEvent | RealtimeFunctionRunEvent;
259
321
 
260
322
  /**
261
323
  * Error object for realtime connection errors.
@@ -279,6 +341,12 @@ export interface RealtimeSubscribeOptions {
279
341
  events?: RealtimeEventType[];
280
342
  /** CFL (Centrali Filter Language) expression for data filtering (e.g., "status = 'active'") */
281
343
  filter?: string;
344
+ /** Filter compute events to a specific job ID (only affects function_run_* events) */
345
+ jobId?: string;
346
+ /** Filter compute events by trigger type: on-demand, event-driven, scheduled, http-trigger */
347
+ triggerType?: 'on-demand' | 'event-driven' | 'scheduled' | 'http-trigger';
348
+ /** Filter compute events to a specific function ID */
349
+ functionId?: string;
282
350
  /** Callback for record events */
283
351
  onEvent: (event: RealtimeEvent) => void;
284
352
  /** Callback for errors */
@@ -1000,6 +1068,17 @@ export class RealtimeManager {
1000
1068
  url.searchParams.set('filter', options.filter);
1001
1069
  }
1002
1070
 
1071
+ // Add compute function filters
1072
+ if (options.jobId) {
1073
+ url.searchParams.set('jobId', options.jobId);
1074
+ }
1075
+ if (options.triggerType) {
1076
+ url.searchParams.set('triggerType', options.triggerType);
1077
+ }
1078
+ if (options.functionId) {
1079
+ url.searchParams.set('functionId', options.functionId);
1080
+ }
1081
+
1003
1082
  // Create EventSource (uses polyfill in Node.js)
1004
1083
  eventSource = new EventSourceImpl(url.toString());
1005
1084
 
@@ -2504,7 +2583,63 @@ export class CentraliSDK {
2504
2583
  return this.request('POST', path);
2505
2584
  }
2506
2585
 
2586
+ // ------------------ Secrets API Methods ------------------
2587
+
2588
+ /**
2589
+ * Reveal plaintext values of secret fields for a record.
2590
+ * Requires secrets:reveal permission.
2591
+ *
2592
+ * @param recordSlug - The structure's record slug
2593
+ * @param id - The record ID
2594
+ * @param fields - Optional array of specific secret field names to reveal
2595
+ * @returns Object with field names as keys and plaintext secret values
2596
+ *
2597
+ * @example
2598
+ * ```ts
2599
+ * // Reveal all secrets
2600
+ * const result = await client.revealSecrets('users', 'record-123');
2601
+ * console.log(result.data.revealed.apiKey); // "sk_live_..."
2602
+ *
2603
+ * // Reveal specific fields
2604
+ * const result = await client.revealSecrets('users', 'record-123', ['apiKey']);
2605
+ * ```
2606
+ */
2607
+ public revealSecrets(
2608
+ recordSlug: string,
2609
+ id: string,
2610
+ fields?: string[]
2611
+ ): Promise<ApiResponse<{ revealed: Record<string, any> }>> {
2612
+ const path = getRecordApiPath(this.options.workspaceId, recordSlug, id) + '/secrets/reveal';
2613
+ return this.request('POST', path, fields ? { fields } : {});
2614
+ }
2507
2615
 
2616
+ /**
2617
+ * Compare a candidate value against a secret field without revealing the stored secret.
2618
+ * Requires secrets:compare permission.
2619
+ *
2620
+ * @param recordSlug - The structure's record slug
2621
+ * @param id - The record ID
2622
+ * @param field - The secret field name to compare against
2623
+ * @param value - The candidate value to compare
2624
+ * @returns Boolean indicating if the values match
2625
+ *
2626
+ * @example
2627
+ * ```ts
2628
+ * const result = await client.compareSecret('users', 'record-123', 'apiKey', 'sk_live_test');
2629
+ * if (result.data.matches) {
2630
+ * console.log('API key is valid');
2631
+ * }
2632
+ * ```
2633
+ */
2634
+ public compareSecret(
2635
+ recordSlug: string,
2636
+ id: string,
2637
+ field: string,
2638
+ value: string
2639
+ ): Promise<ApiResponse<{ matches: boolean }>> {
2640
+ const path = getRecordApiPath(this.options.workspaceId, recordSlug, id) + '/secrets/compare';
2641
+ return this.request('POST', path, { field, value });
2642
+ }
2508
2643
 
2509
2644
  // ------------------ Storage API Methods ------------------
2510
2645
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centrali-io/centrali-sdk",
3
- "version": "2.4.0",
3
+ "version": "2.4.3",
4
4
  "description": "Centrali Node SDK",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",