@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,24 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const fetch_1 = require("../../lib/fetch");
|
|
13
|
-
const random_string_1 = require("../../lib/random-string");
|
|
14
|
-
const command_2 = require("../../model/command");
|
|
15
|
-
const managed_service_config_1 = require("../../model/managed-service-config");
|
|
16
|
-
const service_config_service_1 = require("../../service/service-config-service");
|
|
1
|
+
import { confirm } from "@inquirer/prompts";
|
|
2
|
+
import { Flags, ux } from '@oclif/core';
|
|
3
|
+
import fs from "fs-extra";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { executeAsyncCommand } from "../../lib/command.js";
|
|
6
|
+
import { EntrypointResolver } from "../../lib/entrypoint-resolver.js";
|
|
7
|
+
import { fetchOrThrow } from "../../lib/fetch.js";
|
|
8
|
+
import { randomString } from "../../lib/random-string.js";
|
|
9
|
+
import { AbstractCommand } from '../../model/command.js';
|
|
10
|
+
import { Runtime } from "../../model/managed-service-config.js";
|
|
11
|
+
import { readServiceConfig } from "../../service/service-config-service.js";
|
|
17
12
|
const SUPPORTED_FORMATS = ['yaml'];
|
|
18
13
|
const DEFAULT_TEMPLATE_URL = 'https://docs.hub.kipu-quantum.com/files/openapi-service.yaml';
|
|
19
14
|
const DEFAULT_OUTPUT_FILE = 'openapi.yaml';
|
|
20
15
|
const DEPRECATED_FILE_NAME = 'openapi-spec.yml';
|
|
21
|
-
class Openapi extends
|
|
16
|
+
export default class Openapi extends AbstractCommand {
|
|
22
17
|
static description = 'Generates the OpenAPI description for your project based on the parameter and return types of your run() method. ' +
|
|
23
18
|
'The output of this command will be used when creating or updating your service. ' +
|
|
24
19
|
'Supports PYTHON_TEMPLATE (with src/program.py), PYTHON and DOCKER runtimes (with explicit entrypoint). ' +
|
|
@@ -31,29 +26,29 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
31
26
|
'$ qhubctl openapi --package=src.program',
|
|
32
27
|
];
|
|
33
28
|
static flags = {
|
|
34
|
-
force:
|
|
29
|
+
force: Flags.boolean({
|
|
35
30
|
char: 'f',
|
|
36
31
|
description: 'Overwrite the output file if it already exists',
|
|
37
32
|
required: false,
|
|
38
33
|
}),
|
|
39
|
-
file:
|
|
34
|
+
file: Flags.string({
|
|
40
35
|
description: 'The file to write the OpenAPI description to',
|
|
41
36
|
required: false,
|
|
42
37
|
}),
|
|
43
|
-
format:
|
|
38
|
+
format: Flags.string({
|
|
44
39
|
description: `The format to generate the OpenAPI description [possible values: ${SUPPORTED_FORMATS.join(', ')}]`,
|
|
45
40
|
required: false,
|
|
46
41
|
options: [...SUPPORTED_FORMATS]
|
|
47
42
|
}),
|
|
48
|
-
entrypoint:
|
|
43
|
+
entrypoint: Flags.string({
|
|
49
44
|
description: 'The entrypoint to your program in the format "package.module:function" (default: "src.program:run"). Overrides package and method flags.',
|
|
50
45
|
required: false,
|
|
51
46
|
}),
|
|
52
|
-
package:
|
|
47
|
+
package: Flags.string({
|
|
53
48
|
description: 'The package/module path to your program (e.g., "src.program" or "my_package.main"). Only used if entrypoint is not provided.',
|
|
54
49
|
required: false,
|
|
55
50
|
}),
|
|
56
|
-
method:
|
|
51
|
+
method: Flags.string({
|
|
57
52
|
description: 'The method/function name in your program (default: "run"). Only used if entrypoint is not provided.',
|
|
58
53
|
required: false,
|
|
59
54
|
}),
|
|
@@ -68,7 +63,7 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
68
63
|
// Validate and resolve entrypoint (throws error if invalid)
|
|
69
64
|
let entrypoint;
|
|
70
65
|
try {
|
|
71
|
-
entrypoint =
|
|
66
|
+
entrypoint = EntrypointResolver.resolveEntrypoint(flags);
|
|
72
67
|
}
|
|
73
68
|
catch (error) {
|
|
74
69
|
const errorMessage = this.getErrorMessage(error);
|
|
@@ -77,12 +72,12 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
77
72
|
const outputPath = await this.determineOutputPath(flags);
|
|
78
73
|
const shouldGenerateFile = this.isProjectSupported(flags);
|
|
79
74
|
if (!shouldGenerateFile) {
|
|
80
|
-
|
|
75
|
+
ux.warn(`Cannot generate OpenAPI description from your code. Supported configurations:
|
|
81
76
|
• PYTHON_TEMPLATE runtime with "./src/program.py" file
|
|
82
77
|
• DOCKER, PYTHON, or PYTHON_TEMPLATE runtimes with explicit entrypoint (--entrypoint, or (--package, --method))`);
|
|
83
78
|
return;
|
|
84
79
|
}
|
|
85
|
-
|
|
80
|
+
ux.action.start('Generating OpenAPI description');
|
|
86
81
|
let fileContent;
|
|
87
82
|
if (shouldGenerateFile) {
|
|
88
83
|
fileContent = await this.generateFromCode(entrypoint);
|
|
@@ -91,11 +86,11 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
91
86
|
fileContent = await this.fetchDefaultTemplate();
|
|
92
87
|
}
|
|
93
88
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
fs.writeFileSync(outputPath, fileContent, 'utf8');
|
|
90
|
+
ux.action.stop('Done');
|
|
96
91
|
}
|
|
97
92
|
catch (error) {
|
|
98
|
-
|
|
93
|
+
ux.action.stop('Failed');
|
|
99
94
|
const errorMessage = this.getErrorMessage(error);
|
|
100
95
|
throw new Error(`Failed to write file ${outputPath}: ${errorMessage}`);
|
|
101
96
|
}
|
|
@@ -120,21 +115,21 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
120
115
|
typeof error.message === 'string');
|
|
121
116
|
}
|
|
122
117
|
checkDeprecatedFiles() {
|
|
123
|
-
const deprecatedFile =
|
|
124
|
-
if (
|
|
125
|
-
|
|
118
|
+
const deprecatedFile = path.join(process.cwd(), DEPRECATED_FILE_NAME);
|
|
119
|
+
if (fs.existsSync(deprecatedFile)) {
|
|
120
|
+
ux.warn(`Found deprecated file "${DEPRECATED_FILE_NAME}". Consider renaming it to "${DEFAULT_OUTPUT_FILE}".`);
|
|
126
121
|
}
|
|
127
122
|
}
|
|
128
123
|
async determineOutputPath(flags) {
|
|
129
|
-
const defaultPath =
|
|
130
|
-
const outputPath = flags.file ?
|
|
131
|
-
const outputExists =
|
|
124
|
+
const defaultPath = path.join(process.cwd(), DEFAULT_OUTPUT_FILE);
|
|
125
|
+
const outputPath = flags.file ? path.resolve(flags.file) : defaultPath;
|
|
126
|
+
const outputExists = fs.existsSync(outputPath);
|
|
132
127
|
// Create output directory if it doesn't exist
|
|
133
128
|
if (flags.file) {
|
|
134
|
-
const outputDir =
|
|
135
|
-
if (!
|
|
129
|
+
const outputDir = path.dirname(outputPath);
|
|
130
|
+
if (!fs.existsSync(outputDir)) {
|
|
136
131
|
try {
|
|
137
|
-
|
|
132
|
+
fs.mkdirpSync(outputDir);
|
|
138
133
|
}
|
|
139
134
|
catch (error) {
|
|
140
135
|
const errorMessage = this.getErrorMessage(error);
|
|
@@ -143,13 +138,13 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
143
138
|
}
|
|
144
139
|
}
|
|
145
140
|
if (outputExists && !flags.force) {
|
|
146
|
-
const shouldOverwrite = await
|
|
147
|
-
message: `File "${
|
|
141
|
+
const shouldOverwrite = await confirm({
|
|
142
|
+
message: `File "${path.basename(outputPath)}" already exists. Overwrite?`,
|
|
148
143
|
default: false
|
|
149
144
|
});
|
|
150
145
|
if (!shouldOverwrite) {
|
|
151
|
-
const newPath =
|
|
152
|
-
|
|
146
|
+
const newPath = path.join(path.dirname(outputPath), `${path.basename(outputPath, '.yaml')}-${randomString(5)}.yaml`);
|
|
147
|
+
ux.stdout(`Creating new file: ${path.basename(newPath)}`);
|
|
153
148
|
return newPath;
|
|
154
149
|
}
|
|
155
150
|
}
|
|
@@ -161,13 +156,13 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
161
156
|
let title = "Service API";
|
|
162
157
|
let description;
|
|
163
158
|
try {
|
|
164
|
-
serviceConfig =
|
|
159
|
+
serviceConfig = readServiceConfig(process.cwd());
|
|
165
160
|
title = serviceConfig.name || "Service API";
|
|
166
161
|
description = serviceConfig.summary || '';
|
|
167
162
|
}
|
|
168
163
|
catch {
|
|
169
164
|
// If we can't read the config, use defaults but continue
|
|
170
|
-
|
|
165
|
+
ux.warn(`Could not load qhub.json configuration. Using default title: ${title}`);
|
|
171
166
|
}
|
|
172
167
|
// Escape parameters to prevent command injection
|
|
173
168
|
const safeEntrypoint = entrypoint.replace(/"/g, '\\"');
|
|
@@ -176,7 +171,7 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
176
171
|
// Build Python command with title and description parameters
|
|
177
172
|
const command = `python -c "from qhub.commons.openapi.generator import generate_openapi; generate_openapi(entrypoint='${safeEntrypoint}', title='${safeTitle}', description=${safeDescription === 'None' ? 'None' : `'${safeDescription}'`})"`;
|
|
178
173
|
try {
|
|
179
|
-
const result = await
|
|
174
|
+
const result = await executeAsyncCommand(command);
|
|
180
175
|
const { stdout } = this.validateCommandResult(result);
|
|
181
176
|
return stdout;
|
|
182
177
|
}
|
|
@@ -225,7 +220,7 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
225
220
|
}
|
|
226
221
|
async fetchDefaultTemplate() {
|
|
227
222
|
try {
|
|
228
|
-
const response = await
|
|
223
|
+
const response = await fetchOrThrow(DEFAULT_TEMPLATE_URL, { method: 'GET' });
|
|
229
224
|
return await response.text();
|
|
230
225
|
}
|
|
231
226
|
catch (error) {
|
|
@@ -234,31 +229,31 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
234
229
|
}
|
|
235
230
|
}
|
|
236
231
|
displaySuccess(outputPath) {
|
|
237
|
-
const relativePath =
|
|
232
|
+
const relativePath = path.relative(process.cwd(), outputPath);
|
|
238
233
|
const displayPath = relativePath.startsWith('..') ? outputPath : relativePath;
|
|
239
|
-
|
|
240
|
-
|
|
234
|
+
ux.stdout('');
|
|
235
|
+
ux.stdout(`OpenAPI description created: ${displayPath}`);
|
|
241
236
|
// Provide next steps
|
|
242
|
-
if (
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
237
|
+
if (fs.statSync(outputPath).size > 0) {
|
|
238
|
+
ux.stdout('');
|
|
239
|
+
ux.stdout('Next steps:');
|
|
240
|
+
ux.stdout(' • Review the generated OpenAPI description');
|
|
241
|
+
ux.stdout(' • Use it to create or update your service');
|
|
247
242
|
}
|
|
248
243
|
}
|
|
249
244
|
isProjectSupported(flags) {
|
|
250
245
|
let serviceConfig;
|
|
251
246
|
try {
|
|
252
|
-
serviceConfig =
|
|
247
|
+
serviceConfig = readServiceConfig(process.cwd());
|
|
253
248
|
}
|
|
254
249
|
catch (error) {
|
|
255
250
|
const errorMessage = this.getErrorMessage(error);
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
ux.warn(`Failed to read project configuration: ${errorMessage}`);
|
|
252
|
+
ux.warn('Ensure you have a valid qhub.json file in your project root.');
|
|
258
253
|
return false;
|
|
259
254
|
}
|
|
260
255
|
const hasExplicitEntrypoint = !!(flags.entrypoint || flags.package || flags.method);
|
|
261
|
-
const supportedRuntimes = [
|
|
256
|
+
const supportedRuntimes = [Runtime.PYTHON_TEMPLATE, Runtime.PYTHON, Runtime.DOCKER];
|
|
262
257
|
if (hasExplicitEntrypoint) {
|
|
263
258
|
const isSupported = supportedRuntimes.includes(serviceConfig.runtime);
|
|
264
259
|
if (!isSupported) {
|
|
@@ -267,9 +262,9 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
267
262
|
return isSupported;
|
|
268
263
|
}
|
|
269
264
|
// Default behavior: only PYTHON_TEMPLATE with program.py file
|
|
270
|
-
const programFile =
|
|
271
|
-
const hasProgramFile =
|
|
272
|
-
const isPythonTemplate = serviceConfig.runtime ===
|
|
265
|
+
const programFile = path.join(process.cwd(), 'src', 'program.py');
|
|
266
|
+
const hasProgramFile = fs.existsSync(programFile);
|
|
267
|
+
const isPythonTemplate = serviceConfig.runtime === Runtime.PYTHON_TEMPLATE;
|
|
273
268
|
const isSupported = isPythonTemplate && hasProgramFile;
|
|
274
269
|
if (!isSupported) {
|
|
275
270
|
this.showConfigurationHelp(serviceConfig.runtime, isPythonTemplate, hasProgramFile);
|
|
@@ -277,37 +272,36 @@ class Openapi extends command_2.AbstractCommand {
|
|
|
277
272
|
return isSupported;
|
|
278
273
|
}
|
|
279
274
|
showRuntimeNotSupportedWarning(currentRuntime) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
275
|
+
ux.warn(`Runtime "${currentRuntime}" is not supported for OpenAPI generation.`);
|
|
276
|
+
ux.warn('');
|
|
277
|
+
ux.warn('Supported configurations:');
|
|
278
|
+
ux.warn(' • PYTHON_TEMPLATE: Automatic (requires src/program.py)');
|
|
279
|
+
ux.warn(' • PYTHON/DOCKER: With explicit entrypoint flags');
|
|
280
|
+
ux.warn('');
|
|
281
|
+
ux.warn('Examples:');
|
|
282
|
+
ux.warn(' qhubctl openapi --entrypoint=myapp.main:handler');
|
|
283
|
+
ux.warn(' qhubctl openapi --package=myapp.core --method=process');
|
|
289
284
|
}
|
|
290
285
|
showConfigurationHelp(runtime, isPythonTemplate, hasProgramFile) {
|
|
291
|
-
|
|
292
|
-
|
|
286
|
+
ux.warn('Cannot generate OpenAPI description from your code.');
|
|
287
|
+
ux.warn('');
|
|
293
288
|
if (isPythonTemplate && !hasProgramFile) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
289
|
+
ux.warn('Missing required file: src/program.py');
|
|
290
|
+
ux.warn('');
|
|
291
|
+
ux.warn('Solutions:');
|
|
292
|
+
ux.warn(' • Create src/program.py with your main function, or');
|
|
293
|
+
ux.warn(' • Use explicit entrypoint: --entrypoint=yourmodule.main:function');
|
|
299
294
|
}
|
|
300
295
|
else if (!isPythonTemplate) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
296
|
+
ux.warn(`Runtime "${runtime}" requires explicit entrypoint specification.`);
|
|
297
|
+
ux.warn('');
|
|
298
|
+
ux.warn('Use one of these flags:');
|
|
299
|
+
ux.warn(' --entrypoint=package.module:function');
|
|
300
|
+
ux.warn(' --package=package.module --method=function');
|
|
301
|
+
ux.warn('');
|
|
302
|
+
ux.warn('Examples:');
|
|
303
|
+
ux.warn(' qhubctl openapi --entrypoint=myapp.main:handler');
|
|
304
|
+
ux.warn(' qhubctl openapi --package=myapp.core --method=process');
|
|
310
305
|
}
|
|
311
306
|
}
|
|
312
307
|
}
|
|
313
|
-
exports.default = Openapi;
|
|
@@ -1,15 +1,15 @@
|
|
|
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 Run extends AuthenticatedCommand {
|
|
4
4
|
static readonly args: {
|
|
5
|
-
serviceId: import("@oclif/core/
|
|
5
|
+
serviceId: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
6
6
|
};
|
|
7
7
|
static readonly description = "Creates a job execution";
|
|
8
8
|
static readonly examples: string[];
|
|
9
9
|
static readonly flags: {
|
|
10
|
-
input: import("@oclif/core/
|
|
11
|
-
'input-files': import("@oclif/core/
|
|
12
|
-
detached: import("@oclif/core/
|
|
10
|
+
input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
'input-files': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
detached: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
};
|
|
14
14
|
hubService: QuantumHubService;
|
|
15
15
|
getInputFromFiles(filePaths: string): Promise<Record<string, never> | undefined>;
|
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const quantum_hub_service_1 = __importDefault(require("../../service/quantum-hub-service"));
|
|
15
|
-
const service_config_service_1 = require("../../service/service-config-service");
|
|
16
|
-
const api_1 = require("@quantum-hub/qhub-api/dist/api/platform/api");
|
|
17
|
-
class Run extends command_1.AuthenticatedCommand {
|
|
1
|
+
import { Args, Flags, ux } from '@oclif/core';
|
|
2
|
+
import { waitUntil } from 'async-wait-until';
|
|
3
|
+
import fsExtra from 'fs-extra';
|
|
4
|
+
const { readJsonSync } = fsExtra;
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { AuthenticatedCommand } from '../../model/command.js';
|
|
9
|
+
import { defaultBasePath } from '../../model/user-config.js';
|
|
10
|
+
import QuantumHubService from '../../service/quantum-hub-service.js';
|
|
11
|
+
import { readServiceConfig } from '../../service/service-config-service.js';
|
|
12
|
+
import { HubPlatform } from "@quantum-hub/qhub-api/platform";
|
|
13
|
+
export default class Run extends AuthenticatedCommand {
|
|
18
14
|
static args = {
|
|
19
|
-
serviceId:
|
|
15
|
+
serviceId: Args.string(),
|
|
20
16
|
};
|
|
21
17
|
static description = 'Creates a job execution';
|
|
22
18
|
static examples = [
|
|
@@ -27,13 +23,13 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
27
23
|
'$ qhubctl run --input-files=./config.json,./overrides.json',
|
|
28
24
|
];
|
|
29
25
|
static flags = {
|
|
30
|
-
input:
|
|
31
|
-
'input-files':
|
|
26
|
+
input: Flags.string({ char: 'i', description: 'Input as JSON string.', required: false }),
|
|
27
|
+
'input-files': Flags.string({
|
|
32
28
|
aliases: ['input-files'],
|
|
33
29
|
description: 'Comma-separated paths to files containing input to be merged (default: ./input/data.json,./input/params.json).',
|
|
34
30
|
required: false,
|
|
35
31
|
}),
|
|
36
|
-
detached:
|
|
32
|
+
detached: Flags.boolean({
|
|
37
33
|
description: 'Executes the job in detached mode, i.e., without waiting for it to finish.',
|
|
38
34
|
required: false,
|
|
39
35
|
}),
|
|
@@ -46,22 +42,22 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
46
42
|
for (const filePath of paths) {
|
|
47
43
|
let file = filePath;
|
|
48
44
|
// if the file path is not absolute, try to find it in the current working directory
|
|
49
|
-
if (!
|
|
50
|
-
file =
|
|
45
|
+
if (!fs.existsSync(filePath)) {
|
|
46
|
+
file = path.join(process.cwd(), filePath);
|
|
51
47
|
}
|
|
52
|
-
if (
|
|
48
|
+
if (fs.existsSync(file)) {
|
|
53
49
|
try {
|
|
54
|
-
const content =
|
|
50
|
+
const content = readJsonSync(file, { encoding: 'utf8' });
|
|
55
51
|
Object.assign(mergedInput, content);
|
|
56
52
|
hasValidFile = true;
|
|
57
53
|
}
|
|
58
54
|
catch {
|
|
59
|
-
|
|
55
|
+
ux.warn(`Failed to parse JSON from ${filePath}. Skipping this file.`);
|
|
60
56
|
}
|
|
61
57
|
}
|
|
62
58
|
}
|
|
63
59
|
if (!hasValidFile) {
|
|
64
|
-
const response = await
|
|
60
|
+
const response = await inquirer.prompt({
|
|
65
61
|
message: `No valid input files found. Run without input?`,
|
|
66
62
|
name: 'confirm',
|
|
67
63
|
type: 'confirm',
|
|
@@ -74,7 +70,7 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
74
70
|
}
|
|
75
71
|
async init() {
|
|
76
72
|
await super.init();
|
|
77
|
-
this.hubService = new
|
|
73
|
+
this.hubService = new QuantumHubService(this, this.config, this.userConfig);
|
|
78
74
|
}
|
|
79
75
|
async run() {
|
|
80
76
|
const { args } = await this.parse(Run);
|
|
@@ -83,7 +79,7 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
83
79
|
// if no service id is provided, try to read it from the qhub.json
|
|
84
80
|
if (!serviceId) {
|
|
85
81
|
try {
|
|
86
|
-
const serviceConfig =
|
|
82
|
+
const serviceConfig = readServiceConfig(process.cwd());
|
|
87
83
|
serviceId = serviceConfig.serviceId;
|
|
88
84
|
}
|
|
89
85
|
catch {
|
|
@@ -91,7 +87,7 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
91
87
|
}
|
|
92
88
|
}
|
|
93
89
|
if (!serviceId) {
|
|
94
|
-
|
|
90
|
+
ux.error('Missing service ID. Please provide a service ID as argument or set it in the qhub.json of your project.');
|
|
95
91
|
}
|
|
96
92
|
const service = await this.hubService.getService(serviceId);
|
|
97
93
|
let input;
|
|
@@ -100,7 +96,7 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
100
96
|
input = JSON.parse(flags.input);
|
|
101
97
|
}
|
|
102
98
|
catch {
|
|
103
|
-
|
|
99
|
+
ux.error('Invalid JSON provided.');
|
|
104
100
|
}
|
|
105
101
|
}
|
|
106
102
|
else {
|
|
@@ -110,14 +106,14 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
110
106
|
const payload = { serviceId: service.id, tags: ['cli'], input };
|
|
111
107
|
job = await this.hubService.runJob(payload);
|
|
112
108
|
if (flags.detached) {
|
|
113
|
-
|
|
109
|
+
ux.stdout(`Job (${job.id}) created.`);
|
|
114
110
|
this.exit();
|
|
115
111
|
}
|
|
116
|
-
|
|
112
|
+
ux.action.start(`Running Job (${job.id})`);
|
|
117
113
|
try {
|
|
118
|
-
await
|
|
114
|
+
await waitUntil(async () => {
|
|
119
115
|
job = await this.hubService.getJobById(job.id);
|
|
120
|
-
return job.status ===
|
|
116
|
+
return job.status === HubPlatform.ServiceJobDto.Status.Succeeded || job.status === HubPlatform.ServiceJobDto.Status.Failed || job.status === HubPlatform.ServiceJobDto.Status.Cancelled;
|
|
121
117
|
}, {
|
|
122
118
|
intervalBetweenAttempts: 5000, // every 5 seconds
|
|
123
119
|
timeout: 10 * 60 * 1000, // 10 minute timeout
|
|
@@ -126,30 +122,29 @@ class Run extends command_1.AuthenticatedCommand {
|
|
|
126
122
|
catch {
|
|
127
123
|
// ignore wait until next attempt
|
|
128
124
|
}
|
|
129
|
-
const basePath = this.userConfig.endpoint?.basePath ||
|
|
125
|
+
const basePath = this.userConfig.endpoint?.basePath || defaultBasePath;
|
|
130
126
|
const jobDetailsLink = `${basePath}/service-jobs/${job.id}`;
|
|
131
127
|
switch (job.status) {
|
|
132
|
-
case
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
case HubPlatform.ServiceJobDto.Status.Cancelled: {
|
|
129
|
+
ux.action.stop('Job canceled.');
|
|
130
|
+
ux.stdout(`See details at \u001B]8;;${jobDetailsLink}\u0007${jobDetailsLink}\u001B]8;;\u0007\``);
|
|
135
131
|
break;
|
|
136
132
|
}
|
|
137
|
-
case
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
case HubPlatform.ServiceJobDto.Status.Failed: {
|
|
134
|
+
ux.action.stop('Job failed.');
|
|
135
|
+
ux.stdout(`See details at \u001B]8;;${jobDetailsLink}\u0007${jobDetailsLink}\u001B]8;;\u0007\``);
|
|
140
136
|
break;
|
|
141
137
|
}
|
|
142
|
-
case
|
|
143
|
-
|
|
144
|
-
|
|
138
|
+
case HubPlatform.ServiceJobDto.Status.Succeeded: {
|
|
139
|
+
ux.action.stop('Job succeeded.');
|
|
140
|
+
ux.stdout(`See result at \u001B]8;;${jobDetailsLink}\u0007${jobDetailsLink}\u001B]8;;\u0007\``);
|
|
145
141
|
break;
|
|
146
142
|
}
|
|
147
143
|
default: {
|
|
148
|
-
|
|
149
|
-
|
|
144
|
+
ux.action.stop('Timeout polling status.');
|
|
145
|
+
ux.stdout(`See status details at \u001B]8;;${jobDetailsLink}\u0007${jobDetailsLink}\u001B]8;;\u0007\``);
|
|
150
146
|
}
|
|
151
147
|
}
|
|
152
148
|
this.exit();
|
|
153
149
|
}
|
|
154
150
|
}
|
|
155
|
-
exports.default = Run;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { AbstractCommand } from '../../model/command';
|
|
1
|
+
import { AbstractCommand } from '../../model/command.js';
|
|
2
2
|
export default class Serve extends AbstractCommand {
|
|
3
3
|
static CONTAINER_NAME: string;
|
|
4
4
|
static IMAGE: string;
|
|
5
5
|
static description: string;
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
|
-
port: import("@oclif/core/
|
|
9
|
-
log_level: import("@oclif/core/
|
|
8
|
+
port: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
log_level: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
};
|
|
11
11
|
run(): Promise<void>;
|
|
12
12
|
private isProjectSupported;
|