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