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