luca 1.0.1 → 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.
@@ -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;
@@ -1,7 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateConfig = void 0;
4
- const validateConfig = (config) => {
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);
5
12
  const { baseUrl, items, query, handler } = config;
6
13
  if (items.length === 0) {
7
14
  throw new Error(`Specify config items, eg: items: ["foo", "bar"]`);
@@ -14,4 +21,4 @@ const validateConfig = (config) => {
14
21
  }
15
22
  return config;
16
23
  };
17
- exports.validateConfig = validateConfig;
24
+ exports.openConfig = openConfig;
@@ -1,4 +1,3 @@
1
1
  import { AxiosError } from 'axios';
2
- import { TConfig } from './types';
3
2
  export declare function isAxiosError(error: any): error is AxiosError;
4
- export declare const runConfig: (options?: TConfig) => Promise<void>;
3
+ export declare const runConfig: () => Promise<void>;
@@ -41,7 +41,7 @@ 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;
@@ -50,52 +50,65 @@ function isAxiosError(error) {
50
50
  }
51
51
  exports.isAxiosError = isAxiosError;
52
52
  const log = console.log;
53
- // TODO: error retry
54
- // TODO: run from last element
55
- // TODO: clear result
56
- // TODO: validat config - no config
57
- const runConfig = (options = require((0, consts_1.getConfigPath)())) => __awaiter(void 0, void 0, void 0, function* () {
58
- 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;
59
58
  try {
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;
60
89
  log(chalk_1.default.blue('Luca is running...'));
61
- const config = (0, validateConfig_1.validateConfig)(options);
62
- const { baseUrl, items, query, handler } = config;
90
+ yield writeToLog('Start session', `time: ${new Date()}`);
63
91
  const total = items.length;
64
92
  let index = 0;
65
93
  for (const item of items) {
66
94
  const num = (index += 1);
67
- const isFirst = num === 1;
68
- const isLast = num === total;
69
95
  const url = query(baseUrl, item);
70
- let response = null;
71
- let isErroredRequest = false;
72
- try {
73
- response = yield axios_1.default.get(url);
74
- }
75
- catch (e) {
76
- isErroredRequest = true;
77
- if (isAxiosError(e) && e.response) {
78
- response = e.response;
79
- }
80
- }
81
- finally {
82
- log(chalk_1.default.blue(`${num}/${total}`), `GET ${chalk_1.default[isErroredRequest ? 'red' : 'green'](`(${response === null || response === void 0 ? void 0 : response.status})`)}:`, url);
83
- }
84
96
  try {
85
- const data = handler(response, item);
86
- 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}`);
87
99
  }
88
100
  catch (error) {
89
101
  console.error('handler error', error);
90
102
  }
91
103
  finally {
92
- yield (0, utils_1.delay)(options.delay);
104
+ yield (0, utils_1.wait)(config.delay);
93
105
  }
94
106
  }
95
- 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()}`, '');
96
109
  }
97
110
  catch (e) {
98
- console.error(e);
111
+ log(chalk_1.default.red(e));
99
112
  }
100
113
  });
101
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.1",
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) => TConfig;