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