@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,90 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Allowed Domains Manager
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse } from '../types/common';
|
|
7
|
+
import type { AllowedDomain, AddAllowedDomainOptions } from '../types/allowedDomains';
|
|
8
|
+
import { getAllowedDomainsApiPath } from '../internal/paths';
|
|
9
|
+
|
|
10
|
+
// =====================================================
|
|
11
|
+
// Allowed Domains Manager
|
|
12
|
+
// =====================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* AllowedDomainsManager provides methods for managing allowed domains for compute function external calls.
|
|
16
|
+
* Access via `client.allowedDomains`.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ```ts
|
|
20
|
+
* // List all allowed domains
|
|
21
|
+
* const domains = await client.allowedDomains.list();
|
|
22
|
+
*
|
|
23
|
+
* // Add a new domain
|
|
24
|
+
* const domain = await client.allowedDomains.add({ domain: 'api.example.com' });
|
|
25
|
+
*
|
|
26
|
+
* // Remove a domain
|
|
27
|
+
* await client.allowedDomains.remove('domain-id');
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class AllowedDomainsManager {
|
|
31
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
32
|
+
private workspaceId: string;
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
workspaceId: string,
|
|
36
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
37
|
+
) {
|
|
38
|
+
this.workspaceId = workspaceId;
|
|
39
|
+
this.requestFn = requestFn;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* List all allowed domains in the workspace.
|
|
44
|
+
*
|
|
45
|
+
* @returns List of allowed domains with total count
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const result = await client.allowedDomains.list();
|
|
50
|
+
* console.log('Total domains:', result.meta.total);
|
|
51
|
+
* result.data.forEach(d => console.log(d.domain));
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
public list(): Promise<ApiResponse<AllowedDomain[]>> {
|
|
55
|
+
const path = getAllowedDomainsApiPath(this.workspaceId);
|
|
56
|
+
return this.requestFn<AllowedDomain[]>('GET', path);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Add a new allowed domain.
|
|
61
|
+
*
|
|
62
|
+
* @param options - The domain to add
|
|
63
|
+
* @returns The created allowed domain entry
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const result = await client.allowedDomains.add({ domain: 'api.stripe.com' });
|
|
68
|
+
* console.log('Added:', result.data.domain, result.data.id);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
public add(options: AddAllowedDomainOptions): Promise<ApiResponse<AllowedDomain>> {
|
|
72
|
+
const path = getAllowedDomainsApiPath(this.workspaceId);
|
|
73
|
+
return this.requestFn<AllowedDomain>('POST', path, { domain: options.domain });
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Remove an allowed domain by ID.
|
|
78
|
+
*
|
|
79
|
+
* @param domainId - The ID of the domain to remove
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* await client.allowedDomains.remove('domain-id-123');
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
public remove(domainId: string): Promise<ApiResponse<void>> {
|
|
87
|
+
const path = getAllowedDomainsApiPath(this.workspaceId, domainId);
|
|
88
|
+
return this.requestFn<void>('DELETE', path);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Anomaly Insights Manager
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse } from '../types/common';
|
|
7
|
+
import type {
|
|
8
|
+
AnomalyInsight,
|
|
9
|
+
ListInsightsOptions,
|
|
10
|
+
AnomalyAnalysisResult,
|
|
11
|
+
InsightsSummary,
|
|
12
|
+
} from '../types/insights';
|
|
13
|
+
import {
|
|
14
|
+
getAnomalyInsightsApiPath,
|
|
15
|
+
getStructureInsightsApiPath,
|
|
16
|
+
getAnomalyInsightAcknowledgeApiPath,
|
|
17
|
+
getAnomalyInsightDismissApiPath,
|
|
18
|
+
getAnomalyInsightsBulkAcknowledgeApiPath,
|
|
19
|
+
getAnomalyInsightsSummaryApiPath,
|
|
20
|
+
getAnomalyAnalysisTriggerApiPath,
|
|
21
|
+
} from '../internal/paths';
|
|
22
|
+
|
|
23
|
+
// =====================================================
|
|
24
|
+
// Anomaly Insights Manager
|
|
25
|
+
// =====================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* AnomalyInsightsManager provides methods for querying and managing AI-generated anomaly insights.
|
|
29
|
+
* Access via `client.anomalyInsights`.
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* ```ts
|
|
33
|
+
* // List all active insights
|
|
34
|
+
* const insights = await client.anomalyInsights.list({ status: 'active' });
|
|
35
|
+
*
|
|
36
|
+
* // Get insights for a specific structure
|
|
37
|
+
* const orderInsights = await client.anomalyInsights.listByStructure('orders');
|
|
38
|
+
*
|
|
39
|
+
* // Get insight summary
|
|
40
|
+
* const summary = await client.anomalyInsights.getSummary();
|
|
41
|
+
*
|
|
42
|
+
* // Acknowledge an insight
|
|
43
|
+
* await client.anomalyInsights.acknowledge('insight-id');
|
|
44
|
+
*
|
|
45
|
+
* // Dismiss an insight
|
|
46
|
+
* await client.anomalyInsights.dismiss('insight-id');
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class AnomalyInsightsManager {
|
|
50
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
51
|
+
private workspaceId: string;
|
|
52
|
+
|
|
53
|
+
constructor(
|
|
54
|
+
workspaceId: string,
|
|
55
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
56
|
+
) {
|
|
57
|
+
this.workspaceId = workspaceId;
|
|
58
|
+
this.requestFn = requestFn;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* List anomaly insights with optional filters.
|
|
63
|
+
*
|
|
64
|
+
* @param options - Optional filter and pagination options
|
|
65
|
+
* @returns List of anomaly insights
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // List all active critical insights
|
|
70
|
+
* const insights = await client.anomalyInsights.list({
|
|
71
|
+
* status: 'active',
|
|
72
|
+
* severity: 'critical'
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* // List insights for a specific structure
|
|
76
|
+
* const orderInsights = await client.anomalyInsights.list({
|
|
77
|
+
* structureSlug: 'orders'
|
|
78
|
+
* });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
public list(options?: ListInsightsOptions): Promise<ApiResponse<AnomalyInsight[]>> {
|
|
82
|
+
const path = getAnomalyInsightsApiPath(this.workspaceId);
|
|
83
|
+
return this.requestFn<AnomalyInsight[]>('GET', path, null, options);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* List insights for a specific structure.
|
|
88
|
+
*
|
|
89
|
+
* @param structureSlug - The structure's record slug
|
|
90
|
+
* @param options - Optional filter options
|
|
91
|
+
* @returns List of insights for the structure
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* const insights = await client.anomalyInsights.listByStructure('orders');
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
public listByStructure(
|
|
99
|
+
structureSlug: string,
|
|
100
|
+
options?: Omit<ListInsightsOptions, 'structureSlug'>
|
|
101
|
+
): Promise<ApiResponse<AnomalyInsight[]>> {
|
|
102
|
+
const path = getStructureInsightsApiPath(this.workspaceId, structureSlug);
|
|
103
|
+
return this.requestFn<AnomalyInsight[]>('GET', path, null, options);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get a single insight by ID.
|
|
108
|
+
*
|
|
109
|
+
* @param insightId - The insight UUID
|
|
110
|
+
* @returns The insight details
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* const insight = await client.anomalyInsights.get('insight-id');
|
|
115
|
+
* console.log('Insight:', insight.data.title);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
public get(insightId: string): Promise<ApiResponse<AnomalyInsight>> {
|
|
119
|
+
const path = getAnomalyInsightsApiPath(this.workspaceId, insightId);
|
|
120
|
+
return this.requestFn<AnomalyInsight>('GET', path);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Acknowledge an insight.
|
|
125
|
+
* Marks the insight as reviewed/handled.
|
|
126
|
+
*
|
|
127
|
+
* @param insightId - The insight UUID
|
|
128
|
+
* @returns The updated insight
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* await client.anomalyInsights.acknowledge('insight-id');
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
public acknowledge(insightId: string): Promise<ApiResponse<AnomalyInsight>> {
|
|
136
|
+
const path = getAnomalyInsightAcknowledgeApiPath(this.workspaceId, insightId);
|
|
137
|
+
return this.requestFn<AnomalyInsight>('POST', path);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Dismiss an insight.
|
|
142
|
+
* Marks the insight as not relevant/false positive.
|
|
143
|
+
*
|
|
144
|
+
* @param insightId - The insight UUID
|
|
145
|
+
* @returns The updated insight
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* await client.anomalyInsights.dismiss('insight-id');
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
public dismiss(insightId: string): Promise<ApiResponse<AnomalyInsight>> {
|
|
153
|
+
const path = getAnomalyInsightDismissApiPath(this.workspaceId, insightId);
|
|
154
|
+
return this.requestFn<AnomalyInsight>('POST', path);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Bulk acknowledge multiple insights.
|
|
159
|
+
*
|
|
160
|
+
* @param ids - Array of insight IDs to acknowledge
|
|
161
|
+
* @returns Result with count of updated insights
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```ts
|
|
165
|
+
* const result = await client.anomalyInsights.bulkAcknowledge(['id1', 'id2']);
|
|
166
|
+
* console.log('Acknowledged:', result.data.updated);
|
|
167
|
+
* ```
|
|
168
|
+
*/
|
|
169
|
+
public bulkAcknowledge(ids: string[]): Promise<ApiResponse<{ updated: number; message: string }>> {
|
|
170
|
+
const path = getAnomalyInsightsBulkAcknowledgeApiPath(this.workspaceId);
|
|
171
|
+
return this.requestFn<{ updated: number; message: string }>('POST', path, { ids });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get insights summary/statistics.
|
|
176
|
+
*
|
|
177
|
+
* @param structureSlug - Optional structure to filter summary
|
|
178
|
+
* @returns Summary of insights by status and severity
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* // Get overall summary
|
|
183
|
+
* const summary = await client.anomalyInsights.getSummary();
|
|
184
|
+
* console.log('Critical insights:', summary.data.bySeverity.critical);
|
|
185
|
+
*
|
|
186
|
+
* // Get summary for a specific structure
|
|
187
|
+
* const orderSummary = await client.anomalyInsights.getSummary('orders');
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
public getSummary(structureSlug?: string): Promise<ApiResponse<InsightsSummary>> {
|
|
191
|
+
const path = getAnomalyInsightsSummaryApiPath(this.workspaceId);
|
|
192
|
+
const params = structureSlug ? { structureSlug } : undefined;
|
|
193
|
+
return this.requestFn<InsightsSummary>('GET', path, null, params);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Trigger anomaly analysis for a structure.
|
|
198
|
+
* Starts an AI-powered analysis to detect anomalies in the structure's data.
|
|
199
|
+
*
|
|
200
|
+
* @param structureSlug - The structure's record slug to analyze
|
|
201
|
+
* @returns Result indicating if analysis was triggered and the batch ID
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* const result = await client.anomalyInsights.triggerAnalysis('orders');
|
|
206
|
+
* if (result.data.success) {
|
|
207
|
+
* console.log('Analysis started:', result.data.batchId);
|
|
208
|
+
* }
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
public triggerAnalysis(structureSlug: string): Promise<ApiResponse<AnomalyAnalysisResult>> {
|
|
212
|
+
const path = getAnomalyAnalysisTriggerApiPath(this.workspaceId);
|
|
213
|
+
return this.requestFn<AnomalyAnalysisResult>('POST', path, { structureSlug });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Audit Log Manager (canonical query surface — CEN-1215)
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse } from '../types/common';
|
|
7
|
+
import type { QueryDefinition, QueryResult } from '../../query-types';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* AuditLogManager exposes the canonical query surface for the audit log.
|
|
12
|
+
*
|
|
13
|
+
* Phase 3 of the query foundation (CEN-1214 epic). Workspace-service backed,
|
|
14
|
+
* not data-service — the audit log is a workspace concern. The shape mirrors
|
|
15
|
+
* `RecordsManager` so a caller writing audit-log queries uses the same
|
|
16
|
+
* vocabulary they already know from records.
|
|
17
|
+
*
|
|
18
|
+
* - {@link AuditLogManager.query | query} — full POST `/audit/query`. Use for
|
|
19
|
+
* nested boolean trees, `select` projection, paging.
|
|
20
|
+
* - {@link AuditLogManager.test | test} — authoring dry-run against
|
|
21
|
+
* `/audit/query/test`. Validates and plans without executing.
|
|
22
|
+
*
|
|
23
|
+
* Access via `client.auditLog`.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* // Per-resource history (canonical equivalent of legacy GET /audit/.../history).
|
|
28
|
+
* const history = await client.auditLog.query({
|
|
29
|
+
* resource: 'audit-log',
|
|
30
|
+
* where: {
|
|
31
|
+
* and: [
|
|
32
|
+
* { resourceType: { eq: 'structure' } },
|
|
33
|
+
* { resourceId: { eq: 'r-123' } },
|
|
34
|
+
* ],
|
|
35
|
+
* },
|
|
36
|
+
* sort: [{ field: 'createdAt', direction: 'desc' }],
|
|
37
|
+
* page: { limit: 50 },
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // Workspace-wide activity feed in a date range, projecting only the columns
|
|
41
|
+
* // the table needs (drops the heavy `changes` JSONB).
|
|
42
|
+
* const activity = await client.auditLog.query({
|
|
43
|
+
* resource: 'audit-log',
|
|
44
|
+
* where: {
|
|
45
|
+
* and: [
|
|
46
|
+
* { createdAt: { gte: '2026-04-01' } },
|
|
47
|
+
* { createdAt: { lt: '2026-05-01' } },
|
|
48
|
+
* ],
|
|
49
|
+
* },
|
|
50
|
+
* sort: [{ field: 'createdAt', direction: 'desc' }],
|
|
51
|
+
* page: { limit: 100 },
|
|
52
|
+
* select: { fields: ['type', 'resourceType', 'resourceId', 'actorId', 'summary', 'createdAt'] },
|
|
53
|
+
* });
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export class AuditLogManager {
|
|
57
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
58
|
+
private workspaceId: string;
|
|
59
|
+
|
|
60
|
+
constructor(
|
|
61
|
+
workspaceId: string,
|
|
62
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
63
|
+
) {
|
|
64
|
+
this.workspaceId = workspaceId;
|
|
65
|
+
this.requestFn = requestFn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Run a canonical query against `POST /workspace/<ws>/api/v1/audit/query`.
|
|
70
|
+
*
|
|
71
|
+
* The body **is** a `QueryDefinition`. `resource` is forced to `"audit-log"`
|
|
72
|
+
* — the workspace executor rejects anything else. Returns the canonical
|
|
73
|
+
* `{ data, meta }` envelope.
|
|
74
|
+
*
|
|
75
|
+
* The `where` clause that pins both `resourceType.eq` and `resourceId.eq`
|
|
76
|
+
* uses `audit_logs:retrieve` server-side; everything else uses
|
|
77
|
+
* `audit_logs:list`. Retrieve-only roles can still query their own
|
|
78
|
+
* resource's history this way.
|
|
79
|
+
*/
|
|
80
|
+
public async query<T = any>(
|
|
81
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
82
|
+
): Promise<QueryResult<T>> {
|
|
83
|
+
const path = `workspace/api/v1/${this.workspaceId}/audit/query`;
|
|
84
|
+
const body: QueryDefinition = { ...definition, resource: 'audit-log' };
|
|
85
|
+
const resp = await this.requestFn<T[]>('POST', path, body);
|
|
86
|
+
return resp as unknown as QueryResult<T>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Authoring-time dry-run against `POST /audit/query/test`.
|
|
91
|
+
*
|
|
92
|
+
* Same input shape as {@link AuditLogManager.query | query}. Returns a
|
|
93
|
+
* plan summary on success or structured `QueryError`s on failure, without
|
|
94
|
+
* executing the query. Use from query builders to surface precise errors
|
|
95
|
+
* before saving / running.
|
|
96
|
+
*/
|
|
97
|
+
public async test(
|
|
98
|
+
definition: Omit<QueryDefinition, 'resource'> & { resource?: string }
|
|
99
|
+
): Promise<{ ok: true; plan: { executor: string; resource: string; mode: string; hasUnreadableField: boolean } }> {
|
|
100
|
+
const path = `workspace/api/v1/${this.workspaceId}/audit/query/test`;
|
|
101
|
+
const body: QueryDefinition = { ...definition, resource: 'audit-log' };
|
|
102
|
+
const resp = await this.requestFn<{ ok: true; plan: { executor: string; resource: string; mode: string; hasUnreadableField: boolean } }>('POST', path, body);
|
|
103
|
+
return resp.data;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
// =====================================================
|
|
2
|
+
// Collections Manager (Configuration-as-Code)
|
|
3
|
+
// =====================================================
|
|
4
|
+
|
|
5
|
+
import type { Method } from 'axios';
|
|
6
|
+
import type { ApiResponse } from '../types/common';
|
|
7
|
+
import type {
|
|
8
|
+
Structure,
|
|
9
|
+
CreateStructureInput,
|
|
10
|
+
UpdateStructureInput,
|
|
11
|
+
ListCollectionsOptions,
|
|
12
|
+
ValidateStructureInput,
|
|
13
|
+
} from '../types/structures';
|
|
14
|
+
import {
|
|
15
|
+
getCollectionsApiPath,
|
|
16
|
+
getCollectionBySlugApiPath,
|
|
17
|
+
getCollectionValidateApiPath,
|
|
18
|
+
} from '../internal/paths';
|
|
19
|
+
|
|
20
|
+
// =====================================================
|
|
21
|
+
// Collections Manager (Configuration-as-Code)
|
|
22
|
+
// =====================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* CollectionsManager provides methods for managing data collections (schemas).
|
|
26
|
+
* Collections define the shape of records including properties, validation rules,
|
|
27
|
+
* and schema discovery modes.
|
|
28
|
+
* Access via `client.collections`.
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* ```ts
|
|
32
|
+
* // List all collections
|
|
33
|
+
* const collections = await client.collections.list();
|
|
34
|
+
*
|
|
35
|
+
* // Create a new collection
|
|
36
|
+
* const collection = await client.collections.create({
|
|
37
|
+
* name: 'Orders',
|
|
38
|
+
* recordSlug: 'orders',
|
|
39
|
+
* properties: [
|
|
40
|
+
* { name: 'title', type: 'string', required: true },
|
|
41
|
+
* { name: 'amount', type: 'number', minimum: 0 }
|
|
42
|
+
* ]
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* // Validate before creating
|
|
46
|
+
* const validation = await client.collections.validate({ recordSlug: 'orders' });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export class CollectionsManager {
|
|
50
|
+
private requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>;
|
|
51
|
+
private workspaceId: string;
|
|
52
|
+
|
|
53
|
+
constructor(
|
|
54
|
+
workspaceId: string,
|
|
55
|
+
requestFn: <T>(method: Method, path: string, data?: any, queryParams?: Record<string, any>) => Promise<ApiResponse<T>>
|
|
56
|
+
) {
|
|
57
|
+
this.workspaceId = workspaceId;
|
|
58
|
+
this.requestFn = requestFn;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* List all collections in the workspace.
|
|
63
|
+
*
|
|
64
|
+
* @param options - Optional list parameters (pagination)
|
|
65
|
+
* @returns List of collections
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const collections = await client.collections.list();
|
|
70
|
+
* const page2 = await client.collections.list({ page: 2, limit: 10 });
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
public list(options?: ListCollectionsOptions): Promise<ApiResponse<Structure[]>> {
|
|
74
|
+
const path = getCollectionsApiPath(this.workspaceId);
|
|
75
|
+
return this.requestFn<Structure[]>('GET', path, null, options);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get a collection by ID.
|
|
80
|
+
*
|
|
81
|
+
* @param collectionId - The collection UUID
|
|
82
|
+
* @returns The collection details
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const collection = await client.collections.get('collection-uuid');
|
|
87
|
+
* console.log('Properties:', collection.data.properties.length);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
public get(collectionId: string): Promise<ApiResponse<Structure>> {
|
|
91
|
+
const path = getCollectionsApiPath(this.workspaceId, collectionId);
|
|
92
|
+
return this.requestFn<Structure>('GET', path);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get a collection by its record slug.
|
|
97
|
+
*
|
|
98
|
+
* @param recordSlug - The collection's record slug (e.g., "orders")
|
|
99
|
+
* @returns The collection details
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* const collection = await client.collections.getBySlug('orders');
|
|
104
|
+
* console.log('Collection name:', collection.data.name);
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
public getBySlug(recordSlug: string): Promise<ApiResponse<Structure>> {
|
|
108
|
+
const path = getCollectionBySlugApiPath(this.workspaceId, recordSlug);
|
|
109
|
+
return this.requestFn<Structure>('GET', path);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Create a new collection.
|
|
114
|
+
*
|
|
115
|
+
* @param input - The collection definition
|
|
116
|
+
* @returns The created collection
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* const collection = await client.collections.create({
|
|
121
|
+
* name: 'Orders',
|
|
122
|
+
* recordSlug: 'orders',
|
|
123
|
+
* description: 'Customer orders',
|
|
124
|
+
* properties: [
|
|
125
|
+
* { name: 'title', type: 'string', required: true },
|
|
126
|
+
* { name: 'amount', type: 'number', minimum: 0 },
|
|
127
|
+
* { name: 'status', type: 'string', enum: ['pending', 'completed'] }
|
|
128
|
+
* ],
|
|
129
|
+
* enableVersioning: true,
|
|
130
|
+
* schemaDiscoveryMode: 'strict'
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
public create(input: CreateStructureInput): Promise<ApiResponse<Structure>> {
|
|
135
|
+
const path = getCollectionsApiPath(this.workspaceId);
|
|
136
|
+
return this.requestFn<Structure>('POST', path, input);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Update an existing collection.
|
|
141
|
+
*
|
|
142
|
+
* @param collectionId - The collection UUID
|
|
143
|
+
* @param input - The fields to update
|
|
144
|
+
* @returns The updated collection
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* const updated = await client.collections.update('collection-uuid', {
|
|
149
|
+
* name: 'Updated Orders',
|
|
150
|
+
* properties: [
|
|
151
|
+
* { name: 'title', type: 'string', required: true },
|
|
152
|
+
* { name: 'amount', type: 'number', minimum: 0 },
|
|
153
|
+
* { name: 'priority', type: 'number' }
|
|
154
|
+
* ]
|
|
155
|
+
* });
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
public update(collectionId: string, input: UpdateStructureInput): Promise<ApiResponse<Structure>> {
|
|
159
|
+
const path = getCollectionsApiPath(this.workspaceId, collectionId);
|
|
160
|
+
return this.requestFn<Structure>('PUT', path, input);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Delete a collection.
|
|
165
|
+
*
|
|
166
|
+
* @param collectionId - The collection UUID
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* await client.collections.delete('collection-uuid');
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
public delete(collectionId: string): Promise<ApiResponse<void>> {
|
|
174
|
+
const path = getCollectionsApiPath(this.workspaceId, collectionId);
|
|
175
|
+
return this.requestFn<void>('DELETE', path);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Validate a collection definition without creating it.
|
|
180
|
+
* Useful for checking slug uniqueness and property validity before creation.
|
|
181
|
+
*
|
|
182
|
+
* @param input - The collection definition to validate
|
|
183
|
+
* @returns Validation result
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* const result = await client.collections.validate({
|
|
188
|
+
* slug: 'orders',
|
|
189
|
+
* properties: [{ name: 'title', type: 'string' }]
|
|
190
|
+
* });
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
public validate(input: ValidateStructureInput): Promise<ApiResponse<any>> {
|
|
194
|
+
const path = getCollectionValidateApiPath(this.workspaceId);
|
|
195
|
+
return this.requestFn<any>('POST', path, input);
|
|
196
|
+
}
|
|
197
|
+
}
|