@aderis-erp/cli 1.0.10 → 1.0.12
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 +1 -0
- package/dist/commands/access-groups.js +178 -86
- package/dist/commands/account-transaction-allocations.js +178 -86
- package/dist/commands/account-transactions.js +181 -87
- package/dist/commands/accounts.js +178 -86
- package/dist/commands/agent-runs.d.ts +1 -0
- package/dist/commands/agent-runs.js +183 -87
- package/dist/commands/audit-log.js +178 -86
- package/dist/commands/auth/login.js +4 -3
- package/dist/commands/bank-accounts.js +178 -86
- package/dist/commands/bank-integrations.js +178 -86
- package/dist/commands/business-partners.js +178 -86
- package/dist/commands/chat.d.ts +40 -0
- package/dist/commands/chat.js +1173 -0
- package/dist/commands/config/add.js +4 -3
- package/dist/commands/credit-card-accounts.js +178 -86
- package/dist/commands/documents.js +178 -86
- package/dist/commands/dunning-configs.js +180 -88
- package/dist/commands/dunning-reminders.js +178 -86
- package/dist/commands/dunning-runs.js +178 -86
- package/dist/commands/email-transactions.d.ts +40 -0
- package/dist/commands/email-transactions.js +1173 -0
- package/dist/commands/employees.js +180 -88
- package/dist/commands/entity-configurations.d.ts +40 -0
- package/dist/commands/entity-configurations.js +1169 -0
- package/dist/commands/event-processor-mappings.js +178 -86
- package/dist/commands/files-internal.js +178 -86
- package/dist/commands/health.js +178 -86
- package/dist/commands/inbox.js +181 -89
- package/dist/commands/integrations.js +178 -86
- package/dist/commands/item-categories.js +178 -86
- package/dist/commands/items.js +178 -86
- package/dist/commands/journal-lines.js +178 -86
- package/dist/commands/journals.js +178 -86
- package/dist/commands/ledgers.js +178 -86
- package/dist/commands/office-locations.js +178 -86
- package/dist/commands/payment-methods.js +178 -86
- package/dist/commands/payment-runs.js +178 -86
- package/dist/commands/payment-terms.js +178 -86
- package/dist/commands/price-lists.js +178 -86
- package/dist/commands/processor-mappings.js +178 -86
- package/dist/commands/processors.js +181 -87
- package/dist/commands/purchase-order-types.d.ts +40 -0
- package/dist/commands/purchase-order-types.js +1178 -0
- package/dist/commands/purchase-orders.d.ts +42 -0
- package/dist/commands/purchase-orders.js +1192 -0
- package/dist/commands/reports.js +178 -86
- package/dist/commands/salary-types.js +178 -86
- package/dist/commands/sales-invoices.js +187 -93
- package/dist/commands/sales-orders.js +186 -93
- package/dist/commands/saved-views.js +178 -86
- package/dist/commands/tags.js +178 -86
- package/dist/commands/tax-codes.js +180 -88
- package/dist/commands/tax-matrix.js +178 -86
- package/dist/commands/tenants.js +180 -88
- package/dist/commands/text-templates.js +178 -86
- package/dist/commands/tools.js +178 -86
- package/dist/commands/vat-declarations.d.ts +1 -0
- package/dist/commands/vat-declarations.js +188 -89
- package/dist/commands/vendor-invoices.js +181 -87
- package/dist/commands/webhooks.js +178 -86
- package/dist/commands/workflows.js +178 -86
- package/dist/lib/auth.js +2 -2
- package/dist/lib/config.d.ts +1 -1
- package/dist/lib/config.js +5 -0
- package/oclif.manifest.json +1174 -328
- package/package.json +2 -1
|
@@ -430,76 +430,126 @@ export default class EventProcessorMappings extends Command {
|
|
|
430
430
|
return '';
|
|
431
431
|
};
|
|
432
432
|
const results = [];
|
|
433
|
-
|
|
433
|
+
// Stream output row-by-row so progress is visible during long imports.
|
|
434
|
+
// Pre-compute the identifier column width from the input items so the
|
|
435
|
+
// table stays aligned without buffering all rows.
|
|
436
|
+
// When stdout is piped (IDE terminals, tee, CI), Node switches to async-buffered
|
|
437
|
+
// mode and rows accumulate in the pipe buffer until it fills. Force blocking
|
|
438
|
+
// mode so each \n-terminated write flushes immediately.
|
|
439
|
+
const stdoutHandle = process.stdout._handle;
|
|
440
|
+
if (stdoutHandle?.setBlocking)
|
|
441
|
+
stdoutHandle.setBlocking(true);
|
|
442
|
+
const outputFormat = flags.output || 'table';
|
|
443
|
+
const useCsv = outputFormat === 'csv' || Boolean(flags.csv);
|
|
444
|
+
const useJson = outputFormat === 'json';
|
|
445
|
+
const statusWidth = 8;
|
|
446
|
+
const identifierWidth = Math.max(10, ...items.map(i => getItemIdentifier(i).length));
|
|
447
|
+
if (useCsv) {
|
|
448
|
+
this.log('status,identifier,id,error');
|
|
449
|
+
}
|
|
450
|
+
else if (!useJson) {
|
|
451
|
+
this.log(`${'status'.padEnd(statusWidth)} ${'identifier'.padEnd(identifierWidth)} error`);
|
|
452
|
+
this.log(`${'-'.repeat(statusWidth)} ${'-'.repeat(identifierWidth)} ${'-'.repeat(50)}`);
|
|
453
|
+
}
|
|
454
|
+
const emitRow = (r) => {
|
|
455
|
+
if (useJson)
|
|
456
|
+
return;
|
|
457
|
+
if (useCsv) {
|
|
458
|
+
const err = (r.error || '').replace(/"/g, '""');
|
|
459
|
+
this.log(`${r.status},${r.identifier || ''},${r.id || ''},"${err}"`);
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
this.log(`${r.status.padEnd(statusWidth)} ${(r.identifier || '').padEnd(identifierWidth)} ${r.error || ''}`);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
// Server-managed fields the API rejects in create/update bodies. Stripped
|
|
466
|
+
// before every request so re-importing a previously-exported payload Just Works.
|
|
467
|
+
const STRIP_FIELDS = new Set(['id', '_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy']);
|
|
468
|
+
const stripServerFields = (item) => {
|
|
469
|
+
const out = {};
|
|
470
|
+
for (const [k, v] of Object.entries(item)) {
|
|
471
|
+
if (!STRIP_FIELDS.has(k))
|
|
472
|
+
out[k] = v;
|
|
473
|
+
}
|
|
474
|
+
return out;
|
|
475
|
+
};
|
|
476
|
+
const processItem = async (item) => {
|
|
434
477
|
const identifier = getItemIdentifier(item);
|
|
478
|
+
const body = stripServerFields(item);
|
|
479
|
+
// If the payload carries an id (e.g. re-importing an export), PATCH directly.
|
|
480
|
+
// Fall through to POST only on 404 (so a missing record still gets created).
|
|
481
|
+
const itemId = typeof item.id === 'string' ? item.id : undefined;
|
|
482
|
+
if (itemId) {
|
|
483
|
+
try {
|
|
484
|
+
const updatePath = updateEndpoint.path.replace('{id}', itemId);
|
|
485
|
+
await apiRequest('PATCH', updatePath, {
|
|
486
|
+
data: body,
|
|
487
|
+
contextName: flags.context,
|
|
488
|
+
});
|
|
489
|
+
return { status: 'updated', id: itemId, identifier };
|
|
490
|
+
}
|
|
491
|
+
catch (error) {
|
|
492
|
+
if (!(error instanceof ApiError && error.status === 404)) {
|
|
493
|
+
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
494
|
+
return { status: 'error', id: itemId, identifier, error: msg };
|
|
495
|
+
}
|
|
496
|
+
// 404 → record gone, try create below
|
|
497
|
+
}
|
|
498
|
+
}
|
|
435
499
|
try {
|
|
436
|
-
// Try to create
|
|
437
500
|
const response = await apiRequest('POST', createEndpoint.path, {
|
|
438
|
-
data:
|
|
501
|
+
data: body,
|
|
439
502
|
contextName: flags.context,
|
|
440
503
|
});
|
|
441
504
|
const id = response.data?.id;
|
|
442
|
-
|
|
505
|
+
return { status: 'created', id: id ? String(id) : undefined, identifier };
|
|
443
506
|
}
|
|
444
507
|
catch (error) {
|
|
445
508
|
if (error instanceof ApiError && error.status === 409) {
|
|
446
|
-
// Conflict - try to update existing
|
|
447
509
|
const errorData = error.data;
|
|
448
510
|
const existingId = errorData?.existingId;
|
|
449
511
|
if (existingId) {
|
|
450
512
|
try {
|
|
451
513
|
const updatePath = updateEndpoint.path.replace('{id}', existingId);
|
|
452
514
|
await apiRequest('PATCH', updatePath, {
|
|
453
|
-
data:
|
|
515
|
+
data: body,
|
|
454
516
|
contextName: flags.context,
|
|
455
517
|
});
|
|
456
|
-
|
|
518
|
+
return { status: 'updated', id: existingId, identifier };
|
|
457
519
|
}
|
|
458
520
|
catch (updateError) {
|
|
459
521
|
const msg = updateError instanceof ApiError ? updateError.message : String(updateError);
|
|
460
|
-
|
|
522
|
+
return { status: 'error', id: existingId, identifier, error: `Update failed: ${msg}` };
|
|
461
523
|
}
|
|
462
524
|
}
|
|
463
|
-
|
|
464
|
-
results.push({ status: 'error', identifier, error: 'Conflict but no existingId returned' });
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
else {
|
|
468
|
-
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
469
|
-
results.push({ status: 'error', identifier, error: msg });
|
|
525
|
+
return { status: 'error', identifier, error: 'Conflict but no existingId returned' };
|
|
470
526
|
}
|
|
527
|
+
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
528
|
+
return { status: 'error', identifier, error: msg };
|
|
471
529
|
}
|
|
472
|
-
}
|
|
530
|
+
};
|
|
531
|
+
// Worker pool: keep N requests in flight at all times. Rows are emitted as
|
|
532
|
+
// each request resolves (so output order may differ from input order). The
|
|
533
|
+
// summary at the end remains accurate regardless.
|
|
534
|
+
const concurrency = 4;
|
|
535
|
+
const queue = [...items];
|
|
536
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, queue.length) }, async () => {
|
|
537
|
+
for (;;) {
|
|
538
|
+
const item = queue.shift();
|
|
539
|
+
if (!item)
|
|
540
|
+
return;
|
|
541
|
+
const r = await processItem(item);
|
|
542
|
+
results.push(r);
|
|
543
|
+
emitRow(r);
|
|
544
|
+
}
|
|
545
|
+
}));
|
|
473
546
|
// Summary counts
|
|
474
547
|
const created = results.filter(r => r.status === 'created').length;
|
|
475
548
|
const updated = results.filter(r => r.status === 'updated').length;
|
|
476
549
|
const errors = results.filter(r => r.status === 'error');
|
|
477
|
-
|
|
478
|
-
const outputFormat = flags.output || 'table';
|
|
479
|
-
if (outputFormat === 'json') {
|
|
550
|
+
if (useJson) {
|
|
480
551
|
this.log(JSON.stringify(results, null, 2));
|
|
481
552
|
}
|
|
482
|
-
else if (outputFormat === 'csv' || flags.csv) {
|
|
483
|
-
// CSV output
|
|
484
|
-
this.log('status,identifier,id,error');
|
|
485
|
-
for (const r of results) {
|
|
486
|
-
const err = (r.error || '').replace(/"/g, '""');
|
|
487
|
-
this.log(`${r.status},${r.identifier || ''},${r.id || ''},"${err}"`);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
// Table output (default)
|
|
492
|
-
if (results.length > 0) {
|
|
493
|
-
const statusWidth = 8;
|
|
494
|
-
const identifierWidth = Math.max(10, ...results.map(r => (r.identifier || '').length));
|
|
495
|
-
this.log(`${'status'.padEnd(statusWidth)} ${'identifier'.padEnd(identifierWidth)} error`);
|
|
496
|
-
this.log(`${'-'.repeat(statusWidth)} ${'-'.repeat(identifierWidth)} ${'-'.repeat(50)}`);
|
|
497
|
-
for (const r of results) {
|
|
498
|
-
const status = r.status === 'created' ? 'created' : r.status === 'updated' ? 'updated' : 'error';
|
|
499
|
-
this.log(`${status.padEnd(statusWidth)} ${(r.identifier || '').padEnd(identifierWidth)} ${r.error || ''}`);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
553
|
// Always show summary at the end
|
|
504
554
|
this.log('');
|
|
505
555
|
this.log(`Summary: ${created} created, ${updated} updated, ${errors.length} failed`);
|
|
@@ -779,80 +829,122 @@ export default class EventProcessorMappings extends Command {
|
|
|
779
829
|
return '';
|
|
780
830
|
};
|
|
781
831
|
const results = [];
|
|
782
|
-
|
|
832
|
+
const stdoutHandle = process.stdout._handle;
|
|
833
|
+
if (stdoutHandle?.setBlocking)
|
|
834
|
+
stdoutHandle.setBlocking(true);
|
|
835
|
+
const outputFormat = flags.output || 'table';
|
|
836
|
+
const useCsv = outputFormat === 'csv' || Boolean(flags.csv);
|
|
837
|
+
const useJson = outputFormat === 'json';
|
|
838
|
+
const statusWidth = 8;
|
|
839
|
+
const identifierWidth = Math.max(10, ...items.map(i => getItemIdentifier(i).length));
|
|
840
|
+
if (useCsv) {
|
|
841
|
+
this.log('status,identifier,id,error');
|
|
842
|
+
}
|
|
843
|
+
else if (!useJson) {
|
|
844
|
+
this.log(`${'status'.padEnd(statusWidth)} ${'identifier'.padEnd(identifierWidth)} error`);
|
|
845
|
+
this.log(`${'-'.repeat(statusWidth)} ${'-'.repeat(identifierWidth)} ${'-'.repeat(50)}`);
|
|
846
|
+
}
|
|
847
|
+
const emitRow = (r) => {
|
|
848
|
+
if (useJson)
|
|
849
|
+
return;
|
|
850
|
+
if (useCsv) {
|
|
851
|
+
const err = (r.error || '').replace(/"/g, '""');
|
|
852
|
+
this.log(`${r.status},${r.identifier || ''},${r.id || ''},"${err}"`);
|
|
853
|
+
}
|
|
854
|
+
else {
|
|
855
|
+
this.log(`${r.status.padEnd(statusWidth)} ${(r.identifier || '').padEnd(identifierWidth)} ${r.error || ''}`);
|
|
856
|
+
}
|
|
857
|
+
};
|
|
858
|
+
const STRIP_FIELDS = new Set(['id', '_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy']);
|
|
859
|
+
const stripServerFields = (item) => {
|
|
860
|
+
const out = {};
|
|
861
|
+
for (const [k, v] of Object.entries(item)) {
|
|
862
|
+
if (!STRIP_FIELDS.has(k))
|
|
863
|
+
out[k] = v;
|
|
864
|
+
}
|
|
865
|
+
return out;
|
|
866
|
+
};
|
|
867
|
+
const buildUpdatePath = (existingId) => {
|
|
868
|
+
const firstUpdateParam = updateEndpoint.pathParams[0];
|
|
869
|
+
const nestedIdParam = updateEndpoint.pathParams.find((p, i) => i > 0);
|
|
870
|
+
let updatePath = updateEndpoint.path.replace(`{${firstUpdateParam}}`, parentId);
|
|
871
|
+
if (nestedIdParam) {
|
|
872
|
+
updatePath = updatePath.replace(`{${nestedIdParam}}`, existingId);
|
|
873
|
+
}
|
|
874
|
+
return updatePath;
|
|
875
|
+
};
|
|
876
|
+
const processItem = async (item) => {
|
|
783
877
|
const identifier = getItemIdentifier(item);
|
|
878
|
+
const body = stripServerFields(item);
|
|
879
|
+
const itemId = typeof item.id === 'string' ? item.id : undefined;
|
|
880
|
+
if (itemId) {
|
|
881
|
+
try {
|
|
882
|
+
await apiRequest('PATCH', buildUpdatePath(itemId), {
|
|
883
|
+
data: body,
|
|
884
|
+
contextName: flags.context,
|
|
885
|
+
});
|
|
886
|
+
return { status: 'updated', id: itemId, identifier };
|
|
887
|
+
}
|
|
888
|
+
catch (error) {
|
|
889
|
+
if (!(error instanceof ApiError && error.status === 404)) {
|
|
890
|
+
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
891
|
+
return { status: 'error', id: itemId, identifier, error: msg };
|
|
892
|
+
}
|
|
893
|
+
// 404 → fall through and try create
|
|
894
|
+
}
|
|
895
|
+
}
|
|
784
896
|
try {
|
|
785
|
-
// Try to create
|
|
786
897
|
const response = await apiRequest('POST', basePath, {
|
|
787
|
-
data:
|
|
898
|
+
data: body,
|
|
788
899
|
contextName: flags.context,
|
|
789
900
|
});
|
|
790
901
|
const id = response.data?.id;
|
|
791
|
-
|
|
902
|
+
return { status: 'created', id: id ? String(id) : undefined, identifier };
|
|
792
903
|
}
|
|
793
904
|
catch (error) {
|
|
794
905
|
if (error instanceof ApiError && error.status === 409) {
|
|
795
|
-
// Conflict - try to update existing
|
|
796
906
|
const errorData = error.data;
|
|
797
907
|
const existingId = errorData?.existingId || item.id;
|
|
798
908
|
if (existingId) {
|
|
799
909
|
try {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
const nestedIdParam = updateEndpoint.pathParams.find((p, i) => i > 0);
|
|
803
|
-
let updatePath = updateEndpoint.path.replace(`{${firstUpdateParam}}`, parentId);
|
|
804
|
-
if (nestedIdParam) {
|
|
805
|
-
updatePath = updatePath.replace(`{${nestedIdParam}}`, existingId);
|
|
806
|
-
}
|
|
807
|
-
await apiRequest('PATCH', updatePath, {
|
|
808
|
-
data: item,
|
|
910
|
+
await apiRequest('PATCH', buildUpdatePath(existingId), {
|
|
911
|
+
data: body,
|
|
809
912
|
contextName: flags.context,
|
|
810
913
|
});
|
|
811
|
-
|
|
914
|
+
return { status: 'updated', id: existingId, identifier };
|
|
812
915
|
}
|
|
813
916
|
catch (updateError) {
|
|
814
917
|
const msg = updateError instanceof ApiError ? updateError.message : String(updateError);
|
|
815
|
-
|
|
918
|
+
return { status: 'error', id: existingId, identifier, error: `Update failed: ${msg}` };
|
|
816
919
|
}
|
|
817
920
|
}
|
|
818
|
-
|
|
819
|
-
results.push({ status: 'error', identifier, error: 'Conflict but no existingId returned' });
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
else {
|
|
823
|
-
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
824
|
-
results.push({ status: 'error', identifier, error: msg });
|
|
921
|
+
return { status: 'error', identifier, error: 'Conflict but no existingId returned' };
|
|
825
922
|
}
|
|
923
|
+
const msg = error instanceof ApiError ? `(${error.status}) ${error.message}` : String(error);
|
|
924
|
+
return { status: 'error', identifier, error: msg };
|
|
826
925
|
}
|
|
827
|
-
}
|
|
926
|
+
};
|
|
927
|
+
// Worker pool: 4 requests in flight at a time. Rows are emitted as each
|
|
928
|
+
// request resolves so output order may differ from input order.
|
|
929
|
+
const concurrency = 4;
|
|
930
|
+
const queue = [...items];
|
|
931
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, queue.length) }, async () => {
|
|
932
|
+
for (;;) {
|
|
933
|
+
const item = queue.shift();
|
|
934
|
+
if (!item)
|
|
935
|
+
return;
|
|
936
|
+
const r = await processItem(item);
|
|
937
|
+
results.push(r);
|
|
938
|
+
emitRow(r);
|
|
939
|
+
}
|
|
940
|
+
}));
|
|
828
941
|
// Summary counts
|
|
829
942
|
const created = results.filter(r => r.status === 'created').length;
|
|
830
943
|
const updated = results.filter(r => r.status === 'updated').length;
|
|
831
944
|
const errors = results.filter(r => r.status === 'error');
|
|
832
|
-
|
|
833
|
-
const outputFormat = flags.output || 'table';
|
|
834
|
-
if (outputFormat === 'json') {
|
|
945
|
+
if (useJson) {
|
|
835
946
|
this.log(JSON.stringify(results, null, 2));
|
|
836
947
|
}
|
|
837
|
-
else if (outputFormat === 'csv' || flags.csv) {
|
|
838
|
-
this.log('status,identifier,id,error');
|
|
839
|
-
for (const r of results) {
|
|
840
|
-
const err = (r.error || '').replace(/"/g, '""');
|
|
841
|
-
this.log(`${r.status},${r.identifier || ''},${r.id || ''},"${err}"`);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
else {
|
|
845
|
-
if (results.length > 0) {
|
|
846
|
-
const statusWidth = 8;
|
|
847
|
-
const identifierWidth = Math.max(10, ...results.map(r => (r.identifier || '').length));
|
|
848
|
-
this.log(`${'status'.padEnd(statusWidth)} ${'identifier'.padEnd(identifierWidth)} error`);
|
|
849
|
-
this.log(`${'-'.repeat(statusWidth)} ${'-'.repeat(identifierWidth)} ${'-'.repeat(50)}`);
|
|
850
|
-
for (const r of results) {
|
|
851
|
-
const status = r.status === 'created' ? 'created' : r.status === 'updated' ? 'updated' : 'error';
|
|
852
|
-
this.log(`${status.padEnd(statusWidth)} ${(r.identifier || '').padEnd(identifierWidth)} ${r.error || ''}`);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
948
|
this.log('');
|
|
857
949
|
this.log(`Summary: ${created} created, ${updated} updated, ${errors.length} failed`);
|
|
858
950
|
}
|