luca 1.0.0 → 1.1.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Luca · [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/iZemil/luca/blob/main/LICENSE) ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/izemil/luca)
2
2
 
3
- Tiny [NodeJS package](https://www.npmjs.com/package/luca) to check urls by name list and getting statuses.
3
+ Tiny [NPM package](https://www.npmjs.com/package/luca) to check urls by name list and getting statuses.
4
4
 
5
5
  ## Installation
6
6
 
@@ -1,2 +1,2 @@
1
- export declare const getConfigPath: () => string;
2
- export declare const getResultPath: () => string;
1
+ export declare const CONFIG_PATH: string;
2
+ export declare const LOG_PATH: string;
@@ -23,9 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.getResultPath = exports.getConfigPath = void 0;
26
+ exports.LOG_PATH = exports.CONFIG_PATH = void 0;
27
27
  const path = __importStar(require("path"));
28
- const getConfigPath = () => path.resolve('luca.config.js');
29
- exports.getConfigPath = getConfigPath;
30
- const getResultPath = () => path.resolve('luca.result.json');
31
- exports.getResultPath = getResultPath;
28
+ exports.CONFIG_PATH = path.resolve('luca.config.js');
29
+ exports.LOG_PATH = path.resolve('luca.log');
@@ -0,0 +1,8 @@
1
+ export const delay: number;
2
+ export const baseUrl: string;
3
+ export function query(baseUrl: any, item: any): string;
4
+ export function handler(response: any, item: any): {
5
+ item: any;
6
+ data: any;
7
+ };
8
+ export const items: string[];
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ module.exports = {
3
+ delay: 500,
4
+ baseUrl: 'https://www.npmjs.com/package',
5
+ query: (baseUrl, item) => {
6
+ return `${baseUrl}/${item}`;
7
+ },
8
+ handler: (response, item) => {
9
+ return {
10
+ item,
11
+ data: response.data,
12
+ };
13
+ },
14
+ items: ['foo', 'bar'],
15
+ };
@@ -38,24 +38,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.initConfig = void 0;
39
39
  const chalk_1 = __importDefault(require("chalk"));
40
40
  const fs = __importStar(require("fs/promises"));
41
+ const path = __importStar(require("path"));
41
42
  const consts_1 = require("./consts");
42
43
  const initConfig = () => __awaiter(void 0, void 0, void 0, function* () {
43
44
  try {
44
- const config = (0, consts_1.getConfigPath)();
45
- yield fs.writeFile(config, `module.exports = {
46
- delay: 500,
47
- baseUrl: "https://www.npmjs.com/package",
48
- query: (baseUrl, item) => {
49
- return \`\${baseUrl}/\${item}\`;
50
- },
51
- handler: (response, item) => {
52
- return {
53
- status: response.status,
54
- };
55
- },
56
- items: ['foo', 'bar'],
57
- }`);
58
- console.log(chalk_1.default.green(`Configuration file was created:\n> ${config}`));
45
+ yield fs.copyFile(path.resolve('src/config/default.js'), consts_1.CONFIG_PATH);
46
+ console.log(chalk_1.default.green(`Configuration file was created:\n> ${consts_1.CONFIG_PATH}`));
59
47
  }
60
48
  catch (e) {
61
49
  console.error(e);
@@ -0,0 +1,2 @@
1
+ import { TConfig } from './types';
2
+ export declare const openConfig: () => TConfig;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.openConfig = void 0;
4
+ const utils_1 = require("../utils");
5
+ const consts_1 = require("./consts");
6
+ const openConfig = () => {
7
+ if (!(0, utils_1.checkPath)(consts_1.CONFIG_PATH)) {
8
+ throw new Error(`Config not found`);
9
+ }
10
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
11
+ const config = require(consts_1.CONFIG_PATH);
12
+ const { baseUrl, items, query, handler } = config;
13
+ if (items.length === 0) {
14
+ throw new Error(`Specify config items, eg: items: ["foo", "bar"]`);
15
+ }
16
+ if (!baseUrl) {
17
+ throw new Error(`Specify config baseUrl`);
18
+ }
19
+ if (!handler) {
20
+ throw new Error(`Specify config handler`);
21
+ }
22
+ return config;
23
+ };
24
+ exports.openConfig = openConfig;
@@ -1,2 +1,3 @@
1
- import { TConfig } from './types';
2
- export declare const runConfig: (options?: TConfig) => Promise<void>;
1
+ import { AxiosError } from 'axios';
2
+ export declare function isAxiosError(error: any): error is AxiosError;
3
+ export declare const runConfig: () => Promise<void>;
@@ -35,60 +35,80 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.runConfig = void 0;
38
+ exports.runConfig = exports.isAxiosError = void 0;
39
39
  const axios_1 = __importDefault(require("axios"));
40
40
  const chalk_1 = __importDefault(require("chalk"));
41
41
  const fs = __importStar(require("fs/promises"));
42
42
  const utils_1 = require("../utils");
43
43
  const consts_1 = require("./consts");
44
- const validateConfig_1 = require("./validateConfig");
44
+ const openConfig_1 = require("./openConfig");
45
45
  function isAxiosError(error) {
46
46
  if ('response' in error) {
47
47
  return true;
48
48
  }
49
49
  return false;
50
50
  }
51
+ exports.isAxiosError = isAxiosError;
51
52
  const log = console.log;
52
- const runConfig = (options = require((0, consts_1.getConfigPath)())) => __awaiter(void 0, void 0, void 0, function* () {
53
- const resultPath = (0, consts_1.getResultPath)();
53
+ const ONE_MINUTE = 60 * 1000;
54
+ const handleRequest = (options) => __awaiter(void 0, void 0, void 0, function* () {
55
+ const { url, num, total, sleepDelay = ONE_MINUTE, sleepCount = 0 } = options;
56
+ let response = null;
57
+ let isErroredRequest = false;
54
58
  try {
55
- (0, validateConfig_1.validateConfig)(options);
59
+ response = yield axios_1.default.get(url);
60
+ }
61
+ catch (e) {
62
+ isErroredRequest = true;
63
+ if (isAxiosError(e) && e.response) {
64
+ response = e.response;
65
+ }
66
+ }
67
+ finally {
68
+ log(chalk_1.default.blue(`${num}/${total}`), `GET ${chalk_1.default[isErroredRequest ? 'red' : 'green'](`(${response === null || response === void 0 ? void 0 : response.status})`)}:`, url);
69
+ }
70
+ // Handle: Too Many Requests
71
+ if (sleepCount > 3) {
72
+ throw new Error(`Exceeded ${sleepCount} requests`);
73
+ }
74
+ if (response && response.status === 429) {
75
+ log(chalk_1.default.grey(`sleep...`));
76
+ yield (0, utils_1.wait)(sleepDelay);
77
+ return handleRequest(Object.assign(Object.assign({}, options), { sleepDelay: sleepDelay + ONE_MINUTE, sleepCount: sleepCount + 1 }));
78
+ }
79
+ return response;
80
+ });
81
+ const writeToLog = (...strs) => __awaiter(void 0, void 0, void 0, function* () {
82
+ yield fs.appendFile(consts_1.LOG_PATH, '\n' + strs.join('\n'));
83
+ });
84
+ // TODO: run from last log element
85
+ const runConfig = () => __awaiter(void 0, void 0, void 0, function* () {
86
+ try {
87
+ const config = (0, openConfig_1.openConfig)();
88
+ const { baseUrl, items, query } = config;
56
89
  log(chalk_1.default.blue('Luca is running...'));
57
- const { baseUrl, items, query, handler } = options;
90
+ yield writeToLog('Start session', `time: ${new Date()}`);
58
91
  const total = items.length;
59
92
  let index = 0;
60
93
  for (const item of items) {
94
+ const num = (index += 1);
61
95
  const url = query(baseUrl, item);
62
- let status = undefined;
63
- let response = null;
64
- try {
65
- response = (yield axios_1.default.get(url));
66
- status = response.status;
67
- }
68
- catch (e) {
69
- if (isAxiosError(e) && e.response) {
70
- status = e.response.status;
71
- }
72
- }
73
- log(chalk_1.default.blue(`${index + 1}/${total}`), `GET ${url} (${status})`);
74
96
  try {
75
- const data = handler(response, item);
76
- const isFirst = index === 0;
77
- const isLast = index + 1 === total;
78
- yield fs.appendFile(resultPath, `${isFirst ? '[' : ''}${JSON.stringify(data)}${isLast ? ']' : ','}`);
97
+ const response = yield handleRequest({ url, num, total });
98
+ yield writeToLog(`\nurl: ${url}`, `status: ${response === null || response === void 0 ? void 0 : response.status}`, `data: ${response ? JSON.stringify(config.handler(response, item)) : null}`);
79
99
  }
80
100
  catch (error) {
81
101
  console.error('handler error', error);
82
102
  }
83
103
  finally {
84
- index += 1;
85
- yield (0, utils_1.delay)(options.delay);
104
+ yield (0, utils_1.wait)(config.delay);
86
105
  }
87
106
  }
88
- log(chalk_1.default.green(`Finished:\n> ${resultPath}`));
107
+ log(chalk_1.default.green(`Finished:\n> ${consts_1.LOG_PATH}`));
108
+ writeToLog(`\nEnd session`, `time: ${new Date()}`, '');
89
109
  }
90
110
  catch (e) {
91
- console.error(e);
111
+ log(chalk_1.default.red(e));
92
112
  }
93
113
  });
94
114
  exports.runConfig = runConfig;
@@ -6,3 +6,7 @@ export interface TConfig<T = unknown> {
6
6
  query: (baseUrl: string, item: T) => string;
7
7
  handler: (response: AxiosResponse | null, item: T) => any;
8
8
  }
9
+ export interface THandledData<T = unknown> {
10
+ status: number | null;
11
+ data: T | null;
12
+ }
@@ -1,2 +1,2 @@
1
- export declare function isDir(path: string): boolean;
2
- export declare const delay: (ms: number) => Promise<unknown>;
1
+ export declare function checkPath(path: string, isDir?: boolean): boolean;
2
+ export declare const wait: (ms: number) => Promise<unknown>;
@@ -32,18 +32,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
32
32
  });
33
33
  };
34
34
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.delay = exports.isDir = void 0;
35
+ exports.wait = exports.checkPath = void 0;
36
36
  const fs = __importStar(require("fs"));
37
- function isDir(path) {
37
+ function checkPath(path, isDir = false) {
38
38
  try {
39
39
  const stat = fs.lstatSync(path);
40
- return stat.isDirectory();
40
+ if (isDir) {
41
+ return stat.isDirectory();
42
+ }
43
+ return stat.isFile();
41
44
  }
42
45
  catch (_a) {
43
46
  // lstatSync throws an error if path doesn't exist
44
47
  return false;
45
48
  }
46
49
  }
47
- exports.isDir = isDir;
48
- const delay = (ms) => __awaiter(void 0, void 0, void 0, function* () { return new Promise((res) => setTimeout(res, ms)); });
49
- exports.delay = delay;
50
+ exports.checkPath = checkPath;
51
+ const wait = (ms) => __awaiter(void 0, void 0, void 0, function* () { return new Promise((res) => setTimeout(res, ms)); });
52
+ exports.wait = wait;
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "dist"
17
17
  ],
18
18
  "license": "MIT",
19
- "version": "1.0.0",
19
+ "version": "1.1.0",
20
20
  "scripts": {
21
21
  "build": "tsc",
22
22
  "dev": "tsc-watch ./src/dev.ts --outDir ./dist/ --onSuccess \"node ./dist/dev.js\" --esModuleInterop",
@@ -1,2 +0,0 @@
1
- import { TConfig } from './types';
2
- export declare const validateConfig: (config: TConfig) => void;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateConfig = void 0;
4
- const validateConfig = (config) => {
5
- const { baseUrl, items, query, handler } = config;
6
- if (items.length === 0) {
7
- throw new Error(`Specify config items, eg: items: ["foo", "bar"]`);
8
- }
9
- if (!baseUrl) {
10
- throw new Error(`Specify config baseUrl`);
11
- }
12
- if (!handler) {
13
- throw new Error(`Specify config handler`);
14
- }
15
- };
16
- exports.validateConfig = validateConfig;