@centrali-io/centrali-sdk 5.5.0 → 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.
- package/README.md +164 -14
- package/dist/index.d.ts +1807 -878
- package/dist/index.js +9153 -4076
- package/index.ts +61 -7152
- package/package.json +10 -3
- package/query-types.ts +83 -2
- package/scripts/smoke-types.ts +145 -5
- package/src/client.ts +1507 -0
- package/src/internal/auth.ts +35 -0
- package/src/internal/deprecation.ts +11 -0
- package/src/internal/error.ts +90 -0
- package/src/internal/paths.ts +456 -0
- package/src/internal/queryGuard.ts +21 -0
- package/src/managers/allowedDomains.ts +90 -0
- package/src/managers/anomalyInsights.ts +215 -0
- package/src/managers/auditLog.ts +105 -0
- package/src/managers/collections.ts +197 -0
- package/src/managers/files.ts +182 -0
- package/src/managers/functionRuns.ts +229 -0
- package/src/managers/functions.ts +171 -0
- package/src/managers/orchestrationRuns.ts +122 -0
- package/src/managers/orchestrations.ts +297 -0
- package/src/managers/query.ts +199 -0
- package/src/managers/records.ts +186 -0
- package/src/managers/smartQueries.ts +374 -0
- package/src/managers/structures.ts +205 -0
- package/src/managers/triggers.ts +349 -0
- package/src/managers/validation.ts +303 -0
- package/src/managers/webhookSubscriptions.ts +206 -0
- package/src/realtime/manager.ts +292 -0
- package/src/types/allowedDomains.ts +29 -0
- package/src/types/auth.ts +83 -0
- package/src/types/common.ts +57 -0
- package/src/types/compute.ts +145 -0
- package/src/types/insights.ts +113 -0
- package/src/types/orchestrations.ts +460 -0
- package/src/types/realtime.ts +403 -0
- package/src/types/records.ts +261 -0
- package/src/types/search.ts +44 -0
- package/src/types/smartQueries.ts +303 -0
- package/src/types/structures.ts +203 -0
- package/src/types/triggers.ts +122 -0
- package/src/types/validation.ts +167 -0
- package/src/types/webhooks.ts +114 -0
- package/src/urls.ts +33 -0
- package/dist/query-types.d.ts +0 -187
- package/dist/query-types.js +0 -137
- package/dist/scripts/smoke-types.d.ts +0 -12
- package/dist/scripts/smoke-types.js +0 -102
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Orchestration Runs Manager
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse } from '../types/common';
|
|
7
|
+
import type { OrchestrationRun } from '../types/orchestrations';
|
|
8
|
+
import type { QueryDefinition, QueryResult } from '../../query-types';
|
|
9
|
+
import { getOrchestrationRunsCanonicalApiPath } from '../internal/paths';
|
|
10
|
+
|
|
11
|
+
// =====================================================
|
|
12
|
+
// Orchestration Runs Manager
|
|
13
|
+
// =====================================================
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* OrchestrationRunsManager — canonical query surface for orchestration runs
|
|
17
|
+
* (CEN-1217 / Phase 3 of the query foundation).
|
|
18
|
+
*
|
|
19
|
+
* Available methods:
|
|
20
|
+
* - {@link OrchestrationRunsManager.query | query} — canonical
|
|
21
|
+
* `POST /orchestration-runs/query`. Use for nested boolean trees, `select`
|
|
22
|
+
* projection, paging.
|
|
23
|
+
* - {@link OrchestrationRunsManager.test | test} — authoring dry-run against
|
|
24
|
+
* `/orchestration-runs/query/test`. Validates and plans without executing.
|
|
25
|
+
*
|
|
26
|
+
* Per-orchestration trigger / list / get-by-id helpers stay on
|
|
27
|
+
* `client.orchestrations.{trigger, listRuns, getRun, getRunSteps}` — those
|
|
28
|
+
* back the legacy nested `/orchestrations/{id}/runs` routes (which now emit a
|
|
29
|
+
* Deprecation header pointing here for the list shape).
|
|
30
|
+
*
|
|
31
|
+
* Access via `client.orchestrationRuns`.
|
|
32
|
+
*/
|
|
33
|
+
export class OrchestrationRunsManager {
|
|
34
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
35
|
+
private workspaceId: string;
|
|
36
|
+
|
|
37
|
+
constructor(
|
|
38
|
+
workspaceId: string,
|
|
39
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
40
|
+
) {
|
|
41
|
+
this.workspaceId = workspaceId;
|
|
42
|
+
this.requestFn = requestFn;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Run a canonical query against `POST /workspace/<ws>/api/v1/orchestration-runs/query`.
|
|
47
|
+
*
|
|
48
|
+
* The body **is** a `QueryDefinition`. `resource` is forced to
|
|
49
|
+
* `"orchestration-runs"` — the orchestration-service executor rejects
|
|
50
|
+
* anything else. Returns the canonical `{ data, meta }` envelope.
|
|
51
|
+
*
|
|
52
|
+
* Queryable fields are the fixed-schema columns: `id`, `orchestrationId`,
|
|
53
|
+
* `orchestrationVersion`, `status`, `currentStepId`, `correlationId`,
|
|
54
|
+
* `triggerType`, `hasErrors`, `delayStepCount`, `loopIterationCount`,
|
|
55
|
+
* `failureReason`, `startedAt`, `completedAt`, `ttlExpiresAt`. The JSONB
|
|
56
|
+
* columns (`input`, `context`, `stepOutputs`, `triggerMetadata`,
|
|
57
|
+
* `activeLoop`) are intentionally not queryable —
|
|
58
|
+
* fetch a specific run via
|
|
59
|
+
* `client.orchestrations.getRun(orchestrationId, runId, true)` if you need
|
|
60
|
+
* its payload and step history.
|
|
61
|
+
*
|
|
62
|
+
* The `where` clause that pins `orchestrationId.eq` or `id.eq` (in a pure
|
|
63
|
+
* AND-of-scalar-eq shape) uses `orchestrations:retrieve` server-side;
|
|
64
|
+
* everything else uses `orchestrations:list`. Retrieve-only roles can
|
|
65
|
+
* still query a specific orchestration's run history this way.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // Recent failed runs for a specific orchestration
|
|
70
|
+
* const failures = await client.orchestrationRuns.query({
|
|
71
|
+
* resource: 'orchestration-runs',
|
|
72
|
+
* where: {
|
|
73
|
+
* and: [
|
|
74
|
+
* { orchestrationId: { eq: 'orch-123' } },
|
|
75
|
+
* { status: { eq: 'failed' } },
|
|
76
|
+
* ],
|
|
77
|
+
* },
|
|
78
|
+
* sort: [{ field: 'startedAt', direction: 'desc' }],
|
|
79
|
+
* page: { limit: 50 },
|
|
80
|
+
* });
|
|
81
|
+
*
|
|
82
|
+
* // Workspace-wide run activity in a date window with field projection
|
|
83
|
+
* const activity = await client.orchestrationRuns.query({
|
|
84
|
+
* resource: 'orchestration-runs',
|
|
85
|
+
* where: {
|
|
86
|
+
* and: [
|
|
87
|
+
* { startedAt: { gte: '2026-04-01' } },
|
|
88
|
+
* { startedAt: { lt: '2026-05-01' } },
|
|
89
|
+
* ],
|
|
90
|
+
* },
|
|
91
|
+
* sort: [{ field: 'startedAt', direction: 'desc' }],
|
|
92
|
+
* page: { limit: 100 },
|
|
93
|
+
* select: { fields: ['id', 'orchestrationId', 'status', 'startedAt', 'completedAt', 'hasErrors'] },
|
|
94
|
+
* });
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
public async query<T = OrchestrationRun>(
|
|
98
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
99
|
+
): Promise<QueryResult<T>> {
|
|
100
|
+
const path = getOrchestrationRunsCanonicalApiPath(this.workspaceId, 'query');
|
|
101
|
+
const body: QueryDefinition = { ...definition, resource: 'orchestration-runs' };
|
|
102
|
+
const resp = await this.requestFn<T[]>('POST', path, body);
|
|
103
|
+
return resp as unknown as QueryResult<T>;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Authoring-time dry-run against `POST /orchestration-runs/query/test`.
|
|
108
|
+
*
|
|
109
|
+
* Same input shape as {@link OrchestrationRunsManager.query | query}.
|
|
110
|
+
* Returns a plan summary on success or structured `QueryError`s on
|
|
111
|
+
* failure, without executing the query. Use from query builders to
|
|
112
|
+
* surface precise errors before saving / running.
|
|
113
|
+
*/
|
|
114
|
+
public async test(
|
|
115
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
116
|
+
): Promise<{ ok: true; plan: { executor: string; resource: string; mode: string; hasUnreadableField: boolean } }> {
|
|
117
|
+
const path = getOrchestrationRunsCanonicalApiPath(this.workspaceId, 'query/test');
|
|
118
|
+
const body: QueryDefinition = { ...definition, resource: 'orchestration-runs' };
|
|
119
|
+
const resp = await this.requestFn<{ ok: true; plan: { executor: string; resource: string; mode: string; hasUnreadableField: boolean } }>('POST', path, body);
|
|
120
|
+
return resp.data;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Orchestrations Manager
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse, PaginatedResponse } from '../types/common';
|
|
7
|
+
import type {
|
|
8
|
+
Orchestration,
|
|
9
|
+
CreateOrchestrationInput,
|
|
10
|
+
UpdateOrchestrationInput,
|
|
11
|
+
OrchestrationRun,
|
|
12
|
+
OrchestrationRunStep,
|
|
13
|
+
TriggerOrchestrationRunOptions,
|
|
14
|
+
ListOrchestrationsOptions,
|
|
15
|
+
ListOrchestrationRunsOptions,
|
|
16
|
+
} from '../types/orchestrations';
|
|
17
|
+
import {
|
|
18
|
+
getOrchestrationsApiPath,
|
|
19
|
+
getOrchestrationRunsApiPath,
|
|
20
|
+
getOrchestrationRunStepsApiPath,
|
|
21
|
+
} from '../internal/paths';
|
|
22
|
+
|
|
23
|
+
export class OrchestrationsManager {
|
|
24
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
25
|
+
private workspaceId: string;
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
workspaceId: string,
|
|
29
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
30
|
+
) {
|
|
31
|
+
this.workspaceId = workspaceId;
|
|
32
|
+
this.requestFn = requestFn;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List all orchestrations in the workspace.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Optional pagination and filtering options
|
|
39
|
+
* @returns Paginated list of orchestrations
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* // List all orchestrations
|
|
44
|
+
* const result = await client.orchestrations.list();
|
|
45
|
+
* console.log('Total:', result.data.meta.total);
|
|
46
|
+
*
|
|
47
|
+
* // With pagination and status filter
|
|
48
|
+
* const result = await client.orchestrations.list({
|
|
49
|
+
* limit: 10,
|
|
50
|
+
* offset: 0,
|
|
51
|
+
* status: 'active'
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
public list(options?: ListOrchestrationsOptions): Promise<ApiResponse<PaginatedResponse<Orchestration>>> {
|
|
56
|
+
const path = getOrchestrationsApiPath(this.workspaceId);
|
|
57
|
+
return this.requestFn<PaginatedResponse<Orchestration>>('GET', path, null, options);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get an orchestration by ID.
|
|
62
|
+
*
|
|
63
|
+
* @param orchestrationId - The orchestration ID
|
|
64
|
+
* @returns The orchestration details including all steps
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* const orch = await client.orchestrations.get('orch-id');
|
|
69
|
+
* console.log('Name:', orch.data.name);
|
|
70
|
+
* console.log('Steps:', orch.data.steps.length);
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
public get(orchestrationId: string): Promise<ApiResponse<Orchestration>> {
|
|
74
|
+
const path = getOrchestrationsApiPath(this.workspaceId, orchestrationId);
|
|
75
|
+
return this.requestFn<Orchestration>('GET', path);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create a new orchestration.
|
|
80
|
+
*
|
|
81
|
+
* @param input - The orchestration definition
|
|
82
|
+
* @returns The created orchestration
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const orch = await client.orchestrations.create({
|
|
87
|
+
* slug: 'order-processing',
|
|
88
|
+
* name: 'Order Processing Workflow',
|
|
89
|
+
* trigger: { type: 'on-demand' },
|
|
90
|
+
* steps: [
|
|
91
|
+
* {
|
|
92
|
+
* id: 'validate',
|
|
93
|
+
* type: 'compute',
|
|
94
|
+
* functionId: 'func_validate',
|
|
95
|
+
* onSuccess: { nextStepId: 'process' }
|
|
96
|
+
* },
|
|
97
|
+
* {
|
|
98
|
+
* id: 'process',
|
|
99
|
+
* type: 'compute',
|
|
100
|
+
* functionId: 'func_process'
|
|
101
|
+
* }
|
|
102
|
+
* ]
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
public create(input: CreateOrchestrationInput): Promise<ApiResponse<Orchestration>> {
|
|
107
|
+
const path = getOrchestrationsApiPath(this.workspaceId);
|
|
108
|
+
return this.requestFn<Orchestration>('POST', path, input);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Update an existing orchestration.
|
|
113
|
+
*
|
|
114
|
+
* Updates increment the orchestration version. Running instances use the
|
|
115
|
+
* version at the time they started.
|
|
116
|
+
*
|
|
117
|
+
* @param orchestrationId - The orchestration ID
|
|
118
|
+
* @param input - Fields to update
|
|
119
|
+
* @returns The updated orchestration
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```ts
|
|
123
|
+
* // Activate an orchestration
|
|
124
|
+
* await client.orchestrations.update('orch-id', { status: 'active' });
|
|
125
|
+
*
|
|
126
|
+
* // Update steps
|
|
127
|
+
* await client.orchestrations.update('orch-id', {
|
|
128
|
+
* steps: [...]
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
public update(orchestrationId: string, input: UpdateOrchestrationInput): Promise<ApiResponse<Orchestration>> {
|
|
133
|
+
const path = getOrchestrationsApiPath(this.workspaceId, orchestrationId);
|
|
134
|
+
return this.requestFn<Orchestration>('PUT', path, input);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Delete an orchestration.
|
|
139
|
+
*
|
|
140
|
+
* This also deletes all runs associated with the orchestration.
|
|
141
|
+
*
|
|
142
|
+
* @param orchestrationId - The orchestration ID
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* await client.orchestrations.delete('orch-id');
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
public delete(orchestrationId: string): Promise<ApiResponse<void>> {
|
|
150
|
+
const path = getOrchestrationsApiPath(this.workspaceId, orchestrationId);
|
|
151
|
+
return this.requestFn<void>('DELETE', path);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Trigger an orchestration run.
|
|
156
|
+
*
|
|
157
|
+
* This creates a new run instance and starts executing the workflow.
|
|
158
|
+
* Can be used on on-demand, draft, or active orchestrations.
|
|
159
|
+
* Paused orchestrations cannot be triggered.
|
|
160
|
+
*
|
|
161
|
+
* @param orchestrationId - The orchestration ID
|
|
162
|
+
* @param options - Optional input data and correlation ID
|
|
163
|
+
* @returns The created run
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* // Simple trigger
|
|
168
|
+
* const run = await client.orchestrations.trigger('orch-id');
|
|
169
|
+
*
|
|
170
|
+
* // With input data
|
|
171
|
+
* const run = await client.orchestrations.trigger('orch-id', {
|
|
172
|
+
* input: {
|
|
173
|
+
* orderId: '12345',
|
|
174
|
+
* customerId: 'cust_abc'
|
|
175
|
+
* }
|
|
176
|
+
* });
|
|
177
|
+
*
|
|
178
|
+
* // With correlation ID for tracing
|
|
179
|
+
* const run = await client.orchestrations.trigger('orch-id', {
|
|
180
|
+
* input: { orderId: '12345' },
|
|
181
|
+
* correlationId: 'req-123'
|
|
182
|
+
* });
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
public trigger(orchestrationId: string, options?: TriggerOrchestrationRunOptions): Promise<ApiResponse<OrchestrationRun>> {
|
|
186
|
+
const path = getOrchestrationRunsApiPath(this.workspaceId, orchestrationId);
|
|
187
|
+
const body = {
|
|
188
|
+
input: options?.input ?? {},
|
|
189
|
+
correlationId: options?.correlationId
|
|
190
|
+
};
|
|
191
|
+
return this.requestFn<OrchestrationRun>('POST', path, body);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* List runs for an orchestration.
|
|
196
|
+
*
|
|
197
|
+
* @param orchestrationId - The orchestration ID
|
|
198
|
+
* @param options - Optional pagination and filtering options
|
|
199
|
+
* @returns Paginated list of runs
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* // List all runs
|
|
204
|
+
* const runs = await client.orchestrations.listRuns('orch-id');
|
|
205
|
+
*
|
|
206
|
+
* // Filter by status
|
|
207
|
+
* const failedRuns = await client.orchestrations.listRuns('orch-id', {
|
|
208
|
+
* status: 'failed'
|
|
209
|
+
* });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
public listRuns(orchestrationId: string, options?: ListOrchestrationRunsOptions): Promise<ApiResponse<PaginatedResponse<OrchestrationRun>>> {
|
|
213
|
+
const path = getOrchestrationRunsApiPath(this.workspaceId, orchestrationId);
|
|
214
|
+
return this.requestFn<PaginatedResponse<OrchestrationRun>>('GET', path, null, options);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get a specific run by ID.
|
|
219
|
+
*
|
|
220
|
+
* @param orchestrationId - The orchestration ID
|
|
221
|
+
* @param runId - The run ID
|
|
222
|
+
* @param includeSteps - Whether to include step execution history
|
|
223
|
+
* @returns The run details
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* // Get basic run info
|
|
228
|
+
* const run = await client.orchestrations.getRun('orch-id', 'run-id');
|
|
229
|
+
* console.log('Status:', run.data.status);
|
|
230
|
+
*
|
|
231
|
+
* // Include step history
|
|
232
|
+
* const run = await client.orchestrations.getRun('orch-id', 'run-id', true);
|
|
233
|
+
* console.log('Steps:', run.data.steps);
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
public getRun(orchestrationId: string, runId: string, includeSteps?: boolean): Promise<ApiResponse<OrchestrationRun & { steps?: OrchestrationRunStep[] }>> {
|
|
237
|
+
const path = getOrchestrationRunsApiPath(this.workspaceId, orchestrationId, runId);
|
|
238
|
+
const params = includeSteps ? { include: 'steps' } : undefined;
|
|
239
|
+
return this.requestFn<OrchestrationRun & { steps?: OrchestrationRunStep[] }>('GET', path, null, params);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get step execution history for a run.
|
|
244
|
+
*
|
|
245
|
+
* @param orchestrationId - The orchestration ID
|
|
246
|
+
* @param runId - The run ID
|
|
247
|
+
* @returns List of step executions
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* const steps = await client.orchestrations.getRunSteps('orch-id', 'run-id');
|
|
252
|
+
* for (const step of steps.data.data) {
|
|
253
|
+
* console.log(`${step.stepId}: ${step.status}`);
|
|
254
|
+
* }
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
public getRunSteps(orchestrationId: string, runId: string): Promise<ApiResponse<{ data: OrchestrationRunStep[]; meta: { total: number } }>> {
|
|
258
|
+
const path = getOrchestrationRunStepsApiPath(this.workspaceId, orchestrationId, runId);
|
|
259
|
+
return this.requestFn<{ data: OrchestrationRunStep[]; meta: { total: number } }>('GET', path);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Activate an orchestration.
|
|
264
|
+
*
|
|
265
|
+
* Convenience method to set status to 'active'.
|
|
266
|
+
* Active orchestrations can be triggered by scheduled events, record events, and webhooks.
|
|
267
|
+
*
|
|
268
|
+
* @param orchestrationId - The orchestration ID
|
|
269
|
+
* @returns The updated orchestration
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* ```ts
|
|
273
|
+
* await client.orchestrations.activate('orch-id');
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
public activate(orchestrationId: string): Promise<ApiResponse<Orchestration>> {
|
|
277
|
+
return this.update(orchestrationId, { status: 'active' });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Pause an orchestration.
|
|
282
|
+
*
|
|
283
|
+
* Convenience method to set status to 'paused'.
|
|
284
|
+
* Paused orchestrations cannot be triggered by any mechanism.
|
|
285
|
+
*
|
|
286
|
+
* @param orchestrationId - The orchestration ID
|
|
287
|
+
* @returns The updated orchestration
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* await client.orchestrations.pause('orch-id');
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
public pause(orchestrationId: string): Promise<ApiResponse<Orchestration>> {
|
|
295
|
+
return this.update(orchestrationId, { status: 'paused' });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Query Manager (canonical query primitives — CEN-1202)
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
validateQueryDefinition,
|
|
7
|
+
translateLegacyQuery,
|
|
8
|
+
parseUrlQuery,
|
|
9
|
+
queryErrorsToHttp,
|
|
10
|
+
} from '@centrali/query';
|
|
11
|
+
import type {
|
|
12
|
+
QueryDefinition,
|
|
13
|
+
QueryError,
|
|
14
|
+
ValidationResult,
|
|
15
|
+
} from '../../query-types';
|
|
16
|
+
import { CentraliError } from '../internal/error';
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Vendored option/result types
|
|
20
|
+
//
|
|
21
|
+
// These mirror the option/result shapes exported from `@centrali/query`
|
|
22
|
+
// (validator.ts, legacyTranslator.ts, urlParser.ts, errorAdapter.ts). They
|
|
23
|
+
// are vendored locally so the published `dist/index.d.ts` does not pull in
|
|
24
|
+
// `@centrali/query` (which would force consumers to install the workspace
|
|
25
|
+
// package — failing the SDK's "one install" promise and breaking
|
|
26
|
+
// `tsc --skipLibCheck=false`).
|
|
27
|
+
//
|
|
28
|
+
// Drift is caught by the parity tests in `tests/queryParity.test.ts` —
|
|
29
|
+
// the runtime functions imported above expect the upstream shapes, and
|
|
30
|
+
// any incompatibility surfaces as a TypeScript error at SDK build time.
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/** Mirror of `@centrali/query`'s `ValidateOptions`. */
|
|
34
|
+
export type QueryValidateOptions = {
|
|
35
|
+
rejectReservedClauses?: boolean;
|
|
36
|
+
reservedClauses?: readonly (keyof QueryDefinition)[];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** Mirror of `@centrali/query`'s `LegacyTranslateWarning`. */
|
|
40
|
+
export type LegacyTranslateWarning = {
|
|
41
|
+
kind:
|
|
42
|
+
| 'regex_translated'
|
|
43
|
+
| 'operator_renamed'
|
|
44
|
+
| 'variable_syntax_canonicalized'
|
|
45
|
+
| 'operator_dropped';
|
|
46
|
+
path: string;
|
|
47
|
+
from: string;
|
|
48
|
+
to?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Mirror of `@centrali/query`'s `LegacyTranslateResult`. */
|
|
52
|
+
export type LegacyTranslateResult = {
|
|
53
|
+
query: QueryDefinition;
|
|
54
|
+
warnings: LegacyTranslateWarning[];
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** Mirror of `@centrali/query`'s `LegacyTranslateOptions`. */
|
|
58
|
+
export type LegacyTranslateOptions = {
|
|
59
|
+
resource?: string;
|
|
60
|
+
dataProperties?: ReadonlySet<string>;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** Mirror of `@centrali/query`'s `ParsedUrlQuery`. */
|
|
64
|
+
export type ParsedUrlQuery = {
|
|
65
|
+
query: QueryDefinition;
|
|
66
|
+
searchTerm?: string;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** Mirror of `@centrali/query`'s `UrlParserOptions`. */
|
|
70
|
+
export type UrlParserOptions = {
|
|
71
|
+
resource: string;
|
|
72
|
+
filterableFields?: readonly string[];
|
|
73
|
+
defaultLimit?: number;
|
|
74
|
+
maxLimit?: number;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** Mirror of `@centrali/query`'s `QueryHttpErrorCode`. */
|
|
78
|
+
export type QueryHttpErrorCode =
|
|
79
|
+
| 'UNSUPPORTED_CLAUSE'
|
|
80
|
+
| 'UNSUPPORTED_OPERATOR'
|
|
81
|
+
| 'UNSUPPORTED_LEGACY_OPERATOR'
|
|
82
|
+
| 'UNREADABLE_FIELD'
|
|
83
|
+
| 'INVALID_QUERY'
|
|
84
|
+
| 'LEGACY_WRITE_UNSUPPORTED'
|
|
85
|
+
| 'UNKNOWN_VARIABLE'
|
|
86
|
+
| 'VARIABLE_TYPE_MISMATCH'
|
|
87
|
+
| 'MISSING_REQUIRED_VARIABLE'
|
|
88
|
+
| 'EXTRA_VARIABLE'
|
|
89
|
+
| 'JOINS_LENGTH_EXCEEDED'
|
|
90
|
+
| 'UNSUPPORTED_COMBINATION'
|
|
91
|
+
| 'DUPLICATE_JOIN_ALIAS';
|
|
92
|
+
|
|
93
|
+
/** Mirror of `@centrali/query`'s `QueryHttpError`. */
|
|
94
|
+
export type QueryHttpError = {
|
|
95
|
+
status: number;
|
|
96
|
+
code: QueryHttpErrorCode;
|
|
97
|
+
message: string;
|
|
98
|
+
errors: QueryError[];
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* QueryManager exposes the canonical query primitives bundled into the SDK.
|
|
103
|
+
*
|
|
104
|
+
* The same source that runs server-side (`@centrali/query`) is bundled into
|
|
105
|
+
* the SDK artifact, so callers can validate a `QueryDefinition` locally and
|
|
106
|
+
* skip a roundtrip when the body is malformed. Output is byte-for-byte
|
|
107
|
+
* identical to the server's validator.
|
|
108
|
+
*
|
|
109
|
+
* Access via `client.query`.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* const result = client.query.validate({
|
|
114
|
+
* resource: 'orders',
|
|
115
|
+
* where: { 'data.status': { eq: 'open' } },
|
|
116
|
+
* page: { limit: 50 },
|
|
117
|
+
* });
|
|
118
|
+
* if (!result.ok) {
|
|
119
|
+
* for (const err of result.errors) console.log(err.code, err.path, err.message);
|
|
120
|
+
* }
|
|
121
|
+
*
|
|
122
|
+
* // Migrate a legacy saved-query body to canonical
|
|
123
|
+
* const t = client.query.translateLegacy({ collection: 'orders', limit: 25 });
|
|
124
|
+
* if (t.ok) console.log(t.value.query, t.value.warnings);
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
export class QueryManager {
|
|
128
|
+
/**
|
|
129
|
+
* Validate a canonical `QueryDefinition` locally. Returns the same
|
|
130
|
+
* `ValidationResult` shape the server returns — `ok: true` plus the
|
|
131
|
+
* narrowed value, or `ok: false` plus the error list.
|
|
132
|
+
*/
|
|
133
|
+
public validate(
|
|
134
|
+
definition: unknown,
|
|
135
|
+
options?: QueryValidateOptions
|
|
136
|
+
): ValidationResult<QueryDefinition> {
|
|
137
|
+
return validateQueryDefinition(definition, options);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Translate a legacy query body (`{ collection, $eq, ... }`) into a
|
|
142
|
+
* canonical `QueryDefinition`. Useful for migration tooling and for
|
|
143
|
+
* smart-query authors carrying older bodies forward.
|
|
144
|
+
*
|
|
145
|
+
* Returns translation warnings alongside the canonical query so callers
|
|
146
|
+
* can surface "this used to be a regex / dropped operator" notes.
|
|
147
|
+
*/
|
|
148
|
+
public translateLegacy(
|
|
149
|
+
legacyBody: unknown,
|
|
150
|
+
options?: LegacyTranslateOptions
|
|
151
|
+
): ValidationResult<LegacyTranslateResult> {
|
|
152
|
+
return translateLegacyQuery(legacyBody, options) as ValidationResult<LegacyTranslateResult>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Parse a URL-style flat query (`?status=paid&sort=-createdAt&limit=10`)
|
|
157
|
+
* into a canonical `QueryDefinition` slice. Mirrors the server-side
|
|
158
|
+
* GET-adapter so SDK consumers can pre-build canonical bodies from
|
|
159
|
+
* search-page URL state without a roundtrip.
|
|
160
|
+
*/
|
|
161
|
+
public parseUrl(
|
|
162
|
+
params: Record<string, unknown>,
|
|
163
|
+
options: UrlParserOptions
|
|
164
|
+
): ValidationResult<ParsedUrlQuery> {
|
|
165
|
+
return parseUrlQuery(params, options) as ValidationResult<ParsedUrlQuery>;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Aggregate one or more `QueryError`s into the same `{ status, code,
|
|
170
|
+
* message, errors }` shape the server emits. Use to convert a
|
|
171
|
+
* validation failure into a thrown `CentraliError` matching the wire
|
|
172
|
+
* format.
|
|
173
|
+
*/
|
|
174
|
+
public errorsToHttp(errors: QueryError[]): QueryHttpError {
|
|
175
|
+
return queryErrorsToHttp(errors) as QueryHttpError;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Convert a list of `QueryError`s to a `CentraliError` matching what the
|
|
181
|
+
* server would have sent on a `422`. Used by `RecordsManager.query()` for
|
|
182
|
+
* local pre-rejection.
|
|
183
|
+
*
|
|
184
|
+
* @internal
|
|
185
|
+
*/
|
|
186
|
+
export function queryErrorsToCentraliError(errors: QueryError[]): CentraliError {
|
|
187
|
+
const http = queryErrorsToHttp(errors);
|
|
188
|
+
const fieldErrors = errors
|
|
189
|
+
.filter((e) => typeof e.path === 'string' && e.path.length > 0)
|
|
190
|
+
.map((e) => ({ field: e.path as string, message: e.message }));
|
|
191
|
+
return new CentraliError(
|
|
192
|
+
http.message,
|
|
193
|
+
http.status,
|
|
194
|
+
http.status === 422 ? 'Unprocessable Entity' : 'Bad Request',
|
|
195
|
+
{ code: http.code, message: http.message, errors: http.errors },
|
|
196
|
+
http.code,
|
|
197
|
+
fieldErrors.length > 0 ? fieldErrors : undefined
|
|
198
|
+
);
|
|
199
|
+
}
|