@centrali-io/centrali-sdk 5.5.1 → 6.0.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.
Files changed (49) hide show
  1. package/README.md +164 -14
  2. package/dist/index.d.ts +1807 -878
  3. package/dist/index.js +9153 -4076
  4. package/index.ts +61 -7152
  5. package/package.json +10 -3
  6. package/query-types.ts +83 -2
  7. package/scripts/smoke-types.ts +145 -5
  8. package/src/client.ts +1507 -0
  9. package/src/internal/auth.ts +35 -0
  10. package/src/internal/deprecation.ts +11 -0
  11. package/src/internal/error.ts +90 -0
  12. package/src/internal/paths.ts +456 -0
  13. package/src/internal/queryGuard.ts +21 -0
  14. package/src/managers/allowedDomains.ts +90 -0
  15. package/src/managers/anomalyInsights.ts +215 -0
  16. package/src/managers/auditLog.ts +105 -0
  17. package/src/managers/collections.ts +197 -0
  18. package/src/managers/files.ts +182 -0
  19. package/src/managers/functionRuns.ts +229 -0
  20. package/src/managers/functions.ts +171 -0
  21. package/src/managers/orchestrationRuns.ts +122 -0
  22. package/src/managers/orchestrations.ts +297 -0
  23. package/src/managers/query.ts +199 -0
  24. package/src/managers/records.ts +186 -0
  25. package/src/managers/smartQueries.ts +374 -0
  26. package/src/managers/structures.ts +205 -0
  27. package/src/managers/triggers.ts +349 -0
  28. package/src/managers/validation.ts +303 -0
  29. package/src/managers/webhookSubscriptions.ts +206 -0
  30. package/src/realtime/manager.ts +292 -0
  31. package/src/types/allowedDomains.ts +29 -0
  32. package/src/types/auth.ts +83 -0
  33. package/src/types/common.ts +57 -0
  34. package/src/types/compute.ts +145 -0
  35. package/src/types/insights.ts +113 -0
  36. package/src/types/orchestrations.ts +460 -0
  37. package/src/types/realtime.ts +403 -0
  38. package/src/types/records.ts +261 -0
  39. package/src/types/search.ts +44 -0
  40. package/src/types/smartQueries.ts +303 -0
  41. package/src/types/structures.ts +203 -0
  42. package/src/types/triggers.ts +122 -0
  43. package/src/types/validation.ts +167 -0
  44. package/src/types/webhooks.ts +114 -0
  45. package/src/urls.ts +33 -0
  46. package/dist/query-types.d.ts +0 -187
  47. package/dist/query-types.js +0 -137
  48. package/dist/scripts/smoke-types.d.ts +0 -12
  49. package/dist/scripts/smoke-types.js +0 -102
package/README.md CHANGED
@@ -407,15 +407,126 @@ const results = await centrali.savedQueries.execute('employee', query.data.id);
407
407
  console.log('Found:', results.data.length, 'employees');
408
408
 
409
409
  // Execute with variables (canonical operators — no `$` prefix)
410
- // Saved query body: { where: { 'data.status': { eq: '{{statusFilter}}' } } }
410
+ // Saved query body: { where: { 'data.status': { eq: '${statusFilter}' } } }
411
411
  const filteredResults = await centrali.savedQueries.execute('orders', query.data.id, {
412
412
  variables: {
413
413
  statusFilter: 'active',
414
- startDate: '2024-01-01'
415
- }
414
+ startDate: new Date('2024-01-01'),
415
+ },
416
416
  });
