@vura-data-os/vura-dataverse-sync-core 1.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 +15 -0
- package/out/syncDataverseHandler.js +471 -0
- package/out/syncDataverseHandler.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @vura-data-os/vura-dataverse-sync-core
|
|
2
|
+
|
|
3
|
+
Host-agnostic Dynamics 365 (Dataverse) OData v4 `$batch` sync engine for [VURA](https://github.com/Waleed-S-Kassem/vura-public). No `vscode` dependency — the same logic backs both the VS Code Add-on (`@vura-data-os/vura-dataverse-adapter`) and the `vura-runner` CLI plugin (`@vura-data-os/vura-dataverse-runner-plugin`).
|
|
4
|
+
|
|
5
|
+
## What's in it
|
|
6
|
+
|
|
7
|
+
`handleSyncDataverse(cell, logger, env, commandLine)` — parses `!sync_dataverse --source <table> --target <entity> [--mode upsert|insert] [--batch_size N] [--key <col>]`, resolves the Dataverse entity's primary/alternate keys, reads the local table via `env.runLocalQuery`, chunks and sends `$batch` requests, and renders a success/failure HTML table via `logger.replaceOutput`.
|
|
8
|
+
|
|
9
|
+
`parseArgs(commandLine)` is also exported directly if you need to validate a command line without running the sync.
|
|
10
|
+
|
|
11
|
+
This package isn't meant to be used standalone — install it via `@vura-data-os/vura-dataverse-adapter` (VS Code) or `@vura-data-os/vura-dataverse-runner-plugin` (CLI) instead. See the main repo's [Dataverse Integration](https://github.com/Waleed-S-Kassem/vura-public/blob/main/docs/dataverse_integration.md) doc.
|
|
12
|
+
|
|
13
|
+
## License
|
|
14
|
+
|
|
15
|
+
AGPL-3.0-or-later. See [LICENSE](https://github.com/Waleed-S-Kassem/vura-public/blob/main/LICENSE). For a commercial license, contact [info@nexionlabs.dev](mailto:info@nexionlabs.dev).
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleSyncDataverse = handleSyncDataverse;
|
|
4
|
+
exports.parseArgs = parseArgs;
|
|
5
|
+
const uuid_1 = require("uuid");
|
|
6
|
+
// ─── Main Entry Point ───────────────────────────────────────────────────────────
|
|
7
|
+
async function handleSyncDataverse(cell, logger, env, commandLine) {
|
|
8
|
+
// 1. Parse command arguments
|
|
9
|
+
const args = parseArgs(commandLine);
|
|
10
|
+
// 2. Resolve Dataverse connection from cell metadata
|
|
11
|
+
const connectionId = cell.metadata?.dataverseConnectionId;
|
|
12
|
+
if (!connectionId) {
|
|
13
|
+
throw new Error('No Dataverse connection selected. Use the status bar to pick a Dataverse connection for this cell.');
|
|
14
|
+
}
|
|
15
|
+
const profile = await env.getProfile(connectionId);
|
|
16
|
+
if (!profile) {
|
|
17
|
+
throw new Error(`Connection profile "${connectionId}" not found.`);
|
|
18
|
+
}
|
|
19
|
+
const secret = await env.getProfileSecret(profile.id);
|
|
20
|
+
const orgUrl = `https://${profile.server}`;
|
|
21
|
+
const token = await getToken(profile, secret);
|
|
22
|
+
// 3. Fetch entity metadata
|
|
23
|
+
await logger.logText(`Fetching metadata for entity "${args.target}"…`);
|
|
24
|
+
const metadata = await fetchEntityMetadata(orgUrl, args.target, token);
|
|
25
|
+
// 4. Resolve key
|
|
26
|
+
const resolvedKey = args.key || metadata.primaryIdAttribute;
|
|
27
|
+
let keyType = 'primary';
|
|
28
|
+
if (resolvedKey.toLowerCase() === metadata.primaryIdAttribute.toLowerCase()) {
|
|
29
|
+
keyType = 'primary';
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
const matchingAltKey = metadata.alternateKeys.find(ak => ak.keyAttributes.length === 1 &&
|
|
33
|
+
ak.keyAttributes[0].toLowerCase() === resolvedKey.toLowerCase());
|
|
34
|
+
if (matchingAltKey) {
|
|
35
|
+
keyType = 'alternate';
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
// Check multi-attribute alternate keys (comma-separated)
|
|
39
|
+
const requestedParts = resolvedKey.split(',').map(s => s.trim().toLowerCase());
|
|
40
|
+
const matchingMultiKey = metadata.alternateKeys.find(ak => ak.keyAttributes.length === requestedParts.length &&
|
|
41
|
+
requestedParts.every(rp => ak.keyAttributes.map(a => a.toLowerCase()).includes(rp)));
|
|
42
|
+
if (matchingMultiKey) {
|
|
43
|
+
keyType = 'alternate';
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const availableKeys = [
|
|
47
|
+
`Primary: ${metadata.primaryIdAttribute}`,
|
|
48
|
+
...metadata.alternateKeys.map(ak => `Alternate: ${ak.keyAttributes.join(', ')}`)
|
|
49
|
+
].join('\n • ');
|
|
50
|
+
throw new Error(`Key "${resolvedKey}" is neither the primary key nor a recognized alternate key for "${args.target}".\n\nAvailable keys:\n • ${availableKeys}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
await logger.logText(`Key resolved: "${resolvedKey}" (${keyType} key)`);
|
|
55
|
+
// 5. Read records from the local analytics engine
|
|
56
|
+
await logger.logText(`Reading records from local table "${args.source}"…`);
|
|
57
|
+
let records;
|
|
58
|
+
try {
|
|
59
|
+
records = await env.runLocalQuery(`SELECT * FROM "${args.source}"`);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
throw new Error(`Failed to read from local table "${args.source}": ${err.message}`);
|
|
63
|
+
}
|
|
64
|
+
if (!records || records.length === 0) {
|
|
65
|
+
throw new Error(`Local table "${args.source}" is empty. Nothing to sync.`);
|
|
66
|
+
}
|
|
67
|
+
// 6. Validate columns
|
|
68
|
+
const localColumns = Object.keys(records[0]);
|
|
69
|
+
const dataverseColumnsLower = new Set(metadata.attributes.map(a => a.toLowerCase()));
|
|
70
|
+
const validColumns = [];
|
|
71
|
+
const skippedColumns = [];
|
|
72
|
+
for (const col of localColumns) {
|
|
73
|
+
if (dataverseColumnsLower.has(col.toLowerCase())) {
|
|
74
|
+
validColumns.push(col);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
skippedColumns.push(col);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (skippedColumns.length > 0) {
|
|
81
|
+
await logger.logText(`⚠ Skipping ${skippedColumns.length} unmapped column(s): ${skippedColumns.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
// Ensure the key column(s) exist in local data
|
|
84
|
+
const keyParts = resolvedKey.split(',').map(s => s.trim());
|
|
85
|
+
for (const kp of keyParts) {
|
|
86
|
+
if (!localColumns.some(c => c.toLowerCase() === kp.toLowerCase())) {
|
|
87
|
+
throw new Error(`Key column "${kp}" not found in local table "${args.source}". ` +
|
|
88
|
+
`Available columns: ${localColumns.join(', ')}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
await logger.logText(`Syncing ${records.length} record(s) → "${args.target}" (${metadata.entitySetName}) in batches of ${args.batchSize}…`);
|
|
92
|
+
// 7. Chunk and send batches
|
|
93
|
+
const chunks = [];
|
|
94
|
+
for (let i = 0; i < records.length; i += args.batchSize) {
|
|
95
|
+
chunks.push(records.slice(i, i + args.batchSize));
|
|
96
|
+
}
|
|
97
|
+
let totalSuccess = 0;
|
|
98
|
+
let allErrors = [];
|
|
99
|
+
for (let ci = 0; ci < chunks.length; ci++) {
|
|
100
|
+
await logger.logText(`Sending batch ${ci + 1}/${chunks.length} (${chunks[ci].length} records)…`);
|
|
101
|
+
const { successCount, batchErrors } = await sendBatchRequest(orgUrl, metadata.entitySetName, keyParts, keyType, args.mode, chunks[ci], validColumns, token, ci * args.batchSize);
|
|
102
|
+
totalSuccess += successCount;
|
|
103
|
+
allErrors = allErrors.concat(batchErrors);
|
|
104
|
+
}
|
|
105
|
+
// 8. Render output
|
|
106
|
+
const resultHtml = buildResultHtml({
|
|
107
|
+
totalRecords: records.length,
|
|
108
|
+
totalSuccess,
|
|
109
|
+
errors: allErrors,
|
|
110
|
+
skippedColumns,
|
|
111
|
+
keyType,
|
|
112
|
+
resolvedKey
|
|
113
|
+
});
|
|
114
|
+
await logger.replaceOutput(resultHtml);
|
|
115
|
+
}
|
|
116
|
+
// ─── Argument Parser ────────────────────────────────────────────────────────────
|
|
117
|
+
function parseArgs(commandLine) {
|
|
118
|
+
// Remove leading "!sync_dataverse" and tokenize
|
|
119
|
+
const stripped = commandLine.replace(/^!sync_dataverse\s*/, '');
|
|
120
|
+
const tokens = stripped.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
|
|
121
|
+
const args = {
|
|
122
|
+
source: '',
|
|
123
|
+
target: '',
|
|
124
|
+
mode: 'upsert',
|
|
125
|
+
batchSize: 1000
|
|
126
|
+
};
|
|
127
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
128
|
+
const tok = tokens[i];
|
|
129
|
+
switch (tok) {
|
|
130
|
+
case '--source':
|
|
131
|
+
args.source = unquote(tokens[++i] || '');
|
|
132
|
+
break;
|
|
133
|
+
case '--target':
|
|
134
|
+
args.target = unquote(tokens[++i] || '');
|
|
135
|
+
break;
|
|
136
|
+
case '--mode':
|
|
137
|
+
const mode = unquote(tokens[++i] || '');
|
|
138
|
+
if (mode !== 'upsert' && mode !== 'insert') {
|
|
139
|
+
throw new Error(`Invalid mode "${mode}". Supported modes: upsert, insert`);
|
|
140
|
+
}
|
|
141
|
+
args.mode = mode;
|
|
142
|
+
break;
|
|
143
|
+
case '--batch_size':
|
|
144
|
+
args.batchSize = parseInt(unquote(tokens[++i] || ''), 10) || 1000;
|
|
145
|
+
break;
|
|
146
|
+
case '--key':
|
|
147
|
+
args.key = unquote(tokens[++i] || '');
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (!args.source)
|
|
152
|
+
throw new Error('Missing required argument: --source <cell_id/table_name>');
|
|
153
|
+
if (!args.target)
|
|
154
|
+
throw new Error('Missing required argument: --target <dataverse_entity_logical_name>');
|
|
155
|
+
return args;
|
|
156
|
+
}
|
|
157
|
+
function unquote(s) {
|
|
158
|
+
if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
|
|
159
|
+
return s.slice(1, -1);
|
|
160
|
+
}
|
|
161
|
+
return s;
|
|
162
|
+
}
|
|
163
|
+
// ─── Token Acquisition ──────────────────────────────────────────────────────────
|
|
164
|
+
async function getToken(profile, secret) {
|
|
165
|
+
const msal = require('@azure/msal-node');
|
|
166
|
+
if (profile.authMode === 'ServicePrincipal') {
|
|
167
|
+
const cca = new msal.ConfidentialClientApplication({
|
|
168
|
+
auth: {
|
|
169
|
+
clientId: profile.clientId,
|
|
170
|
+
authority: `https://login.microsoftonline.com/${profile.tenantId}`,
|
|
171
|
+
clientSecret: secret
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const response = await cca.acquireTokenByClientCredential({
|
|
175
|
+
scopes: [`https://${profile.server}/.default`]
|
|
176
|
+
});
|
|
177
|
+
return response.accessToken;
|
|
178
|
+
}
|
|
179
|
+
throw new Error(`Auth mode "${profile.authMode}" is not supported for Dataverse sync. Use ServicePrincipal.`);
|
|
180
|
+
}
|
|
181
|
+
// ─── Metadata Fetching ──────────────────────────────────────────────────────────
|
|
182
|
+
async function fetchEntityMetadata(orgUrl, logicalName, token) {
|
|
183
|
+
const headers = {
|
|
184
|
+
'Authorization': `Bearer ${token}`,
|
|
185
|
+
'Accept': 'application/json',
|
|
186
|
+
'OData-MaxVersion': '4.0',
|
|
187
|
+
'OData-Version': '4.0'
|
|
188
|
+
};
|
|
189
|
+
// 1. Entity definition: PrimaryIdAttribute + EntitySetName
|
|
190
|
+
const defUrl = `${orgUrl}/api/data/v9.2/EntityDefinitions(LogicalName='${logicalName}')?$select=PrimaryIdAttribute,EntitySetName`;
|
|
191
|
+
const defRes = await fetch(defUrl, { headers });
|
|
192
|
+
if (!defRes.ok) {
|
|
193
|
+
const body = await defRes.text();
|
|
194
|
+
throw new Error(`Failed to fetch entity definition for "${logicalName}": ${defRes.status} ${defRes.statusText}\n${body}`);
|
|
195
|
+
}
|
|
196
|
+
const defData = await defRes.json();
|
|
197
|
+
// 2. Alternate keys
|
|
198
|
+
const keysUrl = `${orgUrl}/api/data/v9.2/EntityDefinitions(LogicalName='${logicalName}')/Keys?$select=LogicalName,KeyAttributes`;
|
|
199
|
+
const keysRes = await fetch(keysUrl, { headers });
|
|
200
|
+
let alternateKeys = [];
|
|
201
|
+
if (keysRes.ok) {
|
|
202
|
+
const keysData = await keysRes.json();
|
|
203
|
+
alternateKeys = (keysData.value || []).map((k) => ({
|
|
204
|
+
logicalName: k.LogicalName,
|
|
205
|
+
keyAttributes: k.KeyAttributes || []
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
// 3. Attributes (logical names)
|
|
209
|
+
const attrUrl = `${orgUrl}/api/data/v9.2/EntityDefinitions(LogicalName='${logicalName}')/Attributes?$select=LogicalName`;
|
|
210
|
+
const attrRes = await fetch(attrUrl, { headers });
|
|
211
|
+
let attributes = [];
|
|
212
|
+
if (attrRes.ok) {
|
|
213
|
+
const attrData = await attrRes.json();
|
|
214
|
+
attributes = (attrData.value || []).map((a) => a.LogicalName);
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
primaryIdAttribute: defData.PrimaryIdAttribute,
|
|
218
|
+
entitySetName: defData.EntitySetName,
|
|
219
|
+
alternateKeys,
|
|
220
|
+
attributes
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// ─── Batch Request Builder & Sender ─────────────────────────────────────────────
|
|
224
|
+
async function sendBatchRequest(orgUrl, entitySetName, keyColumns, keyType, mode, records, validColumns, token, globalOffset) {
|
|
225
|
+
const batchId = `batch_${(0, uuid_1.v4)()}`;
|
|
226
|
+
const changesetId = `changeset_${(0, uuid_1.v4)()}`;
|
|
227
|
+
let payload = `--${batchId}\r\n`;
|
|
228
|
+
payload += `Content-Type: multipart/mixed; boundary=${changesetId}\r\n\r\n`;
|
|
229
|
+
records.forEach((rec, index) => {
|
|
230
|
+
payload += `--${changesetId}\r\n`;
|
|
231
|
+
payload += `Content-Type: application/http\r\n`;
|
|
232
|
+
payload += `Content-Transfer-Encoding: binary\r\n`;
|
|
233
|
+
payload += `Content-ID: ${index + 1}\r\n\r\n`;
|
|
234
|
+
// Build the record body with only valid columns
|
|
235
|
+
const body = {};
|
|
236
|
+
for (const col of validColumns) {
|
|
237
|
+
if (rec[col] !== undefined) {
|
|
238
|
+
body[col] = rec[col];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (mode === 'insert') {
|
|
242
|
+
payload += `POST ${orgUrl}/api/data/v9.2/${entitySetName} HTTP/1.1\r\n`;
|
|
243
|
+
payload += `Content-Type: application/json; type=entry\r\n\r\n`;
|
|
244
|
+
payload += JSON.stringify(body) + '\r\n';
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// upsert → PATCH
|
|
248
|
+
const keySegment = buildKeySegment(rec, keyColumns, keyType);
|
|
249
|
+
// For upsert, remove key columns from the body if it's the primary key
|
|
250
|
+
const patchBody = { ...body };
|
|
251
|
+
if (keyType === 'primary') {
|
|
252
|
+
for (const kc of keyColumns) {
|
|
253
|
+
delete patchBody[kc];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
payload += `PATCH ${orgUrl}/api/data/v9.2/${entitySetName}(${keySegment}) HTTP/1.1\r\n`;
|
|
257
|
+
payload += `Content-Type: application/json; type=entry\r\n`;
|
|
258
|
+
payload += `If-Match: *\r\n\r\n`;
|
|
259
|
+
payload += JSON.stringify(patchBody) + '\r\n';
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
payload += `--${changesetId}--\r\n`;
|
|
263
|
+
payload += `--${batchId}--\r\n`;
|
|
264
|
+
const res = await fetch(`${orgUrl}/api/data/v9.2/$batch`, {
|
|
265
|
+
method: 'POST',
|
|
266
|
+
headers: {
|
|
267
|
+
'Authorization': `Bearer ${token}`,
|
|
268
|
+
'Content-Type': `multipart/mixed; boundary=${batchId}`,
|
|
269
|
+
'OData-MaxVersion': '4.0',
|
|
270
|
+
'OData-Version': '4.0',
|
|
271
|
+
'Accept': 'application/json'
|
|
272
|
+
},
|
|
273
|
+
body: payload
|
|
274
|
+
});
|
|
275
|
+
if (!res.ok) {
|
|
276
|
+
const errBody = await res.text();
|
|
277
|
+
throw new Error(`Batch request failed: ${res.status} ${res.statusText}\n${errBody}`);
|
|
278
|
+
}
|
|
279
|
+
const text = await res.text();
|
|
280
|
+
return parseBatchResponse(text, records, keyColumns, globalOffset);
|
|
281
|
+
}
|
|
282
|
+
function buildKeySegment(record, keyColumns, keyType) {
|
|
283
|
+
if (keyType === 'primary') {
|
|
284
|
+
// Primary key is always a single GUID
|
|
285
|
+
return record[keyColumns[0]];
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// Alternate key: key1='value1',key2='value2'
|
|
289
|
+
return keyColumns
|
|
290
|
+
.map(kc => {
|
|
291
|
+
const val = record[kc];
|
|
292
|
+
if (typeof val === 'string') {
|
|
293
|
+
return `${kc}='${val}'`;
|
|
294
|
+
}
|
|
295
|
+
return `${kc}=${val}`;
|
|
296
|
+
})
|
|
297
|
+
.join(',');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// ─── Batch Response Parser ──────────────────────────────────────────────────────
|
|
301
|
+
function parseBatchResponse(responseText, originalRecords, keyColumns, globalOffset) {
|
|
302
|
+
let successCount = 0;
|
|
303
|
+
const batchErrors = [];
|
|
304
|
+
const blocks = responseText.split('Content-ID:');
|
|
305
|
+
blocks.shift(); // remove preamble
|
|
306
|
+
blocks.forEach(block => {
|
|
307
|
+
const idMatch = block.match(/^\s*(\d+)/);
|
|
308
|
+
if (idMatch) {
|
|
309
|
+
const reqIndex = parseInt(idMatch[1]) - 1;
|
|
310
|
+
const record = originalRecords[reqIndex];
|
|
311
|
+
const statusMatch = block.match(/HTTP\/1\.1\s+(\d+)/);
|
|
312
|
+
if (statusMatch) {
|
|
313
|
+
const statusCode = parseInt(statusMatch[1]);
|
|
314
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
315
|
+
successCount++;
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
const jsonMatch = block.match(/\{[\s\S]*\}/);
|
|
319
|
+
let errorMsg = `HTTP ${statusCode}`;
|
|
320
|
+
if (jsonMatch) {
|
|
321
|
+
try {
|
|
322
|
+
const errObj = JSON.parse(jsonMatch[0]);
|
|
323
|
+
errorMsg = errObj.error?.message || errorMsg;
|
|
324
|
+
}
|
|
325
|
+
catch (e) { }
|
|
326
|
+
}
|
|
327
|
+
const keyVal = record
|
|
328
|
+
? keyColumns.map(kc => `${kc}=${record[kc]}`).join(', ')
|
|
329
|
+
: 'Unknown';
|
|
330
|
+
batchErrors.push({
|
|
331
|
+
recordIndex: globalOffset + reqIndex,
|
|
332
|
+
recordKey: keyVal,
|
|
333
|
+
error: errorMsg
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
return { successCount, batchErrors };
|
|
340
|
+
}
|
|
341
|
+
// ─── Output Rendering ───────────────────────────────────────────────────────────
|
|
342
|
+
function buildResultHtml(result) {
|
|
343
|
+
const hasErrors = result.errors.length > 0;
|
|
344
|
+
const statusColor = hasErrors ? '#ff6b6b' : '#51cf66';
|
|
345
|
+
const statusIcon = hasErrors ? '⚠' : '✓';
|
|
346
|
+
const statusText = hasErrors
|
|
347
|
+
? `Partial sync: ${result.totalSuccess} succeeded, ${result.errors.length} failed`
|
|
348
|
+
: `Successfully synced ${result.totalSuccess} record(s)`;
|
|
349
|
+
let html = `
|
|
350
|
+
<!DOCTYPE html>
|
|
351
|
+
<html>
|
|
352
|
+
<head>
|
|
353
|
+
<style>
|
|
354
|
+
.sync-result {
|
|
355
|
+
font-family: var(--vscode-editor-font-family, 'Segoe UI', sans-serif);
|
|
356
|
+
font-size: 13px;
|
|
357
|
+
color: var(--vscode-foreground);
|
|
358
|
+
padding: 12px;
|
|
359
|
+
}
|
|
360
|
+
.sync-header {
|
|
361
|
+
display: flex;
|
|
362
|
+
align-items: center;
|
|
363
|
+
gap: 8px;
|
|
364
|
+
padding: 10px 14px;
|
|
365
|
+
border-radius: 6px;
|
|
366
|
+
margin-bottom: 12px;
|
|
367
|
+
font-weight: 600;
|
|
368
|
+
font-size: 14px;
|
|
369
|
+
}
|
|
370
|
+
.sync-header.success {
|
|
371
|
+
background: rgba(81, 207, 102, 0.12);
|
|
372
|
+
border: 1px solid rgba(81, 207, 102, 0.3);
|
|
373
|
+
color: #51cf66;
|
|
374
|
+
}
|
|
375
|
+
.sync-header.partial {
|
|
376
|
+
background: rgba(255, 107, 107, 0.12);
|
|
377
|
+
border: 1px solid rgba(255, 107, 107, 0.3);
|
|
378
|
+
color: #ff6b6b;
|
|
379
|
+
}
|
|
380
|
+
.sync-meta {
|
|
381
|
+
display: flex;
|
|
382
|
+
gap: 16px;
|
|
383
|
+
flex-wrap: wrap;
|
|
384
|
+
margin-bottom: 12px;
|
|
385
|
+
font-size: 12px;
|
|
386
|
+
opacity: 0.8;
|
|
387
|
+
}
|
|
388
|
+
.sync-meta span {
|
|
389
|
+
background: var(--vscode-badge-background);
|
|
390
|
+
color: var(--vscode-badge-foreground);
|
|
391
|
+
padding: 2px 8px;
|
|
392
|
+
border-radius: 10px;
|
|
393
|
+
}
|
|
394
|
+
.sync-warnings {
|
|
395
|
+
padding: 8px 12px;
|
|
396
|
+
background: rgba(255, 193, 7, 0.1);
|
|
397
|
+
border: 1px solid rgba(255, 193, 7, 0.25);
|
|
398
|
+
border-radius: 4px;
|
|
399
|
+
margin-bottom: 12px;
|
|
400
|
+
font-size: 12px;
|
|
401
|
+
color: #ffc107;
|
|
402
|
+
}
|
|
403
|
+
table {
|
|
404
|
+
border-collapse: collapse;
|
|
405
|
+
width: 100%;
|
|
406
|
+
font-size: 12px;
|
|
407
|
+
}
|
|
408
|
+
th, td {
|
|
409
|
+
border: 1px solid var(--vscode-panel-border, #333);
|
|
410
|
+
padding: 6px 10px;
|
|
411
|
+
text-align: left;
|
|
412
|
+
}
|
|
413
|
+
th {
|
|
414
|
+
background: var(--vscode-editor-inactiveSelectionBackground);
|
|
415
|
+
font-weight: 600;
|
|
416
|
+
position: sticky;
|
|
417
|
+
top: 0;
|
|
418
|
+
}
|
|
419
|
+
tr:nth-child(even) {
|
|
420
|
+
background: var(--vscode-tree-tableOddRowsBackground);
|
|
421
|
+
}
|
|
422
|
+
.error-cell {
|
|
423
|
+
color: #ff6b6b;
|
|
424
|
+
}
|
|
425
|
+
</style>
|
|
426
|
+
</head>
|
|
427
|
+
<body>
|
|
428
|
+
<div class="sync-result">
|
|
429
|
+
<div class="sync-header ${hasErrors ? 'partial' : 'success'}">
|
|
430
|
+
<span>${statusIcon}</span>
|
|
431
|
+
<span>${statusText}</span>
|
|
432
|
+
</div>
|
|
433
|
+
<div class="sync-meta">
|
|
434
|
+
<span>Total: ${result.totalRecords}</span>
|
|
435
|
+
<span>Key: ${result.resolvedKey} (${result.keyType})</span>
|
|
436
|
+
</div>`;
|
|
437
|
+
if (result.skippedColumns.length > 0) {
|
|
438
|
+
html += `
|
|
439
|
+
<div class="sync-warnings">
|
|
440
|
+
⚠ Skipped columns not in Dataverse: ${escapeHtml(result.skippedColumns.join(', '))}
|
|
441
|
+
</div>`;
|
|
442
|
+
}
|
|
443
|
+
if (hasErrors) {
|
|
444
|
+
html += `
|
|
445
|
+
<div style="max-height: 300px; overflow: auto;">
|
|
446
|
+
<table>
|
|
447
|
+
<thead><tr><th>#</th><th>Key</th><th>Error</th></tr></thead>
|
|
448
|
+
<tbody>`;
|
|
449
|
+
for (const err of result.errors) {
|
|
450
|
+
html += `<tr>
|
|
451
|
+
<td>${err.recordIndex + 1}</td>
|
|
452
|
+
<td>${escapeHtml(err.recordKey)}</td>
|
|
453
|
+
<td class="error-cell">${escapeHtml(err.error)}</td>
|
|
454
|
+
</tr>`;
|
|
455
|
+
}
|
|
456
|
+
html += `</tbody></table></div>`;
|
|
457
|
+
}
|
|
458
|
+
html += `</div></body></html>`;
|
|
459
|
+
return html;
|
|
460
|
+
}
|
|
461
|
+
function escapeHtml(unsafe) {
|
|
462
|
+
if (unsafe === undefined || unsafe === null)
|
|
463
|
+
return '';
|
|
464
|
+
return unsafe.toString()
|
|
465
|
+
.replace(/&/g, '&')
|
|
466
|
+
.replace(/</g, '<')
|
|
467
|
+
.replace(/>/g, '>')
|
|
468
|
+
.replace(/"/g, '"')
|
|
469
|
+
.replace(/'/g, ''');
|
|
470
|
+
}
|
|
471
|
+
//# sourceMappingURL=syncDataverseHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syncDataverseHandler.js","sourceRoot":"","sources":["../src/syncDataverseHandler.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vura-data-os/vura-dataverse-sync-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Host-agnostic Microsoft Dataverse $batch sync engine, shared by vura-dataverse-adapter (VS Code) and vura-dataverse-runner-plugin (CLI)",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"vura",
|
|
7
|
+
"data-os",
|
|
8
|
+
"dynamics-365",
|
|
9
|
+
"dataverse",
|
|
10
|
+
"odata",
|
|
11
|
+
"sync"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/nexionlabsdev/vura-public/tree/main/packages/vura-dataverse-sync-core#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/nexionlabsdev/vura-public/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/nexionlabsdev/vura-public/#main",
|
|
20
|
+
"directory": "packages/vura-dataverse-sync-core"
|
|
21
|
+
},
|
|
22
|
+
"license": "AGPL-3.0",
|
|
23
|
+
"author": "Nexion Labs <info@nexionlabs.dev> (https://nexionlabs.dev)",
|
|
24
|
+
"type": "commonjs",
|
|
25
|
+
"main": "out/index.js",
|
|
26
|
+
"types": "out/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"out"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"compile": "tsc -b ./",
|
|
38
|
+
"watch": "tsc -b -w ./",
|
|
39
|
+
"prepublishOnly": "npm run compile"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@azure/msal-node": "^2.6.4",
|
|
43
|
+
"@vura-data-os/core-sdk": "^1.0.1",
|
|
44
|
+
"uuid": "^13.0.2"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^18.19.130",
|
|
48
|
+
"@types/uuid": "^10.0.0",
|
|
49
|
+
"typescript": "^5.9.3"
|
|
50
|
+
}
|
|
51
|
+
}
|