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