@basis-theory-labs/cli 1.3.1 → 1.4.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
@@ -19,7 +19,7 @@ $ npm install -g @basis-theory-labs/cli
19
19
  $ bt COMMAND
20
20
  running command...
21
21
  $ bt (--version)
22
- @basis-theory-labs/cli/1.3.1 linux-x64 node-v18.16.1
22
+ @basis-theory-labs/cli/1.4.0 linux-x64 node-v18.16.1
23
23
  $ bt --help [COMMAND]
24
24
  USAGE
25
25
  $ bt COMMAND
@@ -54,7 +54,7 @@ EXAMPLES
54
54
  $ bt proxies
55
55
  ```
56
56
 
57
- _See code: [dist/commands/proxies/index.ts](https://github.com/Basis-Theory-Labs/basistheory-cli/blob/v1.3.1/dist/commands/proxies/index.ts)_
57
+ _See code: [dist/commands/proxies/index.ts](https://github.com/Basis-Theory-Labs/basistheory-cli/blob/v1.4.0/dist/commands/proxies/index.ts)_
58
58
 
59
59
  ## `bt proxies create`
60
60
 
@@ -115,7 +115,7 @@ Updates an existing Pre-Configured Proxy. Requires `proxy:update` Management App
115
115
  ```
116
116
  USAGE
117
117
  $ bt proxies update ID -x <value> [-n <value>] [-u <value>] [-q <value>] [-s <value>] [-i <value>] [-c <value>]
118
- [-a]
118
+ [-a] [-w]
119
119
 
120
120
  ARGUMENTS
121
121
  ID Proxy id to update
@@ -129,6 +129,7 @@ FLAGS
129
129
  -q, --request-transform-code=<value> path to JavaScript file containing a Request Transform code
130
130
  -s, --response-transform-code=<value> path to JavaScript file containing a Response Transform code
131
131
  -u, --destination-url=<value> URL to which requests will be proxied
132
+ -w, --watch Watch for changes in informed files
132
133
  -x, --management-key=<value> (required) management key used for connecting with the reactor / proxy
133
134
 
134
135
  DESCRIPTION
@@ -163,7 +164,7 @@ EXAMPLES
163
164
  $ bt reactors
