@govuk-pay/cli 0.0.31 → 0.0.33
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/package.json +3 -3
- package/resources/pay-local/templates/docker-compose.hbs +4 -1
- package/src/commands/browse.js +19 -70
- package/src/commands/browse.spec.js +15 -48
- package/src/commands/demo.js +8 -2
- package/src/commands/legacy.js +12 -16
- package/src/commands/local/app_client/app_client.js +232 -0
- package/src/commands/local/app_client/fetch_wrapper.js +106 -0
- package/src/commands/local/config/pay_local_cluster.js +17 -10
- package/src/commands/local/subcommands/account.js +52 -0
- package/src/commands/local/subcommands/browse.js +47 -0
- package/src/commands/local/subcommands/db.js +90 -0
- package/src/commands/local/subcommands/down.js +26 -15
- package/src/commands/local/subcommands/nuke.js +11 -5
- package/src/commands/local/subcommands/otp.js +16 -14
- package/src/commands/local/subcommands/payment.js +81 -0
- package/src/commands/local/subcommands/paymentlink.js +47 -0
- package/src/commands/local/subcommands/restart.js +22 -19
- package/src/commands/local/subcommands/token.js +64 -0
- package/src/commands/local/subcommands/up.js +77 -19
- package/src/commands/local/subcommands/url.js +49 -0
- package/src/commands/local/subcommands/user.js +102 -0
- package/src/commands/local.js +9 -96
- package/src/commands/tunnel.js +17 -28
- package/src/core/commandRouter.js +11 -69
- package/src/core/standardContent.js +1 -5
- package/resources/usageDetails.txt +0 -9
- package/src/commands/help.js +0 -15
|
@@ -3,18 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.loadClusterConfig = exports.PayLocalCluster = void 0;
|
|
6
|
+
exports.loadServicesConfig = exports.loadClusterConfig = exports.PayLocalCluster = exports.CLUSTERS = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const yaml_1 = __importDefault(require("yaml"));
|
|
10
10
|
const md5_js_1 = require("../../../util/md5.js");
|
|
11
|
+
exports.CLUSTERS = ['all', 'admin', 'card', 'paymentlinks', 'webhooks', 'endtoend', 'java', 'toolbox'];
|
|
11
12
|
// This is the complete cluster configuration that will be used as the context for template rendering
|
|
12
13
|
class PayLocalCluster {
|
|
13
14
|
name;
|
|
14
15
|
payServices;
|
|
15
16
|
dbServices;
|
|
16
17
|
reverseProxyServices;
|
|
17
|
-
egressProxy;
|
|
18
18
|
javaApps;
|
|
19
19
|
nodeApps;
|
|
20
20
|
localJavaApps;
|
|
@@ -29,6 +29,7 @@ class PayLocalCluster {
|
|
|
29
29
|
requiresEgressProxy;
|
|
30
30
|
serviceURLEnvVars;
|
|
31
31
|
mountLocalNodeApps;
|
|
32
|
+
mountPayJSCommons;
|
|
32
33
|
noProxyEnvVar;
|
|
33
34
|
defaultServiceConfigsPath;
|
|
34
35
|
environmentOverridesPath;
|
|
@@ -38,7 +39,6 @@ class PayLocalCluster {
|
|
|
38
39
|
this.payServices = clusterConfig.payServices;
|
|
39
40
|
this.dbServices = clusterConfig.dbServices;
|
|
40
41
|
this.reverseProxyServices = clusterConfig.reverseProxyServices;
|
|
41
|
-
this.egressProxy = clusterConfig.egressProxy;
|
|
42
42
|
this.javaApps = this.payServices.filter((service) => service.serviceType === PayServiceType.Java);
|
|
43
43
|
this.nodeApps = this.payServices.filter((service) => service.serviceType === PayServiceType.Node);
|
|
44
44
|
this.remoteJavaApps = this.javaApps.filter((service) => service.localBuild);
|
|
@@ -49,8 +49,9 @@ class PayLocalCluster {
|
|
|
49
49
|
this.anyNodeApps = this.nodeApps.length >= 0;
|
|
50
50
|
this.requiresLocalStack = this.payServices.some((service) => service.requiresLocalStack);
|
|
51
51
|
this.requiresRedis = this.payServices.some((service) => service.usesRedis);
|
|
52
|
-
this.requiresEgressProxy =
|
|
52
|
+
this.requiresEgressProxy = clusterConfig.egressProxy;
|
|
53
53
|
this.mountLocalNodeApps = clusterConfig.mountLocalNodeApps;
|
|
54
|
+
this.mountPayJSCommons = clusterConfig.mountPayJSCommons;
|
|
54
55
|
this.serviceURLEnvVars = [
|
|
55
56
|
this.javaApps.map((javaService) => envVarForJavaService(javaService)),
|
|
56
57
|
this.nodeApps.map((nodeService) => envVarForNodeService(nodeService))
|
|
@@ -64,7 +65,7 @@ class PayLocalCluster {
|
|
|
64
65
|
this.payServices.map((service) => service.name),
|
|
65
66
|
this.dbServices.map((service) => service.name),
|
|
66
67
|
this.reverseProxyServices.map((service) => service.name),
|
|
67
|
-
this.
|
|
68
|
+
this.requiresEgressProxy ? [] : ['egress']
|
|
68
69
|
].flat().join(',');
|
|
69
70
|
this.environmentOverridesPath = clusterConfig.environmentOverridesPath;
|
|
70
71
|
this.defaultServiceConfigsPath = clusterConfig.defaultServiceConfigsPath;
|
|
@@ -89,9 +90,7 @@ var PayServiceType;
|
|
|
89
90
|
PayServiceType["Node"] = "node";
|
|
90
91
|
})(PayServiceType || (PayServiceType = {}));
|
|
91
92
|
function loadClusterConfig(options, workspace, defaultServiceConfigsPath, environmentOverridesPath) {
|
|
92
|
-
const
|
|
93
|
-
const serviceConfigFileContents = node_fs_1.default.readFileSync(servicesConfigPath, 'utf8');
|
|
94
|
-
const servicesConfig = yaml_1.default.parse(serviceConfigFileContents);
|
|
93
|
+
const servicesConfig = loadServicesConfig();
|
|
95
94
|
const payServices = [];
|
|
96
95
|
for (const [, serviceConfig] of Object.entries(servicesConfig)) {
|
|
97
96
|
if (includeAppInCluster(options.cluster, options, serviceConfig)) {
|
|
@@ -116,15 +115,23 @@ function loadClusterConfig(options, workspace, defaultServiceConfigsPath, enviro
|
|
|
116
115
|
name: options.cluster,
|
|
117
116
|
payServices,
|
|
118
117
|
dbServices,
|
|
118
|
+
egressProxy: options.withEgressProxy,
|
|
119
119
|
reverseProxyServices,
|
|
120
120
|
workspace,
|
|
121
|
-
mountLocalNodeApps: options.
|
|
121
|
+
mountLocalNodeApps: options.mountLocalNodeApps,
|
|
122
|
+
mountPayJSCommons: options.mountPayJSCommons,
|
|
122
123
|
defaultServiceConfigsPath,
|
|
123
124
|
environmentOverridesPath
|
|
124
125
|
};
|
|
125
126
|
return new PayLocalCluster(clusterConfig);
|
|
126
127
|
}
|
|
127
128
|
exports.loadClusterConfig = loadClusterConfig;
|
|
129
|
+
function loadServicesConfig() {
|
|
130
|
+
const servicesConfigPath = node_path_1.default.join(__dirname, '..', '..', '..', '..', 'resources', 'pay-local', 'config', 'service_config.yaml');
|
|
131
|
+
const serviceConfigFileContents = node_fs_1.default.readFileSync(servicesConfigPath, 'utf8');
|
|
132
|
+
return yaml_1.default.parse(serviceConfigFileContents);
|
|
133
|
+
}
|
|
134
|
+
exports.loadServicesConfig = loadServicesConfig;
|
|
128
135
|
function includeAppInCluster(cluster, options, serviceConfig) {
|
|
129
136
|
if (cluster === 'all' || cluster === 'nuke' || serviceConfig.clusters.includes(cluster)) {
|
|
130
137
|
if (options.apps.length === 0 || options.apps.includes(serviceConfig.name)) {
|
|
@@ -166,7 +173,7 @@ function payServiceFromPayServiceConfig(config, upOptions, environmentOverridesP
|
|
|
166
173
|
hasSNSTopics: snsTopics.length > 0,
|
|
167
174
|
hasProxy: config.proxy === undefined ? false : config.proxy,
|
|
168
175
|
hasDB: config.db,
|
|
169
|
-
useEgressProxy: config.can_use_egress_proxy === undefined ? false : config.can_use_egress_proxy && upOptions.
|
|
176
|
+
useEgressProxy: config.can_use_egress_proxy === undefined ? false : config.can_use_egress_proxy && upOptions.withEgressProxy,
|
|
170
177
|
dependsOn: config.db ? [`${config.name}_db`] : [],
|
|
171
178
|
expose: [],
|
|
172
179
|
payServiceConfig: config,
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
7
|
+
const app_client_js_1 = __importDefault(require("../app_client/app_client.js"));
|
|
8
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
9
|
+
exports.command = 'account';
|
|
10
|
+
exports.desc = 'Create a local gateway account';
|
|
11
|
+
const builder = (yargs) => {
|
|
12
|
+
return yargs.usage(`$0 local account [--service-id <SERVICE_ID>]\n\n${exports.desc}`)
|
|
13
|
+
.option('service-id', {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'ID of an existing service'
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
exports.builder = builder;
|
|
19
|
+
exports.handler = accountHandler;
|
|
20
|
+
async function accountHandler(argv) {
|
|
21
|
+
await (0, standardContent_1.showHeader)();
|
|
22
|
+
const serviceId = argv.serviceId;
|
|
23
|
+
if (await app_client_js_1.default.isUnhealthy('adminusers')) {
|
|
24
|
+
console.error('The adminusers service is unhealthy, so an account cannot be created');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (await app_client_js_1.default.isUnhealthy('connector')) {
|
|
28
|
+
console.error('The connector service is unhealthy, so an account cannot be created');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
let serviceExternalId;
|
|
32
|
+
if (serviceId === undefined) {
|
|
33
|
+
serviceExternalId = await app_client_js_1.default.createService();
|
|
34
|
+
if (serviceExternalId === undefined) {
|
|
35
|
+
console.error('Service creation failed');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
serviceExternalId = serviceId;
|
|
41
|
+
}
|
|
42
|
+
if (serviceExternalId === undefined) {
|
|
43
|
+
throw new Error('Service external ID is undefined, this should be impossible');
|
|
44
|
+
}
|
|
45
|
+
const account = await app_client_js_1.default.createAccountInServiceWithEmailCollectionMode(serviceExternalId, 'MANDATORY');
|
|
46
|
+
if (account === undefined) {
|
|
47
|
+
console.error('Failed to create a fully set up account');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
console.log(account);
|
|
51
|
+
}
|
|
52
|
+
exports.default = accountHandler;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const app_client_js_1 = __importDefault(require("../app_client/app_client.js"));
|
|
9
|
+
const pay_local_cluster_js_1 = require("../config/pay_local_cluster.js");
|
|
10
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
11
|
+
exports.command = 'browse <service>';
|
|
12
|
+
exports.desc = 'Browse to local service';
|
|
13
|
+
const builder = (yargs) => {
|
|
14
|
+
return yargs
|
|
15
|
+
.usage(`$0 local browse <service> [--proxy]\n\n${exports.desc}`)
|
|
16
|
+
.positional('service', {
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'service'
|
|
19
|
+
})
|
|
20
|
+
.option('proxy', {
|
|
21
|
+
type: 'boolean',
|
|
22
|
+
default: false,
|
|
23
|
+
description: 'Opens the service via the local proxy for the service'
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
exports.builder = builder;
|
|
27
|
+
exports.handler = browseHandler;
|
|
28
|
+
async function browseHandler(argv) {
|
|
29
|
+
await (0, standardContent_1.showHeader)();
|
|
30
|
+
const service = argv.service;
|
|
31
|
+
const proxy = argv.proxy;
|
|
32
|
+
const servicesConfig = (0, pay_local_cluster_js_1.loadServicesConfig)();
|
|
33
|
+
if (!(service in servicesConfig)) {
|
|
34
|
+
console.error(`The service specified (${service}) was not defined in the service_config.yaml file`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const serviceConfig = servicesConfig[service];
|
|
38
|
+
const url = app_client_js_1.default.externalUrlFor(service, '/', proxy);
|
|
39
|
+
(0, node_child_process_1.spawn)('open', [url]);
|
|
40
|
+
if (await app_client_js_1.default.isHealthy(serviceConfig.name)) {
|
|
41
|
+
console.log(`📋 “${url}” opened`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error(`❌ “${url}” opened, however the app did not respond successfully to ${url}/healthcheck`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.default = browseHandler;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const pay_local_cluster_js_1 = require("../config/pay_local_cluster.js");
|
|
6
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
7
|
+
exports.command = 'db <app_name>';
|
|
8
|
+
exports.desc = 'Connect to <app_name> database';
|
|
9
|
+
const builder = (yargs) => {
|
|
10
|
+
return yargs
|
|
11
|
+
.usage(`$0 local db <app_name> [--docker]\n\n${exports.desc}`)
|
|
12
|
+
.positional('app_name', {
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: 'service'
|
|
15
|
+
})
|
|
16
|
+
.option('docker', {
|
|
17
|
+
type: 'boolean',
|
|
18
|
+
default: false,
|
|
19
|
+
description: 'Launch psql inside the apps database container (no psql history)'
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
exports.builder = builder;
|
|
23
|
+
exports.handler = dbHandler;
|
|
24
|
+
async function dbHandler(argv) {
|
|
25
|
+
await (0, standardContent_1.showHeader)();
|
|
26
|
+
const service = argv.app_name;
|
|
27
|
+
const docker = argv.docker;
|
|
28
|
+
const servicesConfig = (0, pay_local_cluster_js_1.loadServicesConfig)();
|
|
29
|
+
if (!(service in servicesConfig)) {
|
|
30
|
+
console.error(`The service specified (${service}) was not defined in the service_config.yaml file`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const serviceConfig = servicesConfig[service];
|
|
34
|
+
if (!serviceConfig.db) {
|
|
35
|
+
console.error(`The service specified (${serviceConfig.name}) does not have a database`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (docker) {
|
|
39
|
+
launchPsqlInDocker(serviceConfig);
|
|
40
|
+
}
|
|
41
|
+
else if (!psqlAvailable()) {
|
|
42
|
+
console.warn('PSQL installation not found locally.');
|
|
43
|
+
launchPsqlInDocker(serviceConfig);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
launchPsql(serviceConfig);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.default = dbHandler;
|
|
50
|
+
function psqlAvailable() {
|
|
51
|
+
const psqlCheck = (0, node_child_process_1.spawnSync)('command', ['-v', 'psql'], { shell: true });
|
|
52
|
+
if (psqlCheck.status === 0) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
function launchPsqlInDocker(serviceConfig) {
|
|
58
|
+
console.log('Running psql in running app db container.');
|
|
59
|
+
console.log('Note: This means you wont have a psql history, and one will not survive restarts of pay local');
|
|
60
|
+
(0, node_child_process_1.spawn)('docker', [
|
|
61
|
+
'exec',
|
|
62
|
+
'-e', 'PGPASSWORD=mysecretpassword', // pragma: allowlist secret
|
|
63
|
+
'-e', 'PGSSLMODE=disable',
|
|
64
|
+
'-ti',
|
|
65
|
+
`${serviceConfig.name}_db`,
|
|
66
|
+
'psql',
|
|
67
|
+
'--host', `${serviceConfig.name}_db`,
|
|
68
|
+
'--user', serviceConfig.name,
|
|
69
|
+
'--dbname', serviceConfig.name
|
|
70
|
+
], { stdio: 'inherit', shell: true });
|
|
71
|
+
}
|
|
72
|
+
function launchPsql(serviceConfig) {
|
|
73
|
+
if (serviceConfig.db_port === undefined) {
|
|
74
|
+
throw new Error(`Service config for ${serviceConfig.name} is missing db_port specification`);
|
|
75
|
+
}
|
|
76
|
+
(0, node_child_process_1.spawn)('psql', [
|
|
77
|
+
'--host', '127.0.0.1',
|
|
78
|
+
'--port', `${serviceConfig.db_port}`,
|
|
79
|
+
'--user', serviceConfig.name,
|
|
80
|
+
'--dbname', serviceConfig.name
|
|
81
|
+
], {
|
|
82
|
+
stdio: 'inherit',
|
|
83
|
+
shell: true,
|
|
84
|
+
env: {
|
|
85
|
+
...process.env,
|
|
86
|
+
PGPASSWORD: 'mysecretpassword', // pragma: allowlist secret
|
|
87
|
+
PGSSLMODE: 'disable'
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -3,34 +3,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.composeFileToDown = exports.ENVIRONMENT_OVERRIDES_PATH = exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = void 0;
|
|
6
|
+
exports.composeFileToDown = exports.handler = exports.builder = exports.desc = exports.command = exports.ENVIRONMENT_OVERRIDES_PATH = exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
9
|
const configs_js_1 = require("../../../util/configs.js");
|
|
10
10
|
const last_up_record_js_1 = require("../config/last_up_record.js");
|
|
11
11
|
const docker_compose_controller_js_1 = __importDefault(require("../docker_compose_controller.js"));
|
|
12
|
+
const pay_local_cluster_js_1 = require("../config/pay_local_cluster.js");
|
|
13
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
12
14
|
exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = node_path_1.default.join('local', 'docker-compose', 'rendered-templates');
|
|
13
15
|
exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = node_path_1.default.join('local', 'docker-compose', 'default-configs-DO-NOT-EDIT');
|
|
14
16
|
exports.ENVIRONMENT_OVERRIDES_PATH = node_path_1.default.join('local', 'environment-overrides');
|
|
15
|
-
|
|
17
|
+
exports.command = 'down';
|
|
18
|
+
exports.desc = 'Bring down a cluster';
|
|
19
|
+
const builder = (yargs) => {
|
|
20
|
+
return yargs
|
|
21
|
+
.usage(`$0 local down [--cluster <cluster>]\n\n${exports.desc}`)
|
|
22
|
+
.option('cluster', {
|
|
23
|
+
type: 'string',
|
|
24
|
+
description: 'Cluster to bring down',
|
|
25
|
+
choices: pay_local_cluster_js_1.CLUSTERS
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
exports.builder = builder;
|
|
29
|
+
exports.handler = downHandler;
|
|
30
|
+
async function downHandler(argv) {
|
|
31
|
+
await (0, standardContent_1.showHeader)();
|
|
32
|
+
const { cluster } = argv;
|
|
16
33
|
const renderedTempaltesPath = (0, configs_js_1.ensureConfigDirectory)(exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH);
|
|
17
|
-
const
|
|
18
|
-
const composeFilePath = composeFileToDown(args, renderedTempaltesPath);
|
|
34
|
+
const composeFilePath = composeFileToDown(cluster, renderedTempaltesPath);
|
|
19
35
|
const composeFileName = node_path_1.default.basename(composeFilePath);
|
|
20
36
|
const clusterToDown = composeFileName.substring(0, composeFileName.lastIndexOf('.yaml'));
|
|
21
37
|
console.log(`Bringing down cluster ${clusterToDown}`);
|
|
22
38
|
docker_compose_controller_js_1.default.down(composeFilePath);
|
|
23
39
|
}
|
|
24
|
-
exports.default =
|
|
25
|
-
function composeFileToDown(
|
|
26
|
-
if (
|
|
27
|
-
const clusterFilePath = node_path_1.default.resolve(renderedTemplatesPath, `${
|
|
40
|
+
exports.default = downHandler;
|
|
41
|
+
function composeFileToDown(cluster, renderedTemplatesPath) {
|
|
42
|
+
if (cluster !== undefined) {
|
|
43
|
+
const clusterFilePath = node_path_1.default.resolve(renderedTemplatesPath, `${cluster}.yaml`);
|
|
28
44
|
if (node_fs_1.default.existsSync(clusterFilePath)) {
|
|
29
45
|
return clusterFilePath;
|
|
30
46
|
}
|
|
31
|
-
throw new Error(`Cannot bring down cluster '${
|
|
47
|
+
throw new Error(`Cannot bring down cluster '${cluster}' since it does not have a rendered docker-compose template in ${renderedTemplatesPath}.\n` +
|
|
32
48
|
'\n' +
|
|
33
|
-
`Perhaps you don't have a cluster running, or the cluster that is running isn't ${
|
|
49
|
+
`Perhaps you don't have a cluster running, or the cluster that is running isn't ${cluster}\n`);
|
|
34
50
|
}
|
|
35
51
|
const mostRecentUpFile = (0, last_up_record_js_1.getLastUp)(renderedTemplatesPath);
|
|
36
52
|
if (mostRecentUpFile !== undefined) {
|
|
@@ -49,8 +65,3 @@ function composeFileToDown(downOptions, renderedTemplatesPath) {
|
|
|
49
65
|
'Perhaps you do not have a running cluster, or you need to `pay local down --cluster <cluster>` specifying the last cluster you launched\n');
|
|
50
66
|
}
|
|
51
67
|
exports.composeFileToDown = composeFileToDown;
|
|
52
|
-
function parseArguments(_options) {
|
|
53
|
-
return {
|
|
54
|
-
cluster: 'card'
|
|
55
|
-
};
|
|
56
|
-
}
|
|
@@ -3,26 +3,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ENVIRONMENT_OVERRIDES_PATH = exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = void 0;
|
|
6
|
+
exports.handler = exports.desc = exports.command = exports.ENVIRONMENT_OVERRIDES_PATH = exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = void 0;
|
|
7
7
|
const up_js_1 = __importDefault(require("./up.js"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const docker_compose_controller_js_1 = __importDefault(require("../docker_compose_controller.js"));
|
|
10
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
10
11
|
exports.DOCKER_COMPOSE_RENDERED_TEMPALTES_PATH = node_path_1.default.join('local', 'docker-compose', 'rendered-templates');
|
|
11
12
|
exports.DOCKER_COMPOSE_SERVICES_CONFIG_PATH = node_path_1.default.join('local', 'docker-compose', 'default-configs-DO-NOT-EDIT');
|
|
12
13
|
exports.ENVIRONMENT_OVERRIDES_PATH = node_path_1.default.join('local', 'environment-overrides');
|
|
13
|
-
|
|
14
|
+
exports.command = 'nuke';
|
|
15
|
+
exports.desc = 'Kill and completely destroy all containers previously started by pay local';
|
|
16
|
+
exports.handler = nukeHandler;
|
|
17
|
+
async function nukeHandler(argv) {
|
|
18
|
+
await (0, standardContent_1.showHeader)();
|
|
14
19
|
const upOptions = {
|
|
15
20
|
cluster: 'nuke',
|
|
16
21
|
proxy: true,
|
|
17
|
-
|
|
22
|
+
withEgressProxy: true,
|
|
18
23
|
apps: [],
|
|
19
24
|
local: [],
|
|
20
25
|
rebuild: false,
|
|
21
26
|
pull: false,
|
|
22
|
-
|
|
27
|
+
mountLocalNodeApps: false,
|
|
28
|
+
mountPayJSCommons: false
|
|
23
29
|
};
|
|
24
30
|
const renderedTemplatePath = await (0, up_js_1.default)(upOptions, true);
|
|
25
31
|
console.log('Nuking cluster');
|
|
26
32
|
docker_compose_controller_js_1.default.nuke(renderedTemplatePath);
|
|
27
33
|
}
|
|
28
|
-
exports.default =
|
|
34
|
+
exports.default = nukeHandler;
|
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
3
4
|
const node_child_process_1 = require("node:child_process");
|
|
4
5
|
const totp_generator_1 = require("totp-generator");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
7
|
+
exports.command = 'opt <key>';
|
|
8
|
+
exports.desc = 'Create otp code';
|
|
9
|
+
const builder = (yargs) => {
|
|
10
|
+
return yargs.positional('key', {
|
|
11
|
+
type: 'string',
|
|
12
|
+
description: 'otp key'
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
exports.builder = builder;
|
|
16
|
+
exports.handler = otpHandler;
|
|
17
|
+
async function otpHandler(argv) {
|
|
18
|
+
await (0, standardContent_1.showHeader)();
|
|
19
|
+
const { otp } = totp_generator_1.TOTP.generate(argv.key);
|
|
8
20
|
console.log(otp);
|
|
9
21
|
copyToClipboard(otp);
|
|
10
22
|
console.log(`📋 “${otp}” copied to clipboard`);
|
|
11
23
|
}
|
|
12
|
-
exports.default =
|
|
13
|
-
function parseArguments(options) {
|
|
14
|
-
if (options.length !== 1) {
|
|
15
|
-
help();
|
|
16
|
-
throw new Error('No key specified');
|
|
17
|
-
}
|
|
18
|
-
return { secret: options[0].trimEnd() };
|
|
19
|
-
}
|
|
24
|
+
exports.default = otpHandler;
|
|
20
25
|
function copyToClipboard(otp) {
|
|
21
26
|
const proc = (0, node_child_process_1.spawn)('pbcopy');
|
|
22
27
|
proc.stdin.write(otp);
|
|
23
28
|
proc.stdin.end();
|
|
24
29
|
}
|
|
25
|
-
function help() {
|
|
26
|
-
console.log('Usage: pay local otp <otp_secret_key>');
|
|
27
|
-
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const app_client_js_1 = __importDefault(require("../app_client/app_client.js"));
|
|
9
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
10
|
+
exports.command = 'payment';
|
|
11
|
+
exports.desc = 'Create a payment';
|
|
12
|
+
const builder = (yargs) => {
|
|
13
|
+
return yargs
|
|
14
|
+
.usage(`$0 local payment [--api-key <api-key>] [--email-collection-mode <email-collection-mode>]\n\n${exports.desc}`)
|
|
15
|
+
.option('api-key', {
|
|
16
|
+
type: 'string',
|
|
17
|
+
description: 'API Key'
|
|
18
|
+
}).option('email-collection-mode', {
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: 'MANDATORY',
|
|
21
|
+
choices: ['MANDATORY', 'OPTIONAL', 'OFF'],
|
|
22
|
+
description: 'Email collection mode to use'
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
exports.builder = builder;
|
|
26
|
+
exports.handler = paymentHandler;
|
|
27
|
+
async function paymentHandler(argv) {
|
|
28
|
+
await (0, standardContent_1.showHeader)();
|
|
29
|
+
let apiKey = argv.apiKey;
|
|
30
|
+
if (await app_client_js_1.default.isUnhealthy('connector')) {
|
|
31
|
+
console.error('The connector service is unhealthy, so a payment cannot be created');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (await app_client_js_1.default.isUnhealthy('publicapi')) {
|
|
35
|
+
console.error('The publicapi service is unhealthy, so a payment cannot be created');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (apiKey === undefined) {
|
|
39
|
+
console.warn('👔 Creating gateway account and service');
|
|
40
|
+
console.warn();
|
|
41
|
+
if (await app_client_js_1.default.isUnhealthy('adminusers')) {
|
|
42
|
+
console.error('The adminusers service is unhealthy, so a gateway account cannot be created to enable a payment to be created');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const serviceExternalID = await app_client_js_1.default.createService();
|
|
46
|
+
if (serviceExternalID === undefined) {
|
|
47
|
+
console.error('Unable to create a service');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const account = await app_client_js_1.default.createAccountInServiceWithEmailCollectionMode(serviceExternalID, argv.emailCollectionMode);
|
|
51
|
+
if (account === undefined) {
|
|
52
|
+
console.error('Failed to create a fully set up account');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const createTokenResult = await app_client_js_1.default.createToken(account.gateway_account_id);
|
|
56
|
+
if (createTokenResult === undefined) {
|
|
57
|
+
console.error('Failed to create an api token');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
apiKey = createTokenResult;
|
|
61
|
+
console.warn(`🆔 Gateway account ID: ${account.gateway_account_id}`);
|
|
62
|
+
console.warn(`💁 Service ID: ${serviceExternalID}`);
|
|
63
|
+
console.warn();
|
|
64
|
+
}
|
|
65
|
+
const createPaymentResult = await app_client_js_1.default.createPayment(apiKey);
|
|
66
|
+
if (createPaymentResult === undefined) {
|
|
67
|
+
console.error('Failed to create a payment');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
console.warn(`💷 Payment ID: ${createPaymentResult.payment_id}`);
|
|
71
|
+
console.warn(`🎫 API token: ${apiKey}`);
|
|
72
|
+
console.warn();
|
|
73
|
+
const nextUrl = createPaymentResult._links.next_url?.href;
|
|
74
|
+
if (nextUrl === undefined) {
|
|
75
|
+
console.error('The response from creating the payment did not include a next_url link');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
console.log(`Opening next_url (${nextUrl} in your browser`);
|
|
79
|
+
(0, node_child_process_1.spawn)('open', [nextUrl]);
|
|
80
|
+
}
|
|
81
|
+
exports.default = paymentHandler;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handler = exports.builder = exports.desc = exports.command = void 0;
|
|
7
|
+
const node_child_process_1 = __importDefault(require("node:child_process"));
|
|
8
|
+
const app_client_js_1 = __importDefault(require("../app_client/app_client.js"));
|
|
9
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
10
|
+
exports.command = 'paymentlink';
|
|
11
|
+
exports.desc = 'Create a payment link';
|
|
12
|
+
const builder = (yargs) => {
|
|
13
|
+
return yargs
|
|
14
|
+
.usage(`$0 local paymentlink --api-key <api-key>\n\n${exports.desc}`)
|
|
15
|
+
.option('api-key', {
|
|
16
|
+
demandOption: true,
|
|
17
|
+
type: 'string',
|
|
18
|
+
description: 'API Key'
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
exports.builder = builder;
|
|
22
|
+
exports.handler = paymentLinkHandler;
|
|
23
|
+
async function paymentLinkHandler(argv) {
|
|
24
|
+
await (0, standardContent_1.showHeader)();
|
|
25
|
+
const apiKey = argv.apiKey;
|
|
26
|
+
if (await app_client_js_1.default.isUnhealthy('products')) {
|
|
27
|
+
console.error('The products service is unhealthy, so a payment link cannot be created');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
else if (await app_client_js_1.default.isUnhealthy('products-ui')) {
|
|
31
|
+
console.error('The products-ui service is unhealthy, so a payment link cannot be created');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const paymentLinks = await app_client_js_1.default.createPaymentLink(apiKey);
|
|
35
|
+
if (paymentLinks === undefined) {
|
|
36
|
+
console.error('Payment link creation failed');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
paymentLinks.forEach((link) => { console.log(`${link.method} ${link.rel}: ${link.href}`); });
|
|
40
|
+
const payLink = paymentLinks.find((link) => link.rel === 'pay');
|
|
41
|
+
if (payLink === undefined) {
|
|
42
|
+
console.error('The response to create a payment link did not include a link with the rel of "pay"');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
node_child_process_1.default.spawn('open', [payLink.href]);
|
|
46
|
+
}
|
|
47
|
+
exports.default = paymentLinkHandler;
|
|
@@ -3,33 +3,36 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.handler = exports.builder = exports.desc = exports.command = exports.DOCKER_COMPOSE_RENDERED_TEMPLATES_PATH = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const configs_js_1 = require("../../../util/configs.js");
|
|
9
9
|
const last_up_record_js_1 = require("../config/last_up_record.js");
|
|
10
10
|
const docker_compose_controller_js_1 = __importDefault(require("../docker_compose_controller.js"));
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const standardContent_1 = require("../../../core/standardContent");
|
|
12
|
+
exports.DOCKER_COMPOSE_RENDERED_TEMPLATES_PATH = node_path_1.default.join('local', 'docker-compose', 'rendered-templates');
|
|
13
|
+
exports.command = 'restart <app>';
|
|
14
|
+
exports.desc = 'Restart a container and waits for it to be healthy';
|
|
15
|
+
const builder = (yargs) => {
|
|
16
|
+
return yargs
|
|
17
|
+
.usage(`$0 local restart <app>\n\n${exports.desc}`)
|
|
18
|
+
.positional('app', {
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: 'App to restart'
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
exports.builder = builder;
|
|
24
|
+
exports.handler = restartHandler;
|
|
25
|
+
async function restartHandler(argv) {
|
|
26
|
+
await (0, standardContent_1.showHeader)();
|
|
27
|
+
const service = argv.app;
|
|
28
|
+
const renderedTempaltesPath = (0, configs_js_1.ensureConfigDirectory)(exports.DOCKER_COMPOSE_RENDERED_TEMPLATES_PATH);
|
|
15
29
|
const composeFilePath = (0, last_up_record_js_1.getLastUp)(renderedTempaltesPath);
|
|
16
30
|
if (composeFilePath === undefined) {
|
|
17
31
|
throw new Error('Cannot find the docker-compose file for the running cluster');
|
|
18
32
|
}
|
|
19
33
|
const composeFileName = node_path_1.default.basename(composeFilePath);
|
|
20
34
|
const clusterName = composeFileName.substring(0, composeFileName.lastIndexOf('.yaml'));
|
|
21
|
-
console.log(`\nRestarting '${
|
|
22
|
-
docker_compose_controller_js_1.default.restart(composeFilePath,
|
|
23
|
-
}
|
|
24
|
-
exports.default = DownHandler;
|
|
25
|
-
function parseArguments(options) {
|
|
26
|
-
if (options.length !== 1) {
|
|
27
|
-
throw new Error('Incorrect number of arguments, expected 1 to restart command\n' +
|
|
28
|
-
'\n' +
|
|
29
|
-
' Usage: pay local restart <service>\n' +
|
|
30
|
-
'\n');
|
|
31
|
-
}
|
|
32
|
-
return {
|
|
33
|
-
service: options[0]
|
|
34
|
-
};
|
|
35
|
+
console.log(`\nRestarting '${service} in cluster ${clusterName}`);
|
|
36
|
+
docker_compose_controller_js_1.default.restart(composeFilePath, service);
|
|
35
37
|
}
|
|
38
|
+
exports.default = restartHandler;
|