@hahnpro/hpc-api 2025.10.4 → 2025.11.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @hahnpro/hpc-api
2
2
 
3
+ ## 2025.10.5
4
+
5
+ ### Major Changes
6
+
7
+ - Optimized SSE event handling in HttpClient and updated the corresponding function signatures in the API services.
8
+
3
9
  ## 2025.10.4
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hahnpro/hpc-api",
3
- "version": "2025.10.4",
3
+ "version": "2025.11.1",
4
4
  "description": "Module for easy access to the HahnPRO Cloud API",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -12,6 +12,7 @@ export interface RequestParameter {
12
12
  limit?: number;
13
13
  page?: number;
14
14
  populate?: string;
15
+ select?: string;
15
16
  sort?: string;
16
17
  lang?: string;
17
18
  }
@@ -19,12 +19,13 @@ export type { TagRule, NotificationRule, StatusRule } from './notification-rule.
19
19
  export type { Owner } from './owner.interface';
20
20
  export type { Organization, OrganizationCreateDto, OrganizationData, OrganizationDataKind, OrganizationDomain, OrganizationName, OrganizationRolesAdjustment, OrganizationSearchQuery, SubscriptionType, UserWithOrgRoles, } from './organization.interface';
21
21
  export type { OrganizationRoleRepresentation } from './organization-role-representation.interface';
22
- export type { OrganizationResourcesProgress, OrganizationResourcesProgressDto, OrganizationResourcesProgressErrorDto, } from './organizations-resources.interface';
22
+ export type { OrganizationResourcesProgress, OrganizationResourcesProgressDto, OrganizationResourcesProgressErrorDto, CreateOrgWithResourcesDto, } from './organizations-resources.interface';
23
23
  export type { Resource, ResourceReference } from './resource.interface';
24
24
  export type { JsonSchema, JsonSchemaArray, JsonSchemaForm, JsonSchemaType, JsonSchemaTypeName } from './schema.interface';
25
25
  export type { DeleteQuery, DeleteAssetTypeQuery, DeleteAssetQuery } from './query.interface';
26
26
  export type { SearchOptions, SearchResult, SearchSortOption, SortableField } from './search.interface';
27
27
  export type { Secret } from './secret.interface';
28
+ export type { ServerSentEvent } from './sse.interface';
28
29
  export type { FileType, Artifact, Storage, StorageProvider } from './storage.interface';
29
30
  export type { Task, LogbookEntry, LogbookEntryDto } from './task.interface';
30
31
  export type { TimeSeries, TimeSeriesBucket, TimeSeriesCondition, TimeSeriesValue, TS_GROUPS } from './timeseries.interface';
@@ -1,9 +1,12 @@
1
1
  export type OrganizationResourcesProgress = OrganizationResourcesProgressDto | OrganizationResourcesProgressErrorDto;
2
2
  export interface OrganizationResourcesProgressDto {
3
- step: string;
4
- stepNumber: number;
5
- maxSteps: number;
3
+ readonly step: string;
4
+ readonly stepNumber: number;
5
+ readonly maxSteps: number;
6
6
  }
7
7
  export interface OrganizationResourcesProgressErrorDto {
8
- message: string;
8
+ readonly message: string;
9
+ }
10
+ export interface CreateOrgWithResourcesDto {
11
+ readonly resourceSetName: string;
9
12
  }