417
417
  ```
418
418
 
419
+ #### Typed parameters (Phase 4)
420
+
421
+ Saved queries persist typed parameter declarations alongside the query body
422
+ (`SmartQuery.variables`). `get()` returns them so callers can introspect the
423
+ required shape, and `executeTyped<TVars>()` enforces it at the call site:
424
+
425
+ ```typescript
426
+ const query = await centrali.savedQueries.get('orders', 'monthly-revenue');
427
+ console.log(query.data.variables);
428
+ // { month: { type: 'datetime', required: true }, region: { type: 'string', required: true } }
429
+
430
+ interface MonthlyRevenueVars {
431
+ month: Date;
432
+ region: string;
433
+ }
434
+
435
+ const rows = await centrali.savedQueries.executeTyped<MonthlyRevenueVars>(
436
+ 'orders',
437
+ 'monthly-revenue',
438
+ { month: new Date('2026-04-01'), region: 'us-east' },
439
+ );
440
+
441
+ // Compile error — wrong type for `month`:
442
+ // await centrali.savedQueries.executeTyped<MonthlyRevenueVars>('orders', 'monthly-revenue', {
443
+ // month: 'not-a-date',
444
+ // region: 'us-east',
445
+ // });
446
+ ```
447
+
448
+ `executeTyped<TVars>` accepts any object — there is no `extends ExecuteSavedQueryValues` constraint, so plain TS interfaces (no string index signature) work.
449
+
450
+ The untyped `execute()` form accepts `Record<string, ScalarValue | ScalarValue[] | Date | Date[]>` for callers that don't have a typed shape — including arrays of dates for `array<datetime>` declarations.
451
+
452
+ #### Authoring saved queries with canonical syntax
453
+
454
+ To author a saved query that uses canonical operators (`eq`/`gte`/…) and typed parameters, pass `query` (a canonical `QueryDefinition`) and `variables` (typed declarations). The SDK routes those calls to the canonical `/saved-queries` endpoints:
455
+
456
+ ```typescript
457
+ const created = await centrali.savedQueries.create('orders', {
458
+ name: 'Active Orders',
459
+ query: {
460
+ resource: 'orders',
461
+ where: { 'data.status': { eq: '${statusFilter}' } },
462
+ sort: [{ field: 'createdAt', direction: 'desc' }],
463
+ page: { limit: 100 },
464
+ },
465
+ variables: {
466
+ statusFilter: { type: 'string', required: true },
467
+ },
468
+ });
469
+
470
+ await centrali.savedQueries.update('orders', created.data.id, {
471
+ query: {
472
+ resource: 'orders',
473
+ where: { 'data.amount': { gte: '${minTotal}' } },
474
+ page: { limit: 50 },
475
+ },
476
+ variables: { minTotal: { type: 'number', required: true } },
477
+ });
478
+
479
+ // Dry-run a draft — exercises the same typed validator as a saved execute.
480
+ await centrali.savedQueries.test('orders', {
481
+ query: {
482
+ resource: 'orders',
483
+ where: { 'data.amount': { gte: '${minTotal}' } },
484
+ page: { limit: 5 },
485
+ },
486
+ variableDeclarations: { minTotal: { type: 'number', required: true } },
487
+ variables: { minTotal: 100 },
488
+ });
489
+ ```
490
+
491
+ Pre-Phase-4 callers may still pass `queryDefinition` (legacy `$eq`/`$gte` shape) instead of `query`; those calls route to the legacy slug-based endpoints and cannot carry typed `variables` declarations.
492
+
493
+ #### Promoting an untyped saved query to typed
494
+
495
+ Saved queries that predate Phase 4 carry `variables: null` and substitute placeholders as plain strings. To promote one to typed validation:
496
+
497
+ ```typescript
498
+ // 1. Load the row to see what placeholders are referenced
499
+ const existing = await centrali.savedQueries.get('orders', 'monthly-revenue');
500
+
501
+ // 2. Update with a `variables` declaration map. Every `${name}` referenced
502
+ // in the body must be declared, otherwise the server returns
503
+ // `unknown_variable`.
504
+ await centrali.savedQueries.update('orders', existing.data.id, {
505
+ variables: {
506
+ month: { type: 'datetime', required: true, description: 'Month bucket (UTC)' },
507
+ region: { type: 'string', required: true },
508
+ },
509
+ });
510
+
511
+ // 3. Subsequent executes are validated against the declarations server-side
512
+ // (no coercion — "123" is rejected for `number`, etc.). Type mismatches
513
+ // surface as `variable_type_mismatch`, missing required keys as
514
+ // `missing_required_variable`, extras as `extra_variable`.
515
+ //
516
+ // `Date` works for `datetime` because axios JSON-serializes it to an
517
+ // ISO-8601 string before the request — the server itself only ever sees
518
+ // the string and parses it via `Date.parse()`.
519
+ await centrali.savedQueries.executeTyped<{ month: Date; region: string }>(
520
+ 'orders',
521
+ existing.data.id,
522
+ { month: new Date('2026-04-01'), region: 'us-east' },
523
+ );
524
+ ```
525
+
526
+ Sending `variables: null` on `update()` reverts a typed row to untyped (legacy) substitution. Sending `{}` would put it into strict zero-variable mode and reject any remaining `${name}` placeholder in the body.
527
+
528
+ Legacy `{{name}}` substitution still works on untyped rows during the deprecation window, but new saved queries — and any row being promoted to typed — must use canonical `${name}` placeholders.
529
+
419
530
  `centrali.savedQueries.*` is the canonical namespace, routed through the `/saved-queries/*` HTTP endpoints (Phase 4 of the [query foundation](https://github.com/blueinit/centrali/blob/main/docs/maintainers/overview/query-foundation.md), CEN-1198). New code should always use it.
420
531
 
421
532
  #### Migration from `centrali.smartQueries.*` (deprecated alias)
@@ -675,7 +786,7 @@ console.log('Job queued:', job.data);
675
786
 
676
787
  // Poll for the result using function runs
677
788
  // (The job ID maps to a function run — query by trigger to find it)
678
- const runs = await centrali.runs.listByTrigger('trigger-id', { limit: 1 });
789
+ const runs = await centrali.functionRuns.listByTrigger('trigger-id', { limit: 1 });
679
790
  const latestRun = runs.data.data[0];
680
791
  console.log('Status:', latestRun.status); // pending | running | completed | failure | timeout
681
792
  console.log('Result:', latestRun.runData); // execution output (once completed)
@@ -684,24 +795,63 @@ console.log('Error:', latestRun.errorMessage); // error details (if failed)
684
795
 
685
796
  #### Function Runs (Execution History)
686
797
 
687
- Query execution history for debugging and observability:
798
+ Query execution history for debugging and observability. Access via
799
+ `client.functionRuns` (canonical, since 5.6.0). The legacy `client.runs`
800
+ accessor remains as a deprecated alias and emits a one-shot deprecation
801
+ warning.
802
+
803
+ The canonical `functionRuns.query()` surface (CEN-1216, since 5.6.0) is the
804
+ recommended way for new code — same operator vocabulary as `records.query()`,
805
+ returns the canonical `{ data, meta }` envelope.
688
806
 
689
807
  ```typescript
808
+ // Recent failures for a function
809
+ const failures = await centrali.functionRuns.query({
810
+ where: {
811
+ and: [
812
+ { functionId: { eq: 'fn-123' } },
813
+ { status: { eq: 'failure' } },
814
+ ],
815
+ },
816
+ sort: [{ field: 'startedAt', direction: 'desc' }],
817
+ page: { limit: 50 },
818
+ });
819
+
820
+ // Workspace-wide activity in a date window with field projection
821
+ const activity = await centrali.functionRuns.query({
822
+ where: {
823
+ and: [
824
+ { startedAt: { gte: '2026-04-01' } },
825
+ { startedAt: { lt: '2026-05-01' } },
826
+ ],
827
+ },
828
+ sort: [{ field: 'startedAt', direction: 'desc' }],
829
+ page: { limit: 100 },
830
+ select: { fields: ['id', 'functionId', 'status', 'startedAt', 'endedAt', 'errorCode'] },
831
+ });
832
+
833
+ // Authoring dry-run — validate a query without executing it
834
+ const plan = await centrali.functionRuns.test({
835
+ where: { status: { eq: 'completed' } },
836
+ page: { limit: 10 },
837
+ });
838
+
690
839
  // Get a specific run by ID
691
- const run = await centrali.runs.get('run-uuid');
840
+ const run = await centrali.functionRuns.get('run-uuid');
692
841
  console.log('Status:', run.data.status);
693
842
  console.log('Output:', run.data.runData);
694
843
  console.log('Duration:', run.data.startedAt, '→', run.data.endedAt);
844
+ ```
695
845
 
696
- // List runs for a trigger (most recent first)
697
- const triggerRuns = await centrali.runs.listByTrigger('trigger-uuid', {
698
- status: 'failure', // Filter by status
699
- limit: 10
700
- });
846
+ The legacy `functionRuns.listByTrigger()` / `functionRuns.listByFunction()` GET surfaces
847
+ still work and are retained for back-compat — prefer `functionRuns.query()` with
848
+ a `where: { triggerId: { eq: ... } }` or `{ functionId: { eq: ... } }` clause
849
+ for new code.
701
850
 
702
- // List runs for a function
703
- const functionRuns = await centrali.runs.listByFunction('function-uuid');
704
- ```
851
+ Queryable fields are the fixed-schema columns: `id`, `functionId`, `triggerId`,
852
+ `status`, `startedAt`, `endedAt`, `executionSource`, `errorCode`, `errorMessage`,
853
+ etc. The `runData` and `executionContext` JSONB columns are intentionally not
854
+ queryable — use `functionRuns.get(runId)` to fetch a specific run's payload.
705
855
 
706
856
  Run statuses: `pending` → `running` → `completed` | `failure` | `timeout`
707
857