@youcan/cli 1.0.0 → 1.0.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.
Files changed (62) hide show
  1. package/dist/cli/commands/auth/login.js +105 -0
  2. package/dist/cli/commands/auth/logout.js +20 -0
  3. package/dist/cli/commands/index.js +8 -0
  4. package/dist/cli/commands/theme/delete.js +43 -0
  5. package/dist/cli/commands/theme/dev.js +190 -0
  6. package/dist/cli/commands/theme/init.js +85 -0
  7. package/dist/cli/commands/theme/pull.js +54 -0
  8. package/dist/cli/index.js +51 -0
  9. package/dist/config/index.js +25 -0
  10. package/dist/config/messages.js +26 -0
  11. package/dist/core/client/client.js +65 -0
  12. package/dist/core/themes/preview.js +33 -0
  13. package/dist/index.js +3 -0
  14. package/dist/lib/cli/commands/auth/login.d.ts +2 -0
  15. package/dist/lib/cli/commands/auth/logout.d.ts +2 -0
  16. package/dist/lib/cli/commands/auth/types.d.ts +6 -0
  17. package/dist/lib/cli/commands/index.d.ts +6 -0
  18. package/dist/lib/cli/commands/theme/delete.d.ts +2 -0
  19. package/dist/lib/cli/commands/theme/dev.d.ts +2 -0
  20. package/dist/lib/cli/commands/theme/init.d.ts +2 -0
  21. package/dist/lib/cli/commands/theme/pull.d.ts +2 -0
  22. package/dist/lib/cli/commands/theme/types.d.ts +17 -0
  23. package/dist/lib/cli/commands/types.d.ts +22 -0
  24. package/dist/lib/cli/index.d.ts +12 -0
  25. package/dist/lib/config/index.d.ts +21 -0
  26. package/dist/lib/config/messages.d.ts +25 -0
  27. package/dist/lib/core/client/client.d.ts +17 -0
  28. package/dist/lib/core/client/types.d.ts +52 -0
  29. package/dist/lib/core/themes/preview.d.ts +1 -0
  30. package/dist/lib/index.d.ts +1 -0
  31. package/dist/lib/utils/common.d.ts +21 -0
  32. package/dist/lib/utils/git/cloneRepository.d.ts +6 -0
  33. package/dist/lib/utils/helpers.d.ts +3 -0
  34. package/dist/lib/utils/http.d.ts +11 -0
  35. package/dist/lib/utils/network.d.ts +2 -0
  36. package/dist/lib/utils/system/deleteFile.d.ts +5 -0
  37. package/dist/lib/utils/system/openLink.d.ts +1 -0
  38. package/dist/lib/utils/system/saveFile.d.ts +1 -0
  39. package/dist/lib/utils/system/stdout.d.ts +18 -0
  40. package/dist/lib/utils/system/writeToFile.d.ts +6 -0
  41. package/dist/lib/utils/system/zipFolder.d.ts +4 -0
  42. package/dist/lib/utils/system.d.ts +1 -0
  43. package/dist/test/commands/auth/login.d.ts +2 -0
  44. package/dist/test/commands/auth/logout.d.ts +2 -0
  45. package/dist/test/commands/help.d.ts +2 -0
  46. package/dist/test/commands/theme/delete.d.ts +2 -0
  47. package/dist/test/commands/theme/dev.d.ts +2 -0
  48. package/dist/test/commands/theme/init.d.ts +2 -0
  49. package/dist/test/index.test.d.ts +1 -0
  50. package/dist/utils/common.js +57 -0
  51. package/dist/utils/git/cloneRepository.js +18 -0
  52. package/dist/utils/helpers.js +32 -0
  53. package/dist/utils/http.js +25 -0
  54. package/dist/utils/network.js +76 -0
  55. package/dist/utils/system/deleteFile.js +12 -0
  56. package/dist/utils/system/openLink.js +15 -0
  57. package/dist/utils/system/saveFile.js +9 -0
  58. package/dist/utils/system/stdout.js +15 -0
  59. package/dist/utils/system/writeToFile.js +12 -0
  60. package/dist/utils/system/zipFolder.js +32 -0
  61. package/dist/utils/system.js +17 -0
  62. package/package.json +1 -1
