mcp-dataverse 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/.env.example +15 -0
- package/CAPABILITIES.md +992 -0
- package/LICENSE +21 -0
- package/README.md +277 -0
- package/config.example.json +11 -0
- package/dist/auth/auth-provider.factory.d.ts +4 -0
- package/dist/auth/auth-provider.factory.d.ts.map +1 -0
- package/dist/auth/auth-provider.factory.js +15 -0
- package/dist/auth/auth-provider.factory.js.map +1 -0
- package/dist/auth/auth-provider.interface.d.ts +21 -0
- package/dist/auth/auth-provider.interface.d.ts.map +1 -0
- package/dist/auth/auth-provider.interface.js +2 -0
- package/dist/auth/auth-provider.interface.js.map +1 -0
- package/dist/auth/msal-auth-provider.d.ts +14 -0
- package/dist/auth/msal-auth-provider.d.ts.map +1 -0
- package/dist/auth/msal-auth-provider.js +62 -0
- package/dist/auth/msal-auth-provider.js.map +1 -0
- package/dist/auth/pac-auth-provider.d.ts +19 -0
- package/dist/auth/pac-auth-provider.d.ts.map +1 -0
- package/dist/auth/pac-auth-provider.js +153 -0
- package/dist/auth/pac-auth-provider.js.map +1 -0
- package/dist/config/config.loader.d.ts +3 -0
- package/dist/config/config.loader.d.ts.map +1 -0
- package/dist/config/config.loader.js +52 -0
- package/dist/config/config.loader.js.map +1 -0
- package/dist/config/config.schema.d.ts +34 -0
- package/dist/config/config.schema.d.ts.map +1 -0
- package/dist/config/config.schema.js +25 -0
- package/dist/config/config.schema.js.map +1 -0
- package/dist/dataverse/dataverse-client-advanced.d.ts +47 -0
- package/dist/dataverse/dataverse-client-advanced.d.ts.map +1 -0
- package/dist/dataverse/dataverse-client-advanced.js +147 -0
- package/dist/dataverse/dataverse-client-advanced.js.map +1 -0
- package/dist/dataverse/dataverse-client.d.ts +49 -0
- package/dist/dataverse/dataverse-client.d.ts.map +1 -0
- package/dist/dataverse/dataverse-client.js +313 -0
- package/dist/dataverse/dataverse-client.js.map +1 -0
- package/dist/dataverse/dataverse-client.metadata.d.ts +40 -0
- package/dist/dataverse/dataverse-client.metadata.d.ts.map +1 -0
- package/dist/dataverse/dataverse-client.metadata.js +121 -0
- package/dist/dataverse/dataverse-client.metadata.js.map +1 -0
- package/dist/dataverse/dataverse-client.utils.d.ts +14 -0
- package/dist/dataverse/dataverse-client.utils.d.ts.map +1 -0
- package/dist/dataverse/dataverse-client.utils.js +65 -0
- package/dist/dataverse/dataverse-client.utils.js.map +1 -0
- package/dist/dataverse/http-client.d.ts +36 -0
- package/dist/dataverse/http-client.d.ts.map +1 -0
- package/dist/dataverse/http-client.js +103 -0
- package/dist/dataverse/http-client.js.map +1 -0
- package/dist/dataverse/types.d.ts +68 -0
- package/dist/dataverse/types.d.ts.map +1 -0
- package/dist/dataverse/types.js +2 -0
- package/dist/dataverse/types.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +165 -0
- package/dist/server.js.map +1 -0
- package/dist/setup-auth.d.ts +2 -0
- package/dist/setup-auth.d.ts.map +1 -0
- package/dist/setup-auth.js +29 -0
- package/dist/setup-auth.js.map +1 -0
- package/dist/tools/actions.tools.d.ts +170 -0
- package/dist/tools/actions.tools.d.ts.map +1 -0
- package/dist/tools/actions.tools.js +179 -0
- package/dist/tools/actions.tools.js.map +1 -0
- package/dist/tools/annotations.tools.d.ts +82 -0
- package/dist/tools/annotations.tools.d.ts.map +1 -0
- package/dist/tools/annotations.tools.js +180 -0
- package/dist/tools/annotations.tools.js.map +1 -0
- package/dist/tools/audit.tools.d.ts +45 -0
- package/dist/tools/audit.tools.d.ts.map +1 -0
- package/dist/tools/audit.tools.js +163 -0
- package/dist/tools/audit.tools.js.map +1 -0
- package/dist/tools/auth.tools.d.ts +17 -0
- package/dist/tools/auth.tools.d.ts.map +1 -0
- package/dist/tools/auth.tools.js +30 -0
- package/dist/tools/auth.tools.js.map +1 -0
- package/dist/tools/batch.tools.d.ts +45 -0
- package/dist/tools/batch.tools.d.ts.map +1 -0
- package/dist/tools/batch.tools.js +71 -0
- package/dist/tools/batch.tools.js.map +1 -0
- package/dist/tools/crud.tools.d.ts +206 -0
- package/dist/tools/crud.tools.d.ts.map +1 -0
- package/dist/tools/crud.tools.js +213 -0
- package/dist/tools/crud.tools.js.map +1 -0
- package/dist/tools/customization.tools.d.ts +75 -0
- package/dist/tools/customization.tools.d.ts.map +1 -0
- package/dist/tools/customization.tools.js +187 -0
- package/dist/tools/customization.tools.js.map +1 -0
- package/dist/tools/environment.tools.d.ts +40 -0
- package/dist/tools/environment.tools.d.ts.map +1 -0
- package/dist/tools/environment.tools.js +145 -0
- package/dist/tools/environment.tools.js.map +1 -0
- package/dist/tools/file.tools.d.ts +61 -0
- package/dist/tools/file.tools.d.ts.map +1 -0
- package/dist/tools/file.tools.js +142 -0
- package/dist/tools/file.tools.js.map +1 -0
- package/dist/tools/impersonate.tools.d.ts +37 -0
- package/dist/tools/impersonate.tools.d.ts.map +1 -0
- package/dist/tools/impersonate.tools.js +85 -0
- package/dist/tools/impersonate.tools.js.map +1 -0
- package/dist/tools/metadata.tools.d.ts +156 -0
- package/dist/tools/metadata.tools.d.ts.map +1 -0
- package/dist/tools/metadata.tools.js +200 -0
- package/dist/tools/metadata.tools.js.map +1 -0
- package/dist/tools/org.tools.d.ts +26 -0
- package/dist/tools/org.tools.d.ts.map +1 -0
- package/dist/tools/org.tools.js +57 -0
- package/dist/tools/org.tools.js.map +1 -0
- package/dist/tools/quality.tools.d.ts +30 -0
- package/dist/tools/quality.tools.d.ts.map +1 -0
- package/dist/tools/quality.tools.js +69 -0
- package/dist/tools/quality.tools.js.map +1 -0
- package/dist/tools/query.tools.d.ts +120 -0
- package/dist/tools/query.tools.d.ts.map +1 -0
- package/dist/tools/query.tools.js +182 -0
- package/dist/tools/query.tools.js.map +1 -0
- package/dist/tools/relations.tools.d.ts +65 -0
- package/dist/tools/relations.tools.d.ts.map +1 -0
- package/dist/tools/relations.tools.js +64 -0
- package/dist/tools/relations.tools.js.map +1 -0
- package/dist/tools/search.tools.d.ts +68 -0
- package/dist/tools/search.tools.d.ts.map +1 -0
- package/dist/tools/search.tools.js +134 -0
- package/dist/tools/search.tools.js.map +1 -0
- package/dist/tools/solution.tools.d.ts +95 -0
- package/dist/tools/solution.tools.d.ts.map +1 -0
- package/dist/tools/solution.tools.js +130 -0
- package/dist/tools/solution.tools.js.map +1 -0
- package/dist/tools/teams.tools.d.ts +27 -0
- package/dist/tools/teams.tools.d.ts.map +1 -0
- package/dist/tools/teams.tools.js +67 -0
- package/dist/tools/teams.tools.js.map +1 -0
- package/dist/tools/trace.tools.d.ts +63 -0
- package/dist/tools/trace.tools.d.ts.map +1 -0
- package/dist/tools/trace.tools.js +218 -0
- package/dist/tools/trace.tools.js.map +1 -0
- package/dist/tools/tracking.tools.d.ts +35 -0
- package/dist/tools/tracking.tools.d.ts.map +1 -0
- package/dist/tools/tracking.tools.js +40 -0
- package/dist/tools/tracking.tools.js.map +1 -0
- package/dist/tools/users.tools.d.ts +57 -0
- package/dist/tools/users.tools.d.ts.map +1 -0
- package/dist/tools/users.tools.js +146 -0
- package/dist/tools/users.tools.js.map +1 -0
- package/dist/tools/views.tools.d.ts +30 -0
- package/dist/tools/views.tools.d.ts.map +1 -0
- package/dist/tools/views.tools.js +84 -0
- package/dist/tools/views.tools.js.map +1 -0
- package/package.json +81 -0
- package/server.json +30 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import { HttpClient, HttpError } from './http-client.js';
|
|
2
|
+
import { esc, parseMultipartResponse } from './dataverse-client.utils.js';
|
|
3
|
+
const API_VERSION = '9.2';
|
|
4
|
+
/**
|
|
5
|
+
* Maps entity set names with irregular pluralization to their primary key field names.
|
|
6
|
+
* Used as a fallback when OData-EntityId and @odata.id are absent from the response.
|
|
7
|
+
*/
|
|
8
|
+
const ENTITY_SET_TO_PK = {
|
|
9
|
+
opportunities: 'opportunityid',
|
|
10
|
+
territories: 'territoryid',
|
|
11
|
+
categories: 'categoryid',
|
|
12
|
+
activityparties: 'activitypartyid',
|
|
13
|
+
activitymimeattachments: 'activitymimeattachmentid',
|
|
14
|
+
queues: 'queueid',
|
|
15
|
+
queueitems: 'queueitemid',
|
|
16
|
+
};
|
|
17
|
+
export class DataverseClient {
|
|
18
|
+
http;
|
|
19
|
+
authProvider;
|
|
20
|
+
maxRetries;
|
|
21
|
+
constructor(authProvider, maxRetries = 3, timeoutMs = 30_000) {
|
|
22
|
+
this.authProvider = authProvider;
|
|
23
|
+
this.maxRetries = maxRetries;
|
|
24
|
+
this.http = new HttpClient({
|
|
25
|
+
baseURL: `${authProvider.environmentUrl}/api/data/v${API_VERSION}/`,
|
|
26
|
+
timeout: timeoutMs,
|
|
27
|
+
headers: {
|
|
28
|
+
'OData-MaxVersion': '4.0',
|
|
29
|
+
'OData-Version': '4.0',
|
|
30
|
+
'Accept': 'application/json',
|
|
31
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
32
|
+
},
|
|
33
|
+
tokenProvider: () => authProvider.getToken(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async requestWithRetry(fn, attempt = 0) {
|
|
37
|
+
try {
|
|
38
|
+
return await fn();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error instanceof HttpError) {
|
|
42
|
+
// On 401: invalidate cached token and retry once with a fresh token
|
|
43
|
+
if (error.status === 401 && attempt === 0) {
|
|
44
|
+
this.authProvider.invalidateToken();
|
|
45
|
+
return this.requestWithRetry(fn, attempt + 1);
|
|
46
|
+
}
|
|
47
|
+
// On transient errors (429, 503): retry with Retry-After-aware backoff
|
|
48
|
+
const isTransient = [429, 503, 504].includes(error.status);
|
|
49
|
+
if (isTransient && attempt < this.maxRetries) {
|
|
50
|
+
const retryAfterSec = error.responseHeaders['retry-after'];
|
|
51
|
+
const delay = retryAfterSec ? parseInt(retryAfterSec, 10) * 1000 : Math.pow(2, attempt) * 1000;
|
|
52
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
53
|
+
return this.requestWithRetry(fn, attempt + 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
throw this.formatError(error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
formatError(error) {
|
|
60
|
+
if (error instanceof HttpError) {
|
|
61
|
+
const dvError = error.data?.error;
|
|
62
|
+
if (dvError) {
|
|
63
|
+
return new Error(`Dataverse error ${dvError.code ?? ''}: ${dvError.message ?? 'Unknown error'}`);
|
|
64
|
+
}
|
|
65
|
+
if (error.code === 'ECONNABORTED') {
|
|
66
|
+
return new Error('Request timed out. Check your Dataverse environment URL.');
|
|
67
|
+
}
|
|
68
|
+
return error;
|
|
69
|
+
}
|
|
70
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
71
|
+
}
|
|
72
|
+
// ─── Auth ────────────────────────────────────────────────────────────────
|
|
73
|
+
async whoAmI() {
|
|
74
|
+
return this.requestWithRetry(async () => {
|
|
75
|
+
const whoAmIResp = await this.http.get('WhoAmI');
|
|
76
|
+
const { UserId, BusinessUnitId, OrganizationId } = whoAmIResp.data;
|
|
77
|
+
let OrganizationName = '';
|
|
78
|
+
try {
|
|
79
|
+
const orgResp = await this.http.get(`organizations(${OrganizationId})?$select=name`);
|
|
80
|
+
OrganizationName = orgResp.data.name ?? '';
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
OrganizationName = '';
|
|
84
|
+
}
|
|
85
|
+
const EnvironmentUrl = this.authProvider.environmentUrl;
|
|
86
|
+
return { UserId, BusinessUnitId, OrganizationId, OrganizationName, EnvironmentUrl };
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// ─── Metadata ────────────────────────────────────────────────────────────
|
|
90
|
+
async listTables(includeCustomOnly = false) {
|
|
91
|
+
const filter = includeCustomOnly ? '$filter=IsCustomEntity eq true' : '';
|
|
92
|
+
const select = '$select=LogicalName,SchemaName,DisplayName,EntitySetName,PrimaryIdAttribute,PrimaryNameAttribute,IsCustomEntity';
|
|
93
|
+
const query = [select, filter].filter(Boolean).join('&');
|
|
94
|
+
return this.requestWithRetry(() => this.http.get(`EntityDefinitions?${query}`).then(r => r.data.value));
|
|
95
|
+
}
|
|
96
|
+
async getTableMetadata(logicalName, includeAttributes = true) {
|
|
97
|
+
const expand = includeAttributes ? '$expand=Attributes' : '';
|
|
98
|
+
const url = `EntityDefinitions(LogicalName='${esc(logicalName)}')${expand ? '?' + expand : ''}`;
|
|
99
|
+
return this.requestWithRetry(() => this.http.get(url).then(r => r.data));
|
|
100
|
+
}
|
|
101
|
+
async getRelationships(logicalName) {
|
|
102
|
+
const escaped = esc(logicalName);
|
|
103
|
+
const [oneToMany, manyToOne, manyToMany] = await Promise.all([
|
|
104
|
+
this.requestWithRetry(() => this.http
|
|
105
|
+
.get(`EntityDefinitions(LogicalName='${escaped}')/OneToManyRelationships`)
|
|
106
|
+
.then(r => r.data.value)),
|
|
107
|
+
this.requestWithRetry(() => this.http
|
|
108
|
+
.get(`EntityDefinitions(LogicalName='${escaped}')/ManyToOneRelationships`)
|
|
109
|
+
.then(r => r.data.value)),
|
|
110
|
+
this.requestWithRetry(() => this.http
|
|
111
|
+
.get(`EntityDefinitions(LogicalName='${escaped}')/ManyToManyRelationships`)
|
|
112
|
+
.then(r => r.data.value)),
|
|
113
|
+
]);
|
|
114
|
+
return [...oneToMany, ...manyToOne, ...manyToMany];
|
|
115
|
+
}
|
|
116
|
+
// ─── Query ───────────────────────────────────────────────────────────────
|
|
117
|
+
async query(entitySetName, options = {}) {
|
|
118
|
+
const params = [];
|
|
119
|
+
if (options.select?.length)
|
|
120
|
+
params.push(`$select=${options.select.join(',')}`);
|
|
121
|
+
if (options.filter)
|
|
122
|
+
params.push(`$filter=${options.filter}`);
|
|
123
|
+
if (options.orderby)
|
|
124
|
+
params.push(`$orderby=${options.orderby}`);
|
|
125
|
+
if (options.top)
|
|
126
|
+
params.push(`$top=${options.top}`);
|
|
127
|
+
if (options.expand)
|
|
128
|
+
params.push(`$expand=${options.expand}`);
|
|
129
|
+
if (options.count)
|
|
130
|
+
params.push('$count=true');
|
|
131
|
+
if (options.apply)
|
|
132
|
+
params.push(`$apply=${options.apply}`);
|
|
133
|
+
const url = `${entitySetName}${params.length ? '?' + params.join('&') : ''}`;
|
|
134
|
+
return this.requestWithRetry(() => this.http.get(url).then(r => r.data));
|
|
135
|
+
}
|
|
136
|
+
async executeFetchXml(entitySetName, fetchXml) {
|
|
137
|
+
const encoded = encodeURIComponent(fetchXml);
|
|
138
|
+
return this.requestWithRetry(() => this.http
|
|
139
|
+
.get(`${entitySetName}?fetchXml=${encoded}`)
|
|
140
|
+
.then(r => r.data));
|
|
141
|
+
}
|
|
142
|
+
// ─── CRUD ────────────────────────────────────────────────────────────────
|
|
143
|
+
async getRecord(entitySetName, id, select) {
|
|
144
|
+
const params = select ? `?$select=${select.join(',')}` : '';
|
|
145
|
+
return this.requestWithRetry(async () => {
|
|
146
|
+
const response = await this.http.get(`${entitySetName}(${id})${params}`, {
|
|
147
|
+
headers: { Prefer: 'odata.include-annotations="*"' },
|
|
148
|
+
});
|
|
149
|
+
const etag = response.headers['odata-etag'] ??
|
|
150
|
+
response.data['@odata.etag'] ??
|
|
151
|
+
null;
|
|
152
|
+
return { record: response.data, etag };
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async createRecord(entitySetName, data) {
|
|
156
|
+
return this.requestWithRetry(async () => {
|
|
157
|
+
const response = await this.http.post(entitySetName, data, {
|
|
158
|
+
headers: { 'Prefer': 'return=representation' },
|
|
159
|
+
});
|
|
160
|
+
// 1. OData-EntityId header (standard, most reliable)
|
|
161
|
+
const locationHeader = response.headers['odata-entityid'];
|
|
162
|
+
const fromHeader = locationHeader?.match(/\(([^)]+)\)/)?.[1];
|
|
163
|
+
if (fromHeader)
|
|
164
|
+
return fromHeader;
|
|
165
|
+
// 2. @odata.id in body (collection response shape)
|
|
166
|
+
const body = response.data;
|
|
167
|
+
const fromOdataId = body['@odata.id']?.match(/\(([^)]+)\)/)?.[1];
|
|
168
|
+
if (fromOdataId)
|
|
169
|
+
return fromOdataId;
|
|
170
|
+
// 3. Primary key field in body (when return=representation and no OData-EntityId header)
|
|
171
|
+
// Use known irregular pluralizations; fall back to simple s-strip convention.
|
|
172
|
+
const pkGuess = ENTITY_SET_TO_PK[entitySetName] ?? (entitySetName.replace(/s$/, '') + 'id');
|
|
173
|
+
const fromPk = body[pkGuess];
|
|
174
|
+
if (fromPk)
|
|
175
|
+
return fromPk;
|
|
176
|
+
// 4. Location header fallback
|
|
177
|
+
const location = response.headers['location'];
|
|
178
|
+
return location?.match(/\(([^)]+)\)/)?.[1] ?? '';
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
async updateRecord(entitySetName, id, data, etag) {
|
|
182
|
+
await this.requestWithRetry(() => this.http.patch(`${entitySetName}(${id})`, data, {
|
|
183
|
+
headers: { 'If-Match': etag ?? '*' },
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
async deleteRecord(entitySetName, id) {
|
|
187
|
+
await this.requestWithRetry(() => this.http.delete(`${entitySetName}(${id})`));
|
|
188
|
+
}
|
|
189
|
+
async upsertRecord(entitySetName, alternateKey, alternateKeyValue, data, mode = 'upsert', keySegment) {
|
|
190
|
+
return this.requestWithRetry(async () => {
|
|
191
|
+
const url = keySegment
|
|
192
|
+
? `${entitySetName}(${keySegment})`
|
|
193
|
+
: `${entitySetName}(${esc(alternateKey)}='${esc(alternateKeyValue)}')`;
|
|
194
|
+
const headers = { Prefer: 'return=representation' };
|
|
195
|
+
if (mode === 'createOnly')
|
|
196
|
+
headers['If-None-Match'] = '*';
|
|
197
|
+
if (mode === 'updateOnly')
|
|
198
|
+
headers['If-Match'] = '*';
|
|
199
|
+
try {
|
|
200
|
+
const response = await this.http.put(url, data, { headers });
|
|
201
|
+
const operation = response.status === 201 ? 'created' : 'updated';
|
|
202
|
+
const locationHeader = response.headers['odata-entityid'];
|
|
203
|
+
const fromHeader = locationHeader?.match(/\(([^)]+)\)/)?.[1];
|
|
204
|
+
const body = response.data;
|
|
205
|
+
const pkGuess = ENTITY_SET_TO_PK[entitySetName] ?? (entitySetName.replace(/s$/, '') + 'id');
|
|
206
|
+
const id = fromHeader ?? body?.[pkGuess] ?? alternateKeyValue;
|
|
207
|
+
return { operation, id };
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
if (err instanceof HttpError && err.status === 412) {
|
|
211
|
+
if (mode === 'createOnly')
|
|
212
|
+
throw new Error('Record already exists');
|
|
213
|
+
if (mode === 'updateOnly')
|
|
214
|
+
throw new Error('Record not found');
|
|
215
|
+
}
|
|
216
|
+
throw err;
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
// ─── Relations ───────────────────────────────────────────────────────────
|
|
221
|
+
async associate(entitySetName, id, relationshipName, relatedEntitySetName, relatedId) {
|
|
222
|
+
const relatedUrl = `${this.authProvider.environmentUrl}/api/data/v${API_VERSION}/${relatedEntitySetName}(${relatedId})`;
|
|
223
|
+
await this.requestWithRetry(() => this.http.post(`${entitySetName}(${id})/${relationshipName}/$ref`, { '@odata.id': relatedUrl }));
|
|
224
|
+
}
|
|
225
|
+
async disassociate(entitySetName, id, relationshipName, relatedId, relatedEntitySetName) {
|
|
226
|
+
const suffix = relatedId
|
|
227
|
+
? `?$id=${this.authProvider.environmentUrl}/api/data/v${API_VERSION}/${relatedEntitySetName ?? entitySetName}(${relatedId})`
|
|
228
|
+
: '';
|
|
229
|
+
await this.requestWithRetry(() => this.http.delete(`${entitySetName}(${id})/${relationshipName}/$ref${suffix}`));
|
|
230
|
+
}
|
|
231
|
+
// ─── Actions & Functions ─────────────────────────────────────────────────
|
|
232
|
+
async executeAction(actionName, parameters = {}) {
|
|
233
|
+
return this.requestWithRetry(() => this.http.post(actionName, parameters).then(r => r.data));
|
|
234
|
+
}
|
|
235
|
+
async executeFunction(functionName, parameters = {}) {
|
|
236
|
+
const paramStr = Object.entries(parameters)
|
|
237
|
+
.map(([k, v]) => `${esc(k)}='${esc(v)}'`)
|
|
238
|
+
.join(',');
|
|
239
|
+
const url = paramStr ? `${functionName}(${paramStr})` : `${functionName}()`;
|
|
240
|
+
return this.requestWithRetry(() => this.http.get(url).then(r => r.data));
|
|
241
|
+
}
|
|
242
|
+
async executeBoundAction(entitySetName, id, actionName, parameters = {}) {
|
|
243
|
+
return this.requestWithRetry(() => this.http
|
|
244
|
+
.post(`${entitySetName}(${id})/Microsoft.Dynamics.CRM.${actionName}`, parameters)
|
|
245
|
+
.then(r => r.data));
|
|
246
|
+
}
|
|
247
|
+
// ─── Batch ───────────────────────────────────────────────────────────────
|
|
248
|
+
async batchExecute(requests, useChangeset = false) {
|
|
249
|
+
const batchId = `batch_${Date.now()}`;
|
|
250
|
+
let body = '';
|
|
251
|
+
if (useChangeset) {
|
|
252
|
+
const changesetId = `changeset_${Date.now() + 1}`;
|
|
253
|
+
const getOps = requests.filter(r => r.method === 'GET');
|
|
254
|
+
const mutatingOps = requests.filter(r => r.method !== 'GET');
|
|
255
|
+
for (const req of getOps) {
|
|
256
|
+
body += `--${batchId}\n`;
|
|
257
|
+
body += `Content-Type: application/http\n`;
|
|
258
|
+
body += `Content-Transfer-Encoding: binary\n\n`;
|
|
259
|
+
body += `${req.method} ${this.authProvider.environmentUrl}/api/data/v${API_VERSION}/${req.url} HTTP/1.1\n`;
|
|
260
|
+
body += `Accept: application/json\n\n\n`;
|
|
261
|
+
}
|
|
262
|
+
if (mutatingOps.length > 0) {
|
|
263
|
+
body += `--${batchId}\n`;
|
|
264
|
+
body += `Content-Type: multipart/mixed; boundary=${changesetId}\n\n`;
|
|
265
|
+
let contentIdCounter = 1;
|
|
266
|
+
for (const op of mutatingOps) {
|
|
267
|
+
body += `--${changesetId}\n`;
|
|
268
|
+
body += `Content-Type: application/http\n`;
|
|
269
|
+
body += `Content-Transfer-Encoding: binary\n`;
|
|
270
|
+
body += `Content-ID: ${op.contentId ?? contentIdCounter++}\n\n`;
|
|
271
|
+
body += `${op.method} ${this.authProvider.environmentUrl}/api/data/v${API_VERSION}/${op.url} HTTP/1.1\n`;
|
|
272
|
+
body += `Content-Type: application/json\n\n`;
|
|
273
|
+
if (op.body)
|
|
274
|
+
body += JSON.stringify(op.body);
|
|
275
|
+
body += '\n\n';
|
|
276
|
+
}
|
|
277
|
+
body += `--${changesetId}--\n`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
requests.forEach((req) => {
|
|
282
|
+
body += `--${batchId}\n`;
|
|
283
|
+
body += `Content-Type: application/http\n`;
|
|
284
|
+
body += `Content-Transfer-Encoding: binary\n\n`;
|
|
285
|
+
body += `${req.method} ${this.authProvider.environmentUrl}/api/data/v${API_VERSION}/${req.url} HTTP/1.1\n`;
|
|
286
|
+
body += `Content-Type: application/json\n\n`;
|
|
287
|
+
if (req.body)
|
|
288
|
+
body += JSON.stringify(req.body);
|
|
289
|
+
body += '\n';
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
body += `--${batchId}--`;
|
|
293
|
+
const response = await this.requestWithRetry(() => this.http.post('$batch', body, {
|
|
294
|
+
headers: { 'Content-Type': `multipart/mixed;boundary=${batchId}` },
|
|
295
|
+
responseType: 'text',
|
|
296
|
+
}));
|
|
297
|
+
try {
|
|
298
|
+
const contentType = response.headers['content-type'] ?? '';
|
|
299
|
+
const boundaryMatch = contentType.match(/boundary=(?:"([^"]+)"|([^;"\s]+))/);
|
|
300
|
+
const responseBoundary = boundaryMatch?.[1] ?? boundaryMatch?.[2];
|
|
301
|
+
if (!responseBoundary) {
|
|
302
|
+
process.stderr.write('[batchExecute] No multipart boundary in response Content-Type; returning raw data.\n');
|
|
303
|
+
return [response.data];
|
|
304
|
+
}
|
|
305
|
+
return parseMultipartResponse(response.data, responseBoundary);
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
process.stderr.write(`[batchExecute] Failed to parse multipart response; returning raw data. ${String(err)}\n`);
|
|
309
|
+
return [response.data];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
//# sourceMappingURL=dataverse-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverse-client.js","sourceRoot":"","sources":["../../src/dataverse/dataverse-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DataverseClient } from './dataverse-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Extends DataverseClient with dependency and option-set query methods.
|
|
4
|
+
* Kept in a separate file to stay within the 400-line hard limit.
|
|
5
|
+
*/
|
|
6
|
+
export declare class DataverseMetadataClient extends DataverseClient {
|
|
7
|
+
listDependencies(componentType: number, objectId: string): Promise<unknown[]>;
|
|
8
|
+
listTableDependencies(tableName: string, types?: string[]): Promise<{
|
|
9
|
+
tableName: string;
|
|
10
|
+
dependencies: Array<{
|
|
11
|
+
componentType: string;
|
|
12
|
+
name: string;
|
|
13
|
+
id: string;
|
|
14
|
+
state: string;
|
|
15
|
+
triggerEvent: string | null;
|
|
16
|
+
solutionName: string | null;
|
|
17
|
+
}>;
|
|
18
|
+
count: number;
|
|
19
|
+
warning: string | null;
|
|
20
|
+
}>;
|
|
21
|
+
listGlobalOptionSets(): Promise<unknown[]>;
|
|
22
|
+
getOptionSet(name: string): Promise<unknown>;
|
|
23
|
+
getAttributeOptionSet(entityLogicalName: string, attributeLogicalName: string): Promise<{
|
|
24
|
+
entityLogicalName: string;
|
|
25
|
+
attributeLogicalName: string;
|
|
26
|
+
attributeType: string;
|
|
27
|
+
options: Array<{
|
|
28
|
+
label: string;
|
|
29
|
+
value: number;
|
|
30
|
+
}>;
|
|
31
|
+
}>;
|
|
32
|
+
getEntityKeys(tableName: string): Promise<Array<{
|
|
33
|
+
schemaName: string;
|
|
34
|
+
logicalName: string;
|
|
35
|
+
keyAttributes: string[];
|
|
36
|
+
isCustomizable: boolean;
|
|
37
|
+
indexStatus: string;
|
|
38
|
+
}>>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=dataverse-client.metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverse-client.metadata.d.ts","sourceRoot":"","sources":["../../src/dataverse/dataverse-client.metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,eAAe;IAGpD,gBAAgB,CACpB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,EAAE,CAAC;IAUf,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,OAAO,CAAC;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,KAAK,CAAC;YAClB,aAAa,EAAE,MAAM,CAAC;YACtB,IAAI,EAAE,MAAM,CAAC;YACb,EAAE,EAAE,MAAM,CAAC;YACX,KAAK,EAAE,MAAM,CAAC;YACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;YAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;SAC7B,CAAC,CAAC;QACH,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;IAiEI,oBAAoB,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAQ1C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ5C,qBAAqB,CACzB,iBAAiB,EAAE,MAAM,EACzB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC;QACT,iBAAiB,EAAE,MAAM,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,aAAa,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAClD,CAAC;IA0CI,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QACpD,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,EAAE,OAAO,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC,CAAC;CAcJ"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { DataverseClient } from './dataverse-client.js';
|
|
2
|
+
import { esc } from './dataverse-client.utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extends DataverseClient with dependency and option-set query methods.
|
|
5
|
+
* Kept in a separate file to stay within the 400-line hard limit.
|
|
6
|
+
*/
|
|
7
|
+
export class DataverseMetadataClient extends DataverseClient {
|
|
8
|
+
// ─── Dependencies & Option Sets ─────────────────────────────────────────
|
|
9
|
+
async listDependencies(componentType, objectId) {
|
|
10
|
+
return this.requestWithRetry(() => this.http
|
|
11
|
+
.get(`RetrieveDependenciesForDelete(ComponentType=${componentType},ObjectId=${objectId})`)
|
|
12
|
+
.then(r => r.data.value));
|
|
13
|
+
}
|
|
14
|
+
async listTableDependencies(tableName, types) {
|
|
15
|
+
const CATEGORY_MAP = {
|
|
16
|
+
0: 'Workflow',
|
|
17
|
+
1: 'Dialog',
|
|
18
|
+
2: 'BusinessRule',
|
|
19
|
+
3: 'Action',
|
|
20
|
+
4: 'BusinessProcessFlow',
|
|
21
|
+
5: 'Flow',
|
|
22
|
+
};
|
|
23
|
+
const STATE_MAP = {
|
|
24
|
+
0: 'Draft',
|
|
25
|
+
1: 'Active',
|
|
26
|
+
2: 'Inactive',
|
|
27
|
+
};
|
|
28
|
+
const response = await this.requestWithRetry(() => this.http
|
|
29
|
+
.get(`workflows?$filter=primaryentity eq '${esc(tableName)}' and statecode ne 2` +
|
|
30
|
+
`&$select=name,workflowid,statecode,category,triggeroncreate,triggerondelete,triggeronupdateattributelist`)
|
|
31
|
+
.then(r => r.data));
|
|
32
|
+
const all = response.value.map((w) => {
|
|
33
|
+
const events = [];
|
|
34
|
+
if (w.triggeroncreate)
|
|
35
|
+
events.push('Create');
|
|
36
|
+
if (w.triggerondelete)
|
|
37
|
+
events.push('Delete');
|
|
38
|
+
if (w.triggeronupdateattributelist)
|
|
39
|
+
events.push('Update');
|
|
40
|
+
return {
|
|
41
|
+
componentType: CATEGORY_MAP[w.category] ?? `Category${w.category}`,
|
|
42
|
+
name: w.name,
|
|
43
|
+
id: w.workflowid,
|
|
44
|
+
state: STATE_MAP[w.statecode] ?? `State${w.statecode}`,
|
|
45
|
+
triggerEvent: events.length ? events.join(',') : null,
|
|
46
|
+
solutionName: null,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
const dependencies = types?.length
|
|
50
|
+
? all.filter(d => types.includes(d.componentType))
|
|
51
|
+
: all;
|
|
52
|
+
const hasPluginOrCustomApi = types?.some(t => t === 'Plugin' || t === 'CustomAPI');
|
|
53
|
+
const warning = hasPluginOrCustomApi
|
|
54
|
+
? 'Plugin and CustomAPI types require additional SDK message queries and are not yet implemented. Results show Workflow/BusinessRule/Flow/Action dependencies only.'
|
|
55
|
+
: null;
|
|
56
|
+
return {
|
|
57
|
+
tableName,
|
|
58
|
+
dependencies,
|
|
59
|
+
count: dependencies.length,
|
|
60
|
+
warning,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async listGlobalOptionSets() {
|
|
64
|
+
return this.requestWithRetry(() => this.http
|
|
65
|
+
.get('GlobalOptionSetDefinitions')
|
|
66
|
+
.then(r => r.data.value));
|
|
67
|
+
}
|
|
68
|
+
async getOptionSet(name) {
|
|
69
|
+
return this.requestWithRetry(() => this.http
|
|
70
|
+
.get(`GlobalOptionSetDefinitions(Name='${esc(name)}')`)
|
|
71
|
+
.then(r => r.data));
|
|
72
|
+
}
|
|
73
|
+
async getAttributeOptionSet(entityLogicalName, attributeLogicalName) {
|
|
74
|
+
const metadataTypes = [
|
|
75
|
+
'PicklistAttributeMetadata',
|
|
76
|
+
'StatusAttributeMetadata',
|
|
77
|
+
'StateAttributeMetadata',
|
|
78
|
+
];
|
|
79
|
+
for (const typeName of metadataTypes) {
|
|
80
|
+
try {
|
|
81
|
+
const url = `EntityDefinitions(LogicalName='${esc(entityLogicalName)}')/` +
|
|
82
|
+
`Attributes(LogicalName='${esc(attributeLogicalName)}')/` +
|
|
83
|
+
`Microsoft.Dynamics.CRM.${typeName}?$select=LogicalName,DisplayName&$expand=OptionSet`;
|
|
84
|
+
const response = await this.requestWithRetry(() => this.http.get(url).then(r => r.data));
|
|
85
|
+
const optionSet = response['OptionSet'];
|
|
86
|
+
const rawOptions = optionSet?.['Options'] ?? [];
|
|
87
|
+
const options = rawOptions.map(o => {
|
|
88
|
+
const lblObj = o['Label'];
|
|
89
|
+
const locLabel = lblObj?.['UserLocalizedLabel'];
|
|
90
|
+
return {
|
|
91
|
+
label: locLabel?.['Label'] ?? '',
|
|
92
|
+
value: o['Value'],
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
return {
|
|
96
|
+
entityLogicalName,
|
|
97
|
+
attributeLogicalName,
|
|
98
|
+
attributeType: typeName.replace('AttributeMetadata', ''),
|
|
99
|
+
options,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw new Error(`Attribute '${attributeLogicalName}' on entity '${entityLogicalName}' is not a Picklist, Status, or State attribute, or does not exist.`);
|
|
107
|
+
}
|
|
108
|
+
async getEntityKeys(tableName) {
|
|
109
|
+
return this.requestWithRetry(async () => {
|
|
110
|
+
const response = await this.http.get(`EntityDefinitions(LogicalName='${esc(tableName)}')/Keys?$select=SchemaName,LogicalName,KeyAttributes,IsCustomizable,EntityKeyIndexStatus`);
|
|
111
|
+
return response.data.value.map(k => ({
|
|
112
|
+
schemaName: k['SchemaName'],
|
|
113
|
+
logicalName: k['LogicalName'],
|
|
114
|
+
keyAttributes: k['KeyAttributes'],
|
|
115
|
+
isCustomizable: k['IsCustomizable']?.Value ?? false,
|
|
116
|
+
indexStatus: k['EntityKeyIndexStatus'],
|
|
117
|
+
}));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=dataverse-client.metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverse-client.metadata.js","sourceRoot":"","sources":["../../src/dataverse/dataverse-client.metadata.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a Dataverse batch multipart/mixed response body.
|
|
3
|
+
* Each MIME part wraps an inner HTTP response; this function extracts the JSON
|
|
4
|
+
* body and status from each sub-request and returns an array of results.
|
|
5
|
+
* Successful responses (2xx) are returned as parsed objects; error responses
|
|
6
|
+
* are wrapped in `{ error, status }`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseMultipartResponse(body: string, boundary: string): unknown[];
|
|
9
|
+
/**
|
|
10
|
+
* Escape single quotes in OData string literals by doubling them.
|
|
11
|
+
* Prevents OData injection in URL path segments like LogicalName='...'.
|
|
12
|
+
*/
|
|
13
|
+
export declare function esc(value: string): string;
|
|
14
|
+
//# sourceMappingURL=dataverse-client.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverse-client.utils.d.ts","sourceRoot":"","sources":["../../src/dataverse/dataverse-client.utils.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAwChF;AAED;;;GAGG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// ─── Multipart Response Parsing ──────────────────────────────────────────
|
|
2
|
+
/**
|
|
3
|
+
* Returns the index just after the first double-newline (\r\n\r\n or \n\n).
|
|
4
|
+
* Returns -1 if not found.
|
|
5
|
+
*/
|
|
6
|
+
function findDoubleNewline(text) {
|
|
7
|
+
const crlfIdx = text.indexOf('\r\n\r\n');
|
|
8
|
+
const lfIdx = text.indexOf('\n\n');
|
|
9
|
+
if (crlfIdx !== -1 && (lfIdx === -1 || crlfIdx <= lfIdx))
|
|
10
|
+
return crlfIdx + 4;
|
|
11
|
+
if (lfIdx !== -1)
|
|
12
|
+
return lfIdx + 2;
|
|
13
|
+
return -1;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse a Dataverse batch multipart/mixed response body.
|
|
17
|
+
* Each MIME part wraps an inner HTTP response; this function extracts the JSON
|
|
18
|
+
* body and status from each sub-request and returns an array of results.
|
|
19
|
+
* Successful responses (2xx) are returned as parsed objects; error responses
|
|
20
|
+
* are wrapped in `{ error, status }`.
|
|
21
|
+
*/
|
|
22
|
+
export function parseMultipartResponse(body, boundary) {
|
|
23
|
+
const results = [];
|
|
24
|
+
const parts = body.split(`--${boundary}`);
|
|
25
|
+
for (const part of parts) {
|
|
26
|
+
const trimmed = part.trim();
|
|
27
|
+
// Skip preamble (empty) and epilogue (--)
|
|
28
|
+
if (!trimmed || trimmed === '--')
|
|
29
|
+
continue;
|
|
30
|
+
// Part layout: MIME-headers \r\n\r\n inner-HTTP-response
|
|
31
|
+
const mimeEnd = findDoubleNewline(part);
|
|
32
|
+
if (mimeEnd === -1)
|
|
33
|
+
continue;
|
|
34
|
+
const innerHttp = part.slice(mimeEnd);
|
|
35
|
+
// Inner HTTP layout: status-line \r\n response-headers \r\n\r\n body
|
|
36
|
+
const httpHeadersEnd = findDoubleNewline(innerHttp);
|
|
37
|
+
if (httpHeadersEnd === -1)
|
|
38
|
+
continue;
|
|
39
|
+
const statusLine = innerHttp.trimStart().split(/\r?\n/)[0] ?? '';
|
|
40
|
+
const statusMatch = statusLine.match(/^HTTP\/\d+\.\d+\s+(\d{3})/);
|
|
41
|
+
const statusCode = statusMatch ? parseInt(statusMatch[1], 10) : 0;
|
|
42
|
+
const isSuccess = statusCode >= 200 && statusCode < 300;
|
|
43
|
+
const jsonBody = innerHttp.slice(httpHeadersEnd).trim();
|
|
44
|
+
if (!jsonBody) {
|
|
45
|
+
results.push(isSuccess ? null : { error: 'Empty response body', status: statusCode });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(jsonBody);
|
|
50
|
+
results.push(isSuccess ? parsed : { error: parsed, status: statusCode });
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
results.push({ error: jsonBody, status: statusCode });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return results;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Escape single quotes in OData string literals by doubling them.
|
|
60
|
+
* Prevents OData injection in URL path segments like LogicalName='...'.
|
|
61
|
+
*/
|
|
62
|
+
export function esc(value) {
|
|
63
|
+
return value.replace(/'/g, "''");
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=dataverse-client.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataverse-client.utils.js","sourceRoot":"","sources":["../../src/dataverse/dataverse-client.utils.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAE5E;;;GAGG;AACH,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,KAAK,GAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,OAAO,IAAI,KAAK,CAAC;QAAE,OAAO,OAAO,GAAG,CAAC,CAAC;IAC7E,IAAI,KAAK,KAAO,CAAC,CAAC;QAAE,OAAO,KAAK,GAAG,CAAC,CAAC;IACrC,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,QAAgB;IACnE,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAE1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,0CAA0C;QAC1C,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAE3C,2DAA2D;QAC3D,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEtC,yEAAyE;QACzE,MAAM,cAAc,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,cAAc,KAAK,CAAC,CAAC;YAAE,SAAS;QAEpC,MAAM,UAAU,GAAI,SAAS,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAClE,MAAM,UAAU,GAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,SAAS,GAAK,UAAU,IAAI,GAAG,IAAI,UAAU,GAAG,GAAG,CAAC;QAE1D,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC;QAExD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YACtF,SAAS;QACX,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,GAAG,CAAC,KAAa;IAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare class HttpError extends Error {
|
|
2
|
+
readonly status: number;
|
|
3
|
+
readonly data: unknown;
|
|
4
|
+
readonly code?: string | undefined;
|
|
5
|
+
readonly responseHeaders: Record<string, string>;
|
|
6
|
+
constructor(message: string, status: number, data: unknown, code?: string | undefined, responseHeaders?: Record<string, string>);
|
|
7
|
+
}
|
|
8
|
+
export interface HttpRequestOptions {
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
responseType?: 'text';
|
|
11
|
+
}
|
|
12
|
+
export interface HttpResponse<T = unknown> {
|
|
13
|
+
data: T;
|
|
14
|
+
status: number;
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
export declare class HttpClient {
|
|
18
|
+
private readonly baseURL;
|
|
19
|
+
private readonly timeoutMs;
|
|
20
|
+
readonly defaultHeaders: Record<string, string>;
|
|
21
|
+
private readonly tokenProvider;
|
|
22
|
+
constructor(config: {
|
|
23
|
+
baseURL: string;
|
|
24
|
+
timeout?: number;
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
tokenProvider?: () => Promise<string>;
|
|
27
|
+
});
|
|
28
|
+
get<T = unknown>(url: string, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
29
|
+
post<T = unknown>(url: string, body?: unknown, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
30
|
+
patch<T = unknown>(url: string, body?: unknown, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
31
|
+
put<T = unknown>(url: string, body?: unknown, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
32
|
+
delete<T = unknown>(url: string, options?: HttpRequestOptions): Promise<HttpResponse<T>>;
|
|
33
|
+
private resolveUrl;
|
|
34
|
+
private request;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=http-client.d.ts.map
|