164
165
  ```
165
166
 
166
- _See code: [dist/commands/reactors/index.ts](https://github.com/Basis-Theory-Labs/basistheory-cli/blob/v1.3.1/dist/commands/reactors/index.ts)_
167
+ _See code: [dist/commands/reactors/index.ts](https://github.com/Basis-Theory-Labs/basistheory-cli/blob/v1.4.0/dist/commands/reactors/index.ts)_
167
168
 
168
169
  ## `bt reactors logs [ID]`
169
170
 
@@ -9,6 +9,9 @@ class Proxies extends base_1.BaseCommand {
9
9
  async run() {
10
10
  const { flags: { page }, bt, } = await this.parse(Proxies);
11
11
  const proxy = await (0, management_1.selectProxy)(bt, page);
12
+ if (!proxy) {
13
+ return undefined;
14
+ }
12
15
  const action = await (0, prompts_1.select)({
13
16
  message: 'Select action to perform',
14
17
  choices: [
@@ -11,6 +11,9 @@ class Logs extends base_1.BaseCommand {
11
11
  return (0, logs_1.showProxyLogs)(bt, id, port);
12
12
  }
13
13
  const proxy = await (0, management_1.selectProxy)(bt, 1);
14
+ if (!proxy) {
15
+ return undefined;
16
+ }
14
17
  return (0, logs_1.showProxyLogs)(bt, proxy.id, port);
15
18
  }
16
19
  }
@@ -4,6 +4,7 @@ export default class Update extends BaseCommand {
4
4
  static description: string;
5
5
  static examples: string[];
6
6
  static flags: {
7
+ watch: import("@oclif/core/lib/interfaces/parser").BooleanFlag<boolean>;
7
8
  name: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
8
9
  'destination-url': import("@oclif/core/lib/interfaces/parser").OptionFlag<import("url").URL | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
9
10
  'request-transform-code': import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
@@ -2,12 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_1 = require("@oclif/core");
4
4
  const base_1 = require("../../base");
5
+ const files_1 = require("../../files");
5
6
  const management_1 = require("../../proxies/management");
6
7
  const utils_1 = require("../../proxies/utils");
7
8
  class Update extends base_1.BaseCommand {
8
9
  async run() {
9
10
  var _a, _b;
10
- const { bt, args: { id }, flags: { name, 'destination-url': destinationUrl, 'response-transform-code': responseTransformCode, 'request-transform-code': requestTransformCode, 'application-id': applicationId, configuration, 'require-auth': requireAuth, }, metadata, } = await this.parse(Update);
11
+ const { bt, args: { id }, flags: { name, 'destination-url': destinationUrl, 'response-transform-code': responseTransformCode, 'request-transform-code': requestTransformCode, 'application-id': applicationId, configuration, 'require-auth': requireAuth, watch, }, metadata, } = await this.parse(Update);
11
12
  const model = (0, utils_1.createModelFromFlags)({
12
13
  name,
13
14
  destinationUrl: destinationUrl === null || destinationUrl === void 0 ? void 0 : destinationUrl.toString(),
@@ -21,6 +22,25 @@ class Update extends base_1.BaseCommand {
21
22
  });
22
23
  await (0, management_1.patchProxy)(bt, id, model);
23
24
  this.log('Proxy updated successfully!');
25
+ if (watch) {
26
+ const files = [
27
+ requestTransformCode,
28
+ responseTransformCode,
29
+ configuration,
30
+ ].filter((flag) => flag);
31
+ if (files.length) {
32
+ this.log(`Watching files for changes: ${files.join(', ')} `);
33
+ }
34
+ files.forEach((file) => {
35
+ (0, files_1.watchForChanges)(file, async () => {
36
+ core_1.ux.action.start(`Detected change in ${file}. Pushing changes`);
37
+ await (0, management_1.patchProxy)(bt, id, (0, utils_1.createModelFromFlags)({
38
+ responseTransformCode,
39
+ }));
40
+ core_1.ux.action.stop('✅\t');
41
+ });
42
+ });
43
+ }
24
44
  }
25
45
  }
26
46
  exports.default = Update;
@@ -33,6 +53,12 @@ Update.examples = [
33
53
  ];
34
54
  Update.flags = {
35
55
  ...utils_1.PROXY_FLAGS,
56
+ watch: core_1.Flags.boolean({
57
+ char: 'w',
58
+ description: 'Watch for changes in informed files',
59
+ default: false,
60
+ required: false,
61
+ }),
36
62
  };
37
63
  Update.args = {
38
64
  id: core_1.Args.string({
@@ -9,6 +9,9 @@ class Reactors extends base_1.BaseCommand {
9
9
  async run() {
10
10
  const { bt, flags: { page }, } = await this.parse(Reactors);
11
11
  const reactor = await (0, management_1.selectReactor)(bt, page);
12
+ if (!reactor) {
13
+ return undefined;
14
+ }
12
15
  const action = await (0, prompts_1.select)({
13
16
  message: 'Select action to perform',
14
17
  choices: [
@@ -11,6 +11,9 @@ class Logs extends base_1.BaseCommand {
11
11
  return (0, logs_1.showReactorLogs)(bt, id, port);
12
12
  }
13
13
  const reactor = await (0, management_1.selectReactor)(bt, 1);
14
+ if (!reactor) {
15
+ return undefined;
16
+ }
14
17
  return (0, logs_1.showReactorLogs)(bt, reactor.id, port);
15
18
  }
16
19
  }
@@ -0,0 +1,4 @@
1
+ import * as fs from 'fs';
2
+ declare const readFileContents: (filePath: string) => string;
3
+ declare const watchForChanges: (filePath: string, handler: (contents: string) => unknown) => fs.FSWatcher;
4
+ export { readFileContents, watchForChanges };
package/dist/files.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.watchForChanges = exports.readFileContents = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs = tslib_1.__importStar(require("fs"));
6
+ const lodash_debounce_1 = tslib_1.__importDefault(require("lodash.debounce"));
7
+ const path = tslib_1.__importStar(require("path"));
8
+ const readFileContents = (filePath) => fs.readFileSync(path.resolve(process.cwd(), filePath)).toString();
9
+ exports.readFileContents = readFileContents;
10
+ const FILE_WATCH_DEBOUNCE_DELAY = 1000;
11
+ const watchForChanges = (filePath, handler) => {
12
+ let lastContents = '';
13
+ const debounced = (0, lodash_debounce_1.default)(() => {
14
+ const currentContents = readFileContents(filePath);
15
+ if (lastContents !== currentContents) {
16
+ lastContents = currentContents;
17
+ handler(currentContents);
18
+ }
19
+ }, FILE_WATCH_DEBOUNCE_DELAY, {
20
+ trailing: true,
21
+ });
22
+ return fs.watch(filePath, debounced);
23
+ };
24
+ exports.watchForChanges = watchForChanges;
@@ -1,4 +1,6 @@
1
1
  import type { BasisTheory as IBasisTheory } from '@basis-theory/basis-theory-js/types/sdk/sdk';
2
2
  declare const connectToReactor: (bt: IBasisTheory, id: string, url: string) => Promise<void>;
3
+ declare const disconnectFromReactor: (bt: IBasisTheory, id: string) => Promise<void>;
3
4
  declare const connectToProxy: (bt: IBasisTheory, id: string, url: string) => Promise<void>;
4
- export { connectToProxy, connectToReactor };
5
+ declare const disconnectFromProxy: (bt: IBasisTheory, id: string) => Promise<void>;
6
+ export { connectToReactor, disconnectFromReactor, connectToProxy, disconnectFromProxy, };
@@ -1,15 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.connectToReactor = exports.connectToProxy = void 0;
3
+ exports.disconnectFromProxy = exports.connectToProxy = exports.disconnectFromReactor = exports.connectToReactor = void 0;
4
4
  const core_1 = require("@oclif/core");
5
5
  const management_1 = require("../proxies/management");
6
6
  const management_2 = require("../reactors/management");
7
7
  const BT_LOGGING_CONFIGURATION = 'BT_LOGGING_CONFIGURATION';
8
+ /**
9
+ * Creates configuration object to connect/disconnect to a resource
10
+ * @param url - server url for the resource to connect to. If `undefined`,
11
+ * the logging configuration is cleared.
12
+ */
8
13
  const createConfiguration = (url) => ({
9
- [BT_LOGGING_CONFIGURATION]: JSON.stringify({
10
- destination: url,
11
- date: Date.now(),
12
- }),
14
+ [BT_LOGGING_CONFIGURATION]: url
15
+ ? JSON.stringify({
16
+ destination: url,
17
+ date: Date.now(),
18
+ })
19
+ : // eslint-disable-next-line unicorn/no-null
20
+ null,
13
21
  });
14
22
  const connectToReactor = async (bt, id, url) => {
15
23
  core_1.ux.action.start(`Connecting to Reactor (${id})`);
@@ -19,6 +27,14 @@ const connectToReactor = async (bt, id, url) => {
19
27
  core_1.ux.action.stop('✅\t');
20
28
  };
21
29
  exports.connectToReactor = connectToReactor;
30
+ const disconnectFromReactor = async (bt, id) => {
31
+ core_1.ux.action.start(`Disconnecting from Reactor (${id})`);
32
+ await (0, management_2.patchReactor)(bt, id, {
33
+ configuration: createConfiguration(),
34
+ });
35
+ core_1.ux.action.stop('✅\t');
36
+ };
37
+ exports.disconnectFromReactor = disconnectFromReactor;
22
38
  const connectToProxy = async (bt, id, url) => {
23
39
  core_1.ux.action.start(`Connecting to Proxy (${id})`);
24
40
  await (0, management_1.patchProxy)(bt, id, {
@@ -27,3 +43,11 @@ const connectToProxy = async (bt, id, url) => {
27
43
  core_1.ux.action.stop('✅\t');
28
44
  };
29
45
  exports.connectToProxy = connectToProxy;
46
+ const disconnectFromProxy = async (bt, id) => {
47
+ core_1.ux.action.start(`Disconnecting from Proxy (${id})`);
48
+ await (0, management_1.patchProxy)(bt, id, {
49
+ configuration: createConfiguration(),
50
+ });
51
+ core_1.ux.action.stop('✅\t');
52
+ };
53
+ exports.disconnectFromProxy = disconnectFromProxy;
@@ -0,0 +1,4 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ import type { Logger } from 'pino';
3
+ declare const createHttpServer: (logger: Logger) => FastifyInstance;
4
+ export { createHttpServer };
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHttpServer = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fastify_1 = tslib_1.__importDefault(require("fastify"));
6
+ const http_1 = tslib_1.__importDefault(require("http"));
7
+ const parse_1 = require("./parse");
8
+ const debug = require('debug')('logs:http');
9
+ const createHttpServer = (logger) => {
10
+ const fastify = (0, fastify_1.default)({
11
+ serverFactory: (handler) => http_1.default.createServer(handler),
12
+ });
13
+ fastify.post('/logs', (request, reply) => {
14
+ debug('received "log" request');
15
+ reply.code(204).send();
16
+ (0, parse_1.parseLogEvent)(logger, request.body);
17
+ });
18
+ return fastify;
19
+ };
20
+ exports.createHttpServer = createHttpServer;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_LOGS_SERVER_PORT = exports.showReactorLogs = exports.showProxyLogs = void 0;
4
+ const utils_1 = require("../utils");
4
5
  const connect_1 = require("./connect");
5
6
  const server_1 = require("./server");
6
7
  const DEFAULT_LOGS_SERVER_PORT = 8220;
@@ -8,10 +9,12 @@ exports.DEFAULT_LOGS_SERVER_PORT = DEFAULT_LOGS_SERVER_PORT;
8
9
  const showProxyLogs = async (bt, id, port = DEFAULT_LOGS_SERVER_PORT) => {
9
10
  const url = await (0, server_1.createLogServer)(port);
10
11
  await (0, connect_1.connectToProxy)(bt, id, url);
12
+ (0, utils_1.cleanUpOnExit)(() => (0, connect_1.disconnectFromProxy)(bt, id));
11
13
  };
12
14
  exports.showProxyLogs = showProxyLogs;
13
15
  const showReactorLogs = async (bt, id, port = DEFAULT_LOGS_SERVER_PORT) => {
14
16
  const url = await (0, server_1.createLogServer)(port);
15
17
  await (0, connect_1.connectToReactor)(bt, id, url);
18
+ (0, utils_1.cleanUpOnExit)(() => (0, connect_1.disconnectFromReactor)(bt, id));
16
19
  };
17
20
  exports.showReactorLogs = showReactorLogs;
@@ -7,4 +7,5 @@ interface LogEvent {
7
7
  time: number;
8
8
  }
9
9
  declare const parseLogEvent: (logger: pino.Logger, event: LogEvent) => Promise<void>;
10
+ export type { LogEvent };
10
11
  export { parseLogEvent };
@@ -3,32 +3,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseLogEvent = void 0;
4
4
  const debug = require('debug')('logs:parse');
5
5
  const parseLogEvent = async (logger, event) => {
6
- debug(event);
7
- const { deserializeError } = await import('serialize-error');
8
- const [arg1, arg2, ...args] = event.args.map((arg) => {
9
- // eslint-disable-next-line unicorn/no-null
10
- if (arg === null || arg === undefined || typeof arg === 'number') {
11
- return String(arg);
6
+ try {
7
+ debug(event);
8
+ const { deserializeError } = await import('serialize-error');
9
+ const [obj, msg, ...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(obj, msg, ...args);
22
+ break;
23
+ }
24
+ case 'WARN': {
25
+ logger.warn(obj, msg, ...args);
26
+ break;
27
+ }
28
+ case 'ERROR': {
29
+ logger.error(obj, msg, ...args);
30
+ break;
31
+ }
32
+ // No default
12
33
  }
13
- if ((arg === null || arg === void 0 ? void 0 : arg.name) && (arg === null || arg === void 0 ? void 0 : arg.stack)) {
14
- return deserializeError(arg);
15
- }
16
- return arg;
17
- });
18
- switch (event.level) {
19
- case 'INFO': {
20
- logger.info(arg1, arg2, ...args);
21
- break;
22
- }
23
- case 'WARN': {
24
- logger.warn(arg1, arg2, ...args);
25
- break;
26
- }
27
- case 'ERROR': {
28
- logger.error(arg1, arg2, ...args);
29
- break;
30
- }
31
- // No default
34
+ }
35
+ catch (error) {
36
+ debug('Error trying to parse log event', error);
32
37
  }
33
38
  };
34
39
  exports.parseLogEvent = parseLogEvent;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createLogServer = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const core_1 = require("@oclif/core");
5
6
  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 parse_1 = require("./parse");
7
+ const fs = tslib_1.__importStar(require("node:fs"));
8
+ const pino_1 = tslib_1.__importDefault(require("pino"));
9
+ const http_1 = require("./http");
10
+ const socket_1 = require("./socket");
11
11
  const debug = require('debug')('logs:server');
12
12
  const runTunnel = async (port) => {
13
13
  if (!fs.existsSync(cloudflared_1.bin)) {
@@ -34,27 +34,11 @@ const createLogServer = async (port) => {
34
34
  },
35
35
  });
36
36
  debug('creating http server');
37
- const server = (0, node_http_1.createServer)();
37
+ const fastify = (0, http_1.createHttpServer)(logger);
38
38
  debug('creating socket server');
39
- const io = new socket_io_1.Server(server);
40
- io.on('connection', (client) => {
41
- debug(`socket client connected: ${client.handshake.address}`);
42
- client.on('log', (data, callback) => {
43
- debug('received "log" event');
44
- if (typeof callback === 'function') {
45
- debug('ack expected');
46
- // eslint-disable-next-line node/callback-return,node/no-callback-literal
47
- callback('ack');
48
- debug('ack sent');
49
- }
50
- (0, parse_1.parseLogEvent)(logger, data);
51
- });
52
- client.on('disconnect', (reason) => {
53
- debug(`socket client disconnected ${client.handshake.address}: ${reason}`);
54
- });
55
- });
39
+ (0, socket_1.createSocketServer)(fastify.server, logger);
56
40
  debug(`server listening on port ${port}`);
57
- server.listen(port);
41
+ await fastify.listen({ port });
58
42
  core_1.ux.action.stop(`✅\tListening at http://localhost:${port}`);
