@naturalcycles/nodejs-lib 13.7.1 → 13.8.0

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.
@@ -108,7 +108,7 @@ function objectToShellExport(obj, prefix = '') {
108
108
  return '';
109
109
  return (Object.entries(obj)
110
110
  .map(([k, v]) => {
111
- if (v) {
111
+ if (v !== undefined && v !== null) {
112
112
  return `export ${prefix}${k}="${v}"`;
113
113
  }
114
114
  })
@@ -137,7 +137,7 @@ function objectToGithubActionsEnv(obj, prefix = '') {
137
137
  return '';
138
138
  return (Object.entries(obj)
139
139
  .map(([k, v]) => {
140
- if (v) {
140
+ if (v !== undefined && v !== null) {
141
141
  return `${prefix}${k}=${v}`;
142
142
  }
143
143
  })
@@ -32,3 +32,16 @@ export declare function decryptString(str: Base64String, secretKeyBuffer: Buffer
32
32
  * Output is base64 string.
33
33
  */
34
34
  export declare function encryptString(str: string, secretKeyBuffer: Buffer): Base64String;
35
+ /**
36
+ * Wraps `crypto.timingSafeEqual` and allows it to be used with String inputs:
37
+ *
38
+ * 1. Does length check first and short-circuits on length mismatch. Because `crypto.timingSafeEqual` only works with same-length inputs.
39
+ *
40
+ * Relevant read:
41
+ * https://medium.com/nerd-for-tech/checking-api-key-without-shooting-yourself-in-the-foot-javascript-nodejs-f271e47bb428
42
+ * https://codahale.com/a-lesson-in-timing-attacks/
43
+ * https://github.com/suryagh/tsscmp/blob/master/lib/index.js
44
+ *
45
+ * Returns true if inputs are equal, false otherwise.
46
+ */
47
+ export declare function timingSafeStringEqual(s1: string | undefined, s2: string | undefined): boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encryptString = exports.decryptString = exports.encryptObject = exports.decryptObject = exports.decryptRandomIVBuffer = exports.encryptRandomIVBuffer = void 0;
3
+ exports.timingSafeStringEqual = exports.encryptString = exports.decryptString = exports.encryptObject = exports.decryptObject = exports.decryptRandomIVBuffer = exports.encryptRandomIVBuffer = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const node_crypto_1 = tslib_1.__importDefault(require("node:crypto"));
6
6
  const js_lib_1 = require("@naturalcycles/js-lib");
@@ -88,3 +88,21 @@ function getCryptoParams(secretKeyBuffer) {
88
88
  const iv = (0, hash_util_1.md5AsBuffer)(Buffer.concat([secretKeyBuffer, key]));
89
89
  return { key, iv };
90
90
  }
91
+ /**
92
+ * Wraps `crypto.timingSafeEqual` and allows it to be used with String inputs:
93
+ *
94
+ * 1. Does length check first and short-circuits on length mismatch. Because `crypto.timingSafeEqual` only works with same-length inputs.
95
+ *
96
+ * Relevant read:
97
+ * https://medium.com/nerd-for-tech/checking-api-key-without-shooting-yourself-in-the-foot-javascript-nodejs-f271e47bb428
98
+ * https://codahale.com/a-lesson-in-timing-attacks/
99
+ * https://github.com/suryagh/tsscmp/blob/master/lib/index.js
100
+ *
101
+ * Returns true if inputs are equal, false otherwise.
102
+ */
103
+ function timingSafeStringEqual(s1, s2) {
104
+ if (s1 === undefined || s2 === undefined || s1.length !== s2.length)
105
+ return false;
106
+ return node_crypto_1.default.timingSafeEqual(Buffer.from(s1), Buffer.from(s2));
107
+ }
108
+ exports.timingSafeStringEqual = timingSafeStringEqual;
@@ -10,7 +10,7 @@ const __1 = require("../..");
10
10
  * Zips output file automatically, if it ends with `.gz`.
11
11
  */
12
12
  async function ndjsonMap(mapper, opt) {
13
- const { inputFilePath, outputFilePath, logEveryOutput = 100000, limitInput, limitOutput } = opt;
13
+ const { inputFilePath, outputFilePath, logEveryOutput = 100_000, limitInput, limitOutput } = opt;
14
14
  (0, __1.requireFileToExist)(inputFilePath);
15
15
  console.log({
16
16
  inputFilePath,
@@ -14,7 +14,7 @@ const inspectOpt = {
14
14
  * Pass-through transform that optionally logs progress.
15
15
  */
16
16
  function transformLogProgress(opt = {}) {
17
- const { metric = 'progress', heapTotal: logHeapTotal = false, heapUsed: logHeapUsed = false, rss: logRss = true, peakRSS: logPeakRSS = true, logRPS = true, logEvery = 1000, logSizes = false, logSizesBuffer = 100000, logZippedSizes = false, batchSize = 1, extra, logger = console, } = opt;
17
+ const { metric = 'progress', heapTotal: logHeapTotal = false, heapUsed: logHeapUsed = false, rss: logRss = true, peakRSS: logPeakRSS = true, logRPS = true, logEvery = 1000, logSizes = false, logSizesBuffer = 100_000, logZippedSizes = false, batchSize = 1, extra, logger = console, } = opt;
18
18
  const logProgress = opt.logProgress !== false && logEvery !== 0; // true by default
19
19
  const logEvery10 = logEvery * 10;
20
20
  const started = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
- "version": "13.7.1",
3
+ "version": "13.8.0",
4
4
  "scripts": {
5
5
  "prepare": "husky install",
6
6
  "docs-serve": "vuepress dev docs",
@@ -35,7 +35,7 @@
35
35
  "yargs": "^17.0.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@naturalcycles/bench-lib": "^1.0.7",
38
+ "@naturalcycles/bench-lib": "^2.0.0",
39
39
  "@naturalcycles/dev-lib": "^13.0.0",
40
40
  "@types/node": "^20.1.0",
41
41
  "@types/yargs": "^16.0.0",
@@ -48,7 +48,7 @@ export function csvStringParse<T extends AnyObject = any>(
48
48
 
49
49
  return arr.map(row => {
50
50
  // eslint-disable-next-line unicorn/no-array-reduce
51
- return header!.reduce((obj, col, i) => {
51
+ return header.reduce((obj, col, i) => {
52
52
  ;(obj as any)[col] = row[i]
53
53
  return obj
54
54
  }, {} as T)
@@ -148,7 +148,7 @@ export function objectToShellExport(obj: AnyObject, prefix = ''): string {
148
148
  return (
149
149
  Object.entries(obj)
150
150
  .map(([k, v]) => {
151
- if (v) {
151
+ if (v !== undefined && v !== null) {
152
152
  return `export ${prefix}${k}="${v}"`
153
153
  }
154
154
  })
@@ -179,7 +179,7 @@ export function objectToGithubActionsEnv(obj: AnyObject, prefix = ''): string {
179
179
  return (
180
180
  Object.entries(obj)
181
181
  .map(([k, v]) => {
182
- if (v) {
182
+ if (v !== undefined && v !== null) {
183
183
  return `${prefix}${k}=${v}`
184
184
  }
185
185
  })
@@ -93,3 +93,20 @@ function getCryptoParams(secretKeyBuffer: Buffer): { key: Buffer; iv: Buffer } {
93
93
  const iv = md5AsBuffer(Buffer.concat([secretKeyBuffer, key]))
94
94
  return { key, iv }
95
95
  }
96
+
97
+ /**
98
+ * Wraps `crypto.timingSafeEqual` and allows it to be used with String inputs:
99
+ *
100
+ * 1. Does length check first and short-circuits on length mismatch. Because `crypto.timingSafeEqual` only works with same-length inputs.
101
+ *
102
+ * Relevant read:
103
+ * https://medium.com/nerd-for-tech/checking-api-key-without-shooting-yourself-in-the-foot-javascript-nodejs-f271e47bb428
104
+ * https://codahale.com/a-lesson-in-timing-attacks/
105
+ * https://github.com/suryagh/tsscmp/blob/master/lib/index.js
106
+ *
107
+ * Returns true if inputs are equal, false otherwise.
108
+ */
109
+ export function timingSafeStringEqual(s1: string | undefined, s2: string | undefined): boolean {
110
+ if (s1 === undefined || s2 === undefined || s1.length !== s2.length) return false
111
+ return crypto.timingSafeEqual(Buffer.from(s1), Buffer.from(s2))
112
+ }