@quantum-hub/qhubctl 1.2.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +136 -20
  2. package/dist/client/kqh/models/UpdateWorkflowServiceRequest.js +0 -11
  3. package/dist/commands/compress.d.ts +2 -0
  4. package/dist/commands/compress.js +23 -0
  5. package/dist/commands/datapool-upload.d.ts +2 -0
  6. package/dist/commands/datapool-upload.js +184 -0
  7. package/dist/commands/get-context.d.ts +2 -0
  8. package/dist/commands/get-context.js +12 -0
  9. package/dist/commands/init.d.ts +2 -0
  10. package/dist/commands/init.js +66 -0
  11. package/dist/commands/list-contexts.d.ts +2 -0
  12. package/dist/commands/list-contexts.js +28 -0
  13. package/dist/commands/login.d.ts +2 -0
  14. package/dist/commands/login.js +59 -0
  15. package/dist/commands/logout.d.ts +2 -0
  16. package/dist/commands/logout.js +20 -0
  17. package/dist/commands/openapi.d.ts +2 -0
  18. package/dist/commands/openapi.js +244 -0
  19. package/dist/commands/run.d.ts +2 -0
  20. package/dist/commands/run.js +126 -0
  21. package/dist/commands/serve.d.ts +2 -0
  22. package/dist/commands/serve.js +35 -0
  23. package/dist/commands/services.d.ts +2 -0
  24. package/dist/commands/services.js +48 -0
  25. package/dist/commands/set-context.d.ts +2 -0
  26. package/dist/commands/set-context.js +52 -0
  27. package/dist/commands/up.d.ts +2 -0
  28. package/dist/commands/up.js +161 -0
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +1 -1
  31. package/dist/lib/config-dir.d.ts +6 -0
  32. package/dist/lib/config-dir.js +8 -0
  33. package/dist/lib/entrypoint-resolver.js +2 -2
  34. package/dist/lib/output.d.ts +14 -0
  35. package/dist/lib/output.js +22 -0
  36. package/dist/main.d.ts +2 -0
  37. package/dist/main.js +8 -0
  38. package/dist/model/command.d.ts +14 -11
  39. package/dist/model/command.js +44 -40
  40. package/dist/program.d.ts +2 -0
  41. package/dist/program.js +47 -0
  42. package/dist/service/command-service.d.ts +1 -5
  43. package/dist/service/command-service.js +1 -5
  44. package/dist/service/quantum-hub-service.d.ts +1 -3
  45. package/dist/service/quantum-hub-service.js +2 -2
  46. package/package.json +31 -62
  47. package/bin/dev.cmd +0 -3
  48. package/bin/dev.js +0 -17
  49. package/bin/run.cmd +0 -3
  50. package/bin/run.js +0 -12
  51. package/dist/commands/compress/index.d.ts +0 -6
  52. package/dist/commands/compress/index.js +0 -25
  53. package/dist/commands/datapool/upload.d.ts +0 -23
  54. package/dist/commands/datapool/upload.js +0 -260
  55. package/dist/commands/get-context/index.d.ts +0 -6
  56. package/dist/commands/get-context/index.js +0 -10
  57. package/dist/commands/init/index.d.ts +0 -10
  58. package/dist/commands/init/index.js +0 -75
  59. package/dist/commands/list-contexts/index.d.ts +0 -9
  60. package/dist/commands/list-contexts/index.js +0 -30
  61. package/dist/commands/login/index.d.ts +0 -10
  62. package/dist/commands/login/index.js +0 -62
  63. package/dist/commands/logout/index.d.ts +0 -6
  64. package/dist/commands/logout/index.js +0 -18
  65. package/dist/commands/openapi/index.d.ts +0 -26
  66. package/dist/commands/openapi/index.js +0 -307
  67. package/dist/commands/run/index.d.ts +0 -18
  68. package/dist/commands/run/index.js +0 -150
  69. package/dist/commands/serve/index.d.ts +0 -11
  70. package/dist/commands/serve/index.js +0 -51
  71. package/dist/commands/services/index.d.ts +0 -14
  72. package/dist/commands/services/index.js +0 -65
  73. package/dist/commands/set-context/index.d.ts +0 -17
  74. package/dist/commands/set-context/index.js +0 -59
  75. package/dist/commands/up/index.d.ts +0 -19
  76. package/dist/commands/up/index.js +0 -190
  77. package/oclif.manifest.json +0 -548