59
43
  core_1.ux.action.start('Starting tunnel');
60
44
  const url = await runTunnel(port);
@@ -0,0 +1,5 @@
1
+ import type { Server as HttpServer } from 'http';
2
+ import type { Logger } from 'pino';
3
+ import { Server } from 'socket.io';
4
+ declare const createSocketServer: (httpServer: HttpServer, logger: Logger) => Server;
5
+ export { createSocketServer };
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSocketServer = void 0;
4
+ const socket_io_1 = require("socket.io");
5
+ const parse_1 = require("./parse");
6
+ const debug = require('debug')('logs:socket');
7
+ const createSocketServer = (httpServer, logger) => {
8
+ const io = new socket_io_1.Server(httpServer);
9
+ io.on('connection', (client) => {
10
+ debug(`socket client connected: ${client.handshake.address}`);
11
+ client.on('log', (data, callback) => {
12
+ debug('received "log" event');
13
+ if (typeof callback === 'function') {
14
+ debug('ack expected');
15
+ // eslint-disable-next-line node/callback-return,node/no-callback-literal
16
+ callback('ack');
17
+ debug('ack sent');
18
+ }
19
+ (0, parse_1.parseLogEvent)(logger, data);
20
+ });
21
+ client.on('disconnect', (reason) => {
22
+ debug(`socket client disconnected ${client.handshake.address}: ${reason}`);
23
+ });
24
+ });
25
+ return io;
26
+ };
27
+ exports.createSocketServer = createSocketServer;
@@ -1,6 +1,6 @@
1
1
  import type { CreateProxy, PatchProxy, Proxy } from '@basis-theory/basis-theory-js/types/models';
