From 61201ce5a967d9402c948be8d706d7450006e39a Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:27:30 +0400 Subject: [PATCH 01/19] feat(src): add util functions for if-csv --- src/if-csv/util/args.ts | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/if-csv/util/args.ts diff --git a/src/if-csv/util/args.ts b/src/if-csv/util/args.ts new file mode 100644 index 000000000..4b9674882 --- /dev/null +++ b/src/if-csv/util/args.ts @@ -0,0 +1,60 @@ +import {parse} from 'ts-command-line-args'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {checkIfFileIsYaml} from '../../common/util/yaml'; +import {prependFullFilePath} from '../../common/util/helpers'; + +import {CONFIG, STRINGS} from '../config'; +import {STRINGS as COMMON_STRINGS} from '../../common/config'; + +import {IFCsvArgs} from '../types/process-args'; +import {isFileExists} from '../../common/util/fs'; + +const {ParseCliParamsError, CliSourceFileError} = ERRORS; + +const {ARGS, HELP} = CONFIG; +const {PARAMS_NOT_PRESENT} = STRINGS; +const {SOURCE_IS_NOT_YAML, MANIFEST_NOT_FOUND} = COMMON_STRINGS; + +/** + * Parses `if-csv` process arguments. + */ +const validateAndParseIfCsvArgs = () => { + try { + return parse(ARGS, HELP); + } catch (error) { + if (error instanceof Error) { + throw new ParseCliParamsError(error.message); + } + + throw error; + } +}; + +/** + * Checks for `manifest` and `params` flags to be present. + */ +export const parseIfCsvArgs = async () => { + const {manifest, output, params} = validateAndParseIfCsvArgs(); + + if (!params) { + throw new ParseCliParamsError(PARAMS_NOT_PRESENT); + } + + if (manifest) { + const response = prependFullFilePath(manifest); + const isManifestFileExists = await isFileExists(response); + + if (!isManifestFileExists) { + throw new ParseCliParamsError(MANIFEST_NOT_FOUND); + } + + if (checkIfFileIsYaml(manifest)) { + return {manifest, output, params}; + } + + throw new CliSourceFileError(SOURCE_IS_NOT_YAML); + } + + return {output, params}; +}; From 04a57638c837d6a24d6907508280078b46c69bcc Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:30:16 +0400 Subject: [PATCH 02/19] feat(src): add executeCsv helper function for if-csv --- src/if-csv/util/helpers.ts | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/if-csv/util/helpers.ts diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts new file mode 100644 index 000000000..b70ca2194 --- /dev/null +++ b/src/if-csv/util/helpers.ts @@ -0,0 +1,66 @@ +import {stringify} from 'csv-stringify/sync'; +import * as fs from 'fs/promises'; +import {PluginParams} from '@grnsft/if-core/types'; + +import {CsvOptions} from '../types/csv'; + +/** + * Executes a CSV generation based on the provided tree structure, context, output path, and params. + */ +export const executeCsv = async (options: CsvOptions) => { + const {tree, context, outputPath, params} = options; + const columns = ['Path']; + const matrix = [columns]; + const aggregationIsEnabled = !!context.aggregation; + + const traverseTree = (node: any, params: string, path = 'tree') => { + if (node.aggregated) { + if (path === 'tree') { + columns.push('Aggregated'); + } + matrix.push([`${path}.${params}`, node.aggregated[params]]); + } + + if (node.outputs) { + node.outputs.forEach((output: PluginParams) => { + const {timestamp} = output; + + if (!columns.includes(timestamp)) { + columns.push(timestamp); + } + + const lastRow = matrix[matrix.length - 1]; + + if (aggregationIsEnabled) { + lastRow.push(output[params]); + } else { + if (matrix.length === 1 || lastRow.length === columns.length) { + matrix.push([`${path}.${params}`, output[params]]); + } else { + lastRow.push(output[params]); + } + } + }); + } + + if (node.children) { + Object.keys(node.children).forEach(childKey => { + traverseTree( + node.children![childKey], + params, + `${path}.children.${childKey}` + ); + }); + } + }; + + traverseTree(tree, params); + + const csvString = stringify(matrix, {columns}); + + if (!outputPath) { + return csvString; + } + + return await fs.writeFile(`${outputPath}.csv`, csvString); +}; From 142d957d62ea194bd00b477b81595a939c2c8146 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:33:38 +0400 Subject: [PATCH 03/19] feat(src): move `parseManifestFromStdin` function from if-diff helpers to common helpers file --- src/common/util/helpers.ts | 44 +++++++++++++++++++++++++++++++++++++ src/if-diff/index.ts | 3 ++- src/if-diff/util/helpers.ts | 44 ------------------------------------- 3 files changed, 46 insertions(+), 45 deletions(-) diff --git a/src/common/util/helpers.ts b/src/common/util/helpers.ts index 8399e5b3e..01b87c79d 100644 --- a/src/common/util/helpers.ts +++ b/src/common/util/helpers.ts @@ -1,3 +1,4 @@ +import {createInterface} from 'node:readline/promises'; import {exec} from 'child_process'; import * as path from 'path'; import {promisify} from 'util'; @@ -19,3 +20,46 @@ export const prependFullFilePath = (filePath: string) => { return path.normalize(`${processRunningPath}/${filePath}`); }; + +/** + * Checks if there is data piped, then collects it. + * Otherwise returns empty string. + */ +const collectPipedData = async () => { + if (process.stdin.isTTY) { + return ''; + } + + const readline = createInterface({ + input: process.stdin, + }); + + const data: string[] = []; + + for await (const line of readline) { + data.push(line); + } + + return data.join('\n'); +}; + +/** + * Checks if there is piped data, tries to parse yaml from it. + * Returns empty string if haven't found anything. + */ +export const parseManifestFromStdin = async () => { + const pipedSourceManifest = await collectPipedData(); + + if (!pipedSourceManifest) { + return ''; + } + + const regex = /# start((?:.*\n)+?)# end/; + const match = regex.exec(pipedSourceManifest); + + if (!match) { + return ''; + } + + return match![1]; +}; diff --git a/src/if-diff/index.ts b/src/if-diff/index.ts index 52a6a9b4e..aa4ae1871 100644 --- a/src/if-diff/index.ts +++ b/src/if-diff/index.ts @@ -4,7 +4,8 @@ import {loadIfDiffFiles} from './lib/load'; import {compare} from './lib/compare'; import {parseIfDiffArgs} from './util/args'; -import {formatNotMatchingLog, parseManifestFromStdin} from './util/helpers'; +import {formatNotMatchingLog} from './util/helpers'; +import {parseManifestFromStdin} from '../common/util/helpers'; import {validateManifest} from '../common/util/validations'; import {logger} from '../common/util/logger'; diff --git a/src/if-diff/util/helpers.ts b/src/if-diff/util/helpers.ts index 858d5333c..9552e8f5b 100644 --- a/src/if-diff/util/helpers.ts +++ b/src/if-diff/util/helpers.ts @@ -1,4 +1,3 @@ -import {createInterface} from 'node:readline/promises'; import {Difference} from '../types/compare'; /** @@ -83,46 +82,3 @@ export const formatNotMatchingLog = (message: Difference) => { } }); }; - -/** - * Checks if there is data piped, then collects it. - * Otherwise returns empty string. - */ -const collectPipedData = async () => { - if (process.stdin.isTTY) { - return ''; - } - - const readline = createInterface({ - input: process.stdin, - }); - - const data: string[] = []; - - for await (const line of readline) { - data.push(line); - } - - return data.join('\n'); -}; - -/** - * Checks if there is piped data, tries to parse yaml from it. - * Returns empty string if haven't found anything. - */ -export const parseManifestFromStdin = async () => { - const pipedSourceManifest = await collectPipedData(); - - if (!pipedSourceManifest) { - return ''; - } - - const regex = /# start((?:.*\n)+?)# end/; - const match = regex.exec(pipedSourceManifest); - - if (!match) { - return ''; - } - - return match![1]; -}; From db51036b4828ee1bce98f0c4f59ec462ca241a71 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:35:48 +0400 Subject: [PATCH 04/19] test(src): update tests according to changes --- src/__tests__/common/lib/load.test.ts | 2 +- src/__tests__/common/util/helpers.test.ts | 44 ++++++++++++++++++++++ src/__tests__/if-diff/lib/load.test.ts | 4 +- src/__tests__/if-diff/util/helpers.test.ts | 40 -------------------- 4 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 src/__tests__/common/util/helpers.test.ts diff --git a/src/__tests__/common/lib/load.test.ts b/src/__tests__/common/lib/load.test.ts index 43f6ee2af..a76d3bd27 100644 --- a/src/__tests__/common/lib/load.test.ts +++ b/src/__tests__/common/lib/load.test.ts @@ -14,7 +14,7 @@ jest.mock( }), {virtual: true} ); -jest.mock('../../../if-diff/util/helpers', () => ({ +jest.mock('../../../common/util/helpers', () => ({ parseManifestFromStdin: () => { if (process.env.readline === 'valid-source') { return ` diff --git a/src/__tests__/common/util/helpers.test.ts b/src/__tests__/common/util/helpers.test.ts new file mode 100644 index 000000000..92b4f9dab --- /dev/null +++ b/src/__tests__/common/util/helpers.test.ts @@ -0,0 +1,44 @@ +jest.mock('node:readline/promises', () => + require('../../../__mocks__/readline') +); + +import {parseManifestFromStdin} from '../../../common/util/helpers'; + +describe('common/util/helpers: ', () => { + describe('parseManifestFromStdin(): ', () => { + it('returns empty string if there is no data in stdin.', async () => { + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + }); + + it('returns empty string if nothing is piped.', async () => { + const originalIsTTY = process.stdin.isTTY; + process.stdin.isTTY = true; + const response = await parseManifestFromStdin(); + const expectedResult = ''; + + expect(response).toEqual(expectedResult); + process.stdin.isTTY = originalIsTTY; + }); + + it('throws error if there is no manifest in stdin.', async () => { + process.env.readline = 'no_manifest'; + expect.assertions(1); + + const response = await parseManifestFromStdin(); + + expect(response).toEqual(''); + }); + + it('returns empty string if there is no data in stdin.', async () => { + process.env.readline = 'manifest'; + const response = await parseManifestFromStdin(); + const expectedMessage = + '\nname: mock-name\ndescription: mock-description\n'; + + expect(response).toEqual(expectedMessage); + }); + }); +}); diff --git a/src/__tests__/if-diff/lib/load.test.ts b/src/__tests__/if-diff/lib/load.test.ts index f722757e5..8a703df76 100644 --- a/src/__tests__/if-diff/lib/load.test.ts +++ b/src/__tests__/if-diff/lib/load.test.ts @@ -14,7 +14,7 @@ jest.mock( }), {virtual: true} ); -jest.mock('../../../if-diff/util/helpers', () => ({ +jest.mock('../../../common/util/helpers', () => ({ parseManifestFromStdin: () => { if (process.env.readline === 'valid-source') { return ` @@ -44,7 +44,7 @@ import {PluginParams} from '@grnsft/if-core/types'; import {loadIfDiffFiles} from '../../../if-diff/lib/load'; -import {parseManifestFromStdin} from '../../../if-diff/util/helpers'; +import {parseManifestFromStdin} from '../../../common/util/helpers'; import {STRINGS} from '../../../if-diff/config'; diff --git a/src/__tests__/if-diff/util/helpers.test.ts b/src/__tests__/if-diff/util/helpers.test.ts index a7d25599e..eb9a0e553 100644 --- a/src/__tests__/if-diff/util/helpers.test.ts +++ b/src/__tests__/if-diff/util/helpers.test.ts @@ -7,7 +7,6 @@ import { checkIfEqual, formatNotMatchingLog, oneIsPrimitive, - parseManifestFromStdin, } from '../../../if-diff/util/helpers'; describe('if-diff/util/helpers: ', () => { @@ -193,43 +192,4 @@ describe('if-diff/util/helpers: ', () => { console.log = actualLogger; }); }); - - describe('parseManifestFromStdin(): ', () => { - it('returns empty string if there is no data in stdin.', async () => { - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - }); - - it('returns empty string if nothing is piped.', async () => { - const originalIsTTY = process.stdin.isTTY; - process.stdin.isTTY = true; - const response = await parseManifestFromStdin(); - const expectedResult = ''; - - expect(response).toEqual(expectedResult); - process.stdin.isTTY = originalIsTTY; - }); - - it('throws error if there is no manifest in stdin.', async () => { - process.env.readline = 'no_manifest'; - expect.assertions(1); - - const response = await parseManifestFromStdin(); - - expect(response).toEqual(''); - }); - - it('returns empty string if there is no data in stdin.', async () => { - process.env.readline = 'manifest'; - const response = await parseManifestFromStdin(); - const expectedMessage = ` -name: mock-name -description: mock-description -`; - - expect(response).toEqual(expectedMessage); - }); - }); }); From 981e925933a425e9cb3b317c39541319ce8b9d6e Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:37:07 +0400 Subject: [PATCH 05/19] feat(src): add string and types files for if-csv --- src/if-csv/config/index.ts | 2 ++ src/if-csv/config/strings.ts | 3 +++ src/if-csv/types/csv.ts | 8 ++++++++ 3 files changed, 13 insertions(+) create mode 100644 src/if-csv/config/index.ts create mode 100644 src/if-csv/config/strings.ts create mode 100644 src/if-csv/types/csv.ts diff --git a/src/if-csv/config/index.ts b/src/if-csv/config/index.ts new file mode 100644 index 000000000..4972b390b --- /dev/null +++ b/src/if-csv/config/index.ts @@ -0,0 +1,2 @@ +export {CONFIG} from './config'; +export {STRINGS} from './strings'; diff --git a/src/if-csv/config/strings.ts b/src/if-csv/config/strings.ts new file mode 100644 index 000000000..be90a4547 --- /dev/null +++ b/src/if-csv/config/strings.ts @@ -0,0 +1,3 @@ +export const STRINGS = { + PARAMS_NOT_PRESENT: 'Parameter not provided.', +}; diff --git a/src/if-csv/types/csv.ts b/src/if-csv/types/csv.ts new file mode 100644 index 000000000..3e2f969c6 --- /dev/null +++ b/src/if-csv/types/csv.ts @@ -0,0 +1,8 @@ +import {Context} from '../../common/types/manifest'; + +export type CsvOptions = { + tree: any; + context: Context; + outputPath?: string; + params: string; +}; From b96e466e8eef1797ada0324332203a2b5bbcf4da Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:39:23 +0400 Subject: [PATCH 06/19] feat(src): add config and types for args for if-csv --- src/if-csv/config/config.ts | 39 ++++++++++++++++++++++++++++++++ src/if-csv/types/process-args.ts | 5 ++++ 2 files changed, 44 insertions(+) create mode 100644 src/if-csv/config/config.ts create mode 100644 src/if-csv/types/process-args.ts diff --git a/src/if-csv/config/config.ts b/src/if-csv/config/config.ts new file mode 100644 index 000000000..8be9dba75 --- /dev/null +++ b/src/if-csv/config/config.ts @@ -0,0 +1,39 @@ +import {ArgumentConfig, ParseOptions} from 'ts-command-line-args'; + +import {STRINGS} from '../../common/config'; + +import {IFCsvArgs} from '../types/process-args'; + +const {DISCLAIMER_MESSAGE} = STRINGS; + +export const CONFIG = { + ARGS: { + manifest: { + type: String, + optional: true, + alias: 'm', + description: '[path to the manifest file]', + }, + output: { + type: String, + optional: true, + alias: 'o', + description: '[path to the csv output file]', + }, + params: { + type: String, + optional: false, + alias: 'p', + description: '[parameter to export]', + }, + } as ArgumentConfig, + HELP: { + helpArg: 'help', + headerContentSections: [ + {header: 'Impact Framework', content: 'IF-Csv Helpful keywords:'}, + ], + footerContentSections: [ + {header: 'Green Software Foundation', content: DISCLAIMER_MESSAGE}, + ], + } as ParseOptions, +}; diff --git a/src/if-csv/types/process-args.ts b/src/if-csv/types/process-args.ts new file mode 100644 index 000000000..f0bcb44ad --- /dev/null +++ b/src/if-csv/types/process-args.ts @@ -0,0 +1,5 @@ +export interface IFCsvArgs { + manifest?: string; + output?: string; + params: string; +} From 8d199be6b314efef23825ca7256b0386bfbf6f03 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:40:44 +0400 Subject: [PATCH 07/19] test(src): add test for helpers --- src/__tests__/if-csv/util/helpers.test.ts | 196 ++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 src/__tests__/if-csv/util/helpers.test.ts diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts new file mode 100644 index 000000000..61e6f1e9c --- /dev/null +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -0,0 +1,196 @@ +import * as fs from 'fs/promises'; + +import {stringify} from 'csv-stringify/sync'; +import {jest} from '@jest/globals'; + +import {executeCsv} from '../../../if-csv/util/helpers'; + +import {CsvOptions} from '../../../if-csv/types/csv'; + +import { + tree, + context, + outputs, + aggregated, + aggregation, +} from '../../../__mocks__/builtins/export-csv'; + +jest.mock('fs/promises', () => ({ + writeFile: jest.fn<() => Promise>().mockResolvedValue(), +})); + +describe('executeCsv(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + const reformedContext = Object.assign({}, context, {outputs}); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when the `outputs` type is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('generates CSV file when `aggregation` persists.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedContext = Object.assign( + {}, + context, + {outputs}, + {aggregation} + ); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, + }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); + + it('returns string when `outputPath` is not provided', async () => { + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const options: CsvOptions = { + tree, + context, + outputPath: undefined, + params: 'carbon', + }; + + const result = await executeCsv(options); + + expect.assertions(1); + expect(result).toEqual(stringify(matrix, {columns})); + }); + + it('generates CSV file when `aggregation` is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], + ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], + ]; + + const reformedContext = Object.assign({}, context, {outputs}); + const options: CsvOptions = { + tree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); +}); From a24f1b4a17dc7fdeecd2a1e3567d7dcc42d9b8b1 Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:42:59 +0400 Subject: [PATCH 08/19] feat(src): add logic for if-csv --- src/if-csv/index.ts | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/if-csv/index.ts diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts new file mode 100644 index 000000000..a53e54994 --- /dev/null +++ b/src/if-csv/index.ts @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/* eslint-disable no-process-exit */ +import * as YAML from 'js-yaml'; + +import {parseManifestFromStdin} from '../common/util/helpers'; +import {validateManifest} from '../common/util/validations'; +import {debugLogger} from '../common/util/debug-logger'; +import {logger} from '../common/util/logger'; +import {load} from '../common/lib/load'; + +import {injectEnvironment} from '../if-run/lib/environment'; +import {initialize} from '../if-run/lib/initialize'; +import {aggregate} from '../if-run/lib/aggregate'; +import {compute} from '../if-run/lib/compute'; + +import {parseIfCsvArgs} from './util/args'; +import {executeCsv} from './util/helpers'; +import {CsvOptions} from './types/csv'; + +const IfCsv = async () => { + // Call this function with false parameter to prevent log debug messages. + debugLogger.overrideConsoleMethods(false); + + const pipedManifest = await parseManifestFromStdin(); + const {manifest, output, params} = await parseIfCsvArgs(); + const resolvedManifest = manifest || pipedManifest; + let envManifest; + + if (resolvedManifest) { + if (pipedManifest) { + envManifest = await YAML.load(pipedManifest!); + } else { + const {rawManifest} = await load(resolvedManifest); + envManifest = await injectEnvironment(rawManifest); + } + + const {tree, ...context} = validateManifest(envManifest); + const pluginStorage = await initialize(context.initialize.plugins); + const computedTree = await compute(tree, {context, pluginStorage}); + const aggregatedTree = aggregate(computedTree, context.aggregation); + const options: CsvOptions = { + tree: aggregatedTree, + context, + outputPath: output, + params, + }; + const result = await executeCsv(options); + + if (!output && result) { + console.log(result); + } + } + + process.exit(0); +}; + +IfCsv().catch(error => { + if (error instanceof Error) { + logger.error(error); + process.exit(2); + } +}); From 2cac2e374f6b9db83aea60b8f94c55ab98145f5c Mon Sep 17 00:00:00 2001 From: manushak Date: Mon, 8 Jul 2024 14:44:08 +0400 Subject: [PATCH 09/19] feat(package): add if-csv script --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b888aa3d..7c80610c5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "if-diff": "./build/if-diff/index.js", "if-run": "./build/if-run/index.js", "if-env": "./build/if-env/index.js", - "if-check": "./build/if-check/index.js" + "if-check": "./build/if-check/index.js", + "if-csv": "./build/if-csv/index.js" }, "bugs": { "url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+" @@ -76,6 +77,7 @@ "fix": "gts fix", "fix:package": "fixpack", "if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-check/index.ts", + "if-csv": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-csv/index.ts", "if-diff": "npx ts-node src/if-diff/index.ts", "if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-env/index.ts", "if-run": "npx ts-node src/if-run/index.ts", From 01ace664f03515b651016808fbec83778ccdf486 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:31:38 +0400 Subject: [PATCH 10/19] fix(config): add failure string for if-csv --- src/if-csv/config/strings.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/if-csv/config/strings.ts b/src/if-csv/config/strings.ts index be90a4547..717461c1b 100644 --- a/src/if-csv/config/strings.ts +++ b/src/if-csv/config/strings.ts @@ -1,3 +1,4 @@ export const STRINGS = { PARAMS_NOT_PRESENT: 'Parameter not provided.', + FAILURE_MESSAGE_OUTPUTS: 'Manifest outputs are not available!', }; From ebf1770ff44469fcea46b13cd45250a71bb689e1 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:33:24 +0400 Subject: [PATCH 11/19] fix(util): add getManifestData function --- src/if-csv/util/helpers.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index b70ca2194..d9f7ec09d 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -1,8 +1,29 @@ -import {stringify} from 'csv-stringify/sync'; import * as fs from 'fs/promises'; +import {stringify} from 'csv-stringify/sync'; import {PluginParams} from '@grnsft/if-core/types'; +import {ERRORS} from '@grnsft/if-core/utils'; + +import {load} from '../../common/lib/load'; import {CsvOptions} from '../types/csv'; +import {STRINGS} from '../config'; + +const {FAILURE_MESSAGE_OUTPUTS} = STRINGS; +const {ManifestValidationError} = ERRORS; + +/** + * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + */ +export const getManifestData = async (manifest: string) => { + const loadedManifest = await load(manifest); + const children = loadedManifest.rawManifest.tree.children; + + if ((children.child || children['child-0']).outputs) { + return loadedManifest.rawManifest; + } + + throw new ManifestValidationError(FAILURE_MESSAGE_OUTPUTS); +}; /** * Executes a CSV generation based on the provided tree structure, context, output path, and params. From 083340d70f531551d4fe6f7d505578486c60157b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:35:19 +0400 Subject: [PATCH 12/19] fix(src): update logix to accpet executed manifest --- src/if-csv/index.ts | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index a53e54994..94ede0bb4 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -3,18 +3,12 @@ import * as YAML from 'js-yaml'; import {parseManifestFromStdin} from '../common/util/helpers'; -import {validateManifest} from '../common/util/validations'; import {debugLogger} from '../common/util/debug-logger'; +import {Manifest} from '../common/types/manifest'; import {logger} from '../common/util/logger'; -import {load} from '../common/lib/load'; - -import {injectEnvironment} from '../if-run/lib/environment'; -import {initialize} from '../if-run/lib/initialize'; -import {aggregate} from '../if-run/lib/aggregate'; -import {compute} from '../if-run/lib/compute'; +import {executeCsv, getManifestData} from './util/helpers'; import {parseIfCsvArgs} from './util/args'; -import {executeCsv} from './util/helpers'; import {CsvOptions} from './types/csv'; const IfCsv = async () => { @@ -24,23 +18,18 @@ const IfCsv = async () => { const pipedManifest = await parseManifestFromStdin(); const {manifest, output, params} = await parseIfCsvArgs(); const resolvedManifest = manifest || pipedManifest; - let envManifest; + let manifestData: Manifest; if (resolvedManifest) { if (pipedManifest) { - envManifest = await YAML.load(pipedManifest!); + manifestData = (await YAML.load(pipedManifest!)) as Manifest; } else { - const {rawManifest} = await load(resolvedManifest); - envManifest = await injectEnvironment(rawManifest); + manifestData = await getManifestData(manifest!); } - const {tree, ...context} = validateManifest(envManifest); - const pluginStorage = await initialize(context.initialize.plugins); - const computedTree = await compute(tree, {context, pluginStorage}); - const aggregatedTree = aggregate(computedTree, context.aggregation); const options: CsvOptions = { - tree: aggregatedTree, - context, + tree: manifestData.tree, + context: manifestData, outputPath: output, params, }; From bcc872fa23fbc7aff8ed8ff9c43e4e22b927220c Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:36:57 +0400 Subject: [PATCH 13/19] test(util): add tests for getManifestData function --- src/__tests__/if-csv/util/helpers.test.ts | 400 +++++++++++++--------- 1 file changed, 238 insertions(+), 162 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 61e6f1e9c..4712f5773 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -1,12 +1,13 @@ +import {jest} from '@jest/globals'; import * as fs from 'fs/promises'; - import {stringify} from 'csv-stringify/sync'; -import {jest} from '@jest/globals'; - -import {executeCsv} from '../../../if-csv/util/helpers'; +import {ERRORS} from '@grnsft/if-core/utils'; +import {executeCsv, getManifestData} from '../../../if-csv/util/helpers'; import {CsvOptions} from '../../../if-csv/types/csv'; +const {ManifestValidationError} = ERRORS; + import { tree, context, @@ -15,182 +16,257 @@ import { aggregation, } from '../../../__mocks__/builtins/export-csv'; -jest.mock('fs/promises', () => ({ - writeFile: jest.fn<() => Promise>().mockResolvedValue(), -})); - -describe('executeCsv(): ', () => { - it('generates CSV file with correct data.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - const reformedContext = Object.assign({}, context, {outputs}); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, +jest.mock('fs/promises', () => { + const originalModule = + jest.requireActual('fs/promises'); + return { + __esModule: true, + ...originalModule, + writeFile: jest.fn(() => Promise.resolve()), + }; +}); + +describe('if-csv/util/helpers: ', () => { + describe('executeCsv(): ', () => { + it('generates CSV file with correct data.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + const reformedContext = Object.assign({}, context, {outputs}); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, - }); + }); - const options: CsvOptions = { - tree: reformedTree, - context: reformedContext, - outputPath, - params: 'carbon', - }; + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; - await executeCsv(options); + await executeCsv(options); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); - it('generates CSV file when the `outputs` type is missing.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, + it('generates CSV file when the `outputs` type is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, - }); + }); - const options: CsvOptions = { - tree: reformedTree, - context, - outputPath, - params: 'carbon', - }; + const options: CsvOptions = { + tree: reformedTree, + context, + outputPath, + params: 'carbon', + }; - await executeCsv(options); + await executeCsv(options); - expect.assertions(1); + expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); - it('generates CSV file when `aggregation` persists.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); - const reformedTree = Object.assign({}, tree, { - children: { - ...tree.children, - 'child-1': { - ...tree.children['child-1'], - aggregated, - }, - 'child-2': { - ...tree.children['child-2'], - aggregated, + it('generates CSV file when `aggregation` persists.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; + + const reformedContext = Object.assign( + {}, + context, + {outputs}, + {aggregation} + ); + const reformedTree = Object.assign({}, tree, { + children: { + ...tree.children, + 'child-1': { + ...tree.children['child-1'], + aggregated, + }, + 'child-2': { + ...tree.children['child-2'], + aggregated, + }, }, - }, + }); + + const options: CsvOptions = { + tree: reformedTree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); }); - const options: CsvOptions = { - tree: reformedTree, - context: reformedContext, - outputPath, - params: 'carbon', - }; + it('returns string when `outputPath` is not provided', async () => { + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; - await executeCsv(options); + const options: CsvOptions = { + tree, + context, + outputPath: undefined, + params: 'carbon', + }; - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); - }); + const result = await executeCsv(options); + + expect.assertions(1); + expect(result).toEqual(stringify(matrix, {columns})); + }); + + it('generates CSV file when `aggregation` is missing.', async () => { + const outputPath = 'output'; + const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; + const matrix = [ + columns, + ['tree.carbon', 8000.000004051243, 8000.000004051243], + [ + 'tree.children.child-1.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + [ + 'tree.children.child-2.carbon', + 4000.0000020256216, + 4000.0000020256216, + ], + ]; - it('returns string when `outputPath` is not provided', async () => { - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const options: CsvOptions = { - tree, - context, - outputPath: undefined, - params: 'carbon', - }; - - const result = await executeCsv(options); - - expect.assertions(1); - expect(result).toEqual(stringify(matrix, {columns})); + const reformedContext = Object.assign({}, context, {outputs}); + const options: CsvOptions = { + tree, + context: reformedContext, + outputPath, + params: 'carbon', + }; + + await executeCsv(options); + + expect.assertions(1); + expect(fs.writeFile).toHaveBeenCalledWith( + 'output.csv', + stringify(matrix, {columns}) + ); + }); }); - it('generates CSV file when `aggregation` is missing.', async () => { - const outputPath = 'output'; - const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; - const matrix = [ - columns, - ['tree.carbon', 8000.000004051243, 8000.000004051243], - ['tree.children.child-1.carbon', 4000.0000020256216, 4000.0000020256216], - ['tree.children.child-2.carbon', 4000.0000020256216, 4000.0000020256216], - ]; - - const reformedContext = Object.assign({}, context, {outputs}); - const options: CsvOptions = { - tree, - context: reformedContext, - outputPath, - params: 'carbon', - }; - - await executeCsv(options); - - expect.assertions(1); - expect(fs.writeFile).toHaveBeenCalledWith( - 'output.csv', - stringify(matrix, {columns}) - ); + describe('getManifestData(): ', () => { + it('returns correct manifest data.', async () => { + process.env.MOCK_MANIFEST = 'true'; + const mockManifestPath = './src/__mocks__/mock-manifest.yaml'; + const result = await getManifestData(mockManifestPath); + + expect.assertions(2); + expect(result).toHaveProperty('description'); + expect(result).toHaveProperty('tree'); + }); + + it('throws an error when there is not `outputs` in the manifest.', async () => { + process.env.MOCK_MANIFEST = 'false'; + const mockManifestPath = ''; + const load = require('../../../common/lib/load'); + const spyLoad = jest.spyOn(load, 'load'); + + spyLoad.mockReturnValue({ + rawManifest: {tree: {children: {child: {}}}}, + }); + expect.assertions(1); + try { + await getManifestData(mockManifestPath); + } catch (error) { + expect(error).toEqual( + new ManifestValidationError('Manifest outputs are not available!') + ); + } + }); }); }); From 752c014fb454580871a178679efe325bdf53740b Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:43:26 +0400 Subject: [PATCH 14/19] fix(package): add `if-csv` into package-loc.json --- package-lock.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package-lock.json b/package-lock.json index dd24c9128..f01b0fb13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ }, "bin": { "if-check": "build/if-check/index.js", + "if-csv": "build/if-csv/index.js", "if-diff": "build/if-diff/index.js", "if-env": "build/if-env/index.js", "if-run": "build/if-run/index.js" From 96f086c53dfa00831febeba7e7c27e421295acda Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 13:57:39 +0400 Subject: [PATCH 15/19] fix(util): improve getManifestData function --- src/if-csv/util/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index d9f7ec09d..8ae6dd0e5 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -15,11 +15,11 @@ const {ManifestValidationError} = ERRORS; * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. */ export const getManifestData = async (manifest: string) => { - const loadedManifest = await load(manifest); - const children = loadedManifest.rawManifest.tree.children; + const {rawManifest} = await load(manifest); + const children = rawManifest.tree.children; if ((children.child || children['child-0']).outputs) { - return loadedManifest.rawManifest; + return rawManifest; } throw new ManifestValidationError(FAILURE_MESSAGE_OUTPUTS); From 9d8d1fd8f906c325ea1c401a4b909ab97f153063 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 14:03:26 +0400 Subject: [PATCH 16/19] fix(util): improve getManifestData function --- src/if-csv/util/helpers.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index 8ae6dd0e5..397293dd8 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -12,13 +12,13 @@ const {FAILURE_MESSAGE_OUTPUTS} = STRINGS; const {ManifestValidationError} = ERRORS; /** - * Gets the folder path of the manifest file, dependencies from manifest file and install argument from the given arguments. + * Gets the manifest data if `outputs` is present in it. */ export const getManifestData = async (manifest: string) => { const {rawManifest} = await load(manifest); - const children = rawManifest.tree.children; + const {children} = rawManifest.tree; - if ((children.child || children['child-0']).outputs) { + if (children?.child?.outputs || children?.['child-0']?.outputs) { return rawManifest; } From 179238cd0eeb07b3cb23d28a202b4eff667e1749 Mon Sep 17 00:00:00 2001 From: manushak Date: Wed, 10 Jul 2024 17:20:15 +0400 Subject: [PATCH 17/19] test(util): fix tests conflict after merging with the main --- src/__tests__/if-csv/util/helpers.test.ts | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 4712f5773..1859f4850 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -11,10 +11,9 @@ const {ManifestValidationError} = ERRORS; import { tree, context, - outputs, aggregated, aggregation, -} from '../../../__mocks__/builtins/export-csv'; +} from '../../../__mocks__/builtins/export-yaml'; jest.mock('fs/promises', () => { const originalModule = @@ -45,7 +44,6 @@ describe('if-csv/util/helpers: ', () => { 4000.0000020256216, ], ]; - const reformedContext = Object.assign({}, context, {outputs}); const reformedTree = Object.assign({}, tree, { children: { ...tree.children, @@ -62,7 +60,7 @@ describe('if-csv/util/helpers: ', () => { const options: CsvOptions = { tree: reformedTree, - context: reformedContext, + context, outputPath, params: 'carbon', }; @@ -142,12 +140,7 @@ describe('if-csv/util/helpers: ', () => { ], ]; - const reformedContext = Object.assign( - {}, - context, - {outputs}, - {aggregation} - ); + const reformedContext = Object.assign({}, context, {aggregation}); const reformedTree = Object.assign({}, tree, { children: { ...tree.children, @@ -221,10 +214,9 @@ describe('if-csv/util/helpers: ', () => { ], ]; - const reformedContext = Object.assign({}, context, {outputs}); const options: CsvOptions = { tree, - context: reformedContext, + context, outputPath, params: 'carbon', }; From e609d0c194e402d60a10e606b91fa7c7e7230977 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 11:13:29 +0400 Subject: [PATCH 18/19] fix(src): improve manifestData check --- src/if-csv/index.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index 94ede0bb4..72c33379c 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -18,14 +18,11 @@ const IfCsv = async () => { const pipedManifest = await parseManifestFromStdin(); const {manifest, output, params} = await parseIfCsvArgs(); const resolvedManifest = manifest || pipedManifest; - let manifestData: Manifest; if (resolvedManifest) { - if (pipedManifest) { - manifestData = (await YAML.load(pipedManifest!)) as Manifest; - } else { - manifestData = await getManifestData(manifest!); - } + const manifestData = pipedManifest + ? ((await YAML.load(pipedManifest!)) as Manifest) + : await getManifestData(manifest!); const options: CsvOptions = { tree: manifestData.tree, From 669a422f5ea0adb839cf68712ac6bdb784a1f593 Mon Sep 17 00:00:00 2001 From: manushak Date: Tue, 16 Jul 2024 11:25:41 +0400 Subject: [PATCH 19/19] fix(src): rename the `executeCsv` function into `generateCsv` --- src/__tests__/if-csv/util/helpers.test.ts | 14 +++++++------- src/if-csv/index.ts | 4 ++-- src/if-csv/util/helpers.ts | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/__tests__/if-csv/util/helpers.test.ts b/src/__tests__/if-csv/util/helpers.test.ts index 1859f4850..1781f5fbc 100644 --- a/src/__tests__/if-csv/util/helpers.test.ts +++ b/src/__tests__/if-csv/util/helpers.test.ts @@ -3,7 +3,7 @@ import * as fs from 'fs/promises'; import {stringify} from 'csv-stringify/sync'; import {ERRORS} from '@grnsft/if-core/utils'; -import {executeCsv, getManifestData} from '../../../if-csv/util/helpers'; +import {generateCsv, getManifestData} from '../../../if-csv/util/helpers'; import {CsvOptions} from '../../../if-csv/types/csv'; const {ManifestValidationError} = ERRORS; @@ -26,7 +26,7 @@ jest.mock('fs/promises', () => { }); describe('if-csv/util/helpers: ', () => { - describe('executeCsv(): ', () => { + describe('generateCsv(): ', () => { it('generates CSV file with correct data.', async () => { const outputPath = 'output'; const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z']; @@ -65,7 +65,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect(fs.writeFile).toHaveBeenCalledWith( 'output.csv', @@ -112,7 +112,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); @@ -162,7 +162,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); expect(fs.writeFile).toHaveBeenCalledWith( @@ -190,7 +190,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - const result = await executeCsv(options); + const result = await generateCsv(options); expect.assertions(1); expect(result).toEqual(stringify(matrix, {columns})); @@ -221,7 +221,7 @@ describe('if-csv/util/helpers: ', () => { params: 'carbon', }; - await executeCsv(options); + await generateCsv(options); expect.assertions(1); expect(fs.writeFile).toHaveBeenCalledWith( diff --git a/src/if-csv/index.ts b/src/if-csv/index.ts index 72c33379c..602aabe1e 100644 --- a/src/if-csv/index.ts +++ b/src/if-csv/index.ts @@ -7,7 +7,7 @@ import {debugLogger} from '../common/util/debug-logger'; import {Manifest} from '../common/types/manifest'; import {logger} from '../common/util/logger'; -import {executeCsv, getManifestData} from './util/helpers'; +import {generateCsv, getManifestData} from './util/helpers'; import {parseIfCsvArgs} from './util/args'; import {CsvOptions} from './types/csv'; @@ -30,7 +30,7 @@ const IfCsv = async () => { outputPath: output, params, }; - const result = await executeCsv(options); + const result = await generateCsv(options); if (!output && result) { console.log(result); diff --git a/src/if-csv/util/helpers.ts b/src/if-csv/util/helpers.ts index 397293dd8..655611ff3 100644 --- a/src/if-csv/util/helpers.ts +++ b/src/if-csv/util/helpers.ts @@ -26,9 +26,9 @@ export const getManifestData = async (manifest: string) => { }; /** - * Executes a CSV generation based on the provided tree structure, context, output path, and params. + * Generates a CSV file based on the provided tree structure, context, output path, and params. */ -export const executeCsv = async (options: CsvOptions) => { +export const generateCsv = async (options: CsvOptions) => { const {tree, context, outputPath, params} = options; const columns = ['Path']; const matrix = [columns];