@naturalcycles/nodejs-lib 12.62.2 → 12.64.1
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/dist/fs/del.js +4 -4
- package/dist/got/getGot.d.ts +1 -0
- package/dist/got/getGot.js +42 -6
- package/dist/got/got.model.d.ts +7 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -3
- package/dist/validation/joi/joi.shared.schemas.d.ts +2 -2
- package/dist/validation/joi/string.extensions.d.ts +0 -9
- package/dist/validation/joi/string.extensions.js +0 -34
- package/package.json +2 -4
- package/src/fs/del.ts +8 -12
- package/src/got/getGot.ts +48 -7
- package/src/got/got.model.ts +9 -0
- package/src/index.ts +0 -3
- package/src/validation/joi/string.extensions.ts +0 -47
- package/dist/validation/sanitize.util.d.ts +0 -8
- package/dist/validation/sanitize.util.js +0 -13
- package/src/validation/sanitize.util.ts +0 -12
package/dist/fs/del.js
CHANGED
|
@@ -55,14 +55,14 @@ async function del(_opt) {
|
|
|
55
55
|
}));
|
|
56
56
|
const dirnamesSorted = dirnames.sort().reverse();
|
|
57
57
|
// console.log({ dirnamesSorted })
|
|
58
|
-
const deletedDirs =
|
|
58
|
+
const deletedDirs = [];
|
|
59
|
+
for await (const dirpath of dirnamesSorted) {
|
|
59
60
|
if (await isEmptyDir(dirpath)) {
|
|
60
61
|
// console.log(`empty dir: ${dirpath}`)
|
|
61
62
|
await fs.remove(dirpath);
|
|
62
|
-
|
|
63
|
+
deletedDirs.push(dirpath);
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
}, { concurrency: 1 });
|
|
65
|
+
}
|
|
66
66
|
if (verbose || debug)
|
|
67
67
|
console.log({ deletedDirs });
|
|
68
68
|
if (!silent) {
|
package/dist/got/getGot.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ import { GetGotOptions } from './got.model';
|
|
|
6
6
|
* 1. Error handler hook that prints helpful errors.
|
|
7
7
|
* 2. Hooks that log start/end of request (optional, false by default).
|
|
8
8
|
* 3. Reasonable defaults(tm), e.g non-infinite Timeout
|
|
9
|
+
* 4. Preserves error stack traces (!) (experimental!)
|
|
9
10
|
*/
|
|
10
11
|
export declare function getGot(opt?: GetGotOptions): Got;
|
package/dist/got/getGot.js
CHANGED
|
@@ -10,11 +10,12 @@ const __1 = require("..");
|
|
|
10
10
|
* 1. Error handler hook that prints helpful errors.
|
|
11
11
|
* 2. Hooks that log start/end of request (optional, false by default).
|
|
12
12
|
* 3. Reasonable defaults(tm), e.g non-infinite Timeout
|
|
13
|
+
* 4. Preserves error stack traces (!) (experimental!)
|
|
13
14
|
*/
|
|
14
15
|
function getGot(opt = {}) {
|
|
15
16
|
opt.logger || (opt.logger = console);
|
|
16
17
|
if (opt.debug) {
|
|
17
|
-
opt.logStart = opt.logFinished = opt.logResponse = true;
|
|
18
|
+
opt.logStart = opt.logFinished = opt.logResponse = opt.logRequest = true;
|
|
18
19
|
}
|
|
19
20
|
return got_1.default.extend({
|
|
20
21
|
// Most-important is to set to anything non-empty (so, requests don't "hang" by default).
|
|
@@ -40,6 +41,18 @@ function getGot(opt = {}) {
|
|
|
40
41
|
// Which definitely doesn't fit into default "RequestTimeout"
|
|
41
42
|
timeout: 60000,
|
|
42
43
|
...opt,
|
|
44
|
+
handlers: [
|
|
45
|
+
(options, next) => {
|
|
46
|
+
options.context = {
|
|
47
|
+
...options.context,
|
|
48
|
+
started: Date.now(),
|
|
49
|
+
// This is to preserve original stack trace
|
|
50
|
+
// https://github.com/sindresorhus/got/blob/main/documentation/async-stack-traces.md
|
|
51
|
+
err: new Error('RequestError'),
|
|
52
|
+
};
|
|
53
|
+
return next(options);
|
|
54
|
+
},
|
|
55
|
+
],
|
|
43
56
|
hooks: {
|
|
44
57
|
...opt.hooks,
|
|
45
58
|
beforeError: [
|
|
@@ -120,20 +133,42 @@ function gotErrorHook(opt = {}) {
|
|
|
120
133
|
err.message = [[statusCode, method, shortUrl].filter(Boolean).join(' '), body]
|
|
121
134
|
.filter(Boolean)
|
|
122
135
|
.join('\n');
|
|
136
|
+
const stack = err.options.context?.err?.stack;
|
|
137
|
+
if (stack) {
|
|
138
|
+
const originalStack = err.stack.split('\n');
|
|
139
|
+
let originalStackIndex = originalStack.findIndex(line => line.includes(' at '));
|
|
140
|
+
if (originalStackIndex === -1)
|
|
141
|
+
originalStackIndex = originalStack.length - 1;
|
|
142
|
+
// Skipping first line as it has RequestError: ...
|
|
143
|
+
// Skipping second line as it's known to be from e.g at got_1.default.extend.handlers
|
|
144
|
+
const syntheticStack = stack.split('\n').slice(2);
|
|
145
|
+
let firstNonNodeModulesIndex = syntheticStack.findIndex(line => !line.includes('node_modules'));
|
|
146
|
+
if (firstNonNodeModulesIndex === -1)
|
|
147
|
+
firstNonNodeModulesIndex = 0;
|
|
148
|
+
err.stack = [
|
|
149
|
+
// First lines of original error
|
|
150
|
+
...originalStack.slice(0, originalStackIndex),
|
|
151
|
+
// Other lines from "Synthetic error"
|
|
152
|
+
...syntheticStack.slice(firstNonNodeModulesIndex),
|
|
153
|
+
].join('\n');
|
|
154
|
+
// err.stack += '\n --' + stack.replace('Error: RequestError', '')
|
|
155
|
+
}
|
|
123
156
|
return err;
|
|
124
157
|
};
|
|
125
158
|
}
|
|
126
159
|
function gotBeforeRequestHook(opt) {
|
|
127
160
|
return options => {
|
|
128
|
-
options.context = {
|
|
129
|
-
...options.context,
|
|
130
|
-
started: Date.now(),
|
|
131
|
-
};
|
|
132
161
|
if (opt.logStart) {
|
|
133
162
|
const { retryCount } = options.context;
|
|
134
163
|
const shortUrl = getShortUrl(opt, options.url, options.prefixUrl);
|
|
135
164
|
opt.logger.log([' >>', options.method, shortUrl, retryCount && `(retry ${retryCount})`].join(' '));
|
|
136
165
|
}
|
|
166
|
+
if (opt.logRequest) {
|
|
167
|
+
const body = options.json || options.body;
|
|
168
|
+
if (body) {
|
|
169
|
+
opt.logger.log(body);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
137
172
|
};
|
|
138
173
|
}
|
|
139
174
|
// Here we log always, because it's similar to ErrorHook - we always log errors
|
|
@@ -177,7 +212,8 @@ function gotBeforeRetryHook(opt) {
|
|
|
177
212
|
function gotAfterResponseHook(opt = {}) {
|
|
178
213
|
return resp => {
|
|
179
214
|
const success = resp.statusCode >= 200 && resp.statusCode < 400;
|
|
180
|
-
|
|
215
|
+
// Errors are not logged here, as they're logged by gotErrorHook
|
|
216
|
+
if (opt.logFinished && success) {
|
|
181
217
|
const { started, retryCount } = resp.request.options.context;
|
|
182
218
|
const { url, prefixUrl, method } = resp.request.options;
|
|
183
219
|
const shortUrl = getShortUrl(opt, url, prefixUrl);
|
package/dist/got/got.model.d.ts
CHANGED
|
@@ -16,6 +16,12 @@ export interface GetGotOptions extends Options {
|
|
|
16
16
|
* @default false
|
|
17
17
|
*/
|
|
18
18
|
logFinished?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Log request object.
|
|
21
|
+
*
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
logRequest?: boolean;
|
|
19
25
|
/**
|
|
20
26
|
* Log actual response object.
|
|
21
27
|
*
|
|
@@ -48,5 +54,6 @@ export interface GotRequestContext extends AnyObject {
|
|
|
48
54
|
* Millisecond-timestamp of when the request was started. To be able to count "time spent".
|
|
49
55
|
*/
|
|
50
56
|
started: number;
|
|
57
|
+
err?: Error;
|
|
51
58
|
retryCount?: number;
|
|
52
59
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -65,7 +65,6 @@ import { AnySchemaTyped, ArraySchemaTyped, BooleanSchemaTyped, NumberSchemaTyped
|
|
|
65
65
|
export * from './validation/joi/joi.shared.schemas';
|
|
66
66
|
import { JoiValidationError, JoiValidationErrorData } from './validation/joi/joi.validation.error';
|
|
67
67
|
import { convert, getValidationResult, isValid, JoiValidationResult, undefinedIfInvalid, validate } from './validation/joi/joi.validation.util';
|
|
68
|
-
import { sanitizeHTML, SanitizeHTMLOptions } from './validation/sanitize.util';
|
|
69
68
|
import { runScript, RunScriptOptions } from './script';
|
|
70
|
-
export type { RunScriptOptions, JoiValidationErrorData, JoiValidationResult, ValidationErrorItem, ExtendedJoi, SchemaTyped, AnySchema, AnySchemaTyped, ArraySchemaTyped, BooleanSchemaTyped, NumberSchemaTyped, ObjectSchemaTyped, StringSchemaTyped, IDebug, IDebugger, SlackServiceCfg, SlackMessage, SlackMessageProps, SlackApiBody, SlackMessagePrefixHook, ReadableTyped, WritableTyped, TransformTyped, PipelineFromNDJsonFileOptions, PipelineToNDJsonFileOptions, TransformJsonParseOptions, TransformToNDJsonOptions, TransformMapOptions, TransformMapSyncOptions, NDJSONStreamForEachOptions, TransformOptions, TransformMultiThreadedOptions, WorkerClassInterface, WorkerInput, WorkerOutput, TableDiffOptions, InspectAnyOptions, Got, GetGotOptions, AfterResponseHook, BeforeErrorHook, BeforeRequestHook, AjvValidationOptions, AjvSchemaCfg, AjvValidationErrorData,
|
|
71
|
-
export { JoiValidationError, validate, getValidationResult, isValid, undefinedIfInvalid, convert, Joi, LRUMemoCache, Debug, SlackService, slackDefaultMessagePrefixHook, ndjsonStreamForEach, pipelineFromNDJsonFile, pipelineToNDJsonFile, NDJsonStats, streamToNDJsonFile, transformJsonParse, bufferReviver, transformToNDJson, transformMap, transformMapSync, transformMultiThreaded, BaseWorkerClass, tableDiff, inspectAny, inspectAnyStringifyFn, RequestError, TimeoutError, _chunkBuffer, Ajv, AjvSchema, AjvValidationError, readJsonSchemas, readAjvSchemas,
|
|
69
|
+
export type { RunScriptOptions, JoiValidationErrorData, JoiValidationResult, ValidationErrorItem, ExtendedJoi, SchemaTyped, AnySchema, AnySchemaTyped, ArraySchemaTyped, BooleanSchemaTyped, NumberSchemaTyped, ObjectSchemaTyped, StringSchemaTyped, IDebug, IDebugger, SlackServiceCfg, SlackMessage, SlackMessageProps, SlackApiBody, SlackMessagePrefixHook, ReadableTyped, WritableTyped, TransformTyped, PipelineFromNDJsonFileOptions, PipelineToNDJsonFileOptions, TransformJsonParseOptions, TransformToNDJsonOptions, TransformMapOptions, TransformMapSyncOptions, NDJSONStreamForEachOptions, TransformOptions, TransformMultiThreadedOptions, WorkerClassInterface, WorkerInput, WorkerOutput, TableDiffOptions, InspectAnyOptions, Got, GetGotOptions, AfterResponseHook, BeforeErrorHook, BeforeRequestHook, AjvValidationOptions, AjvSchemaCfg, AjvValidationErrorData, };
|
|
70
|
+
export { JoiValidationError, validate, getValidationResult, isValid, undefinedIfInvalid, convert, Joi, LRUMemoCache, Debug, SlackService, slackDefaultMessagePrefixHook, ndjsonStreamForEach, pipelineFromNDJsonFile, pipelineToNDJsonFile, NDJsonStats, streamToNDJsonFile, transformJsonParse, bufferReviver, transformToNDJson, transformMap, transformMapSync, transformMultiThreaded, BaseWorkerClass, tableDiff, inspectAny, inspectAnyStringifyFn, RequestError, TimeoutError, _chunkBuffer, Ajv, AjvSchema, AjvValidationError, readJsonSchemas, readAjvSchemas, runScript, };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.runScript = exports.
|
|
3
|
+
exports.runScript = exports.readAjvSchemas = exports.readJsonSchemas = exports.AjvValidationError = exports.AjvSchema = exports.Ajv = exports._chunkBuffer = exports.TimeoutError = exports.RequestError = exports.inspectAnyStringifyFn = exports.inspectAny = exports.tableDiff = exports.BaseWorkerClass = exports.transformMultiThreaded = exports.transformMapSync = exports.transformMap = exports.transformToNDJson = exports.bufferReviver = exports.transformJsonParse = exports.streamToNDJsonFile = exports.NDJsonStats = exports.pipelineToNDJsonFile = exports.pipelineFromNDJsonFile = exports.ndjsonStreamForEach = exports.slackDefaultMessagePrefixHook = exports.SlackService = exports.Debug = exports.LRUMemoCache = exports.Joi = exports.convert = exports.undefinedIfInvalid = exports.isValid = exports.getValidationResult = exports.validate = exports.JoiValidationError = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const ajv_1 = require("ajv");
|
|
6
6
|
exports.Ajv = ajv_1.default;
|
|
@@ -96,7 +96,5 @@ Object.defineProperty(exports, "getValidationResult", { enumerable: true, get: f
|
|
|
96
96
|
Object.defineProperty(exports, "isValid", { enumerable: true, get: function () { return joi_validation_util_1.isValid; } });
|
|
97
97
|
Object.defineProperty(exports, "undefinedIfInvalid", { enumerable: true, get: function () { return joi_validation_util_1.undefinedIfInvalid; } });
|
|
98
98
|
Object.defineProperty(exports, "validate", { enumerable: true, get: function () { return joi_validation_util_1.validate; } });
|
|
99
|
-
const sanitize_util_1 = require("./validation/sanitize.util");
|
|
100
|
-
Object.defineProperty(exports, "sanitizeHTML", { enumerable: true, get: function () { return sanitize_util_1.sanitizeHTML; } });
|
|
101
99
|
const script_1 = require("./script");
|
|
102
100
|
Object.defineProperty(exports, "runScript", { enumerable: true, get: function () { return script_1.runScript; } });
|
|
@@ -43,5 +43,5 @@ export declare const semVerSchema: import("./string.extensions").ExtendedStringS
|
|
|
43
43
|
export declare const userAgentSchema: import("./string.extensions").ExtendedStringSchema;
|
|
44
44
|
export declare const utcOffsetSchema: import("./number.extensions").ExtendedNumberSchema;
|
|
45
45
|
export declare const ipAddressSchema: import("./string.extensions").ExtendedStringSchema;
|
|
46
|
-
export declare const baseDBEntitySchema: ObjectSchemaTyped<Partial<SavedDBEntity
|
|
47
|
-
export declare const savedDBEntitySchema: ObjectSchemaTyped<SavedDBEntity
|
|
46
|
+
export declare const baseDBEntitySchema: ObjectSchemaTyped<Partial<SavedDBEntity<string>>, Partial<SavedDBEntity<string>>>;
|
|
47
|
+
export declare const savedDBEntitySchema: ObjectSchemaTyped<SavedDBEntity<string>, SavedDBEntity<string>>;
|
|
@@ -3,18 +3,9 @@ import * as Joi from 'joi';
|
|
|
3
3
|
import { AnySchemaTyped } from './joi.model';
|
|
4
4
|
export interface ExtendedStringSchema extends StringSchema, AnySchemaTyped<string> {
|
|
5
5
|
dateString(min?: string, max?: string): this;
|
|
6
|
-
stripHTML(opt?: JoiStripHTMLOptions): this;
|
|
7
6
|
}
|
|
8
7
|
export interface JoiDateStringOptions {
|
|
9
8
|
min?: string;
|
|
10
9
|
max?: string;
|
|
11
10
|
}
|
|
12
|
-
export interface JoiStripHTMLOptions {
|
|
13
|
-
/**
|
|
14
|
-
* 'Strict' would throw an error if it detects any HTML.
|
|
15
|
-
* Non-strict (default) does not error, but DOES convert the string to the string without HTML.
|
|
16
|
-
* Internally uses `sanitize-html` library, with allowedTags = [], and method = 'discard'.
|
|
17
|
-
*/
|
|
18
|
-
strict?: boolean;
|
|
19
|
-
}
|
|
20
11
|
export declare function stringExtensions(joi: typeof Joi): Extension;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.stringExtensions = void 0;
|
|
4
4
|
const time_lib_1 = require("@naturalcycles/time-lib");
|
|
5
|
-
const sanitize = require("sanitize-html");
|
|
6
5
|
function stringExtensions(joi) {
|
|
7
6
|
return {
|
|
8
7
|
type: 'string',
|
|
@@ -68,39 +67,6 @@ function stringExtensions(joi) {
|
|
|
68
67
|
return v; // validation passed
|
|
69
68
|
},
|
|
70
69
|
},
|
|
71
|
-
stripHTML: {
|
|
72
|
-
method(opt) {
|
|
73
|
-
return this.$_addRule({
|
|
74
|
-
name: 'stripHTML',
|
|
75
|
-
args: {
|
|
76
|
-
strict: false,
|
|
77
|
-
...opt,
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
},
|
|
81
|
-
args: [
|
|
82
|
-
{
|
|
83
|
-
name: 'strict',
|
|
84
|
-
ref: true,
|
|
85
|
-
assert: v => typeof v === 'boolean',
|
|
86
|
-
message: 'must be a boolean',
|
|
87
|
-
},
|
|
88
|
-
],
|
|
89
|
-
validate(v, helpers, args) {
|
|
90
|
-
// console.log('!!! stripHTML', args, v)
|
|
91
|
-
const r = sanitize(v, {
|
|
92
|
-
allowedTags: [],
|
|
93
|
-
// disallowedTagsMode: 'discard' // discard is default
|
|
94
|
-
parser: {
|
|
95
|
-
decodeEntities: false, // prevent decoding/changing of &<>"'
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
if (args.strict && r !== v) {
|
|
99
|
-
return helpers.error('string.stripHTML', args);
|
|
100
|
-
}
|
|
101
|
-
return r; // return converted value (or the same, if there was nothing to sanitize)
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
70
|
},
|
|
105
71
|
};
|
|
106
72
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/nodejs-lib",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.64.1",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"docs-serve": "vuepress dev docs",
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"@naturalcycles/js-lib": "^14.0.0",
|
|
18
18
|
"@naturalcycles/time-lib": "^3.0.1",
|
|
19
19
|
"@types/lru-cache": "^5.1.0",
|
|
20
|
-
"@types/sanitize-html": "^2.5.0",
|
|
21
20
|
"@types/through2-concurrent": "^2.0.0",
|
|
22
21
|
"ajv": "^8.6.2",
|
|
23
22
|
"ajv-formats": "^2.1.0",
|
|
@@ -27,7 +26,7 @@
|
|
|
27
26
|
"chalk": "^4.0.0",
|
|
28
27
|
"cp-file": "^9.0.0",
|
|
29
28
|
"debug": "^4.1.1",
|
|
30
|
-
"dotenv": "^
|
|
29
|
+
"dotenv": "^14.2.0",
|
|
31
30
|
"execa": "^5.0.0",
|
|
32
31
|
"fs-extra": "^10.0.0",
|
|
33
32
|
"globby": "^11.0.0",
|
|
@@ -36,7 +35,6 @@
|
|
|
36
35
|
"lru-cache": "^6.0.0",
|
|
37
36
|
"move-file": "^2.0.0",
|
|
38
37
|
"nanoid": "^3.0.0",
|
|
39
|
-
"sanitize-html": "^2.5.2",
|
|
40
38
|
"through2-concurrent": "^2.0.0",
|
|
41
39
|
"yargs": "^17.0.0"
|
|
42
40
|
},
|
package/src/fs/del.ts
CHANGED
|
@@ -90,18 +90,14 @@ export async function del(_opt: DelOptions | DelSingleOption): Promise<void> {
|
|
|
90
90
|
|
|
91
91
|
// console.log({ dirnamesSorted })
|
|
92
92
|
|
|
93
|
-
const deletedDirs =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return false
|
|
102
|
-
},
|
|
103
|
-
{ concurrency: 1 },
|
|
104
|
-
)
|
|
93
|
+
const deletedDirs: string[] = []
|
|
94
|
+
for await (const dirpath of dirnamesSorted) {
|
|
95
|
+
if (await isEmptyDir(dirpath)) {
|
|
96
|
+
// console.log(`empty dir: ${dirpath}`)
|
|
97
|
+
await fs.remove(dirpath)
|
|
98
|
+
deletedDirs.push(dirpath)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
105
101
|
|
|
106
102
|
if (verbose || debug) console.log({ deletedDirs })
|
|
107
103
|
|
package/src/got/getGot.ts
CHANGED
|
@@ -16,12 +16,13 @@ import { GetGotOptions, GotRequestContext } from './got.model'
|
|
|
16
16
|
* 1. Error handler hook that prints helpful errors.
|
|
17
17
|
* 2. Hooks that log start/end of request (optional, false by default).
|
|
18
18
|
* 3. Reasonable defaults(tm), e.g non-infinite Timeout
|
|
19
|
+
* 4. Preserves error stack traces (!) (experimental!)
|
|
19
20
|
*/
|
|
20
21
|
export function getGot(opt: GetGotOptions = {}): Got {
|
|
21
22
|
opt.logger ||= console
|
|
22
23
|
|
|
23
24
|
if (opt.debug) {
|
|
24
|
-
opt.logStart = opt.logFinished = opt.logResponse = true
|
|
25
|
+
opt.logStart = opt.logFinished = opt.logResponse = opt.logRequest = true
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
return got.extend({
|
|
@@ -48,6 +49,19 @@ export function getGot(opt: GetGotOptions = {}): Got {
|
|
|
48
49
|
// Which definitely doesn't fit into default "RequestTimeout"
|
|
49
50
|
timeout: 60_000,
|
|
50
51
|
...opt,
|
|
52
|
+
handlers: [
|
|
53
|
+
(options, next) => {
|
|
54
|
+
options.context = {
|
|
55
|
+
...options.context,
|
|
56
|
+
started: Date.now(),
|
|
57
|
+
// This is to preserve original stack trace
|
|
58
|
+
// https://github.com/sindresorhus/got/blob/main/documentation/async-stack-traces.md
|
|
59
|
+
err: new Error('RequestError'),
|
|
60
|
+
} as GotRequestContext
|
|
61
|
+
|
|
62
|
+
return next(options)
|
|
63
|
+
},
|
|
64
|
+
],
|
|
51
65
|
hooks: {
|
|
52
66
|
...opt.hooks,
|
|
53
67
|
beforeError: [
|
|
@@ -135,17 +149,35 @@ function gotErrorHook(opt: GetGotOptions = {}): BeforeErrorHook {
|
|
|
135
149
|
.filter(Boolean)
|
|
136
150
|
.join('\n')
|
|
137
151
|
|
|
152
|
+
const stack = (err.options.context as GotRequestContext)?.err?.stack
|
|
153
|
+
if (stack) {
|
|
154
|
+
const originalStack = err.stack.split('\n')
|
|
155
|
+
let originalStackIndex = originalStack.findIndex(line => line.includes(' at '))
|
|
156
|
+
if (originalStackIndex === -1) originalStackIndex = originalStack.length - 1
|
|
157
|
+
|
|
158
|
+
// Skipping first line as it has RequestError: ...
|
|
159
|
+
// Skipping second line as it's known to be from e.g at got_1.default.extend.handlers
|
|
160
|
+
const syntheticStack = stack.split('\n').slice(2)
|
|
161
|
+
let firstNonNodeModulesIndex = syntheticStack.findIndex(
|
|
162
|
+
line => !line.includes('node_modules'),
|
|
163
|
+
)
|
|
164
|
+
if (firstNonNodeModulesIndex === -1) firstNonNodeModulesIndex = 0
|
|
165
|
+
|
|
166
|
+
err.stack = [
|
|
167
|
+
// First lines of original error
|
|
168
|
+
...originalStack.slice(0, originalStackIndex),
|
|
169
|
+
// Other lines from "Synthetic error"
|
|
170
|
+
...syntheticStack.slice(firstNonNodeModulesIndex),
|
|
171
|
+
].join('\n')
|
|
172
|
+
// err.stack += '\n --' + stack.replace('Error: RequestError', '')
|
|
173
|
+
}
|
|
174
|
+
|
|
138
175
|
return err
|
|
139
176
|
}
|
|
140
177
|
}
|
|
141
178
|
|
|
142
179
|
function gotBeforeRequestHook(opt: GetGotOptions): BeforeRequestHook {
|
|
143
180
|
return options => {
|
|
144
|
-
options.context = {
|
|
145
|
-
...options.context,
|
|
146
|
-
started: Date.now(),
|
|
147
|
-
} as GotRequestContext
|
|
148
|
-
|
|
149
181
|
if (opt.logStart) {
|
|
150
182
|
const { retryCount } = options.context as GotRequestContext
|
|
151
183
|
const shortUrl = getShortUrl(opt, options.url, options.prefixUrl)
|
|
@@ -153,6 +185,14 @@ function gotBeforeRequestHook(opt: GetGotOptions): BeforeRequestHook {
|
|
|
153
185
|
[' >>', options.method, shortUrl, retryCount && `(retry ${retryCount})`].join(' '),
|
|
154
186
|
)
|
|
155
187
|
}
|
|
188
|
+
|
|
189
|
+
if (opt.logRequest) {
|
|
190
|
+
const body = options.json || options.body
|
|
191
|
+
|
|
192
|
+
if (body) {
|
|
193
|
+
opt.logger!.log(body)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
156
196
|
}
|
|
157
197
|
}
|
|
158
198
|
|
|
@@ -204,7 +244,8 @@ function gotAfterResponseHook(opt: GetGotOptions = {}): AfterResponseHook {
|
|
|
204
244
|
return resp => {
|
|
205
245
|
const success = resp.statusCode >= 200 && resp.statusCode < 400
|
|
206
246
|
|
|
207
|
-
|
|
247
|
+
// Errors are not logged here, as they're logged by gotErrorHook
|
|
248
|
+
if (opt.logFinished && success) {
|
|
208
249
|
const { started, retryCount } = resp.request.options.context as GotRequestContext
|
|
209
250
|
const { url, prefixUrl, method } = resp.request.options
|
|
210
251
|
const shortUrl = getShortUrl(opt, url, prefixUrl)
|
package/src/got/got.model.ts
CHANGED
|
@@ -20,6 +20,13 @@ export interface GetGotOptions extends Options {
|
|
|
20
20
|
*/
|
|
21
21
|
logFinished?: boolean
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Log request object.
|
|
25
|
+
*
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
logRequest?: boolean
|
|
29
|
+
|
|
23
30
|
/**
|
|
24
31
|
* Log actual response object.
|
|
25
32
|
*
|
|
@@ -58,5 +65,7 @@ export interface GotRequestContext extends AnyObject {
|
|
|
58
65
|
*/
|
|
59
66
|
started: number
|
|
60
67
|
|
|
68
|
+
err?: Error
|
|
69
|
+
|
|
61
70
|
retryCount?: number
|
|
62
71
|
}
|
package/src/index.ts
CHANGED
|
@@ -107,7 +107,6 @@ import {
|
|
|
107
107
|
undefinedIfInvalid,
|
|
108
108
|
validate,
|
|
109
109
|
} from './validation/joi/joi.validation.util'
|
|
110
|
-
import { sanitizeHTML, SanitizeHTMLOptions } from './validation/sanitize.util'
|
|
111
110
|
import { runScript, RunScriptOptions } from './script'
|
|
112
111
|
|
|
113
112
|
export type {
|
|
@@ -156,7 +155,6 @@ export type {
|
|
|
156
155
|
AjvValidationOptions,
|
|
157
156
|
AjvSchemaCfg,
|
|
158
157
|
AjvValidationErrorData,
|
|
159
|
-
SanitizeHTMLOptions,
|
|
160
158
|
}
|
|
161
159
|
|
|
162
160
|
export {
|
|
@@ -194,6 +192,5 @@ export {
|
|
|
194
192
|
AjvValidationError,
|
|
195
193
|
readJsonSchemas,
|
|
196
194
|
readAjvSchemas,
|
|
197
|
-
sanitizeHTML,
|
|
198
195
|
runScript,
|
|
199
196
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { dayjs } from '@naturalcycles/time-lib'
|
|
2
2
|
import { Extension, StringSchema } from 'joi'
|
|
3
3
|
import * as Joi from 'joi'
|
|
4
|
-
import * as sanitize from 'sanitize-html'
|
|
5
4
|
import { AnySchemaTyped } from './joi.model'
|
|
6
5
|
|
|
7
6
|
export interface ExtendedStringSchema extends StringSchema, AnySchemaTyped<string> {
|
|
8
7
|
dateString(min?: string, max?: string): this
|
|
9
|
-
stripHTML(opt?: JoiStripHTMLOptions): this
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
export interface JoiDateStringOptions {
|
|
@@ -14,15 +12,6 @@ export interface JoiDateStringOptions {
|
|
|
14
12
|
max?: string
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
export interface JoiStripHTMLOptions {
|
|
18
|
-
/**
|
|
19
|
-
* 'Strict' would throw an error if it detects any HTML.
|
|
20
|
-
* Non-strict (default) does not error, but DOES convert the string to the string without HTML.
|
|
21
|
-
* Internally uses `sanitize-html` library, with allowedTags = [], and method = 'discard'.
|
|
22
|
-
*/
|
|
23
|
-
strict?: boolean
|
|
24
|
-
}
|
|
25
|
-
|
|
26
15
|
export function stringExtensions(joi: typeof Joi): Extension {
|
|
27
16
|
return {
|
|
28
17
|
type: 'string',
|
|
@@ -90,42 +79,6 @@ export function stringExtensions(joi: typeof Joi): Extension {
|
|
|
90
79
|
return v // validation passed
|
|
91
80
|
},
|
|
92
81
|
},
|
|
93
|
-
stripHTML: {
|
|
94
|
-
method(opt?: JoiStripHTMLOptions) {
|
|
95
|
-
return this.$_addRule({
|
|
96
|
-
name: 'stripHTML',
|
|
97
|
-
args: {
|
|
98
|
-
strict: false,
|
|
99
|
-
...opt,
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
|
-
},
|
|
103
|
-
args: [
|
|
104
|
-
{
|
|
105
|
-
name: 'strict',
|
|
106
|
-
ref: true,
|
|
107
|
-
assert: v => typeof v === 'boolean',
|
|
108
|
-
message: 'must be a boolean',
|
|
109
|
-
},
|
|
110
|
-
],
|
|
111
|
-
validate(v: string, helpers, args: JoiStripHTMLOptions) {
|
|
112
|
-
// console.log('!!! stripHTML', args, v)
|
|
113
|
-
|
|
114
|
-
const r = sanitize(v, {
|
|
115
|
-
allowedTags: [], // no html tags allowed at all
|
|
116
|
-
// disallowedTagsMode: 'discard' // discard is default
|
|
117
|
-
parser: {
|
|
118
|
-
decodeEntities: false, // prevent decoding/changing of &<>"'
|
|
119
|
-
},
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
if (args.strict && r !== v) {
|
|
123
|
-
return helpers.error('string.stripHTML', args)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return r // return converted value (or the same, if there was nothing to sanitize)
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
82
|
},
|
|
130
83
|
}
|
|
131
84
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import * as sanitize from 'sanitize-html';
|
|
2
|
-
export declare type SanitizeHTMLOptions = sanitize.IOptions;
|
|
3
|
-
/**
|
|
4
|
-
* Simply a wrapper around `sanitize-html` library.
|
|
5
|
-
*
|
|
6
|
-
* @experimental
|
|
7
|
-
*/
|
|
8
|
-
export declare function sanitizeHTML(s: string, opt?: SanitizeHTMLOptions): string;
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sanitizeHTML = void 0;
|
|
4
|
-
const sanitize = require("sanitize-html");
|
|
5
|
-
/**
|
|
6
|
-
* Simply a wrapper around `sanitize-html` library.
|
|
7
|
-
*
|
|
8
|
-
* @experimental
|
|
9
|
-
*/
|
|
10
|
-
function sanitizeHTML(s, opt) {
|
|
11
|
-
return sanitize(s, opt);
|
|
12
|
-
}
|
|
13
|
-
exports.sanitizeHTML = sanitizeHTML;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import * as sanitize from 'sanitize-html'
|
|
2
|
-
|
|
3
|
-
export type SanitizeHTMLOptions = sanitize.IOptions
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Simply a wrapper around `sanitize-html` library.
|
|
7
|
-
*
|
|
8
|
-
* @experimental
|
|
9
|
-
*/
|
|
10
|
-
export function sanitizeHTML(s: string, opt?: SanitizeHTMLOptions): string {
|
|
11
|
-
return sanitize(s, opt)
|
|
12
|
-
}
|