diff --git a/spec/src/modules/catalog/catalog-files.js b/spec/src/modules/catalog/catalog-files.js index 2090369a..f9b881e4 100644 --- a/spec/src/modules/catalog/catalog-files.js +++ b/spec/src/modules/catalog/catalog-files.js @@ -258,6 +258,86 @@ describe('ConstructorIO - Catalog', () => { }); }); + it('Should replace a catalog of items with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + }; + + catalog.replaceCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should replace a catalog of items with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.replaceCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should replace a catalog of items with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.replaceCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.replaceCatalog(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); @@ -374,6 +454,86 @@ describe('ConstructorIO - Catalog', () => { }); }); + it('Should replace a catalog using tar archive with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + }; + + catalog.replaceCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should replace a catalog using tar archive with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.replaceCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should replace a catalog using tar archive with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.replaceCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.replaceCatalogUsingTarArchive(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); @@ -569,6 +729,86 @@ describe('ConstructorIO - Catalog', () => { }); }); + it('Should update a catalog of items with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + }; + + catalog.updateCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should update a catalog of items with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.updateCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should update a catalog of items with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.updateCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.updateCatalog(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); @@ -686,6 +926,86 @@ describe('ConstructorIO - Catalog', () => { }); }); + it('Should update a catalog using tar archive with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + }; + + catalog.updateCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should update a catalog using tar archive with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.updateCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should update a catalog using tar archive with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.updateCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.updateCatalogUsingTarArchive(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); @@ -915,6 +1235,86 @@ describe('ConstructorIO - Catalog', () => { return expect(catalog.patchCatalog(data)).to.eventually.be.rejectedWith('onMissing must be one of FAIL, IGNORE, or CREATE'); }); + it('Should patch a catalog of items with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + }; + + catalog.patchCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should patch a catalog of items with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.patchCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should patch a catalog of items with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.patchCatalog(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + items: itemsBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.patchCatalog(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); @@ -1014,6 +1414,86 @@ describe('ConstructorIO - Catalog', () => { return expect(catalog.patchCatalogUsingTarArchive(data)).to.eventually.be.rejectedWith('onMissing must be one of FAIL, IGNORE, or CREATE'); }); + it('Should patch a catalog using tar archive with default format parameter (csv) when format is not specified', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + }; + + catalog.patchCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should patch a catalog using tar archive with format parameter set to csv', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'csv', + }; + + catalog.patchCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('csv'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should patch a catalog using tar archive with format parameter set to jsonl', (done) => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'jsonl', + }; + + catalog.patchCatalogUsingTarArchive(data).then((res) => { + const requestedUrlParams = helpers.extractUrlParamsFromFetch(fetchSpy); + + expect(requestedUrlParams).to.have.property('format').to.equal('jsonl'); + expect(res).to.have.property('task_id'); + expect(res).to.have.property('task_status_path'); + done(); + }); + }); + + it('Should be rejected when invalid format parameter is provided', () => { + const { catalog } = new ConstructorIO({ + ...validOptions, + fetch: fetchSpy, + }); + + const data = { + tarArchive: tarArchiveBuffer, + section: 'Products', + format: 'xml', + }; + + return expect(catalog.patchCatalogUsingTarArchive(data)).to.eventually.be.rejectedWith('format must be csv or jsonl'); + }); + if (!skipNetworkTimeoutTests) { it('Should be rejected when network request timeout is provided and reached', () => { const { catalog } = new ConstructorIO(validOptions); diff --git a/src/modules/catalog.js b/src/modules/catalog.js index 17f850aa..083f73f8 100644 --- a/src/modules/catalog.js +++ b/src/modules/catalog.js @@ -59,7 +59,7 @@ async function createQueryParamsAndFormData(parameters) { const formData = new FormData(); if (parameters) { - const { section, notification_email, notificationEmail = notification_email, force, item_groups, onMissing } = parameters; + const { section, notification_email, notificationEmail = notification_email, force, item_groups, onMissing, format = 'csv' } = parameters; let { items, variations, itemGroups = item_groups } = parameters; try { @@ -106,24 +106,32 @@ async function createQueryParamsAndFormData(parameters) { queryParams.on_missing = onMissing; } + if (typeof format !== 'string' || !['csv', 'jsonl'].includes(format.toLowerCase())) { + throw new Error('format must be csv or jsonl'); + } + + const normalizedFormat = format.toLowerCase(); + + queryParams.format = normalizedFormat; + // Pull items from parameters if (items) { formData.append('items', items, { - filename: 'items.csv', + filename: `items.${normalizedFormat}`, }); } // Pull variations from parameters if (variations) { formData.append('variations', variations, { - filename: 'variations.csv', + filename: `variations.${normalizedFormat}`, }); } // Pull item groups from parameters if (itemGroups) { formData.append('item_groups', itemGroups, { - filename: 'item_groups.csv', + filename: `item_groups.${normalizedFormat}`, }); } } @@ -2553,9 +2561,10 @@ class Catalog { * @param {string} parameters.section - The section to update * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items - * @param {file} [parameters.items] - The CSV file with all new items - * @param {file} [parameters.variations] - The CSV file with all new variations - * @param {file} [parameters.itemGroups] - The CSV file with all new itemGroups + * @param {file} [parameters.items] - The file with all new items (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.variations] - The file with all new variations (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.itemGroups] - The file with all new itemGroups (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of all uploaded catalog files (items, variations, and itemGroups). Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2567,6 +2576,7 @@ class Catalog { * items: itemsFileBufferOrStream, * variations: variationsFileBufferOrStream, * itemGroups: itemGroupsFileBufferOrStream, + * format: 'csv' * }); */ async replaceCatalog(parameters = {}, networkParameters = {}) { @@ -2605,9 +2615,10 @@ class Catalog { * @param {string} parameters.section - The section to update * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items - * @param {file} [parameters.items] - The CSV file with all new items - * @param {file} [parameters.variations] - The CSV file with all new variations - * @param {file} [parameters.itemGroups] - The CSV file with all new itemGroups + * @param {file} [parameters.items] - The file with all new items (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.variations] - The file with all new variations (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.itemGroups] - The file with all new itemGroups (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of the uploaded items and variations files. Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2619,6 +2630,7 @@ class Catalog { * items: itemsFileBufferOrStream, * variations: variationsFileBufferOrStream, * itemGroups: itemGroupsFileBufferOrStream, + * format: 'csv' * }); */ async updateCatalog(parameters = {}, networkParameters = {}) { @@ -2658,9 +2670,10 @@ class Catalog { * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items * @param {string} [parameters.onMissing="FAIL"] - Defines the strategy for handling items which are present in the file and missing in the system. IGNORE silently prevents adding them to the system, CREATE creates them, FAIL fails the ingestion in case of their presence - * @param {file} [parameters.items] - The CSV file with all new items - * @param {file} [parameters.variations] - The CSV file with all new variations - * @param {file} [parameters.itemGroups] - The CSV file with all new itemGroups + * @param {file} [parameters.items] - The file with all new items (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.variations] - The file with all new variations (csv or jsonl, depending on the format parameter) + * @param {file} [parameters.itemGroups] - The file with all new itemGroups (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of the uploaded items and variations files. Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2672,6 +2685,7 @@ class Catalog { * items: itemsFileBufferOrStream, * variations: variationsFileBufferOrStream, * itemGroups: itemGroupsFileBufferOrStream, + * format: 'csv' * }); */ async patchCatalog(parameters = {}, networkParameters = {}) { @@ -2710,7 +2724,8 @@ class Catalog { * @param {string} parameters.section - The section to update * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items - * @param {file} [parameters.tarArchive] - The tar file that includes csv files + * @param {file} [parameters.tarArchive] - The tar file that includes catalog files (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of the uploaded items and variations files. Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2720,6 +2735,7 @@ class Catalog { * section: 'Products', * notificationEmail: 'notifications@example.com', * tarArchive: tarArchiveBufferOrStream, + * format: 'csv' * }); */ async replaceCatalogUsingTarArchive(parameters = {}, networkParameters = {}) { @@ -2766,7 +2782,8 @@ class Catalog { * @param {string} parameters.section - The section to update * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items - * @param {file} [parameters.tarArchive] - The tar file that includes csv files + * @param {file} [parameters.tarArchive] - The tar file that includes catalog files (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of the uploaded items and variations files. Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2776,6 +2793,7 @@ class Catalog { * section: 'Products', * notificationEmail: 'notifications@example.com', * tarArchive: tarArchiveBufferOrStream, + * format: 'csv' * }); */ async updateCatalogUsingTarArchive(parameters = {}, networkParameters = {}) { @@ -2825,7 +2843,8 @@ class Catalog { * @param {string} [parameters.notificationEmail] - An email address to receive an email notification if the task fails * @param {boolean} [parameters.force=false] - Process the catalog even if it will invalidate a large number of existing items * @param {string} [parameters.onMissing="FAIL"] - Defines the strategy for handling items which are present in the file and missing in the system. IGNORE silently prevents adding them to the system, CREATE creates them, FAIL fails the ingestion in case of their presence - * @param {file} [parameters.tarArchive] - The tar file that includes csv files + * @param {file} [parameters.tarArchive] - The tar file that includes catalog files (csv or jsonl, depending on the format parameter) + * @param {string} [parameters.format] - File format of the uploaded items and variations files. Can be either csv or jsonl. * @param {object} [networkParameters] - Parameters relevant to the network request * @param {number} [networkParameters.timeout] - Request timeout (in milliseconds) * @returns {Promise} @@ -2835,6 +2854,7 @@ class Catalog { * section: 'Products', * notificationEmail: 'notifications@example.com', * tarArchive: tarArchiveBufferOrStream, + * format: 'csv' * }); */ async patchCatalogUsingTarArchive(parameters = {}, networkParameters = {}) { diff --git a/src/types/catalog.d.ts b/src/types/catalog.d.ts index ff1af734..3b3e97d0 100644 --- a/src/types/catalog.d.ts +++ b/src/types/catalog.d.ts @@ -173,6 +173,7 @@ export interface ReplaceCatalogParameters { items?: File | fs.ReadStream | Duplex variations?: File | fs.ReadStream | Duplex; itemGroups?: File | fs.ReadStream | Duplex; + format?: 'csv' | 'jsonl'; } export interface UpdateCatalogParameters extends ReplaceCatalogParameters {} @@ -185,6 +186,7 @@ export interface PatchCatalogParameters { items?: File | fs.ReadStream | Duplex variations?: File | fs.ReadStream | Duplex; itemGroups?: File | fs.ReadStream | Duplex; + format?: 'csv' | 'jsonl'; } export interface ReplaceCatalogUsingTarArchiveParameters { @@ -192,6 +194,7 @@ export interface ReplaceCatalogUsingTarArchiveParameters { notificationEmail?: string; force?: boolean; tarArchive?: File | fs.ReadStream | Duplex; + format?: 'csv' | 'jsonl'; } export interface UpdateCatalogUsingTarArchiveParameters