contentful-batch-libs
Advanced tools
Comparing version 9.5.1 to 9.6.0
@@ -13,10 +13,12 @@ "use strict"; | ||
exports.writeErrorLogFile = writeErrorLogFile; | ||
var _events = _interopRequireDefault(require("events")); | ||
var _bfj = _interopRequireDefault(require("bfj")); | ||
var _figures = _interopRequireDefault(require("figures")); | ||
var _format = _interopRequireDefault(require("date-fns/format")); | ||
var _parseISO = _interopRequireDefault(require("date-fns/parseISO")); | ||
var _figures = _interopRequireDefault(require("figures")); | ||
var _nodeEvents = _interopRequireDefault(require("node:events")); | ||
var _nodeFs = require("node:fs"); | ||
var _nodeStream = require("node:stream"); | ||
var _promises = require("node:stream/promises"); | ||
var _getEntityName = _interopRequireDefault(require("./get-entity-name")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const logEmitter = exports.logEmitter = new _events.default(); | ||
const logEmitter = exports.logEmitter = new _nodeEvents.default(); | ||
function extractErrorInformation(error) { | ||
@@ -111,3 +113,7 @@ const source = error.originalError || error; | ||
const count = errorLog.reduce((count, curr) => { | ||
if (Object.prototype.hasOwnProperty.call(curr, 'warning')) count.warnings++;else if (Object.prototype.hasOwnProperty.call(curr, 'error')) count.errors++; | ||
if (Object.prototype.hasOwnProperty.call(curr, 'warning')) { | ||
count.warnings++; | ||
} else if (Object.prototype.hasOwnProperty.call(curr, 'error')) { | ||
count.errors++; | ||
} | ||
return count; | ||
@@ -125,18 +131,32 @@ }, { | ||
// Write all log messages instead of infos to the error log file | ||
function writeErrorLogFile(destination, errorLog) { | ||
const logFileData = errorLog.map(formatLogMessageLogfile); | ||
return _bfj.default.write(destination, logFileData, { | ||
circular: 'ignore', | ||
space: 2 | ||
}).then(() => { | ||
/** | ||
* Write all log messages instead of infos to the error log file | ||
* @param {import('node:fs').PathLike} destination | ||
* @param {Record<string, unknown>[]} errorLog | ||
* @returns {Promise<void>} | ||
*/ | ||
async function writeErrorLogFile(destination, errorLog) { | ||
const formatLogTransformer = new _nodeStream.Transform({ | ||
objectMode: true, | ||
transform: (chunk, encoding, callback) => { | ||
const formattedChunk = formatLogMessageLogfile(chunk); | ||
callback(null, Buffer.from(JSON.stringify(formattedChunk))); | ||
} | ||
}); | ||
const logFileWriteStream = (0, _nodeFs.createWriteStream)(destination); | ||
try { | ||
await (0, _promises.pipeline)([_nodeStream.Readable.from(errorLog), formatLogTransformer, logFileWriteStream]); | ||
console.log('\nStored the detailed error log file at:'); | ||
console.log(destination); | ||
}).catch(e => { | ||
} catch (err) { | ||
// avoid crashing when writing the log file fails | ||
console.error(e); | ||
}); | ||
console.error(err); | ||
} | ||
} | ||
// Init listeners for log messages, transform them into proper format and logs/displays them | ||
/** | ||
* Init listeners for log messages, transform them into proper format and logs/displays them | ||
* @param {Record<string,unknown>[]} log | ||
* @returns {Promise<void>} | ||
*/ | ||
function setupLogging(log) { | ||
@@ -159,3 +179,7 @@ function errorLogger(level, error) { | ||
// Format log message to display them as task status | ||
/** | ||
* Format log message to display them as task status | ||
* @template {Ctx} | ||
* @param {import('listr').ListrTaskWrapper<Ctx>} task | ||
*/ | ||
function logToTaskOutput(task) { | ||
@@ -162,0 +186,0 @@ function logToTask(logMessage) { |
{ | ||
"name": "contentful-batch-libs", | ||
"version": "9.5.1", | ||
"version": "9.6.0", | ||
"description": "Library modules used by contentful batch utility CLI tools.", | ||
@@ -26,3 +26,2 @@ "main": "dist/index.js", | ||
"dependencies": { | ||
"bfj": "7.1.0", | ||
"date-fns": "^2.28.0", | ||
@@ -39,10 +38,10 @@ "figures": "3.2.0", | ||
"@types/lodash.clonedeep": "^4.5.7", | ||
"@types/node": "^17.0.38", | ||
"@types/node": "^20.8.4", | ||
"@typescript-eslint/eslint-plugin": "^6.7.5", | ||
"babel-eslint": "^10.1.0", | ||
"babel-jest": "^27.3.1", | ||
"babel-jest": "^29.7.0", | ||
"babel-plugin-add-module-exports": "^1.0.4", | ||
"babel-preset-env": "^1.7.0", | ||
"contentful": "^9.1.31", | ||
"contentful-management": "^10.6.0", | ||
"contentful": "^10.6.1", | ||
"contentful-management": "^11.1.1", | ||
"cz-conventional-changelog": "^3.3.0", | ||
@@ -55,3 +54,3 @@ "eslint": "^8.51.0", | ||
"eslint-plugin-promise": "^6.1.1", | ||
"husky": "7.0.4", | ||
"husky": "8.0.3", | ||
"jest": "^29.7.0", | ||
@@ -58,0 +57,0 @@ "listr2": "^7.0.1", |
@@ -0,1 +1,3 @@ | ||
import fs from 'node:fs' | ||
import { Writable } from 'node:stream' | ||
import { | ||
@@ -10,7 +12,4 @@ formatLogMessageOneLine, | ||
} from '../lib/logging' | ||
import figures from 'figures' | ||
import bfj from 'bfj' | ||
function isValidDate (date) { | ||
@@ -20,6 +19,2 @@ return !isNaN(Date.parse(date)) | ||
jest.mock('bfj', () => ({ | ||
write: jest.fn(() => Promise.resolve()) | ||
})) | ||
const consoleLogSpy = jest.spyOn(global.console, 'log') | ||
@@ -70,7 +65,12 @@ const logEmitterAddListenerSpy = jest.spyOn(logEmitter, 'addListener') | ||
const output = formatLogMessageOneLine({ error, level: 'error' }) | ||
expect(output).toBe('Error: Status: status - status text - Message: Some API error - Entity: 42 - Details: error detail - Request ID: 3') | ||
expect(output).toBe( | ||
'Error: Status: status - status text - Message: Some API error - Entity: 42 - Details: error detail - Request ID: 3' | ||
) | ||
}) | ||
test('format one line message with level error', () => { | ||
const output = formatLogMessageOneLine({ error: Error('normal error message'), level: 'error' }) | ||
const output = formatLogMessageOneLine({ | ||
error: Error('normal error message'), | ||
level: 'error' | ||
}) | ||
expect(output).toBe('Error: normal error message') | ||
@@ -80,3 +80,6 @@ }) | ||
test('format one line message with level warning', () => { | ||
const output = formatLogMessageOneLine({ warning: 'warning text', level: 'warning' }) | ||
const output = formatLogMessageOneLine({ | ||
warning: 'warning text', | ||
level: 'warning' | ||
}) | ||
expect(output).toBe('warning text') | ||
@@ -117,3 +120,5 @@ }) | ||
expect(output.error.data.message).toBe(apiError.message) | ||
expect(output.error.data.details.errors[0].name).toBe(apiError.details.errors[0].name) | ||
expect(output.error.data.details.errors[0].name).toBe( | ||
apiError.details.errors[0].name | ||
) | ||
}) | ||
@@ -140,7 +145,10 @@ | ||
test('displays error log well formatted', () => { | ||
const extendedExampleErrorLog = [...exampleErrorLog, { | ||
ts: new Date('2022-01-01T01:05:43+01:00').toJSON(), | ||
level: 'warning', | ||
warning: 'another warning' | ||
}] | ||
const extendedExampleErrorLog = [ | ||
...exampleErrorLog, | ||
{ | ||
ts: new Date('2022-01-01T01:05:43+01:00').toJSON(), | ||
level: 'warning', | ||
warning: 'another warning' | ||
} | ||
] | ||
@@ -150,6 +158,14 @@ displayErrorLog(extendedExampleErrorLog) | ||
expect(consoleLogSpy.mock.calls).toHaveLength(4) | ||
expect(consoleLogSpy.mock.calls[0][0]).toContain('The following 1 errors and 2 warnings occurred:') | ||
expect(consoleLogSpy.mock.calls[1][0]).toMatch(/\d{2}:\d{2}:\d{2} - warning text/) | ||
expect(consoleLogSpy.mock.calls[2][0]).toMatch(/\d{2}:\d{2}:\d{2} - Error: error message/) | ||
expect(consoleLogSpy.mock.calls[3][0]).toMatch(/\d{2}:\d{2}:\d{2} - another warning/) | ||
expect(consoleLogSpy.mock.calls[0][0]).toContain( | ||
'The following 1 errors and 2 warnings occurred:' | ||
) | ||
expect(consoleLogSpy.mock.calls[1][0]).toMatch( | ||
/\d{2}:\d{2}:\d{2} - warning text/ | ||
) | ||
expect(consoleLogSpy.mock.calls[2][0]).toMatch( | ||
/\d{2}:\d{2}:\d{2} - Error: error message/ | ||
) | ||
expect(consoleLogSpy.mock.calls[3][0]).toMatch( | ||
/\d{2}:\d{2}:\d{2} - another warning/ | ||
) | ||
}) | ||
@@ -161,21 +177,49 @@ | ||
expect(consoleLogSpy.mock.calls).toHaveLength(1) | ||
expect(consoleLogSpy.mock.calls[0][0]).toContain('No errors or warnings occurred') | ||
expect(consoleLogSpy.mock.calls[0][0]).toContain( | ||
'No errors or warnings occurred' | ||
) | ||
}) | ||
test('writes error log file to disk', async () => { | ||
expect.assertions(8) | ||
expect.assertions(9) | ||
const destination = '/just/some/path/to/a/file.log' | ||
await expect(writeErrorLogFile(destination, exampleErrorLog)).resolves.not.toThrow() | ||
const chunks = [] | ||
const writeStreamSpy = jest | ||
.spyOn(fs, 'createWriteStream') | ||
.mockImplementation(() => { | ||
return new Writable({ | ||
write: (chunk, b, cb) => { | ||
try { | ||
chunks.push(JSON.parse(chunk.toString('utf-8'))) | ||
cb() | ||
} catch (err) { | ||
cb(err) | ||
} | ||
} | ||
}) | ||
}) | ||
await expect( | ||
writeErrorLogFile(destination, exampleErrorLog) | ||
).resolves.not.toThrow() | ||
expect(consoleLogSpy.mock.calls).toHaveLength(2) | ||
expect(consoleLogSpy.mock.calls[0][0]).toBe('\nStored the detailed error log file at:') | ||
expect(consoleLogSpy.mock.calls[0][0]).toBe( | ||
'\nStored the detailed error log file at:' | ||
) | ||
expect(consoleLogSpy.mock.calls[1][0]).toBe(destination) | ||
expect(bfj.write.mock.calls).toHaveLength(1) | ||
expect(bfj.write.mock.calls[0][0]).toBe(destination) | ||
expect(bfj.write.mock.calls[0][1]).toMatchObject(exampleErrorLog) | ||
expect(bfj.write.mock.calls[0][2]).toMatchObject({ | ||
circular: 'ignore', | ||
space: 2 | ||
expect(writeStreamSpy.mock.calls).toHaveLength(1) | ||
expect(writeStreamSpy.mock.calls[0][0]).toBe(destination) | ||
chunks.forEach((chunk) => { | ||
if ('error' in chunk) { | ||
const { error, ...rest } = chunk | ||
expect(typeof error).toBe('object') | ||
expect(exampleErrorLog).toContainEqual(expect.objectContaining(rest)) | ||
} else { | ||
expect(exampleErrorLog).toContainEqual(chunk) | ||
} | ||
}) | ||
@@ -268,3 +312,5 @@ }) | ||
expect(taskMock.output).not.toBe(`${figures.tick} this should no more change the task output`) | ||
expect(taskMock.output).not.toBe( | ||
`${figures.tick} this should no more change the task output` | ||
) | ||
}) |
@@ -5,2 +5,3 @@ import type { EventEmitter } from 'events' | ||
import type HttpsProxyAgent from 'https-proxy-agent' | ||
import type { PathLike } from 'node:fs' | ||
import type { ListrDefaultRendererValue, ListrGetRendererClassFromValue, ListrRendererValue, ListrTask } from 'listr2' | ||
@@ -47,3 +48,3 @@ | ||
export function writeErrorLogFile(destination: string, errorLog: unknown[]): Promise<void>; | ||
export function writeErrorLogFile(destination: PathLike, errorLog: unknown[]): Promise<void>; | ||
@@ -50,0 +51,0 @@ export function proxyStringToObject(proxyString: string): ProxyObject; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42191
5
1192
- Removedbfj@7.1.0
- Removedbfj@7.1.0(transitive)
- Removedbluebird@3.7.2(transitive)
- Removedcheck-types@11.2.3(transitive)
- Removeddeep-is@0.1.4(transitive)
- Removedescodegen@1.14.3(transitive)
- Removedesprima@1.2.24.0.1(transitive)
- Removedestraverse@4.3.0(transitive)
- Removedesutils@2.0.3(transitive)
- Removedfast-levenshtein@2.0.6(transitive)
- Removedhoopy@0.1.4(transitive)
- Removedjsonpath@1.1.1(transitive)
- Removedlevn@0.3.0(transitive)
- Removedoptionator@0.8.3(transitive)
- Removedprelude-ls@1.1.2(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedstatic-eval@2.0.2(transitive)
- Removedtryer@1.0.1(transitive)
- Removedtype-check@0.3.2(transitive)
- Removedunderscore@1.12.1(transitive)
- Removedword-wrap@1.2.5(transitive)