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