@@ -0,0 +1,6 @@
1
+ export interface ServerSentEvent<T> {
2
+ data: T;
3
+ event?: string;
4
+ id?: string;
5
+ retry?: number;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,12 +1,12 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { APIBaseMock } from '.';
3
- import { Organization, OrganizationResourcesProgressDto } from '../interfaces';
3
+ import { CreateOrgWithResourcesDto, Organization, OrganizationResourcesProgress, ServerSentEvent } from '../interfaces';
4
4
  import { OrganizationsResourcesService } from '../services';
5
5
  export declare class OrganizationsResourcesMockService extends APIBaseMock<Organization> implements OrganizationsResourcesService {
6
6
  resourceSetNames: string[];
7
7
  constructor(resourceSetNames: string[]);
8
8
  getResourceSetNames(): Promise<string[]>;
9
- createResourcesForOrganization(organizationId: string, resourceSetName: string): Promise<string>;
10
- getResourceCreationProgress(organizationId: string): Observable<OrganizationResourcesProgressDto>;
11
- getSseObservable(organizationId: string, path: 'creationTask'): Observable<OrganizationResourcesProgressDto>;
9
+ createResourcesForOrganization(organizationId: string, body: CreateOrgWithResourcesDto): Promise<string>;
10
+ getResourceCreationProgress(organizationId: string): Observable<ServerSentEvent<OrganizationResourcesProgress>>;
11
+ getSseObservable(organizationId: string, path: 'creationTask'): Observable<ServerSentEvent<OrganizationResourcesProgress>>;
12
12
  }
@@ -11,14 +11,14 @@ class OrganizationsResourcesMockService extends _1.APIBaseMock {
11
11
  getResourceSetNames() {
12
12
  return Promise.resolve(this.resourceSetNames);
13
13
  }
14
- createResourcesForOrganization(organizationId, resourceSetName) {
14
+ createResourcesForOrganization(organizationId, body) {
15
15
  throw new Error('Method not implemented.');
16
16
  }
17
17
  getResourceCreationProgress(organizationId) {
18
18
  throw new Error('Method not implemented.');
19
19
  }
20
20
  getSseObservable(organizationId, path) {
21
- throw new Error('Method not implemented.');
21
+ return undefined;
22
22
  }
23
23
  }
24
24
  exports.OrganizationsResourcesMockService = OrganizationsResourcesMockService;
@@ -1,8 +1,7 @@
1
- import { EventSourceMessage } from '@microsoft/fetch-event-source';
2
1
  import { AxiosInstance, Method } from 'axios';
3
2
  import { EventSource } from 'eventsource';
4
3
  import { Observable } from 'rxjs';
5
- import { Config, Issuer, TokenOption } from '../interfaces';
4
+ import { Config, Issuer, ServerSentEvent, TokenOption } from '../interfaces';
6
5
  import { Queue } from '../queue';
7
6
  import { TokenSet } from '../token-set';
8
7
  export interface HttpClientConfig {
@@ -46,7 +45,7 @@ export declare class HttpClientService {
46
45
  put: <T>(url: string, data: any, config?: Config) => Promise<T>;
47
46
  patch: <T>(url: string, data: any, config?: Config) => Promise<T>;
48
47
  protected request: <T>(method: Method, url: string, config?: Config, data?: any) => Promise<T>;
49
- getSseObservable<T>(path: string, onmessage: (event: EventSourceMessage) => T): Observable<T>;
48
+ getSseObservable<T>(path: string): Observable<ServerSentEvent<T>>;
50
49
  addEventSource(url: string, listener: (event: MessageEvent) => void, errorListener?: (event: MessageEvent) => void, options?: TokenOption): Promise<string>;
51
50
  destroyEventSource(id: string): void;
52
51
  destroyAllEventSources(): void;
@@ -68,46 +68,58 @@ class HttpClientService {
68
68
  this.authAxiosInstance = axios_1.default.create({ baseURL: this.authBaseURL, timeout: 10000 });
69
69
  this.requestQueue = new queue_1.Queue({ concurrency: 1, timeout: 70000, throwOnTimeout: true });
70
70
  }
71
- getSseObservable(path, onmessage) {
72
- const subject = new rxjs_1.Subject();
73
- this.getAccessToken()
74
- .then((token) => {
71
+ getSseObservable(path) {
72
+ return new rxjs_1.Observable((subscriber) => {
75
73
  const ctrl = new AbortController();
76
- (0, fetch_event_source_1.fetchEventSource)(`${this.baseURL.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`, {
77
- headers: { authorization: 'Bearer ' + token },
78
- signal: ctrl.signal,
79
- onopen: async (response) => {
80
- if (!response.ok) {
81
- subject.error(new Error(`HTTP ${response.status}: ${response.statusText}`));
74
+ this.getAccessToken()
75
+ .then((token) => {
76
+ (0, fetch_event_source_1.fetchEventSource)(`${this.baseURL.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`, {
77
+ headers: { Authorization: `Bearer ${token}` },
78
+ signal: ctrl.signal,
79
+ onopen: async (response) => {
80
+ if (!response.ok) {
81
+ subscriber.error(new Error(`HTTP ${response.status}: ${response.statusText}`));
82
+ ctrl.abort();
83
+ }
84
+ },
85
+ onmessage: (event) => {
86
+ if (!event.data && !event.event && !event.id) {
87
+ return;
88
+ }
89
+ else if (event.event === 'error') {
90
+ subscriber.error(new Error(event.data));
91
+ }
92
+ else {
93
+ try {
94
+ const parsedData = JSON.parse(event.data);
95
+ subscriber.next({
96
+ data: parsedData,
97
+ event: event.event,
98
+ id: event.id,
99
+ retry: event.retry,
100
+ });
101
+ }
102
+ catch (err) {
103
+ subscriber.error(err);
104
+ }
105
+ }
106
+ },
107
+ onclose: () => {
108
+ subscriber.complete();
109
+ },
110
+ onerror: (err) => {
111
+ subscriber.error(err);
82
112
  ctrl.abort();
83
- }
84
- },
85
- onmessage(event) {
86
- if (event.id === '' && event.data === '' && event.event === '' && !event.retry) {
87
- // Skip empty messages used as keep-alive signals
88
- return;
89
- }
90
- try {
91
- subject.next(onmessage(event));
92
- }
93
- catch (error) {
94
- subject.error({ message: error.message ?? String(error) });
95
- }
96
- },
97
- onclose() {
98
- subject.complete();
99
- ctrl.abort();
100
- },
101
- onerror(err) {
102
- subject.error(err);
103
- ctrl.abort();
104
- },
113
+ },
114
+ });
115
+ })
116
+ .catch((err) => {
117
+ subscriber.error(err);
105
118
  });
106
- })
107
- .catch((err) => {
108
- subject.error(err);
119
+ return () => {
120
+ ctrl.abort();
121
+ };
109
122
  });
110
- return subject.asObservable();
111
123
  }
112
124
  async addEventSource(url, listener, errorListener, options = {}) {
113
125
  const id = globalThis.crypto.randomUUID();
@@ -1,11 +1,12 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { APIBase } from '../api-base';
3
- import { OrganizationResourcesProgressDto } from '../interfaces';
3
+ import { CreateOrgWithResourcesDto, OrganizationResourcesProgress, ServerSentEvent } from '../interfaces';
4
4
  import { HttpClientService } from './';
5
5
  export declare class OrganizationsResourcesService extends APIBase {
6
6
  constructor(httpClient: HttpClientService);
7
7
  /**
8
8
  * Fetches the names of all available resource sets.
9
+ *
9
10
  * @returns {Promise<string[]>} A promise that resolves to an array of resource set names.
10
11
  */
11
12
  getResourceSetNames(): Promise<string[]>;
@@ -15,22 +16,23 @@ export declare class OrganizationsResourcesService extends APIBase {
15
16
  * The progress status update messages can be received by subscribing to the `getResourceCreationProgress` method with the same organization ID.
16
17
  *
17
18
  * @param {string} organizationId - The ID of the organization for which resources are to be created.
18
- * @param {string} resourceSetName - The name of the resource set to be used for resource creation from the S3 bucket.
19
+ * @param {CreateOrgWithResourcesDto} body - The options for resource creation, including the resource set name.
19
20
  * @returns {Promise<string>} - A promise that resolves to the id of the resource creation task.
20
21
  */
21
- createResourcesForOrganization(organizationId: string, resourceSetName: string): Promise<string>;
22
+ createResourcesForOrganization(organizationId: string, body: CreateOrgWithResourcesDto): Promise<string>;
22
23
  /**
23
24
  * Subscribes to server-sent events to receive real-time progress updates on the resource tasks for a specific organization.
25
+ *
24
26
  * @param {string} organizationId - The ID of the organization to monitor the resources progress updates for.
25
27
  * @param {string} path - The API path segment for the SSE endpoint
26
- * @returns {Observable<OrganizationResourcesProgress>} An observable that emits progress updates.
28
+ * @returns {Observable<ServerSentEvent<OrganizationResourcesProgress>>} An observable that emits progress updates.
27
29
  */
28
- getSseObservable(organizationId: string, path: 'creationTask'): Observable<OrganizationResourcesProgressDto>;
30
+ getSseObservable(organizationId: string, path: 'creationTask'): Observable<ServerSentEvent<OrganizationResourcesProgress>>;
29
31
  /**
30
32
  * Subscribes to server-sent events to receive real-time progress updates on the resource creation task for a specific organization
31
33
  *
32
34
  * @param {string} organizationId - The ID of the organization to monitor the resource creation progress for.
33
35
  * @returns {Observable<OrganizationResourcesProgress>} An observable that emits progress updates.
34
36
  */
35
- getResourceCreationProgress(organizationId: string): Observable<OrganizationResourcesProgressDto>;
37
+ getResourceCreationProgress(organizationId: string): Observable<ServerSentEvent<OrganizationResourcesProgress>>;
36
38
  }
@@ -8,6 +8,7 @@ class OrganizationsResourcesService extends api_base_1.APIBase {
8
8
  }
9
9
  /**
10
10
  * Fetches the names of all available resource sets.
11
+ *
11
12
  * @returns {Promise<string[]>} A promise that resolves to an array of resource set names.
12
13
  */
13
14
  getResourceSetNames() {
@@ -19,34 +20,21 @@ class OrganizationsResourcesService extends api_base_1.APIBase {
19
20
  * The progress status update messages can be received by subscribing to the `getResourceCreationProgress` method with the same organization ID.
20
21
  *
21
22
  * @param {string} organizationId - The ID of the organization for which resources are to be created.
22
- * @param {string} resourceSetName - The name of the resource set to be used for resource creation from the S3 bucket.
23
+ * @param {CreateOrgWithResourcesDto} body - The options for resource creation, including the resource set name.
23
24
  * @returns {Promise<string>} - A promise that resolves to the id of the resource creation task.
24
25
  */
25
- createResourcesForOrganization(organizationId, resourceSetName) {
26
- return this.httpClient.post(`${this.basePath}/${organizationId}`, { resourceSetName });
26
+ createResourcesForOrganization(organizationId, body) {
27
+ return this.httpClient.post(`${this.basePath}/${organizationId}`, body);
27
28
  }
28
29
  /**
29
30
  * Subscribes to server-sent events to receive real-time progress updates on the resource tasks for a specific organization.
31
+ *
30
32
  * @param {string} organizationId - The ID of the organization to monitor the resources progress updates for.
31
33
  * @param {string} path - The API path segment for the SSE endpoint
32
- * @returns {Observable<OrganizationResourcesProgress>} An observable that emits progress updates.
34
+ * @returns {Observable<ServerSentEvent<OrganizationResourcesProgress>>} An observable that emits progress updates.
33
35
  */
34
36
  getSseObservable(organizationId, path) {
35
- return this.httpClient.getSseObservable(`${this.basePath}/${path}/${organizationId}`, (event) => {
36
- let data = null;
37
- try {
38
- data = JSON.parse(event.data);
39
- }
40
- catch (err) {
41
- throw new Error('Failed to parse SSE event data as JSON: ' + (err.message ?? String(err)));
42
- }
43
- if ('message' in data) {
44
- throw new Error(data.message);
45
- }
46
- else {
47
- return data;
48
- }
49
- });
37
+ return this.httpClient.getSseObservable(`${this.basePath}/${path}/${organizationId}`);
50
38
  }
51
39
  /**
52
40
  * Subscribes to server-sent events to receive real-time progress updates on the resource creation task for a specific organization