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