2
2
  import type { BasisTheory as IBasisTheory } from '@basis-theory/basis-theory-js/types/sdk';
3
- declare const selectProxy: (bt: IBasisTheory, page: number) => Promise<Proxy>;
3
+ declare const selectProxy: (bt: IBasisTheory, page: number) => Promise<Proxy | undefined>;
4
4
  declare const createProxy: (bt: IBasisTheory, model: CreateProxy) => Promise<Proxy>;
5
5
  declare const patchProxy: (bt: IBasisTheory, id: string, model: PatchProxy) => Promise<void>;
6
6
  export { selectProxy, createProxy, patchProxy };
@@ -11,38 +11,44 @@ const listProxies = async (bt, page) => {
11
11
  size,
12
12
  page,
13
13
  });
14
- const last = (proxies.pagination.pageNumber - 1) * size;
15
- const data = proxies.data.map((proxy, index) => ({
16
- '#': last + (index + 1),
17
- ...proxy,
18
- }));
19
- core_1.ux.table(data, {
20
- '#': {},
21
- id: {},
22
- name: {},
23
- key: {},
24
- /* eslint-disable camelcase */
25
- destination_url: {
26
- header: 'Destination URL',
27
- get: (proxy) => proxy.destinationUrl,
28
- },
29
- require_auth: {
30
- header: 'Require Auth',
31
- get: (proxy) => (proxy.requireAuth ? 'yes' : 'no'),
32
- },
33
- request_transform: {
34
- header: 'Request Transform',
35
- get: (proxy) => { var _a; return (((_a = proxy.requestTransform) === null || _a === void 0 ? void 0 : _a.code) ? 'yes' : 'no'); },
36
- },
37
- response_transform: {
38
- header: 'Response Transform',
39
- get: (proxy) => { var _a; return (((_a = proxy.responseTransform) === null || _a === void 0 ? void 0 : _a.code) ? 'yes' : 'no'); },
40
- },
41
- application_id: {
42
- header: 'Application Id',
43
- },
44
- /* eslint-enable camelcase */
45
- });
14
+ let data = [];
15
+ if (proxies.pagination.totalItems > 0) {
16
+ const last = (proxies.pagination.pageNumber - 1) * size;
17
+ data = proxies.data.map((proxy, index) => ({
18
+ '#': last + (index + 1),
19
+ ...proxy,
20
+ }));
21
+ core_1.ux.table(data, {
22
+ '#': {},
23
+ id: {},
24
+ name: {},
25
+ key: {},
26
+ /* eslint-disable camelcase */
27
+ destination_url: {
28
+ header: 'Destination URL',
29
+ get: (proxy) => proxy.destinationUrl,
30
+ },
31
+ require_auth: {
32
+ header: 'Require Auth',
33
+ get: (proxy) => (proxy.requireAuth ? 'yes' : 'no'),
34
+ },
35
+ request_transform: {
36
+ header: 'Request Transform',
37
+ get: (proxy) => { var _a; return (((_a = proxy.requestTransform) === null || _a === void 0 ? void 0 : _a.code) ? 'yes' : 'no'); },
38
+ },
39
+ response_transform: {
40
+ header: 'Response Transform',
41
+ get: (proxy) => { var _a; return (((_a = proxy.responseTransform) === null || _a === void 0 ? void 0 : _a.code) ? 'yes' : 'no'); },
42
+ },
43
+ application_id: {
44
+ header: 'Application Id',
45
+ },
46
+ /* eslint-enable camelcase */
47
+ });
48
+ }
49
+ else {
50
+ core_1.ux.log('No proxies found.');
51
+ }
46
52
  return {
47
53
  data,
48
54
  pagination: proxies.pagination,
@@ -50,6 +56,9 @@ const listProxies = async (bt, page) => {
50
56
  };
51
57
  const selectProxy = async (bt, page) => {
52
58
  const proxies = await listProxies(bt, page);
59
+ if (proxies.pagination.totalItems === 0) {
60
+ return undefined;
61
+ }
53
62
  const selection = await (0, utils_1.selectOrNavigate)(proxies, '#');
54
63
  if (selection === 'previous') {
55
64
  return selectProxy(bt, page - 1);
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { CreateProxy as CreateProxyModel, PatchProxy as PatchProxyModel } from '@basis-theory/basis-theory-js/types/models/proxies';
2
+ import type { CreateProxy as CreateProxyModel, PatchProxy as PatchProxyModel } from '@basis-theory/basis-theory-js/types/models/proxies';
3
3
  declare const PROXY_FLAGS: {
4
4
  name: import("@oclif/core/lib/interfaces/parser").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
5
5
  'destination-url': import("@oclif/core/lib/interfaces/parser").OptionFlag<import("url").URL | undefined, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
@@ -27,10 +27,8 @@ interface ProxyFlagProps {
27
27
  */
28
28
  configuration?: string;
29
29
  }
30
- interface CreateProxy extends Omit<CreateProxyModel, 'application' | 'configuration' | 'requestTransform' | 'responseTransform'>, ProxyFlagProps {
31
- }
32
- interface PatchProxy extends Omit<PatchProxyModel, 'application' | 'configuration' | 'requestTransform' | 'responseTransform'>, ProxyFlagProps {
33
- }
30
+ type CreateProxy = ProxyFlagProps & Omit<CreateProxyModel, 'application' | 'configuration' | 'requestTransform' | 'responseTransform'>;
31
+ type PatchProxy = ProxyFlagProps & Omit<PatchProxyModel, 'application' | 'configuration' | 'requestTransform' | 'responseTransform'>;
34
32
  declare function createModelFromFlags(payload: CreateProxy): CreateProxyModel;
35
33
  declare function createModelFromFlags(payload: PatchProxy): PatchProxyModel;
36
34
  export { PROXY_FLAGS, createModelFromFlags };
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createModelFromFlags = exports.PROXY_FLAGS = void 0;
4
4
  const core_1 = require("@oclif/core");
5
5
  const dotenv_1 = require("dotenv");
6
- const utils_1 = require("../utils");
6
+ const files_1 = require("../files");
7
7
  const PROXY_FLAGS = {
8
8
  name: core_1.Flags.string({
9
9
  char: 'n',
@@ -43,14 +43,14 @@ function createModelFromFlags({ name, destinationUrl, requestTransformCode, resp
43
43
  name,
44
44
  destinationUrl,
45
45
  requestTransform: requestTransformCode
46
- ? { code: (0, utils_1.readFileContents)(requestTransformCode) }
46
+ ? { code: (0, files_1.readFileContents)(requestTransformCode) }
47
47
  : undefined,
48
48
  responseTransform: responseTransformCode
49
- ? { code: (0, utils_1.readFileContents)(responseTransformCode) }
49
+ ? { code: (0, files_1.readFileContents)(responseTransformCode) }
50
50
  : undefined,
51
51
  application: applicationId ? { id: applicationId } : undefined,
52
52
  configuration: configuration
53
- ? (0, dotenv_1.parse)((0, utils_1.readFileContents)(configuration))
53
+ ? (0, dotenv_1.parse)((0, files_1.readFileContents)(configuration))
54
54
  : undefined,
55
55
  requireAuth,
56
56
  };
@@ -1,5 +1,5 @@
1
1
  import type { Reactor, PatchReactor } from '@basis-theory/basis-theory-js/types/models';
2
2
  import type { BasisTheory as IBasisTheory } from '@basis-theory/basis-theory-js/types/sdk';
3
- declare const selectReactor: (bt: IBasisTheory, page: number) => Promise<Reactor>;
3
+ declare const selectReactor: (bt: IBasisTheory, page: number) => Promise<Reactor | undefined>;
4
4
  declare const patchReactor: (bt: IBasisTheory, id: string, model: PatchReactor) => Promise<void>;
5
5
  export { selectReactor, patchReactor };
@@ -11,16 +11,22 @@ const listReactors = async (bt, page) => {
11
11
  size,
12
12
  page,
13
13
  });
14
- const last = (reactors.pagination.pageNumber - 1) * size;
15
- const data = reactors.data.map((reactor, index) => ({
16
- '#': last + (index + 1),
17
- ...reactor,
18
- }));
19
- core_1.ux.table(data, {
20
- '#': {},
21
- id: {},
22
- name: {},
23
- });
14
+ let data = [];
15
+ if (reactors.pagination.totalItems > 0) {
16
+ const last = (reactors.pagination.pageNumber - 1) * size;
17
+ data = reactors.data.map((reactor, index) => ({
18
+ '#': last + (index + 1),
19
+ ...reactor,
20
+ }));
21
+ core_1.ux.table(data, {
22
+ '#': {},
23
+ id: {},
24
+ name: {},
25
+ });
26
+ }
27
+ else {
28
+ core_1.ux.log('No reactors found.');
29
+ }
24
30
  return {
25
31
  data,
26
32
  pagination: reactors.pagination,
@@ -28,6 +34,9 @@ const listReactors = async (bt, page) => {
28
34
  };
29
35
  const selectReactor = async (bt, page) => {
30
36
  const reactors = await listReactors(bt, page);
37
+ if (reactors.pagination.totalItems === 0) {
38
+ return undefined;
39
+ }
31
40
  const selection = await (0, utils_1.selectOrNavigate)(reactors, '#');
32
41
  if (selection === 'previous') {
33
42
  return selectReactor(bt, page - 1);
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
1
3
  import { PaginatedList } from '@basis-theory/basis-theory-js/types/sdk';
2
4
  import confirm from '@inquirer/confirm';
3
5
  import input from '@inquirer/input';
@@ -5,5 +7,5 @@ declare const selectOrNavigate: <T>(list: PaginatedList<T>, prop: string) => Pro
5
7
  declare const promptStringIfUndefined: (value: string | undefined, options: Parameters<typeof input>[0]) => Promise<string>;
6
8
  declare const promptUrlIfUndefined: (value: URL | undefined, options: Parameters<typeof input>[0]) => Promise<URL>;
7
9
  declare const promptBooleanIfUndefined: (value: boolean | undefined, options: Parameters<typeof confirm>[0]) => Promise<boolean>;
8
- declare const readFileContents: (filePath: string) => string;
9
- export { selectOrNavigate, promptStringIfUndefined, promptUrlIfUndefined, promptBooleanIfUndefined, readFileContents, };
10
+ declare const cleanUpOnExit: (action: () => unknown) => typeof process;
11
+ export { selectOrNavigate, promptStringIfUndefined, promptUrlIfUndefined, promptBooleanIfUndefined, cleanUpOnExit, };
package/dist/utils.js CHANGED
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.readFileContents = exports.promptBooleanIfUndefined = exports.promptUrlIfUndefined = exports.promptStringIfUndefined = exports.selectOrNavigate = void 0;
4
- const confirm_1 = require("@inquirer/confirm");
5
- const input_1 = require("@inquirer/input");
3
+ exports.cleanUpOnExit = exports.promptBooleanIfUndefined = exports.promptUrlIfUndefined = exports.promptStringIfUndefined = exports.selectOrNavigate = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const confirm_1 = tslib_1.__importDefault(require("@inquirer/confirm"));
6
+ const input_1 = tslib_1.__importDefault(require("@inquirer/input"));
6
7
  const core_1 = require("@oclif/core");
7
- const fs = require("fs");
8
- const path = require("path");
9
8
  const selectOrNavigate = async (list, prop) => {
10
9
  const { data, pagination } = list;
11
10
  let prompt = `Select one (${prop})`;
@@ -17,7 +16,9 @@ const selectOrNavigate = async (list, prop) => {
17
16
  if (hasNext) {
18
17
  prompt += " or 'n' for next page ";
19
18
  }
20
- const selection = await core_1.ux.prompt(prompt);
19
+ const selection = await (0, input_1.default)({
20
+ message: prompt,
21
+ });
21
22
  if (selection === 'p' && hasPrevious) {
22
23
  return 'previous';
23
24
  }
@@ -65,5 +66,8 @@ const promptBooleanIfUndefined = (value, options) => {
65
66
  return (0, confirm_1.default)(options);
66
67
  };
67
68
  exports.promptBooleanIfUndefined = promptBooleanIfUndefined;
68
- const readFileContents = (filePath) => fs.readFileSync(path.resolve(process.cwd(), filePath)).toString();
69
- exports.readFileContents = readFileContents;
69
+ const cleanUpOnExit = (action) => process.on('SIGINT', async () => {
70
+ await action();
71
+ process.exit(1);
72
+ });
73
+ exports.cleanUpOnExit = cleanUpOnExit;
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.1",
2
+ "version": "1.4.0",
3
3
  "commands": {
4
4
  "proxies:create": {
5
5
  "id": "proxies:create",
@@ -241,6 +241,14 @@
241
241
  "char": "a",
242
242
  "description": "whether the Proxy requires Basis Theory authentication to be invoked. Default: true",
243
243
  "allowNo": true
244
+ },
245
+ "watch": {
246
+ "name": "watch",
247
+ "type": "boolean",
248
+ "char": "w",
249
+ "description": "Watch for changes in informed files",
250
+ "required": false,
251
+ "allowNo": false
244
252
  }
245
253
  },
246
254
  "args": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basis-theory-labs/cli",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Basis Theory CLI tool",
5
5
  "author": "Davi Aquino @djejaquino",
6
6
  "bin": {
@@ -17,7 +17,7 @@
17
17
  "/oclif.manifest.json"
18
18
  ],
19
19
  "dependencies": {
20
- "@basis-theory/basis-theory-js": "^1.78.1",
20
+ "@basis-theory/basis-theory-js": "^1.79.2",
21
21
  "@inquirer/confirm": "^2.0.3",
22
22
  "@inquirer/input": "^1.2.1",
23
23
  "@inquirer/prompts": "^2.1.1",
@@ -28,6 +28,8 @@
28
28
  "cloudflared": "^0.4.0",
29
29
  "debug": "^4.3.4",
30
30
  "dotenv": "^16.3.1",
31
+ "fastify": "^4.19.2",
32
+ "lodash.debounce": "^4.0.8",
31
33
  "pino": "^8.14.1",
32
34
  "pino-pretty": "^10.0.0",
33
35
  "serialize-error": "^11.0.0",
@@ -44,6 +46,7 @@
44
46
  "@semantic-release/release-notes-generator": "^11.0.3",
45
47
  "@types/chai": "^4",
46
48
  "@types/debug": "^4.1.8",
49
+ "@types/lodash.debounce": "^4.0.7",
47
50
  "@types/mocha": "^9.0.0",
48
51
  "@types/node": "^16.18.36",
49
52
  "chai": "^4",