@@ -0,0 +1,65 @@
1
+ import { FormData } from 'formdata-node';
2
+ import { mergeDeepLeft } from 'ramda';
3
+ import fetch from 'node-fetch';
4
+ import { post, get } from '../../utils/http.js';
5
+ import config from '../../config/index.js';
6
+ import { delay } from '../../utils/common.js';
7
+
8
+ class Client {
9
+ constructor() {
10
+ this.accessToken = null;
11
+ }
12
+ setAccessToken(token) {
13
+ this.accessToken = token;
14
+ }
15
+ getAccessToken() {
16
+ return this.accessToken;
17
+ }
18
+ isAuthenticated() {
19
+ return this.accessToken != null;
20
+ }
21
+ async initTheme(data) {
22
+ const form = new FormData();
23
+ Object.entries(data).forEach(([key, value]) => form.append(key, value));
24
+ const { id } = await post(`${config.SELLER_AREA_API_BASE_URI}/themes/init`, this.withDefaults({ body: form }));
25
+ return id;
26
+ }
27
+ async getThemeMeta(themeId) {
28
+ return await get(`${config.SELLER_AREA_API_BASE_URI}/themes/${themeId}/metadata`, this.withDefaults({}));
29
+ }
30
+ async pullTheme(themeId) {
31
+ return await fetch(`${config.SELLER_AREA_API_BASE_URI}/themes/${themeId}`, this.withDefaults({}));
32
+ }
33
+ async listThemes() {
34
+ return await get(`${config.SELLER_AREA_API_BASE_URI}/themes`, this.withDefaults({}));
35
+ }
36
+ async deleteTheme(themeId) {
37
+ return await post(`${config.SELLER_AREA_API_BASE_URI}/themes/${themeId}/delete`, this.withDefaults({}));
38
+ }
39
+ async updateFile(themeId, data) {
40
+ const form = new FormData();
41
+ Object.entries(data).forEach(([key, value]) => form.append(key, value));
42
+ await post(`${config.SELLER_AREA_API_BASE_URI}/themes/${themeId}/update`, this.withDefaults({ body: form }));
43
+ await delay(100);
44
+ }
45
+ async deleteFile(themeId, data) {
46
+ const form = new FormData();
47
+ Object.entries(data).forEach(([key, value]) => form.append(key, value));
48
+ await post(`${config.SELLER_AREA_API_BASE_URI}/themes/${themeId}/update`, this.withDefaults({ body: form }));
49
+ await delay(100);
50
+ }
51
+ async getStoreInfo() {
52
+ return await get(`${config.SELLER_AREA_API_BASE_URI}/me`, this.withDefaults());
53
+ }
54
+ withDefaults(override = {}) {
55
+ return mergeDeepLeft(override, {
56
+ headers: {
57
+ Accept: 'application/json',
58
+ Authorization: `Bearer ${this.accessToken}`,
59
+ },
60
+ hostname: config.SELLER_AREA_API_BASE_URI,
61
+ });
62
+ }
63
+ }
64
+
65
+ export { Client as default };
@@ -0,0 +1,33 @@
1
+ import { createServer } from 'http';
2
+ import { Server } from 'socket.io';
3
+ import puppeteer from 'puppeteer';
4
+ import stdout from '../../utils/system/stdout.js';
5
+ import config from '../../config/index.js';
6
+
7
+ async function openPreviewPage(url) {
8
+ const browser = await puppeteer.launch({
9
+ headless: false,
10
+ defaultViewport: null,
11
+ userDataDir: '/tmp/youcan_puppeteer',
12
+ });
13
+ browser.on('disconnected', () => {
14
+ stdout.info('Browser closed');
15
+ return process.exit(0);
16
+ });
17
+ const page = await browser.newPage();
18
+ await page.goto(url);
19
+ return page;
20
+ }
21
+ async function previewTheme(url) {
22
+ const httpServer = createServer();
23
+ const io = new Server(httpServer);
24
+ const previewPage = await openPreviewPage(url);
25
+ io.on('connection', (socket) => {
26
+ socket.on('theme:update', async () => {
27
+ await previewPage.reload({ waitUntil: 'domcontentloaded' });
28
+ });
29
+ });
30
+ httpServer.listen(config.PREVIEW_SERVER_PORT);
31
+ }
32
+
33
+ export { previewTheme as default };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import cli from './cli/index.js';
2
+
3
+ cli.init();
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '@/cli/commands/types';
2
+ export default function command(_cli: CLI): CommandDefinition;
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '@/cli/commands/types';
2
+ export default function command(cli: CLI): CommandDefinition;
@@ -0,0 +1,6 @@
1
+ export interface TokenResponse {
2
+ token_type: string;
3
+ expires_in: string;
4
+ access_token: string;
5
+ refresh_toekn: string;
6
+ }
@@ -0,0 +1,6 @@
1
+ export { default as LoginCommand } from './auth/login';
2
+ export { default as LogoutCommand } from './auth/logout';
3
+ export { default as InitCommand } from './theme/init';
4
+ export { default as DevCommand } from './theme/dev';
5
+ export { default as DeleteCommand } from './theme/delete';
6
+ export { default as PullCommand } from './theme/pull';
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '@/cli/commands/types';
2
+ export default function command(cli: CLI): CommandDefinition;
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '../types';
2
+ export default function command(cli: CLI): CommandDefinition;
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '@/cli/commands/types';
2
+ export default function command(cli: CLI): CommandDefinition;
@@ -0,0 +1,2 @@
1
+ import type { CLI, CommandDefinition } from '../types';
2
+ export default function command(cli: CLI): CommandDefinition;
@@ -0,0 +1,17 @@
1
+ export interface FileEventOptions {
2
+ path: string;
3
+ size: number;
4
+ roundtrip: number;
5
+ event: string;
6
+ }
7
+ export interface ThemeMetaData {
8
+ id: string;
9
+ name: string;
10
+ size: number;
11
+ version: string;
12
+ live: boolean;
13
+ }
14
+ export interface listThemesResponse {
15
+ dev: ThemeMetaData[];
16
+ published: ThemeMetaData[];
17
+ }
@@ -0,0 +1,22 @@
1
+ import type { CAC } from 'cac';
2
+ import type Client from '@/core/client/client';
3
+ export interface CommandOptionDefinition {
4
+ name: string;
5
+ description: string;
6
+ config?: {
7
+ default?: any;
8
+ type?: any[];
9
+ };
10
+ }
11
+ export interface CommandDefinition {
12
+ name: string;
13
+ group: string;
14
+ aliases?: string[];
15
+ description: string;
16
+ action: ReturnType<any>;
17
+ options?: CommandOptionDefinition[];
18
+ }
19
+ export interface CLI {
20
+ handler: CAC;
21
+ client: Client;
22
+ }
@@ -0,0 +1,12 @@
1
+ import * as commands from './commands';
2
+ import type { CommandDefinition } from './commands/types';
3
+ import Client from '@/core/client/client';
4
+ declare const cli: {
5
+ client: Client;
6
+ handler: import("cac").CAC;
7
+ registerCommand(command: (cli: typeof this) => CommandDefinition): void;
8
+ getAvailableCommands(): (typeof commands.LoginCommand | typeof commands.LogoutCommand | typeof commands.InitCommand | typeof commands.DevCommand | typeof commands.DeleteCommand | typeof commands.PullCommand)[];
9
+ init(): Promise<void>;
10
+ prepareClient(): Promise<void>;
11
+ };
12
+ export default cli;
@@ -0,0 +1,21 @@
1
+ declare const _default: {
2
+ OAUTH_CLIENT_ID: number;
3
+ OAUTH_CALLBACK_PORT: number;
4
+ OAUTH_CALLBACK_SERVER_TIMEOUT: number;
5
+ OAUTH_CALLBACK_URL: string;
6
+ OAUTH_CLIENT_SECRET: string;
7
+ OAUTH_AUTH_CODE_URL: string;
8
+ OAUTH_ACCESS_TOKEN_URL: string;
9
+ SELLER_AREA_API_BASE_URI: string;
10
+ SELLER_AREA_WEB_BASE_URI: string;
11
+ STARTER_THEME_GIT_REPOSITORY: string;
12
+ AVAILABLE_THEMES: {
13
+ name: string;
14
+ repository: string;
15
+ }[];
16
+ CLI_GLOBAL_CONFIG_DIR: string;
17
+ CLI_GLOBAL_CONFIG_PATH: string;
18
+ THEME_FILE_TYPES: string[];
19
+ PREVIEW_SERVER_PORT: number;
20
+ };
21
+ export default _default;
@@ -0,0 +1,25 @@
1
+ declare const _default: {
2
+ LOGIN_OPEN_LINK: string;
3
+ LOGIN_SUCCESS: string;
4
+ INIT_SUCCESS: string;
5
+ INIT_CLONE_START: string;
6
+ AUTH_USER_NOT_LOGGED_IN: string;
7
+ AUTH_USER_LOGGED_OUT: string;
8
+ DELETE_NO_THEME_SELECTED: string;
9
+ DELETE_THEME_DELETED: string;
10
+ DELETE_NO_REMOTE_THEMES: string;
11
+ DELETE_SELECT_THEME: string;
12
+ DELETE_IN_PROGRESS: string;
13
+ DELETE_ERROR: string;
14
+ DEV_PREVIEW_SERVER_CONNECTED: string;
15
+ DEV_WATCHING_FILES: string;
16
+ DEV_NO_THEME_DETECTED: string;
17
+ PULL_NO_THEME_FOUND: string;
18
+ PULL_PULLING_THEME: string;
19
+ PULL_UNPACKING_THEME: string;
20
+ PULL_THEME_PULLED: string;
21
+ PREVIEW_BROWSER_CLOSED: string;
22
+ PREVIEW_THEME_UPDATED: string;
23
+ PREVIEW_RELOADED: string;
24
+ };
25
+ export default _default;
@@ -0,0 +1,17 @@
1
+ import type { DeleteThemeFileRequestData, InitThemeRequest as InitThemeRequestData, StoreInfoResponse, ThemeMetaResponse, UpdateThemeFileRequestData } from './types';
2
+ export default class Client {
3
+ private accessToken;
4
+ constructor();
5
+ setAccessToken(token: string): void;
6
+ getAccessToken(): string | null;
7
+ isAuthenticated(): boolean;
8
+ initTheme(data: InitThemeRequestData): Promise<string>;
9
+ getThemeMeta(themeId: string): Promise<ThemeMetaResponse>;
10
+ pullTheme(themeId: string): Promise<import("node-fetch").Response>;
11
+ listThemes(): Promise<unknown>;
12
+ deleteTheme(themeId: string): Promise<unknown>;
13
+ updateFile(themeId: string, data: UpdateThemeFileRequestData): Promise<void>;
14
+ deleteFile(themeId: string, data: DeleteThemeFileRequestData): Promise<void>;
15
+ getStoreInfo(): Promise<StoreInfoResponse>;
16
+ private withDefaults;
17
+ }
@@ -0,0 +1,52 @@
1
+ import type { File } from 'formdata-node';
2
+ export interface InitThemeRequest {
3
+ archive: File;
4
+ theme_name: string;
5
+ theme_author: string;
6
+ theme_version: string;
7
+ theme_support_url: string;
8
+ theme_documentation_url: string;
9
+ }
10
+ export interface UpdateThemeFileRequestData {
11
+ file_type: string;
12
+ file_name: string;
13
+ file_content: File;
14
+ file_operation: 'save';
15
+ }
16
+ export interface DeleteThemeFileRequestData {
17
+ file_type: string;
18
+ file_name: string;
19
+ file_operation: 'delete';
20
+ }
21
+ export interface InitThemeResponse {
22
+ id: string;
23
+ }
24
+ export interface StoreInfoResponse {
25
+ name: string;
26
+ slug: string;
27
+ domain: string;
28
+ }
29
+ export interface ThemeFileInfo {
30
+ id: string;
31
+ type: string;
32
+ name: string;
33
+ file_name: string;
34
+ updated: boolean;
35
+ deleted: boolean;
36
+ size: number;
37
+ hash: string;
38
+ }
39
+ export interface ThemeMetaResponse {
40
+ theme_name: string;
41
+ theme_author: string;
42
+ theme_version: string;
43
+ theme_support_url: string;
44
+ theme_documentation_url: string;
45
+ config: ThemeFileInfo[];
46
+ layout: ThemeFileInfo[];
47
+ sections: ThemeFileInfo[];
48
+ templates: ThemeFileInfo[];
49
+ locales: ThemeFileInfo[];
50
+ snippets: ThemeFileInfo[];
51
+ assets: ThemeFileInfo[];
52
+ }
@@ -0,0 +1 @@
1
+ export default function previewTheme(url: string): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import type { PathLike } from 'fs';
4
+ export declare const homeDir: string;
5
+ /**
6
+ * Get youcan token from $HOME/.youcan file
7
+ * @returns string - youcan token
8
+ */
9
+ export declare function getUserToken(): Promise<string>;
10
+ export declare function getCurrentThemeId(dir: PathLike): Promise<string | null>;
11
+ export declare class LoadingSpinner {
12
+ private message;
13
+ timer: NodeJS.Timer | null;
14
+ constructor(message: string);
15
+ start(): this;
16
+ private flush;
17
+ stop(): this;
18
+ error(message?: string | null): this;
19
+ static exec(message: string, closure: (spinner: LoadingSpinner) => Promise<void>): Promise<void>;
20
+ }
21
+ export declare function delay(ms: number): Promise<void>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Clone a git repository
3
+ * @param url - URL to open
4
+ * @param folder
5
+ */
6
+ export default function cloneRepository(url: string, folder: string): boolean;
@@ -0,0 +1,3 @@
1
+ export declare function stripln(buffer: string, ln: number): string;
2
+ export declare function splitln(buffer: string, limit: number): string[];
3
+ export declare function getcols(buffer: string, indices: number[], limit?: number | null): string[][];
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" />
2
+ import { Agent } from 'https';
3
+ import type { RequestInit } from 'node-fetch';
4
+ export declare const DEFAULT_HTTP_CLIENT_OPTIONS: {
5
+ headers: {
6
+ Accept: string;
7
+ };
8
+ agent: Agent;
9
+ };
10
+ export declare function get<T>(endpoint: string, options?: RequestInit): Promise<T>;
11
+ export declare function post<T>(endpoint: string, options?: RequestInit): Promise<T>;
@@ -0,0 +1,2 @@
1
+ export declare function isPortAvailable(port: string | number): Promise<boolean>;
2
+ export declare function getPidByPort(port: number | string): Promise<number | null>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param filePath - The path of the file to delete.
3
+ *
4
+ */
5
+ export default function deleteFile(filePath: string): void;
@@ -0,0 +1 @@
1
+ export default function openLink(url: string): void;
@@ -0,0 +1 @@
1
+ export declare function saveHttpFile(res: any, filename: string): Promise<void>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Print to standard output with meaningful colors
3
+ */
4
+ declare function log(arg: string): void;
5
+ declare function info(arg: string): void;
6
+ declare function warn(arg: string): void;
7
+ declare function error(arg: string): void;
8
+ declare function success(arg: string): void;
9
+ declare function clear(): void;
10
+ declare const _default: {
11
+ log: typeof log;
12
+ info: typeof info;
13
+ warn: typeof warn;
14
+ error: typeof error;
15
+ clear: typeof clear;
16
+ success: typeof success;
17
+ };
18
+ export default _default;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @param filePath - The path to the file to write to.
3
+ * @param content - The content to write to the file.
4
+ * @returns A promise that resolves when the file has been written.
5
+ */
6
+ export default function writeToFile(filePath: string, content: string): void;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Zip folder and save it to a given path and return zip folder path
3
+ */
4
+ export default function zipFolder(folderPath: string, folderName: string): Promise<string>;
@@ -0,0 +1 @@
1
+ export declare const kill: (pid: number, signal?: string, timeout?: number) => Promise<void>;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import os from 'os';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import kleur from 'kleur';
5
+
6
+ os.homedir();
7
+ async function getCurrentThemeId(dir) {
8
+ const filepath = path.resolve(dir.toString(), '.youcan');
9
+ if (!fs.existsSync(filepath))
10
+ return null;
11
+ return await fs.promises.readFile(filepath, 'utf-8')
12
+ .then(b => JSON.parse(b).theme_id);
13
+ }
14
+ class LoadingSpinner {
15
+ constructor(message) {
16
+ this.message = message;
17
+ this.message = message;
18
+ this.timer = null;
19
+ }
20
+ start() {
21
+ process.stdout.write('\x1B[?25l');
22
+ const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
23
+ let i = 0;
24
+ this.timer = setInterval(() => {
25
+ process.stdout.write(`\r${frames[i = ++i % frames.length]} ${this.message}`);
26
+ }, 100);
27
+ return this;
28
+ }
29
+ flush() {
30
+ if (this.timer) {
31
+ clearInterval(this.timer);
32
+ this.timer = null;
33
+ }
34
+ }
35
+ stop() {
36
+ this.flush();
37
+ process.stdout.write('\r');
38
+ process.stdout.write(kleur.green(`✔ ${this.message}\n`));
39
+ return this;
40
+ }
41
+ error(message = null) {
42
+ this.flush();
43
+ process.stdout.write('\r');
44
+ process.stdout.write(kleur.red(`✖ ${message !== null && message !== void 0 ? message : this.message}\n`));
45
+ return this;
46
+ }
47
+ static async exec(message, closure) {
48
+ const spinner = new LoadingSpinner(message).start();
49
+ await closure(spinner);
50
+ spinner.timer && spinner.stop();
51
+ }
52
+ }
53
+ function delay(ms) {
54
+ return new Promise(resolve => setTimeout(resolve, ms));
55
+ }
56
+
57
+ export { LoadingSpinner, delay, getCurrentThemeId };
@@ -0,0 +1,18 @@
1
+ import { execSync } from 'child_process';
2
+
3
+ /**
4
+ * Clone a git repository
5
+ * @param url - URL to open
6
+ * @param folder
7
+ */
8
+ function cloneRepository(url, folder) {
9
+ try {
10
+ execSync(`git clone '${url}' '${folder}'`);
11
+ return true;
12
+ }
13
+ catch (error) {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ export { cloneRepository as default };
@@ -0,0 +1,32 @@
1
+ function stripln(buffer, ln) {
2
+ let index = 0;
3
+ while (ln-- > 0) {
4
+ const lfIndex = buffer.indexOf('\n', index);
5
+ if (lfIndex >= 0)
6
+ index = lfIndex + 1;
7
+ }
8
+ return index > 0 ? buffer.substring(index) : buffer;
9
+ }
10
+ function splitln(buffer, limit) {
11
+ const cols = buffer.trim().split(/\s+/);
12
+ if (cols.length > limit)
13
+ cols[limit - 1] = cols.slice(limit - 1).join(' ');
14
+ return cols;
15
+ }
16
+ function getcols(buffer, indices, limit = null) {
17
+ const lines = buffer.split(/(\r\n|\n|\r)/);
18
+ const cols = [];
19
+ if (!limit)
20
+ limit = Math.max.apply(null, indices) + 1;
21
+ lines.forEach((ln) => {
22
+ const lncols = splitln(ln, limit);
23
+ const lncol = [];
24
+ indices.forEach((index) => {
25
+ lncol.push(lncols[index] || '');
26
+ });
27
+ cols.push(lncol);
28
+ });
29
+ return cols;
30
+ }
31
+
32
+ export { getcols, splitln, stripln };
@@ -0,0 +1,25 @@
1
+ import { Agent } from 'https';
2
+ import fetch from 'node-fetch';
3
+ import { mergeDeepLeft } from 'ramda';
4
+
5
+ const HttpsAgent = new Agent({ keepAlive: true, keepAliveMsecs: 5 * 60 * 1000 });
6
+ const DEFAULT_HTTP_CLIENT_OPTIONS = {
7
+ headers: {
8
+ Accept: 'application/json',
9
+ },
10
+ agent: HttpsAgent,
11
+ };
12
+ async function request(endpoint, options = {}) {
13
+ const response = await fetch(endpoint, mergeDeepLeft(options, DEFAULT_HTTP_CLIENT_OPTIONS));
14
+ if (!response.ok)
15
+ throw new Error(await response.text(), { cause: response });
16
+ return response.json();
17
+ }
18
+ async function get(endpoint, options = {}) {
19
+ return request(endpoint, { ...options, method: 'GET' });
20
+ }
21
+ async function post(endpoint, options = {}) {
22
+ return request(endpoint, { ...options, method: 'POST' });
23
+ }
24
+
25
+ export { DEFAULT_HTTP_CLIENT_OPTIONS, get, post };