@basis-theory-labs/cli 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.
package/README.md ADDED
@@ -0,0 +1,55 @@
1
+ Basis Theory CLI
2
+ =================
3
+
4
+ Basis Theory CLI tool
5
+
6
+ Make sure to either have a `BT_MANAGEMENT_KEY` env var exported or pass a `management-key` flag to the commands.
7
+
8
+ <!-- toc -->
9
+ * [Usage](#usage)
10
+ * [Commands](#commands)
11
+ <!-- tocstop -->
12
+ # Usage
13
+ <!-- usage -->
14
+ ```sh-session
15
+ $ npm install -g @basis-theory-labs/cli
16
+ $ bt COMMAND
17
+ running command...
18
+ $ bt (--version)
19
+ @basis-theory-labs/cli/1.0.1 linux-x64 node-v18.16.0
20
+ $ bt --help [COMMAND]
21
+ USAGE
22
+ $ bt COMMAND
23
+ ...
24
+ ```
25
+ <!-- usagestop -->
26
+ # Commands
27
+ <!-- commands -->
28
+ * [`bt logs`](#bt-logs)
29
+
30
+ ## `bt logs`
31
+
32
+ Display live Reactor / Proxy Transform logs output. Requires `reactor:read`, `reactor:update`, `proxy:read` and `proxy:update` Management Application permissions
33
+
34
+ ```
35
+ USAGE
36
+ $ bt logs --management-key <value> [-p <value>] [--proxy-id <value>] [--reactor-id <value>]
37
+
38
+ FLAGS
39
+ -p, --port=<value> [default: 8220] port to listen for incoming logs
40
+ --management-key=<value> (required) management key used for connecting with the reactor / proxy
41
+ --proxy-id=<value> proxy id to connect to
42
+ --reactor-id=<value> reactor id to connect to
43
+
44
+ DESCRIPTION
45
+ Display live Reactor / Proxy Transform logs output. Requires `reactor:read`, `reactor:update`, `proxy:read` and
46
+ `proxy:update` Management Application permissions
47
+
48
+ EXAMPLES
49
+ $ bt logs
50
+
51
+ $ bt logs -p 3000
52
+ ```
53
+
54
+ _See code: [dist/commands/logs.ts](https://github.com/Basis-Theory-Labs/basistheory-cli/blob/v1.0.1/dist/commands/logs.ts)_
55
+ <!-- commandsstop -->
package/bin/dev ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+
3
+ const oclif = require('@oclif/core')
4
+
5
+ const path = require('path')
6
+ const project = path.join(__dirname, '..', 'tsconfig.json')
7
+
8
+ // In dev mode -> use ts-node and dev plugins
9
+ process.env.NODE_ENV = 'development'
10
+
11
+ require('ts-node').register({project})
12
+
13
+ // In dev mode, always show stack traces
14
+ oclif.settings.debug = true;
15
+
16
+ // Start the CLI
17
+ oclif.run().then(oclif.flush).catch(oclif.Errors.handle)
package/bin/dev.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\dev" %*
package/bin/run ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ const oclif = require('@oclif/core')
4
+
5
+ oclif.run().then(require('@oclif/core/flush')).catch(require('@oclif/core/handle'))
package/bin/run.cmd ADDED
@@ -0,0 +1,3 @@
1
+ @echo off
2
+
3
+ node "%~dp0\run" %*
@@ -0,0 +1,12 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Logs extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ port: import("@oclif/core/lib/interfaces/parser").OptionFlag<number, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
7
+ 'management-key': import("@oclif/core/lib/interfaces/parser").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
8
+ 'proxy-id': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
9
+ 'reactor-id': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const management_1 = require("../logs/management");
5
+ const server_1 = require("../logs/server");
6
+ class Logs extends core_1.Command {
7
+ async run() {
8
+ const { flags: { port, 'management-key': managementKey, 'reactor-id': reactorId, 'proxy-id': proxyId, }, } = await this.parse(Logs);
9
+ const url = await (0, server_1.createLogServer)(this, port);
10
+ await (0, management_1.connectToResource)({
11
+ managementKey,
12
+ proxyId,
13
+ reactorId,
14
+ url,
15
+ });
16
+ }
17
+ }
18
+ exports.default = Logs;
19
+ Logs.description = 'Display live Reactor / Proxy Transform logs output. Requires `reactor:read`, `reactor:update`, `proxy:read` and `proxy:update` Management Application permissions';
20
+ Logs.examples = [
21
+ '<%= config.bin %> <%= command.id %>',
22
+ '<%= config.bin %> <%= command.id %> -p 3000',
23
+ ];
24
+ Logs.flags = {
25
+ port: core_1.Flags.integer({
26
+ char: 'p',
27
+ description: 'port to listen for incoming logs',
28
+ default: 8220,
29
+ }),
30
+ 'management-key': core_1.Flags.string({
31
+ env: 'BT_MANAGEMENT_KEY',
32
+ description: 'management key used for connecting with the reactor / proxy',
33
+ required: true,
34
+ }),
35
+ 'proxy-id': core_1.Flags.string({
36
+ description: 'proxy id to connect to',
37
+ exactlyOne: ['proxy-id', 'reactor-id'],
38
+ }),
39
+ 'reactor-id': core_1.Flags.string({
40
+ description: 'reactor id to connect to',
41
+ exactlyOne: ['proxy-id', 'reactor-id'],
42
+ }),
43
+ };
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.run = void 0;
4
+ var core_1 = require("@oclif/core");
5
+ Object.defineProperty(exports, "run", { enumerable: true, get: function () { return core_1.run; } });
@@ -0,0 +1,8 @@
1
+ interface ConnectParams {
2
+ managementKey: string;
3
+ reactorId?: string;
4
+ proxyId?: string;
5
+ url: string;
6
+ }
7
+ declare const connectToResource: ({ managementKey, reactorId, proxyId, url, }: ConnectParams) => Promise<void>;
8
+ export { connectToResource };
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.connectToResource = void 0;
4
+ const basis_theory_js_1 = require("@basis-theory/basis-theory-js");
5
+ const core_1 = require("@oclif/core");
6
+ const BT_LOGGING_CONFIGURATION = 'BT_REMOTE_LOGGING';
7
+ const createConfiguration = (url, current = {}) => ({
8
+ ...current,
9
+ [BT_LOGGING_CONFIGURATION]: JSON.stringify({
10
+ destination: url,
11
+ date: Date.now(),
12
+ }),
13
+ });
14
+ const connectToReactor = async (bt, reactorId, url) => {
15
+ core_1.ux.action.start('Connecting to Reactor');
16
+ const reactor = await bt.reactors.retrieve(reactorId);
17
+ await bt.reactors.update(reactorId, {
18
+ name: reactor.name,
19
+ configuration: createConfiguration(url, reactor.configuration),
20
+ application: reactor.application,
21
+ });
22
+ core_1.ux.action.stop('✅\t');
23
+ };
24
+ const connectToProxy = async (bt, proxyId, url) => {
25
+ core_1.ux.action.start('Connecting to Proxy');
26
+ const proxy = await bt.proxies.retrieve(proxyId);
27
+ await bt.proxies.update(proxyId, {
28
+ ...proxy,
29
+ ...(proxy.applicationId
30
+ ? {
31
+ application: {
32
+ id: proxy.applicationId,
33
+ },
34
+ }
35
+ : {}),
36
+ configuration: createConfiguration(url, proxy.configuration),
37
+ });
38
+ core_1.ux.action.stop('✅\t');
39
+ };
40
+ const connectToResource = async ({ managementKey, reactorId, proxyId, url, }) => {
41
+ const bt = await new basis_theory_js_1.BasisTheory().init(managementKey);
42
+ if (typeof reactorId === 'string') {
43
+ return connectToReactor(bt, reactorId, url);
44
+ }
45
+ return connectToProxy(bt, proxyId, url);
46
+ };
47
+ exports.connectToResource = connectToResource;
@@ -0,0 +1,10 @@
1
+ import pino from 'pino';
2
+ interface LogEvent {
3
+ args: any[];
4
+ correlationId: string;
5
+ reactorId: string;
6
+ level: 'INFO' | 'WARN' | 'ERROR';
7
+ time: number;
8
+ }
9
+ declare const parseLogEvent: (logger: pino.Logger) => (event: LogEvent) => Promise<void>;
10
+ export { parseLogEvent };
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseLogEvent = void 0;
4
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
5
+ const debug = require('debug')('logs:parser');
6
+ const parseLogEvent = (logger) => async (event) => {
7
+ debug(event);
8
+ const { deserializeError } = await import('serialize-error');
9
+ const [arg1, arg2, ...args] = event.args.map((arg) => {
10
+ // eslint-disable-next-line unicorn/no-null
11
+ if (arg === null || arg === undefined || typeof arg === 'number') {
12
+ return String(arg);
13
+ }
14
+ if ((arg === null || arg === void 0 ? void 0 : arg.name) && (arg === null || arg === void 0 ? void 0 : arg.stack)) {
15
+ return deserializeError(arg);
16
+ }
17
+ return arg;
18
+ });
19
+ switch (event.level) {
20
+ case 'INFO': {
21
+ logger.info(arg1, arg2, ...args);
22
+ break;
23
+ }
24
+ case 'WARN': {
25
+ logger.warn(arg1, arg2, ...args);
26
+ break;
27
+ }
28
+ case 'ERROR': {
29
+ logger.error(arg1, arg2, ...args);
30
+ break;
31
+ }
32
+ // No default
33
+ }
34
+ };
35
+ exports.parseLogEvent = parseLogEvent;
@@ -0,0 +1,3 @@
1
+ import type { Command } from '@oclif/core';
2
+ declare const createLogServer: (command: Command, port: number) => Promise<string>;
3
+ export { createLogServer };
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLogServer = void 0;
4
+ const core_1 = require("@oclif/core");
5
+ const cloudflared_1 = require("cloudflared");
6
+ const fs = require("node:fs");
7
+ const node_http_1 = require("node:http");
8
+ const pino_1 = require("pino");
9
+ const socket_io_1 = require("socket.io");
10
+ const parser_1 = require("./parser");
11
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
12
+ const debug = require('debug')('logs:server');
13
+ const runTunnel = async (port) => {
14
+ if (!fs.existsSync(cloudflared_1.bin)) {
15
+ await (0, cloudflared_1.install)(cloudflared_1.bin);
16
+ }
17
+ debug('starting tunnel');
18
+ const { url: urlPromise } = (0, cloudflared_1.tunnel)({
19
+ '--url': `localhost:${port}`,
20
+ });
21
+ const url = await urlPromise;
22
+ debug(`tunnel started at ${url}`);
23
+ return url;
24
+ };
25
+ const createLogServer = async (command, port) => {
26
+ core_1.ux.action.start('Starting log server');
27
+ const logger = (0, pino_1.default)({
28
+ transport: {
29
+ target: 'pino-pretty',
30
+ options: {
31
+ colorize: true,
32
+ colorizeObjects: false,
33
+ ignore: 'pid,hostname',
34
+ },
35
+ },
36
+ });
37
+ debug('creating http server');
38
+ const server = (0, node_http_1.createServer)();
39
+ debug('creating socket server');
40
+ const io = new socket_io_1.Server(server);
41
+ io.on('connection', (client) => {
42
+ debug(`socket client connected: ${client.handshake.address}`);
43
+ client.on('log', (0, parser_1.parseLogEvent)(logger));
44
+ client.on('disconnect', (reason) => {
45
+ debug(`socket client disconnected ${client.handshake.address}: ${reason}`);
46
+ });
47
+ });
48
+ debug(`server listening on port ${port}`);
49
+ server.listen(port);
50
+ core_1.ux.action.stop(`✅\tListening at http://localhost:${port}`);
51
+ core_1.ux.action.start('Starting tunnel');
52
+ const url = await runTunnel(port);
53
+ core_1.ux.action.stop(`✅\t\tListening at ${url}`);
54
+ return url;
55
+ };
56
+ exports.createLogServer = createLogServer;
@@ -0,0 +1,48 @@
1
+ {
2
+ "version": "1.0.1",
3
+ "commands": {
4
+ "logs": {
5
+ "id": "logs",
6
+ "description": "Display live Reactor / Proxy Transform logs output. Requires `reactor:read`, `reactor:update`, `proxy:read` and `proxy:update` Management Application permissions",
7
+ "strict": true,
8
+ "pluginName": "@basis-theory-labs/cli",
9
+ "pluginAlias": "@basis-theory-labs/cli",
10
+ "pluginType": "core",
11
+ "aliases": [],
12
+ "examples": [
13
+ "<%= config.bin %> <%= command.id %>",
14
+ "<%= config.bin %> <%= command.id %> -p 3000"
15
+ ],
16
+ "flags": {
17
+ "port": {
18
+ "name": "port",
19
+ "type": "option",
20
+ "char": "p",
21
+ "description": "port to listen for incoming logs",
22
+ "multiple": false,
23
+ "default": 8220
24
+ },
25
+ "management-key": {
26
+ "name": "management-key",
27
+ "type": "option",
28
+ "description": "management key used for connecting with the reactor / proxy",
29
+ "required": true,
30
+ "multiple": false
31
+ },
32
+ "proxy-id": {
33
+ "name": "proxy-id",
34
+ "type": "option",
35
+ "description": "proxy id to connect to",
36
+ "multiple": false
37
+ },
38
+ "reactor-id": {
39
+ "name": "reactor-id",
40
+ "type": "option",
41
+ "description": "reactor id to connect to",
42
+ "multiple": false
43
+ }
44
+ },
45
+ "args": {}
46
+ }
47
+ }
48
+ }
package/package.json ADDED
@@ -0,0 +1,91 @@
1
+ {
2
+ "name": "@basis-theory-labs/cli",
3
+ "version": "1.0.1",
4
+ "description": "Basis Theory CLI tool",
5
+ "author": "Davi Aquino @djejaquino",
6
+ "bin": {
7
+ "bt": "./bin/run"
8
+ },
9
+ "homepage": "https://github.com/Basis-Theory-Labs/basistheory-cli",
10
+ "license": "MIT",
11
+ "main": "dist/index.js",
12
+ "repository": "Basis-Theory-Labs/basistheory-cli",
13
+ "files": [
14
+ "/bin",
15
+ "/dist",
16
+ "/npm-shrinkwrap.json",
17
+ "/oclif.manifest.json"
18
+ ],
19
+ "dependencies": {
20
+ "@basis-theory/basis-theory-js": "^1.77.0",
21
+ "@oclif/core": "^2",
22
+ "@oclif/plugin-help": "^5",
23
+ "@oclif/plugin-plugins": "^2.4.7",
24
+ "cloudflared": "^0.4.0",
25
+ "debug": "^4.3.4",
26
+ "pino": "^8.14.1",
27
+ "pino-pretty": "^10.0.0",
28
+ "serialize-error": "^11.0.0",
29
+ "socket.io": "^4.6.2"
30
+ },
31
+ "devDependencies": {
32
+ "@basis-theory/eslint-config": "^1.2.0",
33
+ "@oclif/test": "^2.3.22",
34
+ "@semantic-release/changelog": "^6.0.3",
35
+ "@semantic-release/commit-analyzer": "^10.0.1",
36
+ "@semantic-release/git": "^10.0.1",
37
+ "@semantic-release/github": "^9.0.3",
38
+ "@semantic-release/npm": "^10.0.4",
39
+ "@semantic-release/release-notes-generator": "^11.0.3",
40
+ "@types/chai": "^4",
41
+ "@types/debug": "^4.1.8",
42
+ "@types/mocha": "^9.0.0",
43
+ "@types/node": "^16.18.36",
44
+ "chai": "^4",
45
+ "eslint": "^7.32.0",
46
+ "eslint-config-oclif": "^4",
47
+ "eslint-config-oclif-typescript": "^1.0.3",
48
+ "mocha": "^9.2.2",
49
+ "oclif": "^3",
50
+ "prettier": "^2.8.8",
51
+ "semantic-release": "^21.0.5",
52
+ "shx": "^0.3.3",
53
+ "ts-node": "^10.9.1",
54
+ "tslib": "^2.5.3",
55
+ "typescript": "^4.9.5"
56
+ },
57
+ "oclif": {
58
+ "bin": "bt",
59
+ "dirname": "bt",
60
+ "commands": "./dist/commands",
61
+ "plugins": [],
62
+ "topicSeparator": " ",
63
+ "topics": {
64
+ "logs": {
65
+ "description": "See realtime logs from Reactors and Proxies"
66
+ }
67
+ }
68
+ },
69
+ "scripts": {
70
+ "build": "shx rm -rf dist && tsc -b",
71
+ "lint": "eslint . --ext .ts --config .eslintrc",
72
+ "postpack": "shx rm -f oclif.manifest.json",
73
+ "posttest": "yarn lint",
74
+ "prepack": "yarn build && oclif manifest && oclif readme",
75
+ "test": "mocha --forbid-only \"test/**/*.test.ts\"",
76
+ "version": "oclif readme && git add README.md",
77
+ "release": "semantic-release"
78
+ },
79
+ "engines": {
80
+ "node": ">=12.0.0"
81
+ },
82
+ "bugs": "https://github.com/Basis-Theory-Labs/basistheory-cli/issues",
83
+ "keywords": [
84
+ "oclif"
85
+ ],
86
+ "types": "dist/index.d.ts",
87
+ "prettier": "@basis-theory/eslint-config/prettier",
88
+ "publishConfig": {
89
+ "access": "public"
90
+ }
91
+ }