@quantum-hub/qhubctl 1.1.1 → 1.1.3
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 +1 -1
- package/bin/dev.js +3 -1
- package/bin/run.js +1 -1
- package/dist/client/kqh/apis/ServicePlatformApplicationsApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformApplicationsApi.js +9 -46
- package/dist/client/kqh/apis/ServicePlatformDashboardApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformDashboardApi.js +5 -42
- package/dist/client/kqh/apis/ServicePlatformDataPoolsApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformDataPoolsApi.js +11 -48
- package/dist/client/kqh/apis/ServicePlatformJobsApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformJobsApi.js +9 -46
- package/dist/client/kqh/apis/ServicePlatformMarketplaceApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformMarketplaceApi.js +5 -42
- package/dist/client/kqh/apis/ServicePlatformMeteringAPIApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformMeteringAPIApi.js +5 -42
- package/dist/client/kqh/apis/ServicePlatformServicesApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformServicesApi.js +34 -71
- package/dist/client/kqh/apis/ServicePlatformSubscriptionsApi.d.ts +2 -2
- package/dist/client/kqh/apis/ServicePlatformSubscriptionsApi.js +7 -44
- package/dist/client/kqh/apis/TaxonomiesApi.d.ts +2 -2
- package/dist/client/kqh/apis/TaxonomiesApi.js +12 -49
- package/dist/client/kqh/apis/index.d.ts +9 -9
- package/dist/client/kqh/apis/index.js +9 -25
- package/dist/client/kqh/index.d.ts +3 -3
- package/dist/client/kqh/index.js +3 -19
- package/dist/client/kqh/models/AccessTokenDto.js +5 -12
- package/dist/client/kqh/models/AmountMajorDto.js +4 -10
- package/dist/client/kqh/models/ApiDto.d.ts +2 -2
- package/dist/client/kqh/models/ApiDto.js +13 -20
- package/dist/client/kqh/models/ApiOverviewDto.d.ts +1 -1
- package/dist/client/kqh/models/ApiOverviewDto.js +10 -17
- package/dist/client/kqh/models/ApplicationDto.js +5 -12
- package/dist/client/kqh/models/BuildJobDto.d.ts +1 -1
- package/dist/client/kqh/models/BuildJobDto.js +9 -16
- package/dist/client/kqh/models/CpuConfiguration.d.ts +1 -1
- package/dist/client/kqh/models/CpuConfiguration.js +7 -13
- package/dist/client/kqh/models/CreateApplicationRequest.js +4 -10
- package/dist/client/kqh/models/CreateDataPoolRequest.js +4 -10
- package/dist/client/kqh/models/CreateExternalServicePricingPlanRequest.d.ts +1 -1
- package/dist/client/kqh/models/CreateExternalServicePricingPlanRequest.js +8 -15
- package/dist/client/kqh/models/CreateJobRequest.d.ts +1 -1
- package/dist/client/kqh/models/CreateJobRequest.js +9 -15
- package/dist/client/kqh/models/CreateManagedServicePricingPlanRequest.js +6 -13
- package/dist/client/kqh/models/CreateProductRequest.js +4 -10
- package/dist/client/kqh/models/CreateSubscriptionRequest.js +4 -10
- package/dist/client/kqh/models/CreateWorkflowServiceRequest.js +4 -10
- package/dist/client/kqh/models/DataPoolDto.d.ts +3 -3
- package/dist/client/kqh/models/DataPoolDto.js +21 -28
- package/dist/client/kqh/models/DataPoolRef.js +4 -10
- package/dist/client/kqh/models/DataSourceDescriptorDto.d.ts +1 -1
- package/dist/client/kqh/models/DataSourceDescriptorDto.js +8 -15
- package/dist/client/kqh/models/FileDto.js +4 -10
- package/dist/client/kqh/models/FileSource.d.ts +1 -1
- package/dist/client/kqh/models/FileSource.js +4 -10
- package/dist/client/kqh/models/GpuConfiguration.d.ts +1 -1
- package/dist/client/kqh/models/GpuConfiguration.js +8 -15
- package/dist/client/kqh/models/JobDto.d.ts +2 -2
- package/dist/client/kqh/models/JobDto.js +13 -20
- package/dist/client/kqh/models/JobOverviewDto.d.ts +1 -1
- package/dist/client/kqh/models/JobOverviewDto.js +8 -15
- package/dist/client/kqh/models/MemoryConfiguration.d.ts +1 -1
- package/dist/client/kqh/models/MemoryConfiguration.js +7 -13
- package/dist/client/kqh/models/MeteringRequest.js +4 -10
- package/dist/client/kqh/models/MeteringResponse.js +4 -10
- package/dist/client/kqh/models/MonthAmountDto.d.ts +2 -2
- package/dist/client/kqh/models/MonthAmountDto.js +10 -16
- package/dist/client/kqh/models/OwnerDto.js +4 -10
- package/dist/client/kqh/models/PageDataPoolDto.d.ts +3 -3
- package/dist/client/kqh/models/PageDataPoolDto.js +13 -19
- package/dist/client/kqh/models/PageableObject.d.ts +1 -1
- package/dist/client/kqh/models/PageableObject.js +7 -13
- package/dist/client/kqh/models/PricingPlanDto.d.ts +1 -1
- package/dist/client/kqh/models/PricingPlanDto.js +8 -15
- package/dist/client/kqh/models/ProductAmountDto.d.ts +1 -1
- package/dist/client/kqh/models/ProductAmountDto.js +7 -13
- package/dist/client/kqh/models/ProductDto.js +5 -12
- package/dist/client/kqh/models/ProductGroupDto.d.ts +2 -2
- package/dist/client/kqh/models/ProductGroupDto.js +10 -16
- package/dist/client/kqh/models/ProductUsageDto.js +4 -10
- package/dist/client/kqh/models/RegistrySource.d.ts +1 -1
- package/dist/client/kqh/models/RegistrySource.js +7 -13
- package/dist/client/kqh/models/RepositorySource.d.ts +1 -1
- package/dist/client/kqh/models/RepositorySource.js +7 -13
- package/dist/client/kqh/models/ResourceConfiguration.js +10 -16
- package/dist/client/kqh/models/ReviewDto.js +5 -12
- package/dist/client/kqh/models/RuntimeConfiguration.js +5 -12
- package/dist/client/kqh/models/ServiceDefinitionCommand.js +5 -12
- package/dist/client/kqh/models/ServiceDefinitionDto.d.ts +5 -5
- package/dist/client/kqh/models/ServiceDefinitionDto.js +21 -28
- package/dist/client/kqh/models/ServiceDefinitionDtoSource.d.ts +3 -3
- package/dist/client/kqh/models/ServiceDefinitionDtoSource.js +18 -23
- package/dist/client/kqh/models/ServiceDefinitionOverviewDto.js +6 -13
- package/dist/client/kqh/models/ServiceDto.d.ts +1 -1
- package/dist/client/kqh/models/ServiceDto.js +8 -15
- package/dist/client/kqh/models/ServiceExecutionConsumerDto.js +5 -12
- package/dist/client/kqh/models/ServiceExecutionDto.js +4 -10
- package/dist/client/kqh/models/ServiceOverviewDto.js +8 -15
- package/dist/client/kqh/models/ServiceSource.js +10 -16
- package/dist/client/kqh/models/SortObject.js +4 -10
- package/dist/client/kqh/models/SubscriptionDto.d.ts +3 -3
- package/dist/client/kqh/models/SubscriptionDto.js +13 -19
- package/dist/client/kqh/models/TaxonomyElement.js +4 -10
- package/dist/client/kqh/models/UpdateDataPoolRequest.js +4 -10
- package/dist/client/kqh/models/UpdateResourceConfigurationRequest.d.ts +3 -3
- package/dist/client/kqh/models/UpdateResourceConfigurationRequest.js +18 -23
- package/dist/client/kqh/models/UpdateVersionRequest.d.ts +1 -1
- package/dist/client/kqh/models/UpdateVersionRequest.js +7 -13
- package/dist/client/kqh/models/UpdateWorkflowServiceRequest.js +4 -10
- package/dist/client/kqh/models/ValidationResult.js +5 -12
- package/dist/client/kqh/models/index.d.ts +57 -57
- package/dist/client/kqh/models/index.js +57 -73
- package/dist/client/kqh/runtime.js +17 -32
- package/dist/client/users/apis/AuthenticationApi.d.ts +2 -2
- package/dist/client/users/apis/AuthenticationApi.js +4 -41
- package/dist/client/users/apis/ExpertsApi.d.ts +2 -2
- package/dist/client/users/apis/ExpertsApi.js +5 -42
- package/dist/client/users/apis/SearchApi.d.ts +2 -2
- package/dist/client/users/apis/SearchApi.js +5 -42
- package/dist/client/users/apis/UserSettingsApi.d.ts +2 -2
- package/dist/client/users/apis/UserSettingsApi.js +11 -48
- package/dist/client/users/apis/UserSettingsPersonalAccessTokensApi.d.ts +2 -2
- package/dist/client/users/apis/UserSettingsPersonalAccessTokensApi.js +7 -44
- package/dist/client/users/apis/UsersApi.d.ts +2 -2
- package/dist/client/users/apis/UsersApi.js +4 -41
- package/dist/client/users/apis/index.d.ts +6 -6
- package/dist/client/users/apis/index.js +6 -22
- package/dist/client/users/index.d.ts +3 -3
- package/dist/client/users/index.js +3 -19
- package/dist/client/users/models/AccessTokenCreateRequest.js +5 -12
- package/dist/client/users/models/AccessTokenDto.js +5 -12
- package/dist/client/users/models/AccessTokensResponse.d.ts +1 -1
- package/dist/client/users/models/AccessTokensResponse.js +7 -13
- package/dist/client/users/models/DefaultAccessTokenResponse.js +4 -10
- package/dist/client/users/models/Language.js +4 -10
- package/dist/client/users/models/PageUserDto.d.ts +3 -3
- package/dist/client/users/models/PageUserDto.js +13 -19
- package/dist/client/users/models/Pageable.js +4 -10
- package/dist/client/users/models/PageableObject.d.ts +1 -1
- package/dist/client/users/models/PageableObject.js +7 -13
- package/dist/client/users/models/PersonalAccessTokenPrincipal.d.ts +1 -1
- package/dist/client/users/models/PersonalAccessTokenPrincipal.js +7 -13
- package/dist/client/users/models/Skill.js +4 -10
- package/dist/client/users/models/SortObject.js +4 -10
- package/dist/client/users/models/UpdateUserRequest.js +4 -10
- package/dist/client/users/models/UserDto.d.ts +2 -2
- package/dist/client/users/models/UserDto.js +10 -16
- package/dist/client/users/models/UserOverviewDto.js +4 -10
- package/dist/client/users/models/index.d.ts +14 -14
- package/dist/client/users/models/index.js +14 -30
- package/dist/client/users/runtime.js +17 -32
- package/dist/commands/compress/index.d.ts +1 -1
- package/dist/commands/compress/index.js +13 -19
- package/dist/commands/datapool/upload.d.ts +4 -4
- package/dist/commands/datapool/upload.js +24 -30
- package/dist/commands/get-context/index.d.ts +1 -1
- package/dist/commands/get-context/index.js +2 -5
- package/dist/commands/init/index.d.ts +3 -3
- package/dist/commands/init/index.js +30 -36
- package/dist/commands/list-contexts/index.d.ts +2 -2
- package/dist/commands/list-contexts/index.js +11 -17
- package/dist/commands/login/index.d.ts +3 -3
- package/dist/commands/login/index.js +16 -22
- package/dist/commands/logout/index.d.ts +1 -1
- package/dist/commands/logout/index.js +7 -10
- package/dist/commands/openapi/index.d.ts +7 -7
- package/dist/commands/openapi/index.js +81 -87
- package/dist/commands/run/index.d.ts +6 -6
- package/dist/commands/run/index.js +43 -48
- package/dist/commands/serve/index.d.ts +3 -3
- package/dist/commands/serve/index.js +31 -37
- package/dist/commands/services/index.d.ts +5 -5
- package/dist/commands/services/index.js +17 -23
- package/dist/commands/set-context/index.d.ts +4 -4
- package/dist/commands/set-context/index.js +13 -19
- package/dist/commands/up/index.d.ts +5 -5
- package/dist/commands/up/index.js +51 -57
- package/dist/index.js +1 -4
- package/dist/lib/command.js +5 -10
- package/dist/lib/debug.js +1 -5
- package/dist/lib/entrypoint-resolver.js +3 -7
- package/dist/lib/error.js +8 -12
- package/dist/lib/fetch.js +4 -10
- package/dist/lib/init-user-input.d.ts +1 -1
- package/dist/lib/init-user-input.js +16 -20
- package/dist/lib/random-name.js +1 -5
- package/dist/lib/random-string.js +1 -5
- package/dist/lib/repository.js +9 -17
- package/dist/lib/stream-to-blob.d.ts +1 -1
- package/dist/lib/stream-to-blob.js +1 -5
- package/dist/lib/up/get-description.js +9 -15
- package/dist/lib/up/ignore.js +9 -15
- package/dist/lib/up/zip.js +18 -24
- package/dist/model/account.js +1 -2
- package/dist/model/command.d.ts +2 -2
- package/dist/model/command.js +11 -19
- package/dist/model/managed-service-config.js +4 -7
- package/dist/model/user-config.js +3 -6
- package/dist/service/auth-service.d.ts +3 -3
- package/dist/service/auth-service.js +8 -14
- package/dist/service/command-service.d.ts +2 -2
- package/dist/service/command-service.js +1 -5
- package/dist/service/quantum-hub-service.d.ts +10 -10
- package/dist/service/quantum-hub-service.js +21 -24
- package/dist/service/service-config-service.d.ts +1 -1
- package/dist/service/service-config-service.js +14 -21
- package/dist/service/user-config-service.d.ts +1 -1
- package/dist/service/user-config-service.js +14 -21
- package/dist/service/user-service.d.ts +2 -2
- package/dist/service/user-service.js +8 -11
- package/oclif.manifest.json +170 -170
- package/package.json +4 -2
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const random_string_1 = require("../../lib/random-string");
|
|
13
|
-
const command_2 = require("../../model/command");
|
|
14
|
-
const managed_service_config_1 = require("../../model/managed-service-config");
|
|
15
|
-
const service_config_service_1 = require("../../service/service-config-service");
|
|
16
|
-
class Serve extends command_2.AbstractCommand {
|
|
1
|
+
import { Flags, ux } from '@oclif/core';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import Listr from 'listr';
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import terminalLink from 'terminal-link';
|
|
6
|
+
import { executeAsyncCommand, executeCommand } from '../../lib/command.js';
|
|
7
|
+
import { randomString } from '../../lib/random-string.js';
|
|
8
|
+
import { AbstractCommand } from '../../model/command.js';
|
|
9
|
+
import { Runtime } from "../../model/managed-service-config.js";
|
|
10
|
+
import { readServiceConfig } from "../../service/service-config-service.js";
|
|
11
|
+
export default class Serve extends AbstractCommand {
|
|
17
12
|
static CONTAINER_NAME = 'planqk-cli-serve';
|
|
18
13
|
static IMAGE = 'registry.gitlab.com/planqk-foss/planqk-cli-serve:latest';
|
|
19
14
|
static description = 'Runs your project in a containerized environment and expose it through a ' +
|
|
@@ -25,12 +20,12 @@ class Serve extends command_2.AbstractCommand {
|
|
|
25
20
|
'$ qhubctl serve -p <port> --log_level <log_level>',
|
|
26
21
|
];
|
|
27
22
|
static flags = {
|
|
28
|
-
port:
|
|
23
|
+
port: Flags.integer({
|
|
29
24
|
char: 'p',
|
|
30
25
|
description: 'The port on which the local web server accepts requests',
|
|
31
26
|
required: false,
|
|
32
27
|
}),
|
|
33
|
-
log_level:
|
|
28
|
+
log_level: Flags.string({
|
|
34
29
|
description: 'The log level for the service, possible values: DEBUG, INFO, WARNING, ERROR, CRITICAL',
|
|
35
30
|
required: false,
|
|
36
31
|
default: 'INFO',
|
|
@@ -43,14 +38,14 @@ class Serve extends command_2.AbstractCommand {
|
|
|
43
38
|
if (!this.isProjectSupported()) {
|
|
44
39
|
this.error('Please make sure you have a "./src/program.py" file and "runtime" is set to "PYTHON_TEMPLATE" (qhub.json).');
|
|
45
40
|
}
|
|
46
|
-
const containerName = `${Serve.CONTAINER_NAME}-${
|
|
47
|
-
const tasks = new
|
|
41
|
+
const containerName = `${Serve.CONTAINER_NAME}-${randomString(10)}`;
|
|
42
|
+
const tasks = new Listr([
|
|
48
43
|
{
|
|
49
|
-
task: () =>
|
|
44
|
+
task: () => executeAsyncCommand(`docker pull ${Serve.IMAGE}`),
|
|
50
45
|
title: 'Ensuring latest base image',
|
|
51
46
|
},
|
|
52
47
|
{
|
|
53
|
-
task: () =>
|
|
48
|
+
task: () => executeAsyncCommand(`docker run -e LOG_LEVEL=${logLevel} -e PORT=${hostPort} -p ${hostPort}:${hostPort} -v "$(pwd):/workspace" --name ${containerName} ${Serve.IMAGE}`),
|
|
54
49
|
title: 'Building container',
|
|
55
50
|
},
|
|
56
51
|
{
|
|
@@ -58,18 +53,18 @@ class Serve extends command_2.AbstractCommand {
|
|
|
58
53
|
title: 'Starting container',
|
|
59
54
|
},
|
|
60
55
|
]);
|
|
61
|
-
|
|
56
|
+
ux.stdout('Starting service locally...');
|
|
62
57
|
tasks.run()
|
|
63
58
|
.then(() => {
|
|
64
59
|
const baseUrl = `http://localhost:${hostPort}`;
|
|
65
60
|
const docsUrl = `${baseUrl}/docs`;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
ux.stdout('\nLocal service running at:');
|
|
62
|
+
ux.stdout(terminalLink(baseUrl, baseUrl));
|
|
63
|
+
ux.stdout('\nDocumentation and interactive API client available at:');
|
|
64
|
+
ux.stdout(terminalLink(docsUrl, docsUrl));
|
|
65
|
+
ux.stdout('');
|
|
71
66
|
try {
|
|
72
|
-
|
|
67
|
+
executeCommand(`docker start -i -a ${containerName}`);
|
|
73
68
|
}
|
|
74
69
|
catch {
|
|
75
70
|
this.error(`There might be problems with your dependencies. Don't forget to verify the requirements.txt file`);
|
|
@@ -77,17 +72,16 @@ class Serve extends command_2.AbstractCommand {
|
|
|
77
72
|
})
|
|
78
73
|
.catch(error => this.error(error))
|
|
79
74
|
.finally(() => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return
|
|
75
|
+
ux.stdout('\nStopping and removing container...');
|
|
76
|
+
executeCommand(`docker stop ${containerName} > /dev/null 2>&1`);
|
|
77
|
+
return executeAsyncCommand(`docker rm ${containerName} > /dev/null 2>&1`);
|
|
83
78
|
});
|
|
84
79
|
}
|
|
85
80
|
isProjectSupported() {
|
|
86
|
-
const programFile =
|
|
87
|
-
const hasProgramFile =
|
|
88
|
-
const serviceConfig =
|
|
89
|
-
const isPythonTemplate = serviceConfig.runtime ==
|
|
81
|
+
const programFile = path.join(process.cwd(), 'src', 'program.py');
|
|
82
|
+
const hasProgramFile = fs.existsSync(programFile);
|
|
83
|
+
const serviceConfig = readServiceConfig(process.cwd());
|
|
84
|
+
const isPythonTemplate = serviceConfig.runtime == Runtime.PYTHON_TEMPLATE;
|
|
90
85
|
return isPythonTemplate && hasProgramFile;
|
|
91
86
|
}
|
|
92
87
|
}
|
|
93
|
-
exports.default = Serve;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { AuthenticatedCommand } from '../../model/command';
|
|
2
|
-
import QuantumHubService from '../../service/quantum-hub-service';
|
|
1
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
2
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
3
3
|
export default class Services extends AuthenticatedCommand {
|
|
4
4
|
static readonly description = "List all services of the current context.";
|
|
5
5
|
static readonly examples: string[];
|
|
6
6
|
static readonly flags: {
|
|
7
|
-
json: import("@oclif/core/
|
|
8
|
-
name: import("@oclif/core/
|
|
9
|
-
all: import("@oclif/core/
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
};
|
|
11
11
|
quantumHubService: QuantumHubService;
|
|
12
12
|
init(): Promise<void>;
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const core_1 = require("@oclif/core");
|
|
7
|
-
const tty_table_1 = __importDefault(require("tty-table"));
|
|
8
|
-
const command_1 = require("../../model/command");
|
|
9
|
-
const quantum_hub_service_1 = __importDefault(require("../../service/quantum-hub-service"));
|
|
10
|
-
class Services extends command_1.AuthenticatedCommand {
|
|
1
|
+
import { Flags, ux } from '@oclif/core';
|
|
2
|
+
import Table from "tty-table";
|
|
3
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
4
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
5
|
+
export default class Services extends AuthenticatedCommand {
|
|
11
6
|
static description = 'List all services of the current context.';
|
|
12
7
|
static examples = [
|
|
13
8
|
'$ qhubctl services',
|
|
@@ -17,15 +12,15 @@ class Services extends command_1.AuthenticatedCommand {
|
|
|
17
12
|
'$ qhubctl services --json --all',
|
|
18
13
|
];
|
|
19
14
|
static flags = {
|
|
20
|
-
json:
|
|
15
|
+
json: Flags.boolean({
|
|
21
16
|
description: 'output in JSON format',
|
|
22
17
|
default: false,
|
|
23
18
|
}),
|
|
24
|
-
name:
|
|
19
|
+
name: Flags.string({
|
|
25
20
|
description: 'filter services by name (case-insensitive full match)',
|
|
26
21
|
required: false,
|
|
27
22
|
}),
|
|
28
|
-
all:
|
|
23
|
+
all: Flags.boolean({
|
|
29
24
|
description: 'display all service properties (only available with --json)',
|
|
30
25
|
default: false,
|
|
31
26
|
}),
|
|
@@ -34,17 +29,17 @@ class Services extends command_1.AuthenticatedCommand {
|
|
|
34
29
|
async init() {
|
|
35
30
|
const { flags } = await this.parse(Services);
|
|
36
31
|
await super.init(!flags.json);
|
|
37
|
-
this.quantumHubService = new
|
|
32
|
+
this.quantumHubService = new QuantumHubService(this, this.config, this.userConfig);
|
|
38
33
|
}
|
|
39
34
|
async run() {
|
|
40
35
|
const { flags } = await this.parse(Services);
|
|
41
36
|
// Validate flag combinations
|
|
42
37
|
if (flags.all && !flags.json) {
|
|
43
|
-
|
|
38
|
+
ux.warn('The --all flag can only be used with --json output. Continuing without --all.');
|
|
44
39
|
}
|
|
45
|
-
|
|
40
|
+
ux.action.start('Loading services');
|
|
46
41
|
let services = await this.quantumHubService.getServices();
|
|
47
|
-
|
|
42
|
+
ux.action.stop('Done');
|
|
48
43
|
// Filter by name if provided
|
|
49
44
|
if (flags.name) {
|
|
50
45
|
const nameFilter = flags.name.toLowerCase();
|
|
@@ -53,19 +48,18 @@ class Services extends command_1.AuthenticatedCommand {
|
|
|
53
48
|
const tableData = services
|
|
54
49
|
.map(service => ({ id: service.id, name: service.name }));
|
|
55
50
|
if (flags.json) {
|
|
56
|
-
|
|
51
|
+
ux.stdout(JSON.stringify(flags.all ? services : tableData, null, 2));
|
|
57
52
|
return;
|
|
58
53
|
}
|
|
59
54
|
const header = [
|
|
60
55
|
{ value: "id", alias: "ID", align: "left" },
|
|
61
56
|
{ value: "name", alias: "Name", align: "left" },
|
|
62
57
|
];
|
|
63
|
-
const t = (
|
|
58
|
+
const t = Table(header, tableData);
|
|
64
59
|
const contextName = this.userConfig.context?.displayName;
|
|
65
60
|
const filterInfo = flags.name ? ` (filtered by name: "${flags.name}")` : '';
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
61
|
+
ux.stdout(`Available services for ${contextName}${filterInfo}:`);
|
|
62
|
+
ux.stdout(t.render());
|
|
63
|
+
ux.stdout();
|
|
69
64
|
}
|
|
70
65
|
}
|
|
71
|
-
exports.default = Services;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import Account from '../../model/account';
|
|
2
|
-
import { AuthenticatedCommand } from '../../model/command';
|
|
3
|
-
import QuantumHubService from '../../service/quantum-hub-service';
|
|
1
|
+
import Account from '../../model/account.js';
|
|
2
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
3
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
4
4
|
export default class SetContext extends AuthenticatedCommand {
|
|
5
5
|
static args: {
|
|
6
|
-
contextId: import("@oclif/core/
|
|
6
|
+
contextId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
7
7
|
};
|
|
8
8
|
static description: string;
|
|
9
9
|
static examples: string[];
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
-
const command_1 = require("../../model/command");
|
|
9
|
-
const quantum_hub_service_1 = __importDefault(require("../../service/quantum-hub-service"));
|
|
10
|
-
const user_config_service_1 = require("../../service/user-config-service");
|
|
11
|
-
class SetContext extends command_1.AuthenticatedCommand {
|
|
1
|
+
import { Args, ux } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
4
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
5
|
+
import { writeUserConfig } from '../../service/user-config-service.js';
|
|
6
|
+
export default class SetContext extends AuthenticatedCommand {
|
|
12
7
|
static args = {
|
|
13
|
-
contextId:
|
|
8
|
+
contextId: Args.string(),
|
|
14
9
|
};
|
|
15
10
|
static description = 'Set the current context, i.e., the personal or organization account you are currently working with.';
|
|
16
11
|
static examples = [
|
|
@@ -30,24 +25,24 @@ class SetContext extends command_1.AuthenticatedCommand {
|
|
|
30
25
|
}
|
|
31
26
|
async init() {
|
|
32
27
|
await super.init();
|
|
33
|
-
this.quantumHubService = new
|
|
28
|
+
this.quantumHubService = new QuantumHubService(this, this.config, this.userConfig);
|
|
34
29
|
}
|
|
35
30
|
async run() {
|
|
36
31
|
const { args } = await this.parse(SetContext);
|
|
37
32
|
const { contextId } = args;
|
|
38
33
|
let selectedContext;
|
|
39
34
|
if (!contextId) {
|
|
40
|
-
|
|
35
|
+
ux.action.start('Loading available contexts');
|
|
41
36
|
}
|
|
42
37
|
const accounts = await this.quantumHubService.getAccounts();
|
|
43
38
|
if (!contextId) {
|
|
44
|
-
|
|
39
|
+
ux.action.stop('Done');
|
|
45
40
|
}
|
|
46
41
|
if (contextId) {
|
|
47
42
|
selectedContext = accounts.find(account => account.id === contextId);
|
|
48
43
|
}
|
|
49
44
|
else {
|
|
50
|
-
const response = await
|
|
45
|
+
const response = await inquirer.prompt({
|
|
51
46
|
choices: this.getPromptOptions(accounts),
|
|
52
47
|
message: 'Choose a context',
|
|
53
48
|
name: 'context',
|
|
@@ -62,8 +57,7 @@ class SetContext extends command_1.AuthenticatedCommand {
|
|
|
62
57
|
...this.userConfig,
|
|
63
58
|
context: selectedContext,
|
|
64
59
|
};
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
writeUserConfig(this.config.configDir, userConfig);
|
|
61
|
+
ux.stdout(`Switched to context "${selectedContext?.displayName}".`);
|
|
67
62
|
}
|
|
68
63
|
}
|
|
69
|
-
exports.default = SetContext;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { AuthenticatedCommand } from '../../model/command';
|
|
2
|
-
import QuantumHubService from '../../service/quantum-hub-service';
|
|
1
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
2
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
3
3
|
export default class Up extends AuthenticatedCommand {
|
|
4
4
|
static description: string;
|
|
5
5
|
static examples: string[];
|
|
6
6
|
static flags: {
|
|
7
|
-
silent: import("@oclif/core/
|
|
8
|
-
'no-save-id': import("@oclif/core/
|
|
9
|
-
name: import("@oclif/core/
|
|
7
|
+
silent: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
'no-save-id': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
};
|
|
11
11
|
qhubService: QuantumHubService;
|
|
12
12
|
getOpenapi(): Promise<Blob | undefined>;
|
|
@@ -1,21 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const zip_1 = require("../../lib/up/zip");
|
|
15
|
-
const command_1 = require("../../model/command");
|
|
16
|
-
const quantum_hub_service_1 = __importDefault(require("../../service/quantum-hub-service"));
|
|
17
|
-
const service_config_service_1 = require("../../service/service-config-service");
|
|
18
|
-
class Up extends command_1.AuthenticatedCommand {
|
|
1
|
+
import { confirm } from '@inquirer/prompts';
|
|
2
|
+
import { Flags, ux } from '@oclif/core';
|
|
3
|
+
import { waitUntil } from 'async-wait-until';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { BuildJobDtoStatusEnum, BuildJobDtoStepEnum, ValidationResultStateEnum, } from '../../client/kqh/index.js';
|
|
7
|
+
import { streamToBlob } from '../../lib/stream-to-blob.js';
|
|
8
|
+
import { getDescriptionText } from '../../lib/up/get-description.js';
|
|
9
|
+
import { zipProjectFolder } from '../../lib/up/zip.js';
|
|
10
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
11
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
12
|
+
import { readServiceConfig, writeServiceConfig } from '../../service/service-config-service.js';
|
|
13
|
+
export default class Up extends AuthenticatedCommand {
|
|
19
14
|
static description = 'Creates or updates a service';
|
|
20
15
|
static examples = [
|
|
21
16
|
'$ qhubctl up',
|
|
@@ -24,64 +19,64 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
24
19
|
'$ qhubctl up --name "test-service" --no-save-id',
|
|
25
20
|
];
|
|
26
21
|
static flags = {
|
|
27
|
-
silent:
|
|
22
|
+
silent: Flags.boolean({
|
|
28
23
|
description: 'Suppresses all outputs, helpful when executed in a CI/CD pipeline.',
|
|
29
24
|
required: false,
|
|
30
25
|
}),
|
|
31
|
-
'no-save-id':
|
|
26
|
+
'no-save-id': Flags.boolean({
|
|
32
27
|
description: 'Prevents storing the created service ID in qhub.json file.',
|
|
33
28
|
required: false,
|
|
34
29
|
}),
|
|
35
|
-
name:
|
|
30
|
+
name: Flags.string({
|
|
36
31
|
description: 'Override the service name from qhub.json with a custom name.',
|
|
37
32
|
required: false,
|
|
38
33
|
}),
|
|
39
34
|
};
|
|
40
35
|
qhubService;
|
|
41
36
|
async getOpenapi() {
|
|
42
|
-
const openapiYamlPath =
|
|
43
|
-
const openapiYmlPath =
|
|
37
|
+
const openapiYamlPath = path.join(process.cwd(), 'openapi.yaml');
|
|
38
|
+
const openapiYmlPath = path.join(process.cwd(), 'openapi.yml');
|
|
44
39
|
let openapi = undefined;
|
|
45
|
-
if (
|
|
46
|
-
openapi =
|
|
40
|
+
if (fs.existsSync(openapiYamlPath)) {
|
|
41
|
+
openapi = fs.createReadStream(openapiYamlPath, 'utf8');
|
|
47
42
|
}
|
|
48
|
-
else if (
|
|
49
|
-
openapi =
|
|
43
|
+
else if (fs.existsSync(openapiYmlPath)) {
|
|
44
|
+
openapi = fs.createReadStream(openapiYmlPath, 'utf8');
|
|
50
45
|
}
|
|
51
46
|
if (openapi) {
|
|
52
|
-
return
|
|
47
|
+
return streamToBlob(openapi);
|
|
53
48
|
}
|
|
54
49
|
return undefined;
|
|
55
50
|
}
|
|
56
51
|
async init() {
|
|
57
52
|
await super.init();
|
|
58
|
-
this.qhubService = new
|
|
53
|
+
this.qhubService = new QuantumHubService(this, this.config, this.userConfig);
|
|
59
54
|
}
|
|
60
55
|
async run() {
|
|
61
56
|
const { flags } = await this.parse(Up);
|
|
62
|
-
const serviceConfig =
|
|
57
|
+
const serviceConfig = readServiceConfig(process.cwd());
|
|
63
58
|
let createNewService = true;
|
|
64
59
|
const silentMode = flags.silent;
|
|
65
60
|
if (!('descriptionFile' in serviceConfig)) {
|
|
66
|
-
|
|
61
|
+
ux.stdout('Warning: Since version 2.14.0, the "description" property in qhub.json has changed to "descriptionFile".\nFor more information, visit: https://docs.hub.kipu-quantum.com/qhub-json-reference.html\n');
|
|
67
62
|
}
|
|
68
|
-
const deprecatedOpenapiFile =
|
|
69
|
-
if (
|
|
70
|
-
|
|
63
|
+
const deprecatedOpenapiFile = path.join(process.cwd(), 'openapi-spec.yml');
|
|
64
|
+
if (fs.existsSync(deprecatedOpenapiFile)) {
|
|
65
|
+
ux.warn('You are having the deprecated file "openapi-spec.yml" in your project. Please consider renaming it to "openapi.yaml".');
|
|
71
66
|
}
|
|
72
67
|
// if service already exists we update it
|
|
73
68
|
const serviceExistsInPlatform = await this.checkIfServiceExistsInPlatform(serviceConfig);
|
|
74
69
|
if (serviceConfig.serviceId && !serviceExistsInPlatform) {
|
|
75
|
-
|
|
76
|
-
createNewService = await
|
|
70
|
+
ux.stdout(`We could not find a service with id '${serviceConfig.serviceId}' in the current context!`);
|
|
71
|
+
createNewService = await confirm({ message: 'Do you want to create a new service?' });
|
|
77
72
|
if (!createNewService) {
|
|
78
73
|
this.exit();
|
|
79
74
|
}
|
|
80
75
|
}
|
|
81
76
|
const serviceFiles = {
|
|
82
77
|
openapi: await this.getOpenapi(),
|
|
83
|
-
descriptionText: await
|
|
84
|
-
sourceCode: await
|
|
78
|
+
descriptionText: await getDescriptionText(process.cwd()),
|
|
79
|
+
sourceCode: await zipProjectFolder('./'),
|
|
85
80
|
};
|
|
86
81
|
const service = serviceExistsInPlatform ?
|
|
87
82
|
await this.updateService(serviceConfig, serviceFiles, silentMode) :
|
|
@@ -91,35 +86,35 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
91
86
|
this.error('Service definition not found');
|
|
92
87
|
}
|
|
93
88
|
const buildJob = await this.buildServiceJob(service, serviceDefinition, silentMode);
|
|
94
|
-
if (buildJob && buildJob.status ===
|
|
89
|
+
if (buildJob && buildJob.status === BuildJobDtoStatusEnum.Success) {
|
|
95
90
|
const msg = `Service ${serviceExistsInPlatform ? 'updated' : 'created'} \u{1F680}`;
|
|
96
91
|
if (silentMode) {
|
|
97
|
-
|
|
92
|
+
ux.stdout(msg);
|
|
98
93
|
}
|
|
99
94
|
else {
|
|
100
|
-
|
|
95
|
+
ux.action.stop(msg);
|
|
101
96
|
}
|
|
102
97
|
}
|
|
103
|
-
else if (buildJob && buildJob.status ===
|
|
98
|
+
else if (buildJob && buildJob.status === BuildJobDtoStatusEnum.Failure) {
|
|
104
99
|
const { validationResult } = buildJob;
|
|
105
100
|
let reason = 'Failed creating service';
|
|
106
|
-
if (validationResult?.state ===
|
|
101
|
+
if (validationResult?.state === ValidationResultStateEnum.Error && validationResult.summary) {
|
|
107
102
|
reason = `${reason}: ${validationResult.summary}`;
|
|
108
103
|
}
|
|
109
104
|
if (silentMode) {
|
|
110
|
-
|
|
105
|
+
ux.stdout(reason);
|
|
111
106
|
}
|
|
112
107
|
else {
|
|
113
|
-
|
|
108
|
+
ux.action.stop(reason);
|
|
114
109
|
}
|
|
115
110
|
}
|
|
116
111
|
else {
|
|
117
112
|
const msg = 'Still pending, please check the platform UI to determine the status';
|
|
118
113
|
if (silentMode) {
|
|
119
|
-
|
|
114
|
+
ux.stdout(msg);
|
|
120
115
|
}
|
|
121
116
|
else {
|
|
122
|
-
|
|
117
|
+
ux.action.stop(msg);
|
|
123
118
|
}
|
|
124
119
|
}
|
|
125
120
|
this.exit();
|
|
@@ -127,17 +122,17 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
127
122
|
async buildServiceJob(service, serviceDefinition, silentMode) {
|
|
128
123
|
let buildJob;
|
|
129
124
|
try {
|
|
130
|
-
await
|
|
125
|
+
await waitUntil(async () => {
|
|
131
126
|
buildJob = await this.qhubService.getBuildJob(service, serviceDefinition);
|
|
132
127
|
if (!silentMode) {
|
|
133
|
-
if (buildJob.step ===
|
|
134
|
-
|
|
128
|
+
if (buildJob.step === BuildJobDtoStepEnum.BuildImage) {
|
|
129
|
+
ux.action.start('Building Image (1/2)');
|
|
135
130
|
}
|
|
136
|
-
else if (buildJob.step ===
|
|
137
|
-
|
|
131
|
+
else if (buildJob.step === BuildJobDtoStepEnum.PushImage) {
|
|
132
|
+
ux.action.start('Pushing Image (2/2)');
|
|
138
133
|
}
|
|
139
134
|
}
|
|
140
|
-
return buildJob.status ===
|
|
135
|
+
return buildJob.status === BuildJobDtoStatusEnum.Success || buildJob.status === BuildJobDtoStatusEnum.Failure;
|
|
141
136
|
}, {
|
|
142
137
|
intervalBetweenAttempts: 5000, // every 5 seconds
|
|
143
138
|
timeout: silentMode ? 60 * 60 * 1000 : 20 * 60 * 1000, // silent mode: 60 minutes, normal: 20 minutes
|
|
@@ -162,7 +157,7 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
162
157
|
}
|
|
163
158
|
async createService(serviceConfig, files, silentMode, noSaveId = false, customName) {
|
|
164
159
|
if (!silentMode) {
|
|
165
|
-
|
|
160
|
+
ux.action.start('Creating service');
|
|
166
161
|
}
|
|
167
162
|
// Override the service name if custom name is provided
|
|
168
163
|
const configToUse = { ...serviceConfig };
|
|
@@ -174,7 +169,7 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
174
169
|
serviceConfig.serviceId = service?.id;
|
|
175
170
|
// Only persist to file if not using no-save-id flag
|
|
176
171
|
if (!noSaveId) {
|
|
177
|
-
|
|
172
|
+
writeServiceConfig(process.cwd(), serviceConfig);
|
|
178
173
|
}
|
|
179
174
|
// update description separately when creating a new service
|
|
180
175
|
if (files.descriptionText) {
|
|
@@ -188,9 +183,8 @@ class Up extends command_1.AuthenticatedCommand {
|
|
|
188
183
|
}
|
|
189
184
|
async updateService(serviceConfig, files, silentMode) {
|
|
190
185
|
if (!silentMode) {
|
|
191
|
-
|
|
186
|
+
ux.action.start('Updating service');
|
|
192
187
|
}
|
|
193
188
|
return this.qhubService.updateService(serviceConfig, files.descriptionText, files.sourceCode, files.openapi);
|
|
194
189
|
}
|
|
195
190
|
}
|
|
196
|
-
exports.default = Up;
|
package/dist/index.js
CHANGED
package/dist/lib/command.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.executeCommand = exports.executeAsyncCommand = void 0;
|
|
4
|
-
const node_child_process_1 = require("node:child_process");
|
|
5
|
-
const executeAsyncCommand = async (command) => {
|
|
1
|
+
import { exec, execSync } from "node:child_process";
|
|
2
|
+
export const executeAsyncCommand = async (command) => {
|
|
6
3
|
return new Promise((resolve, reject) => {
|
|
7
|
-
|
|
4
|
+
exec(command, (error, stdout, stderr) => {
|
|
8
5
|
if (error) {
|
|
9
6
|
reject(error);
|
|
10
7
|
}
|
|
@@ -14,8 +11,6 @@ const executeAsyncCommand = async (command) => {
|
|
|
14
11
|
});
|
|
15
12
|
});
|
|
16
13
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(0, node_child_process_1.execSync)(`${command}`, { stdio: stdioOption ?? 'inherit' });
|
|
14
|
+
export const executeCommand = (command, stdioOption) => {
|
|
15
|
+
execSync(`${command}`, { stdio: stdioOption ?? 'inherit' });
|
|
20
16
|
};
|
|
21
|
-
exports.executeCommand = executeCommand;
|
package/dist/lib/debug.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.debugEnabled = void 0;
|
|
4
|
-
const debugEnabled = () => Boolean(process.env.DEBUG && process.env.DEBUG !== '');
|
|
5
|
-
exports.debugEnabled = debugEnabled;
|
|
1
|
+
export const debugEnabled = () => Boolean(process.env.DEBUG && process.env.DEBUG !== '');
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.EntrypointResolver = void 0;
|
|
4
|
-
const core_1 = require("@oclif/core");
|
|
5
|
-
class EntrypointResolver {
|
|
1
|
+
import { ux } from '@oclif/core';
|
|
2
|
+
export class EntrypointResolver {
|
|
6
3
|
/**
|
|
7
4
|
* Resolves the entrypoint string from various flag combinations.
|
|
8
5
|
* Defaults to "src.program:run" if no flags are provided.
|
|
@@ -53,7 +50,7 @@ class EntrypointResolver {
|
|
|
53
50
|
this.validateObjectPath(objectPath, entrypoint);
|
|
54
51
|
// Warn if object path starts with underscore (private methods/classes)
|
|
55
52
|
if (objectPath.startsWith('_')) {
|
|
56
|
-
|
|
53
|
+
ux.warn(`Object "${objectPath}" starts with underscore. Make sure this is intended for a private object.`);
|
|
57
54
|
}
|
|
58
55
|
}
|
|
59
56
|
/**
|
|
@@ -122,4 +119,3 @@ class EntrypointResolver {
|
|
|
122
119
|
return entrypoint.split(':')[1];
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
|
-
exports.EntrypointResolver = EntrypointResolver;
|
package/dist/lib/error.js
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const handleError = async (error) => {
|
|
8
|
-
if (error instanceof kqh_1.ResponseError) {
|
|
9
|
-
return (0, fetch_1.getErrorMessage)(error.response);
|
|
1
|
+
import { FetchError, ResponseError } from '../client/kqh/index.js';
|
|
2
|
+
import { debugEnabled } from './debug.js';
|
|
3
|
+
import { getErrorMessage } from './fetch.js';
|
|
4
|
+
export const handleError = async (error) => {
|
|
5
|
+
if (error instanceof ResponseError) {
|
|
6
|
+
return getErrorMessage(error.response);
|
|
10
7
|
}
|
|
11
|
-
if (error instanceof
|
|
8
|
+
if (error instanceof FetchError) {
|
|
12
9
|
const errorMessage = error.cause ? error.cause.message : error.message;
|
|
13
10
|
return `Internal error occurred, please try again later (${errorMessage})`;
|
|
14
11
|
}
|
|
15
|
-
if (
|
|
12
|
+
if (debugEnabled()) {
|
|
16
13
|
console.error(JSON.stringify(error));
|
|
17
14
|
}
|
|
18
15
|
return 'Internal error occurred, please contact your KQH administrator';
|
|
19
16
|
};
|
|
20
|
-
exports.handleError = handleError;
|