@uipath/data-fabric-tool 1.1.0 → 1.195.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/dist/tool.js +1638 -1164
- package/package.json +16 -24
- package/src/commands/choice-sets.spec.ts +538 -83
- package/src/commands/choice-sets.ts +550 -146
- package/src/commands/entities.spec.ts +58 -145
- package/src/commands/entities.ts +160 -367
- package/src/commands/files.spec.ts +18 -32
- package/src/commands/files.ts +33 -89
- package/src/commands/records.spec.ts +102 -207
- package/src/commands/records.ts +112 -328
- package/src/tool.ts +5 -1
- package/src/utils/output.spec.ts +78 -0
- package/src/utils/output.ts +51 -0
- package/src/utils/sdk-client.spec.ts +59 -0
- package/src/utils/sdk-client.ts +23 -0
- package/src/utils/pagination.ts +0 -10
package/src/commands/entities.ts
CHANGED
|
@@ -17,7 +17,8 @@ import type {
|
|
|
17
17
|
import { EntityFieldDataType } from "@uipath/uipath-typescript";
|
|
18
18
|
import type { Command } from "commander";
|
|
19
19
|
import { readJsonInput } from "../utils/input";
|
|
20
|
-
import {
|
|
20
|
+
import { fail, requireDestructiveConfirmation } from "../utils/output";
|
|
21
|
+
import { connectOrFail } from "../utils/sdk-client";
|
|
21
22
|
|
|
22
23
|
interface ListOptions {
|
|
23
24
|
tenant?: string;
|
|
@@ -50,28 +51,25 @@ interface DeleteOptions {
|
|
|
50
51
|
|
|
51
52
|
const ENTITIES_LIST_EXAMPLES: CommandExample[] = [
|
|
52
53
|
{
|
|
53
|
-
Description: "List Data Fabric entities",
|
|
54
|
+
Description: "List Data Fabric entities.",
|
|
54
55
|
Command: "uip df entities list --native-only",
|
|
55
56
|
Output: {
|
|
56
57
|
Code: "EntityList",
|
|
57
58
|
Data: [
|
|
58
59
|
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Source: "Native",
|
|
73
|
-
Description: "Customer records",
|
|
74
|
-
FieldCount: 6,
|
|
60
|
+
id: "a1b2c3d4-0000-0000-0000-000000000001",
|
|
61
|
+
name: "Invoice",
|
|
62
|
+
displayName: "Invoice",
|
|
63
|
+
entityType: "Standard",
|
|
64
|
+
description: "Invoice records",
|
|
65
|
+
isRbacEnabled: false,
|
|
66
|
+
fields: [
|
|
67
|
+
{
|
|
68
|
+
id: "f1000000-0000-0000-0000-000000000001",
|
|
69
|
+
name: "amount",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
externalFields: [],
|
|
75
73
|
},
|
|
76
74
|
],
|
|
77
75
|
},
|
|
@@ -80,34 +78,35 @@ const ENTITIES_LIST_EXAMPLES: CommandExample[] = [
|
|
|
80
78
|
|
|
81
79
|
const ENTITIES_GET_EXAMPLES: CommandExample[] = [
|
|
82
80
|
{
|
|
83
|
-
Description: "Get entity schema by ID",
|
|
81
|
+
Description: "Get entity schema by ID.",
|
|
84
82
|
Command: "uip df entities get a1b2c3d4-0000-0000-0000-000000000001",
|
|
85
83
|
Output: {
|
|
86
84
|
Code: "EntitySchema",
|
|
87
85
|
Data: {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
ID: "f1000000-0000-0000-0000-000000000001",
|
|
96
|
-
Name: "id",
|
|
97
|
-
DisplayName: "ID",
|
|
98
|
-
Type: "Guid",
|
|
99
|
-
Required: true,
|
|
100
|
-
PrimaryKey: true,
|
|
101
|
-
System: true,
|
|
102
|
-
},
|
|
86
|
+
id: "a1b2c3d4-0000-0000-0000-000000000001",
|
|
87
|
+
name: "Invoice",
|
|
88
|
+
displayName: "Invoice",
|
|
89
|
+
entityType: "Standard",
|
|
90
|
+
description: "Invoice records",
|
|
91
|
+
isRbacEnabled: false,
|
|
92
|
+
fields: [
|
|
103
93
|
{
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
94
|
+
id: "f1000000-0000-0000-0000-000000000002",
|
|
95
|
+
name: "amount",
|
|
96
|
+
displayName: "Amount",
|
|
97
|
+
fieldDataType: { name: "DECIMAL" },
|
|
98
|
+
sqlType: {
|
|
99
|
+
name: "DECIMAL",
|
|
100
|
+
decimalPrecision: 2,
|
|
101
|
+
minValue: 0,
|
|
102
|
+
maxValue: 999999,
|
|
103
|
+
},
|
|
104
|
+
isRequired: true,
|
|
105
|
+
isUnique: false,
|
|
106
|
+
isEncrypted: false,
|
|
107
|
+
isRbacEnabled: false,
|
|
108
|
+
isPrimaryKey: false,
|
|
109
|
+
isSystemField: false,
|
|
111
110
|
},
|
|
112
111
|
],
|
|
113
112
|
},
|
|
@@ -134,12 +133,12 @@ const ENTITIES_DELETE_EXAMPLES: CommandExample[] = [
|
|
|
134
133
|
const ENTITIES_CREATE_EXAMPLES: CommandExample[] = [
|
|
135
134
|
{
|
|
136
135
|
Description:
|
|
137
|
-
"Create an entity with
|
|
136
|
+
"Create an entity with choice-set, relationship, and file fields. " +
|
|
138
137
|
"CHOICE_SET_SINGLE/CHOICE_SET_MULTIPLE require 'choiceSetId' (from 'df choice-sets list'). " +
|
|
139
|
-
"RELATIONSHIP
|
|
140
|
-
"Note:
|
|
138
|
+
"RELATIONSHIP and FILE both require 'referenceEntityId' (UUID of the target entity, from 'df entities list') and 'referenceFieldId' (UUID of the field on the target entity, from 'df entities get <target-id>'). " +
|
|
139
|
+
"Note: a RELATIONSHIP column on a record always stores the target record's UUID 'Id' (regardless of which 'referenceFieldId' configured the join) — see 'df records insert' for how to write the value.",
|
|
141
140
|
Command:
|
|
142
|
-
'uip df entities create Expense --body \'{"displayName":"Expense","fields":[{"fieldName":"category","type":"CHOICE_SET_SINGLE","choiceSetId":"c1d2e3f4-0000-0000-0000-000000000001","isRequired":true},{"fieldName":"tags","type":"CHOICE_SET_MULTIPLE","choiceSetId":"c1d2e3f4-0000-0000-0000-000000000002"},{"fieldName":"submitter","type":"RELATIONSHIP","
|
|
141
|
+
'uip df entities create Expense --body \'{"displayName":"Expense","fields":[{"fieldName":"category","type":"CHOICE_SET_SINGLE","choiceSetId":"c1d2e3f4-0000-0000-0000-000000000001","isRequired":true},{"fieldName":"tags","type":"CHOICE_SET_MULTIPLE","choiceSetId":"c1d2e3f4-0000-0000-0000-000000000002"},{"fieldName":"submitter","type":"RELATIONSHIP","referenceEntityId":"a1b2c3d4-0000-0000-0000-000000000010","referenceFieldId":"f1000000-0000-0000-0000-000000000100","isRequired":true},{"fieldName":"receipt","type":"FILE","referenceEntityId":"a1b2c3d4-0000-0000-0000-000000000099","referenceFieldId":"f1000000-0000-0000-0000-000000000199"}]}\'',
|
|
143
142
|
Output: {
|
|
144
143
|
Code: "EntityCreated",
|
|
145
144
|
Data: { ID: "a1b2c3d4-0000-0000-0000-000000000004" },
|
|
@@ -196,54 +195,25 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
196
195
|
)
|
|
197
196
|
.examples(ENTITIES_LIST_EXAMPLES)
|
|
198
197
|
.trackedAction(processContext, async (options: ListOptions) => {
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
if (clientError) {
|
|
204
|
-
OutputFormatter.error({
|
|
205
|
-
Result: RESULTS.Failure,
|
|
206
|
-
Message: "Error connecting to Data Fabric",
|
|
207
|
-
Instructions: await extractErrorMessage(clientError),
|
|
208
|
-
});
|
|
209
|
-
processContext.exit(1);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
198
|
+
const sdk = await connectOrFail(options.tenant);
|
|
199
|
+
if (!sdk) return;
|
|
212
200
|
|
|
213
201
|
const [listError, result] = await catchError(sdk.entities.getAll());
|
|
214
202
|
|
|
215
203
|
if (listError) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
221
|
-
processContext.exit(1);
|
|
222
|
-
return;
|
|
204
|
+
return fail(
|
|
205
|
+
"Error listing entities",
|
|
206
|
+
await extractErrorMessage(listError),
|
|
207
|
+
);
|
|
223
208
|
}
|
|
224
209
|
|
|
225
|
-
const entityList = (result ?? [])
|
|
226
|
-
.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
externalFields[0]?.externalConnectionDetail
|
|
233
|
-
?.connectorName;
|
|
234
|
-
return {
|
|
235
|
-
Name: entity.name,
|
|
236
|
-
DisplayName: entity.displayName || entity.name,
|
|
237
|
-
ID: entity.id,
|
|
238
|
-
Type: entity.entityType,
|
|
239
|
-
Source: isNative
|
|
240
|
-
? "Native"
|
|
241
|
-
: `Federated${connectorName ? ` (${connectorName})` : ""}`,
|
|
242
|
-
Description: entity.description || "",
|
|
243
|
-
FieldCount: entity.fields.length,
|
|
244
|
-
};
|
|
245
|
-
})
|
|
246
|
-
.filter((e) => !options.nativeOnly || e.Source === "Native");
|
|
210
|
+
const entityList = (result ?? []).filter((e) => {
|
|
211
|
+
if (!options.nativeOnly) return true;
|
|
212
|
+
const entity = e as unknown as RawEntityGetResponse;
|
|
213
|
+
const externalFields: ExternalSourceFields[] =
|
|
214
|
+
entity.externalFields ?? [];
|
|
215
|
+
return externalFields.length === 0;
|
|
216
|
+
});
|
|
247
217
|
|
|
248
218
|
OutputFormatter.success({
|
|
249
219
|
Result: RESULTS.Success,
|
|
@@ -263,68 +233,33 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
263
233
|
.trackedAction(
|
|
264
234
|
processContext,
|
|
265
235
|
async (id: string, options: GetOptions) => {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
if (clientError) {
|
|
271
|
-
OutputFormatter.error({
|
|
272
|
-
Result: RESULTS.Failure,
|
|
273
|
-
Message: "Error connecting to Data Fabric",
|
|
274
|
-
Instructions: await extractErrorMessage(clientError),
|
|
275
|
-
});
|
|
276
|
-
processContext.exit(1);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
236
|
+
const sdk = await connectOrFail(options.tenant);
|
|
237
|
+
if (!sdk) return;
|
|
279
238
|
|
|
280
239
|
const [getError, entity] = await catchError(
|
|
281
240
|
sdk.entities.getById(id),
|
|
282
241
|
);
|
|
283
242
|
|
|
284
243
|
if (getError) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
});
|
|
290
|
-
processContext.exit(1);
|
|
291
|
-
return;
|
|
244
|
+
return fail(
|
|
245
|
+
`Error getting entity schema '${id}'`,
|
|
246
|
+
await extractErrorMessage(getError),
|
|
247
|
+
);
|
|
292
248
|
}
|
|
293
249
|
|
|
294
250
|
const e = entity as unknown as RawEntityGetResponse;
|
|
295
251
|
|
|
296
252
|
if (!e?.fields) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
"Verify the entity ID exists. Use 'df entities list' to see available entities.",
|
|
302
|
-
});
|
|
303
|
-
processContext.exit(1);
|
|
304
|
-
return;
|
|
253
|
+
return fail(
|
|
254
|
+
`Entity '${id}' not found`,
|
|
255
|
+
"Verify the entity ID exists. Use 'df entities list' to see available entities.",
|
|
256
|
+
);
|
|
305
257
|
}
|
|
306
258
|
|
|
307
|
-
const fields = e.fields.map((field) => ({
|
|
308
|
-
ID: field.id,
|
|
309
|
-
Name: field.name,
|
|
310
|
-
DisplayName: field.displayName,
|
|
311
|
-
Type: field.fieldDataType?.name,
|
|
312
|
-
Required: field.isRequired,
|
|
313
|
-
PrimaryKey: field.isPrimaryKey,
|
|
314
|
-
System: field.isSystemField,
|
|
315
|
-
}));
|
|
316
|
-
|
|
317
259
|
OutputFormatter.success({
|
|
318
260
|
Result: RESULTS.Success,
|
|
319
261
|
Code: "EntitySchema",
|
|
320
|
-
Data:
|
|
321
|
-
Name: e.name,
|
|
322
|
-
DisplayName: e.displayName || e.name,
|
|
323
|
-
ID: e.id,
|
|
324
|
-
Type: e.entityType,
|
|
325
|
-
Description: e.description || "",
|
|
326
|
-
Fields: fields,
|
|
327
|
-
},
|
|
262
|
+
Data: e,
|
|
328
263
|
});
|
|
329
264
|
},
|
|
330
265
|
);
|
|
@@ -357,13 +292,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
357
292
|
);
|
|
358
293
|
|
|
359
294
|
if (parseError) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
});
|
|
365
|
-
processContext.exit(1);
|
|
366
|
-
return;
|
|
295
|
+
return fail(
|
|
296
|
+
"Error parsing entity definition",
|
|
297
|
+
parseError.message,
|
|
298
|
+
);
|
|
367
299
|
}
|
|
368
300
|
|
|
369
301
|
if (
|
|
@@ -371,27 +303,18 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
371
303
|
parsed === null ||
|
|
372
304
|
Array.isArray(parsed)
|
|
373
305
|
) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
"Provide a JSON object with a 'fields' array and optional displayName, description, isRbacEnabled.",
|
|
379
|
-
});
|
|
380
|
-
processContext.exit(1);
|
|
381
|
-
return;
|
|
306
|
+
return fail(
|
|
307
|
+
"Entity definition must be a JSON object",
|
|
308
|
+
"Provide a JSON object with a 'fields' array and optional displayName, description, isRbacEnabled.",
|
|
309
|
+
);
|
|
382
310
|
}
|
|
383
311
|
|
|
384
312
|
const definition = parsed as Record<string, unknown>;
|
|
385
313
|
if (!Array.isArray(definition.fields)) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
Instructions:
|
|
391
|
-
"Provide a JSON object with a 'fields' array containing field definitions.",
|
|
392
|
-
});
|
|
393
|
-
processContext.exit(1);
|
|
394
|
-
return;
|
|
314
|
+
return fail(
|
|
315
|
+
"Entity definition must include a 'fields' array",
|
|
316
|
+
"Provide a JSON object with a 'fields' array containing field definitions.",
|
|
317
|
+
);
|
|
395
318
|
}
|
|
396
319
|
|
|
397
320
|
const hasInvalidField = (definition.fields as unknown[]).some(
|
|
@@ -402,39 +325,21 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
402
325
|
"string",
|
|
403
326
|
);
|
|
404
327
|
if (hasInvalidField) {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
'Example: {"fieldName":"title","type":"STRING"}',
|
|
410
|
-
});
|
|
411
|
-
processContext.exit(1);
|
|
412
|
-
return;
|
|
328
|
+
return fail(
|
|
329
|
+
"Each field must include a 'fieldName' string",
|
|
330
|
+
'Example: {"fieldName":"title","type":"STRING"}',
|
|
331
|
+
);
|
|
413
332
|
}
|
|
414
333
|
|
|
415
334
|
if (hasInvalidFieldType(definition.fields as unknown[])) {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
});
|
|
421
|
-
processContext.exit(1);
|
|
422
|
-
return;
|
|
335
|
+
return fail(
|
|
336
|
+
"Invalid field type in fields",
|
|
337
|
+
`Valid types: ${VALID_FIELD_TYPES_LIST}`,
|
|
338
|
+
);
|
|
423
339
|
}
|
|
424
340
|
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
);
|
|
428
|
-
|
|
429
|
-
if (clientError) {
|
|
430
|
-
OutputFormatter.error({
|
|
431
|
-
Result: RESULTS.Failure,
|
|
432
|
-
Message: "Error connecting to Data Fabric",
|
|
433
|
-
Instructions: await extractErrorMessage(clientError),
|
|
434
|
-
});
|
|
435
|
-
processContext.exit(1);
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
341
|
+
const sdk = await connectOrFail(options.tenant);
|
|
342
|
+
if (!sdk) return;
|
|
438
343
|
|
|
439
344
|
const createOpts = {
|
|
440
345
|
...(definition.displayName !== undefined && {
|
|
@@ -460,13 +365,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
460
365
|
);
|
|
461
366
|
|
|
462
367
|
if (createError) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
});
|
|
468
|
-
processContext.exit(1);
|
|
469
|
-
return;
|
|
368
|
+
return fail(
|
|
369
|
+
"Error creating entity",
|
|
370
|
+
await extractErrorMessage(createError),
|
|
371
|
+
);
|
|
470
372
|
}
|
|
471
373
|
|
|
472
374
|
OutputFormatter.success({
|
|
@@ -509,13 +411,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
509
411
|
);
|
|
510
412
|
|
|
511
413
|
if (parseError) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
});
|
|
517
|
-
processContext.exit(1);
|
|
518
|
-
return;
|
|
414
|
+
return fail(
|
|
415
|
+
"Error parsing update options",
|
|
416
|
+
parseError.message,
|
|
417
|
+
);
|
|
519
418
|
}
|
|
520
419
|
|
|
521
420
|
if (
|
|
@@ -523,14 +422,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
523
422
|
parsed === null ||
|
|
524
423
|
Array.isArray(parsed)
|
|
525
424
|
) {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
"Provide a JSON object with addFields, updateFields, removeFields, displayName, description, or isRbacEnabled.",
|
|
531
|
-
});
|
|
532
|
-
processContext.exit(1);
|
|
533
|
-
return;
|
|
425
|
+
return fail(
|
|
426
|
+
"Update options must be a JSON object",
|
|
427
|
+
"Provide a JSON object with addFields, updateFields, removeFields, displayName, description, or isRbacEnabled.",
|
|
428
|
+
);
|
|
534
429
|
}
|
|
535
430
|
|
|
536
431
|
const input = parsed as Record<string, unknown>;
|
|
@@ -539,42 +434,30 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
539
434
|
input.addFields !== undefined &&
|
|
540
435
|
!Array.isArray(input.addFields)
|
|
541
436
|
) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
'Example: {"addFields":[{"fieldName":"title","type":"STRING"}]}',
|
|
547
|
-
});
|
|
548
|
-
processContext.exit(1);
|
|
549
|
-
return;
|
|
437
|
+
return fail(
|
|
438
|
+
"'addFields' must be an array",
|
|
439
|
+
'Example: {"addFields":[{"fieldName":"title","type":"STRING"}]}',
|
|
440
|
+
);
|
|
550
441
|
}
|
|
551
442
|
|
|
552
443
|
if (
|
|
553
444
|
input.updateFields !== undefined &&
|
|
554
445
|
!Array.isArray(input.updateFields)
|
|
555
446
|
) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
'Example: {"updateFields":[{"id":"<fieldId>","displayName":"New Name"}]}',
|
|
561
|
-
});
|
|
562
|
-
processContext.exit(1);
|
|
563
|
-
return;
|
|
447
|
+
return fail(
|
|
448
|
+
"'updateFields' must be an array",
|
|
449
|
+
'Example: {"updateFields":[{"id":"<fieldId>","displayName":"New Name"}]}',
|
|
450
|
+
);
|
|
564
451
|
}
|
|
565
452
|
|
|
566
453
|
if (
|
|
567
454
|
input.removeFields !== undefined &&
|
|
568
455
|
!Array.isArray(input.removeFields)
|
|
569
456
|
) {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
'Example: {"removeFields":[{"fieldName":"old_field"}]}',
|
|
575
|
-
});
|
|
576
|
-
processContext.exit(1);
|
|
577
|
-
return;
|
|
457
|
+
return fail(
|
|
458
|
+
"'removeFields' must be an array",
|
|
459
|
+
'Example: {"removeFields":[{"fieldName":"old_field"}]}',
|
|
460
|
+
);
|
|
578
461
|
}
|
|
579
462
|
|
|
580
463
|
let trimmedReason: string | undefined;
|
|
@@ -591,41 +474,18 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
591
474
|
return typeof fn !== "string" || fn.trim() === "";
|
|
592
475
|
});
|
|
593
476
|
if (hasInvalidRemove) {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
Instructions:
|
|
599
|
-
'Example: {"removeFields":[{"fieldName":"old_field"}]}',
|
|
600
|
-
});
|
|
601
|
-
processContext.exit(1);
|
|
602
|
-
return;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
if (options.confirm !== true) {
|
|
606
|
-
OutputFormatter.error({
|
|
607
|
-
Result: RESULTS.Failure,
|
|
608
|
-
Message:
|
|
609
|
-
"Confirmation required for destructive operation",
|
|
610
|
-
Instructions:
|
|
611
|
-
"Pass --confirm to acknowledge field deletion is irreversible.",
|
|
612
|
-
});
|
|
613
|
-
processContext.exit(1);
|
|
614
|
-
return;
|
|
477
|
+
return fail(
|
|
478
|
+
"Each field in removeFields must include a non-empty 'fieldName' string",
|
|
479
|
+
'Example: {"removeFields":[{"fieldName":"old_field"}]}',
|
|
480
|
+
);
|
|
615
481
|
}
|
|
616
482
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
Instructions:
|
|
624
|
-
'Pass --reason "<text>" to record why fields are being removed.',
|
|
625
|
-
});
|
|
626
|
-
processContext.exit(1);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
483
|
+
const reason = requireDestructiveConfirmation(
|
|
484
|
+
options,
|
|
485
|
+
'Pass --reason "<text>" to record why fields are being removed.',
|
|
486
|
+
);
|
|
487
|
+
if (reason === null) return;
|
|
488
|
+
trimmedReason = reason;
|
|
629
489
|
|
|
630
490
|
removedFieldNames = (
|
|
631
491
|
removeFields as { fieldName: string }[]
|
|
@@ -642,25 +502,17 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
642
502
|
},
|
|
643
503
|
);
|
|
644
504
|
if (hasInvalidField) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
Instructions:
|
|
650
|
-
'Example: {"fieldName":"title","type":"STRING"}',
|
|
651
|
-
});
|
|
652
|
-
processContext.exit(1);
|
|
653
|
-
return;
|
|
505
|
+
return fail(
|
|
506
|
+
"Each field in addFields must include a non-empty 'fieldName' string",
|
|
507
|
+
'Example: {"fieldName":"title","type":"STRING"}',
|
|
508
|
+
);
|
|
654
509
|
}
|
|
655
510
|
|
|
656
511
|
if (hasInvalidFieldType(input.addFields as unknown[])) {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
});
|
|
662
|
-
processContext.exit(1);
|
|
663
|
-
return;
|
|
512
|
+
return fail(
|
|
513
|
+
"Invalid field type in addFields",
|
|
514
|
+
`Valid types: ${VALID_FIELD_TYPES_LIST}`,
|
|
515
|
+
);
|
|
664
516
|
}
|
|
665
517
|
|
|
666
518
|
const addNames = (
|
|
@@ -670,14 +522,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
670
522
|
(name, i) => addNames.indexOf(name) !== i,
|
|
671
523
|
);
|
|
672
524
|
if (duplicateAdd !== undefined) {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
"Each entry in addFields must have a unique fieldName.",
|
|
678
|
-
});
|
|
679
|
-
processContext.exit(1);
|
|
680
|
-
return;
|
|
525
|
+
return fail(
|
|
526
|
+
`Duplicate fieldName '${duplicateAdd}' in addFields`,
|
|
527
|
+
"Each entry in addFields must have a unique fieldName.",
|
|
528
|
+
);
|
|
681
529
|
}
|
|
682
530
|
|
|
683
531
|
if (removedFieldNames.length > 0) {
|
|
@@ -685,14 +533,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
685
533
|
removedFieldNames.includes(name),
|
|
686
534
|
);
|
|
687
535
|
if (conflict !== undefined) {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
"A single update cannot add and remove the same field. Split into two calls if you need to recreate it.",
|
|
693
|
-
});
|
|
694
|
-
processContext.exit(1);
|
|
695
|
-
return;
|
|
536
|
+
return fail(
|
|
537
|
+
`Field '${conflict}' appears in both addFields and removeFields`,
|
|
538
|
+
"A single update cannot add and remove the same field. Split into two calls if you need to recreate it.",
|
|
539
|
+
);
|
|
696
540
|
}
|
|
697
541
|
}
|
|
698
542
|
}
|
|
@@ -706,31 +550,15 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
706
550
|
return typeof fid !== "string" || fid.trim() === "";
|
|
707
551
|
});
|
|
708
552
|
if (hasInvalidField) {
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
Instructions:
|
|
714
|
-
'Use \'df entities get <entityId>\' to find field IDs. Example: {"id":"<fieldId>","displayName":"Total Amount","isRequired":true}',
|
|
715
|
-
});
|
|
716
|
-
processContext.exit(1);
|
|
717
|
-
return;
|
|
553
|
+
return fail(
|
|
554
|
+
"Each field in updateFields must include a non-empty 'id' string",
|
|
555
|
+
'Use \'df entities get <entityId>\' to find field IDs. Example: {"id":"<fieldId>","displayName":"Total Amount","isRequired":true}',
|
|
556
|
+
);
|
|
718
557
|
}
|
|
719
558
|
}
|
|
720
559
|
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
);
|
|
724
|
-
|
|
725
|
-
if (clientError) {
|
|
726
|
-
OutputFormatter.error({
|
|
727
|
-
Result: RESULTS.Failure,
|
|
728
|
-
Message: "Error connecting to Data Fabric",
|
|
729
|
-
Instructions: await extractErrorMessage(clientError),
|
|
730
|
-
});
|
|
731
|
-
processContext.exit(1);
|
|
732
|
-
return;
|
|
733
|
-
}
|
|
560
|
+
const sdk = await connectOrFail(options.tenant);
|
|
561
|
+
if (!sdk) return;
|
|
734
562
|
|
|
735
563
|
const entityService: EntityServiceModel = sdk.entities;
|
|
736
564
|
const [updateError] = await catchError(
|
|
@@ -738,13 +566,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
738
566
|
);
|
|
739
567
|
|
|
740
568
|
if (updateError) {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
});
|
|
746
|
-
processContext.exit(1);
|
|
747
|
-
return;
|
|
569
|
+
return fail(
|
|
570
|
+
"Error updating entity",
|
|
571
|
+
await extractErrorMessage(updateError),
|
|
572
|
+
);
|
|
748
573
|
}
|
|
749
574
|
|
|
750
575
|
OutputFormatter.success({
|
|
@@ -777,43 +602,14 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
777
602
|
.trackedAction(
|
|
778
603
|
processContext,
|
|
779
604
|
async (id: string, options: DeleteOptions) => {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
Message:
|
|
784
|
-
"Confirmation required for destructive operation",
|
|
785
|
-
Instructions:
|
|
786
|
-
"Pass --confirm to acknowledge this is irreversible.",
|
|
787
|
-
});
|
|
788
|
-
processContext.exit(1);
|
|
789
|
-
return;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
const reason = options.reason?.trim();
|
|
793
|
-
if (reason === undefined || reason === "") {
|
|
794
|
-
OutputFormatter.error({
|
|
795
|
-
Result: RESULTS.Failure,
|
|
796
|
-
Message: "Reason required for destructive operation",
|
|
797
|
-
Instructions:
|
|
798
|
-
'Pass --reason "<text>" to record why the entity is being deleted.',
|
|
799
|
-
});
|
|
800
|
-
processContext.exit(1);
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
const [clientError, sdk] = await catchError(
|
|
805
|
-
createDataFabricClient(options.tenant),
|
|
605
|
+
const reason = requireDestructiveConfirmation(
|
|
606
|
+
options,
|
|
607
|
+
'Pass --reason "<text>" to record why the entity is being deleted.',
|
|
806
608
|
);
|
|
609
|
+
if (reason === null) return;
|
|
807
610
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
Result: RESULTS.Failure,
|
|
811
|
-
Message: "Error connecting to Data Fabric",
|
|
812
|
-
Instructions: await extractErrorMessage(clientError),
|
|
813
|
-
});
|
|
814
|
-
processContext.exit(1);
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
611
|
+
const sdk = await connectOrFail(options.tenant);
|
|
612
|
+
if (!sdk) return;
|
|
817
613
|
|
|
818
614
|
const entityService: EntityServiceModel = sdk.entities;
|
|
819
615
|
const [deleteError] = await catchError(
|
|
@@ -821,13 +617,10 @@ export const registerEntitiesCommand = (program: Command) => {
|
|
|
821
617
|
);
|
|
822
618
|
|
|
823
619
|
if (deleteError) {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
});
|
|
829
|
-
processContext.exit(1);
|
|
830
|
-
return;
|
|
620
|
+
return fail(
|
|
621
|
+
`Error deleting entity '${id}'`,
|
|
622
|
+
await extractErrorMessage(deleteError),
|
|
623
|
+
);
|
|
831
624
|
}
|
|
832
625
|
|
|
833
626
|
OutputFormatter.success({
|