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