@@ -1,59 +0,0 @@
1
- import { Args, ux } from '@oclif/core';
2
- import { AuthenticatedCommand } from '../../model/command.js';
3
- import QuantumHubService from '../../service/quantum-hub-service.js';
4
- import { writeUserConfig } from '../../service/user-config-service.js';
5
- import { select } from "@inquirer/prompts";
6
- export default class SetContext extends AuthenticatedCommand {
7
- static args = {
8
- contextId: Args.string(),
9
- };
10
- static description = 'Set the current context, i.e., the personal or organization account you are currently working with.';
11
- static examples = [
12
- '$ qhubctl set-context',
13
- '$ qhubctl set-context <context-id>',
14
- ];
15
- quantumHubService;
16
- getPromptOptions(accounts) {
17
- const options = [];
18
- for (const account of accounts) {
19
- options.push({
20
- name: account.isOrganization ? `${account.displayName} (Organization)` : account.displayName,
21
- value: account,
22
- });
23
- }
24
- return options;
25
- }
26
- async init() {
27
- await super.init();
28
- this.quantumHubService = new QuantumHubService(this, this.config, this.userConfig);
29
- }
30
- async run() {
31
- const { args } = await this.parse(SetContext);
32
- let { contextId } = args;
33
- if (!contextId) {
34
- ux.action.start('Loading available contexts');
35
- }
36
- const accounts = await this.quantumHubService.getAccounts();
37
- if (!contextId) {
38
- ux.action.stop('Done');
39
- }
40
- if (!contextId) {
41
- const response = await select({
42
- choices: this.getPromptOptions(accounts),
43
- message: 'Choose a context',
44
- default: accounts[0],
45
- });
46
- contextId = response.id;
47
- }
48
- const selectedContext = accounts.find(account => account.id === contextId);
49
- if (!selectedContext) {
50
- this.error(`Context with id "${contextId}" not found.`);
51
- }
52
- const userConfig = {
53
- ...this.userConfig,
54
- context: selectedContext,
55
- };
56
- writeUserConfig(this.config.configDir, userConfig);
57
- ux.stdout(`Switched to context "${selectedContext?.displayName}".`);
58
- }
59
- }
@@ -1,19 +0,0 @@
1
- import { AuthenticatedCommand } from '../../model/command.js';
2
- import QuantumHubService from '../../service/quantum-hub-service.js';
3
- export default class Up extends AuthenticatedCommand {
4
- static description: string;
5
- static examples: string[];
6
- static flags: {
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
- };
11
- qhubService: QuantumHubService;
12
- getOpenapi(): Promise<Blob | undefined>;
13
- init(): Promise<void>;
14
- run(): Promise<void>;
15
- private buildServiceJob;
16
- private checkIfServiceExistsInPlatform;
17
- private createService;
18
- private updateService;
19
- }
@@ -1,190 +0,0 @@
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 {
14
- static description = 'Creates or updates a service';
15
- static examples = [
16
- '$ qhubctl up',
17
- '$ qhubctl up --no-save-id',
18
- '$ qhubctl up --name "my-custom-service-name"',
19
- '$ qhubctl up --name "test-service" --no-save-id',
20
- ];
21
- static flags = {
22
- silent: Flags.boolean({
23
- description: 'Suppresses all outputs, helpful when executed in a CI/CD pipeline.',
24
- required: false,
25
- }),
26
- 'no-save-id': Flags.boolean({
27
- description: 'Prevents storing the created service ID in qhub.json file.',
28
- required: false,
29
- }),
30
- name: Flags.string({
31
- description: 'Override the service name from qhub.json with a custom name.',
32
- required: false,
33
- }),
34
- };
35
- qhubService;
36
- async getOpenapi() {
37
- const openapiYamlPath = path.join(process.cwd(), 'openapi.yaml');
38
- const openapiYmlPath = path.join(process.cwd(), 'openapi.yml');
39
- let openapi = undefined;
40
- if (fs.existsSync(openapiYamlPath)) {
41
- openapi = fs.createReadStream(openapiYamlPath, 'utf8');
42
- }
43
- else if (fs.existsSync(openapiYmlPath)) {
44
- openapi = fs.createReadStream(openapiYmlPath, 'utf8');
45
- }
46
- if (openapi) {
47
- return streamToBlob(openapi);
48
- }
49
- return undefined;
50
- }
51
- async init() {
52
- await super.init();
53
- this.qhubService = new QuantumHubService(this, this.config, this.userConfig);
54
- }
55
- async run() {
56
- const { flags } = await this.parse(Up);
57
- const serviceConfig = readServiceConfig(process.cwd());
58
- let createNewService = true;
59
- const silentMode = flags.silent;
60
- if (!('descriptionFile' in serviceConfig)) {
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');
62
- }
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".');
66
- }
67
- // if service already exists we update it
68
- const serviceExistsInPlatform = await this.checkIfServiceExistsInPlatform(serviceConfig);
69
- if (serviceConfig.serviceId && !serviceExistsInPlatform) {
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?' });
72
- if (!createNewService) {
73
- this.exit();
74
- }
75
- }
76
- const serviceFiles = {
77
- openapi: await this.getOpenapi(),
78
- descriptionText: await getDescriptionText(process.cwd()),
79
- sourceCode: await zipProjectFolder('./'),
80
- };
81
- const service = serviceExistsInPlatform ?
82
- await this.updateService(serviceConfig, serviceFiles, silentMode) :
83
- await this.createService(serviceConfig, serviceFiles, silentMode, flags['no-save-id'], flags.name);
84
- const serviceDefinition = service && service.serviceDefinitions && service.serviceDefinitions[0];
85
- if (!serviceDefinition) {
86
- this.error('Service definition not found');
87
- }
88
- const buildJob = await this.buildServiceJob(service, serviceDefinition, silentMode);
89
- if (buildJob && buildJob.status === BuildJobDtoStatusEnum.Success) {
90
- const msg = `Service ${serviceExistsInPlatform ? 'updated' : 'created'} \u{1F680}`;
91
- if (silentMode) {
92
- ux.stdout(msg);
93
- }
94
- else {
95
- ux.action.stop(msg);
96
- }
97
- }
98
- else if (buildJob && buildJob.status === BuildJobDtoStatusEnum.Failure) {
99
- const { validationResult } = buildJob;
100
- let reason = 'Failed creating service';
101
- if (validationResult?.state === ValidationResultStateEnum.Error && validationResult.summary) {
102
- reason = `${reason}: ${validationResult.summary}`;
103
- }
104
- if (silentMode) {
105
- ux.stdout(reason);
106
- }
107
- else {
108
- ux.action.stop(reason);
109
- }
110
- }
111
- else {
112
- const msg = 'Still pending, please check the platform UI to determine the status';
113
- if (silentMode) {
114
- ux.stdout(msg);
115
- }
116
- else {
117
- ux.action.stop(msg);
118
- }
119
- }
120
- this.exit();
121
- }
122
- async buildServiceJob(service, serviceDefinition, silentMode) {
123
- let buildJob;
124
- try {
125
- await waitUntil(async () => {
126
- buildJob = await this.qhubService.getBuildJob(service, serviceDefinition);
127
- if (!silentMode) {
128
- if (buildJob.step === BuildJobDtoStepEnum.BuildImage) {
129
- ux.action.start('Building Image (1/2)');
130
- }
131
- else if (buildJob.step === BuildJobDtoStepEnum.PushImage) {
132
- ux.action.start('Pushing Image (2/2)');
133
- }
134
- }
135
- return buildJob.status === BuildJobDtoStatusEnum.Success || buildJob.status === BuildJobDtoStatusEnum.Failure;
136
- }, {
137
- intervalBetweenAttempts: 5000, // every 5 seconds
138
- timeout: silentMode ? 60 * 60 * 1000 : 20 * 60 * 1000, // silent mode: 60 minutes, normal: 20 minutes
139
- });
140
- }
141
- catch (error) {
142
- this.error('Error while waiting for the build job to finish: ' + error);
143
- }
144
- return buildJob;
145
- }
146
- async checkIfServiceExistsInPlatform(serviceConfig) {
147
- if (serviceConfig.serviceId) {
148
- try {
149
- await this.qhubService.getService(serviceConfig.serviceId);
150
- return true;
151
- }
152
- catch {
153
- return false;
154
- }
155
- }
156
- return false;
157
- }
158
- async createService(serviceConfig, files, silentMode, noSaveId = false, customName) {
159
- if (!silentMode) {
160
- ux.action.start('Creating service');
161
- }
162
- // Override the service name if custom name is provided
163
- const configToUse = { ...serviceConfig };
164
- if (customName) {
165
- configToUse.name = customName;
166
- }
167
- const service = await this.qhubService.createService(configToUse, files.sourceCode, files.openapi);
168
- // Always set the service ID temporarily for subsequent operations
169
- serviceConfig.serviceId = service?.id;
170
- // Only persist to file if not using no-save-id flag
171
- if (!noSaveId) {
172
- writeServiceConfig(process.cwd(), serviceConfig);
173
- }
174
- // update description separately when creating a new service
175
- if (files.descriptionText) {
176
- await this.qhubService.updateDescription(serviceConfig, files.descriptionText);
177
- }
178
- // make sure we update the OpenAPI description if it exists
179
- if (files.openapi) {
180
- await this.qhubService.updateOpenapi(serviceConfig, files.openapi);
181
- }
182
- return service;
183
- }
184
- async updateService(serviceConfig, files, silentMode) {
185
- if (!silentMode) {
186
- ux.action.start('Updating service');
187
- }
188
- return this.qhubService.updateService(serviceConfig, files.descriptionText, files.sourceCode, files.openapi);
189
- }
190
- }