@hahnpro/hpc-api 2024.4.0-0 → 2025.2.0

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 (134) hide show
  1. package/CHANGELOG.md +383 -0
  2. package/README.md +507 -0
  3. package/package.json +9 -7
  4. package/src/index.js +27 -20
  5. package/src/index.js.map +1 -0
  6. package/src/lib/Queue.js +21 -10
  7. package/src/lib/Queue.js.map +1 -0
  8. package/src/lib/api-base.js +15 -3
  9. package/src/lib/api-base.js.map +1 -0
  10. package/src/lib/api.js +53 -42
  11. package/src/lib/api.js.map +1 -0
  12. package/src/lib/asset.interface.js +6 -1
  13. package/src/lib/asset.interface.js.map +1 -0
  14. package/src/lib/asset.service.js +45 -20
  15. package/src/lib/asset.service.js.map +1 -0
  16. package/src/lib/assettypes.service.js +26 -12
  17. package/src/lib/assettypes.service.js.map +1 -0
  18. package/src/lib/content.interface.js +15 -3
  19. package/src/lib/content.interface.js.map +1 -0
  20. package/src/lib/content.service.js +62 -32
  21. package/src/lib/content.service.js.map +1 -0
  22. package/src/lib/data.interface.js +13 -1
  23. package/src/lib/data.interface.js.map +1 -0
  24. package/src/lib/data.service.js +45 -24
  25. package/src/lib/data.service.js.map +1 -0
  26. package/src/lib/endpoint.interface.js +6 -1
  27. package/src/lib/endpoint.interface.js.map +1 -0
  28. package/src/lib/endpoint.service.js +16 -4
  29. package/src/lib/endpoint.service.js.map +1 -0
  30. package/src/lib/events.interface.js +6 -1
  31. package/src/lib/events.interface.js.map +1 -0
  32. package/src/lib/events.service.js +16 -4
  33. package/src/lib/events.service.js.map +1 -0
  34. package/src/lib/flow-deployment.interface.js +6 -1
  35. package/src/lib/flow-deployment.interface.js.map +1 -0
  36. package/src/lib/flow-deployment.service.js +58 -25
  37. package/src/lib/flow-deployment.service.js.map +1 -0
  38. package/src/lib/flow-function.interface.js +6 -1
  39. package/src/lib/flow-function.interface.js.map +1 -0
  40. package/src/lib/flow-function.service.js +20 -6
  41. package/src/lib/flow-function.service.js.map +1 -0
  42. package/src/lib/flow-module.interface.js +6 -1
  43. package/src/lib/flow-module.interface.js.map +1 -0
  44. package/src/lib/flow-module.service.js +20 -6
  45. package/src/lib/flow-module.service.js.map +1 -0
  46. package/src/lib/flow.interface.js +6 -1
  47. package/src/lib/flow.interface.js.map +1 -0
  48. package/src/lib/flow.service.js +27 -13
  49. package/src/lib/flow.service.js.map +1 -0
  50. package/src/lib/http.service.d.ts +1 -1
  51. package/src/lib/http.service.js +102 -62
  52. package/src/lib/http.service.js.map +1 -0
  53. package/src/lib/label.interface.js +6 -1
  54. package/src/lib/label.interface.js.map +1 -0
  55. package/src/lib/label.service.js +17 -5
  56. package/src/lib/label.service.js.map +1 -0
  57. package/src/lib/mock/api-base.mock.js +17 -6
  58. package/src/lib/mock/api-base.mock.js.map +1 -0
  59. package/src/lib/mock/api.mock.js +204 -193
  60. package/src/lib/mock/api.mock.js.map +1 -0
  61. package/src/lib/mock/asset.mock.service.js +55 -38
  62. package/src/lib/mock/asset.mock.service.js.map +1 -0
  63. package/src/lib/mock/assetTypes.mock.service.js +45 -27
  64. package/src/lib/mock/assetTypes.mock.service.js.map +1 -0
  65. package/src/lib/mock/content.mock.service.js +45 -37
  66. package/src/lib/mock/content.mock.service.js.map +1 -0
  67. package/src/lib/mock/data.mock.service.js +49 -40
  68. package/src/lib/mock/data.mock.service.js.map +1 -0
  69. package/src/lib/mock/endpoint.mock.service.js +17 -5
  70. package/src/lib/mock/endpoint.mock.service.js.map +1 -0
  71. package/src/lib/mock/events.mock.service.js +16 -4
  72. package/src/lib/mock/events.mock.service.js.map +1 -0
  73. package/src/lib/mock/flow-deployment.mock.service.js +81 -36
  74. package/src/lib/mock/flow-deployment.mock.service.js.map +1 -0
  75. package/src/lib/mock/flow-functions.mock.service.js +33 -20
  76. package/src/lib/mock/flow-functions.mock.service.js.map +1 -0
  77. package/src/lib/mock/flow-modules.mock.service.js +18 -6
  78. package/src/lib/mock/flow-modules.mock.service.js.map +1 -0
  79. package/src/lib/mock/flow.mock.service.js +44 -29
  80. package/src/lib/mock/flow.mock.service.js.map +1 -0
  81. package/src/lib/mock/index.js +18 -11
  82. package/src/lib/mock/index.js.map +1 -0
  83. package/src/lib/mock/label.mock.service.js +17 -5
  84. package/src/lib/mock/label.mock.service.js.map +1 -0
  85. package/src/lib/mock/notification.mock.service.js +16 -4
  86. package/src/lib/mock/notification.mock.service.js.map +1 -0
  87. package/src/lib/mock/secret.mock.service.js +24 -12
  88. package/src/lib/mock/secret.mock.service.js.map +1 -0
  89. package/src/lib/mock/task.mock.service.js +24 -12
  90. package/src/lib/mock/task.mock.service.js.map +1 -0
  91. package/src/lib/mock/timeseries.mock.service.js +88 -43
  92. package/src/lib/mock/timeseries.mock.service.js.map +1 -0
  93. package/src/lib/mock/trash.mock.service.js +28 -14
  94. package/src/lib/mock/trash.mock.service.js.map +1 -0
  95. package/src/lib/mock/user.mock.service.js +17 -6
  96. package/src/lib/mock/user.mock.service.js.map +1 -0
  97. package/src/lib/mock/vault.mock.service.js +17 -5
  98. package/src/lib/mock/vault.mock.service.js.map +1 -0
  99. package/src/lib/notification.interface.js +6 -1
  100. package/src/lib/notification.interface.js.map +1 -0
  101. package/src/lib/notification.service.js +16 -4
  102. package/src/lib/notification.service.js.map +1 -0
  103. package/src/lib/proxy.service.js +19 -7
  104. package/src/lib/proxy.service.js.map +1 -0
  105. package/src/lib/resource.interface.js +6 -1
  106. package/src/lib/resource.interface.js.map +1 -0
  107. package/src/lib/schema.interface.js +6 -1
  108. package/src/lib/schema.interface.js.map +1 -0
  109. package/src/lib/secret.interface.js +6 -1
  110. package/src/lib/secret.interface.js.map +1 -0
  111. package/src/lib/secret.service.js +23 -11
  112. package/src/lib/secret.service.js.map +1 -0
  113. package/src/lib/storage.interface.js +6 -1
  114. package/src/lib/storage.interface.js.map +1 -0
  115. package/src/lib/task.interface.js +6 -1
  116. package/src/lib/task.interface.js.map +1 -0
  117. package/src/lib/task.service.js +23 -11
  118. package/src/lib/task.service.js.map +1 -0
  119. package/src/lib/timeseries.interface.js +6 -1
  120. package/src/lib/timeseries.interface.js.map +1 -0
  121. package/src/lib/timeseries.service.js +97 -66
  122. package/src/lib/timeseries.service.js.map +1 -0
  123. package/src/lib/token-set.js +15 -3
  124. package/src/lib/token-set.js.map +1 -0
  125. package/src/lib/trash.service.js +23 -5
  126. package/src/lib/trash.service.js.map +1 -0
  127. package/src/lib/user-settings.interface.js +6 -1
  128. package/src/lib/user-settings.interface.js.map +1 -0
  129. package/src/lib/user.service.js +18 -7
  130. package/src/lib/user.service.js.map +1 -0
  131. package/src/lib/vault.interface.js +6 -1
  132. package/src/lib/vault.interface.js.map +1 -0
  133. package/src/lib/vault.service.js +23 -6
  134. package/src/lib/vault.service.js.map +1 -0
package/README.md ADDED
@@ -0,0 +1,507 @@
1
+ # Hahn PRO Cloud API
2
+
3
+ ## 1. Fundamentals
4
+
5
+ The Hahn PRO Cloud API is a RESTful API, therefore the communication consists of HTTP-calls.
6
+ The services provided are independent microservices, each with their own subpaths.
7
+
8
+ In this document there are code-samples for the most common API use-cases in typescript
9
+ and python. HahnPRO provides an SDK, which simplifies the communication in typescript.
10
+ Currently, there is no SDK for python.
11
+
12
+ ## 2. Authentication
13
+
14
+ To use the API you will have to authenticate yourself with every request. For this a `Authentication`
15
+ header with a [JWT-Token](https://jwt.io/introduction) is needed.
16
+
17
+ To get the JWT-Token, you have to use your API-Username and Password to get the token from Keycloak. The request to
18
+ keycloak needs to be a POST request with `{'grant_type': 'client_credentials'}` as the body.
19
+
20
+ The token is valid for a set amount of time, after which you will need to reauthenticate.
21
+ In the `expires_in` response field you can get the time for which the token will be valid.
22
+
23
+ <details>
24
+ <summary markdown="span">Python</summary>
25
+
26
+ In the following sample-code the user gets asked for their password, which then gets used to ask Keycloak for the
27
+ JWT-Token. The token then gets used in the `Authentication` header.
28
+
29
+ You will need to set the variables `API_BASE_URL`, `AUTH_BASE_URL`, `AUTH_REALM` and `API_USER`. The `AUTH_BASE_URL`
30
+ will often be the same as the `API_BASE_URL`.
31
+
32
+ ```python
33
+ import requests
34
+ import getpass
35
+
36
+ # gets an access token
37
+ keycloak_url = AUTH_BASE_URL + '/auth/realms/' + AUTH_REALM + '/protocol/openid-connect/token'
38
+ headers = {'Content-Type':'application/x-www-form-urlencoded'}
39
+ apiPw = getpass.getpass('Password for ' + API_USER)
40
+ auth=(API_USER, apiPw)
41
+ data = {'grant_type': 'client_credentials'}
42
+ res = requests.post(keycloak_url, auth=auth, headers=headers, data=data )
43
+ apiPw = '';
44
+ token = res.json()['access_token']
45
+ print('token: ' + token[:5] + '...' + str(len(token)))
46
+ headers = {'Authorization':'Bearer ' + token,
47
+ 'Content-Type': 'application/json'}
48
+
49
+ ```
50
+
51
+ The `headers` need to be sent with every request to the API.
52
+
53
+ </details>
54
+
55
+ <details>
56
+ <summary markdown="span">Typescript</summary>
57
+
58
+ The Hahn-PRO Flow-SDK does most of the work in getting and using the token. You only have to set the `API_BASE_URL` (
59
+ defaults to `https://testing.hahnpro.com`), `AUTH_BASE_URL` (defaults to `API_BASE_URL`),
60
+ `AUTH_REALM` (defaults to `hpc`), `API_USER` and `AUTH_SECRET` environment variables;
61
+
62
+ ```typescript
63
+ import { API } from '@hahnpro/flow-sdk';
64
+
65
+ // explicitly set the envs
66
+ process.env.API_BASE_URL = '*your API URL*';
67
+ process.env.AUTH_BASE_URL = '*URL of the Keycloak instance the authenticate with*'; // only needed if distinct from API_BASE_URL
68
+ process.env.AUTH_REALM = '*the Keycloak Realm*';
69
+ process.env.API_USER = '*your username*';
70
+ process.env.AUTH_SECRET = '*your secret*';
71
+
72
+ // or by using dotenv
73
+ import * as dotenv from 'dotenv';
74
+
75
+ dotenv.config();
76
+
77
+ const api = new API();
78
+ ```
79
+
80
+ The JWT-Token is automatically requested and used with every request you send, using the `api` object.
81
+
82
+ </details>
83
+
84
+ ## 3. Basic Example Use-Cases
85
+
86
+ ### 3.1. General
87
+
88
+ ### 3.1.1 Populate
89
+
90
+ When you get assets from the API, the Asset-Type and the parent-Asset are given as IDs. You can get the Asset-Type and
91
+ Parent objects by sending the `populate` queryparameter.
92
+
93
+ `...?populate=type,parent`
94
+
95
+ ### 3.1.2 Filter
96
+
97
+ To get filtered results a filter string has to be provided:
98
+
99
+ | Attribute | filter string |
100
+ | --------- | --------------- |
101
+ | tags | tags=@tag1 tag2 |
102
+ | type | type==type |
103
+ | parent | parent==1234 |
104
+
105
+ Multiple filters can be concatenated with the `;` symbol.
106
+
107
+ `...?filter=tags=@test;parent==1234`
108
+
109
+ ### 3.1.3 Read/Read-Write Permissions
110
+
111
+ Every single object from the API has the fields `readPermissions` and `readWritePermissions`.
112
+ These determine which objects can be read or written.
113
+ When writing a new object to the API, these fields have to be sent.
114
+
115
+ You can only set the roles that you have, e.g. when you don´t have the role `test` you
116
+ can´t set this role in the `readPermissions` or `readWritePermissions` arrays.
117
+
118
+ To see the roles you have, you can check the `realm_access.roles` field of the JWT-Token.
119
+
120
+ <details>
121
+ <summary markdown="span">Python</summary>
122
+
123
+ Get user roles from JWT-Token.
124
+
125
+ ```python
126
+ import jwt
127
+
128
+ def getUserRoles(token):
129
+ algorithm = jwt.get_unverified_header(token)['alg']
130
+ data = jwt.decode(token, algorithms=algorithm, audience='account', options={"verify_signature": False})
131
+ return data['realm_access']['roles']
132
+ ```
133
+
134
+ This example uses the [`pyjwt` library](https://pyjwt.readthedocs.io/en/stable/).
135
+
136
+ </details>
137
+
138
+ <details>
139
+ <summary markdown="span">Python</summary>
140
+
141
+ Get user roles from JWT-Token.
142
+
143
+ ```typescript
144
+ const roles = await api.users.getCurrentUserRoles();
145
+ ```
146
+
147
+ </details>
148
+
149
+ ### 3.2. Assets
150
+
151
+ In this example some Assets will be fetched and modified.
152
+
153
+ <details>
154
+ <summary markdown="span">Python</summary>
155
+
156
+ ```python
157
+ API_AM_PATH = '/api/assets'
158
+ ```
159
+
160
+ Get all assets:
161
+
162
+ ```python
163
+ res = requests.get(API_BASE_URL + API_AM_PATH, headers=headers)
164
+ assets = res.json()['docs']
165
+ ```
166
+
167
+ Get a single Asset:
168
+
169
+ ```python
170
+ assetId = '1234'
171
+ res = requests.get(API_BASE_URL + API_AM_PATH + '/' + assetId, headers=headers)
172
+ asset = res.json()
173
+ ```
174
+
175
+ Get all Assets with tag:
176
+
177
+ ```python
178
+ filterString = '?filter=tags=@test'
179
+ res = requests.get(API_BASE_URL + API_AM_PATH + filterString, headers=headers)
180
+ assets = res.json()['docs']
181
+ ```
182
+
183
+ Populate Asset-type and Parent-Asset:
184
+
185
+ ```python
186
+ populateString = '?populate=type,parent'
187
+ res = requests.get(API_BASE_URL + API_AM_PATH + populateString, headers=headers)
188
+ print(res.json()['docs'])
189
+ ```
190
+
191
+ Create a new Asset:
192
+
193
+ ```python
194
+ asset = {
195
+ name: 'newAsset',
196
+ type: '1234',
197
+ readPermissions: ['test'],
198
+ readWritePermissions: ['test', 'admin']
199
+ }
200
+
201
+ res = requests.post(API_BASE_URL + API_AM_PATH, data=json.dumps(asset), headers=headers)
202
+ ```
203
+
204
+ Update existing asset:
205
+
206
+ ```python
207
+ import json
208
+
209
+ # get asset
210
+ assetId = '1234'
211
+ res = requests.get(API_BASE_URL + API_AM_PATH + '/' + assetId, headers=headers)
212
+ asset = res.json()
213
+
214
+ # update asset
215
+ asset['tags'] = ['qwertz', 'test']
216
+
217
+ # save aset
218
+ res = requests.put(API_BASE_URL + API_AM_PATH + '/' + assetId, data=json.dumps(asset), headers=headers)
219
+ ```
220
+
221
+ </details>
222
+
223
+ <details>
224
+ <summary markdown="span">Typescript</summary>
225
+
226
+ Get all assets:
227
+
228
+ ```typescript
229
+ // get a paginated list of all Assets
230
+ const all = await api.assets.getMany();
231
+ const assets = all.docs; // asset-objects are contained in the docs array
232
+ ```
233
+
234
+ Get a single Asset:
235
+
236
+ ```typescript
237
+ const asset = await api.assets.getOne('*ID of asset*');
238
+ ```
239
+
240
+ Get all Assets with tag:
241
+
242
+ ```typescript
243
+ const filtered = await api.assets.getManyFiltered({ tags: ['test'] });
244
+ const assets = filtered.docs;
245
+ ```
246
+
247
+ Populate Asset-type and Parent-Asset:
248
+
249
+ ```typescript
250
+ const many = await api.assets.getMany({ populate: 'type,parent' });
251
+ const assets = many.docs;
252
+ ```
253
+
254
+ Create a new Asset:
255
+
256
+ ```typescript
257
+ const asset: Asset = {
258
+ name: 'newAsset',
259
+ type: '1234',
260
+ readPermissions: ['test'],
261
+ readWritePermissions: ['test', 'admin'],
262
+ };
263
+
264
+ await api.assets.addOne(asset);
265
+ ```
266
+
267
+ Update existing Asset:
268
+
269
+ ```typescript
270
+ const asset = await api.assets.getOne('1234');
271
+ // modify
272
+ asset.tags.push('newTag');
273
+
274
+ await api.assets.updateOne('1234', asset);
275
+ ```
276
+
277
+ </details>
278
+
279
+ ### 3.3. Content
280
+
281
+ The Content object from the api contains all the metadata of the content-file, but not the actual file. The file has to
282
+ be downloaded separately.
283
+
284
+ To upload a new File you have to send it as `multipart/form-data` in the `file` field.
285
+
286
+ <details>
287
+ <summary markdown="span">Python</summary>
288
+
289
+ ```python
290
+ API_CM_PATH = '/api/contents'
291
+ ```
292
+
293
+ Get all Content:
294
+
295
+ ```python
296
+ res = requests.get(API_BASE_URL + API_CM_PATH, headers=headers)
297
+ contents = res.json()['docs']
298
+ ```
299
+
300
+ Download Content:
301
+
302
+ ```python
303
+ contentId = '1234'
304
+ res = requests.get(API_BASE_URL + API_CM_PATH + '/' + contentId + '/download', headers=headers)
305
+ blob = res.content
306
+ ```
307
+
308
+ Download Content attached to an Asset:
309
+
310
+ ```python
311
+ ASSET_WITH_CONTENT = '1234'
312
+ res = requests.get(API_BASE_URL + API_AM_PATH +'/' + ASSET_WITH_CONTENT, headers=headers)
313
+ attachments = res.json()['attachments']
314
+
315
+ res = requests.get(API_BASE_URL + API_CM_PATH + '/' + attachments[0] + '/download', headers=headers)
316
+ blob = res.content
317
+ ```
318
+
319
+ Upload new Content:
320
+
321
+ If you are using the same `headers` set from the authentication example, you have
322
+ to the `Content-Type` header.
323
+
324
+ ```python
325
+ del headers['Content-Type']
326
+ ```
327
+
328
+ ```python
329
+ files = {'file': open('somefile.txt', 'rb')}
330
+ payload={
331
+ 'readPermissions': 'test',
332
+ 'readWritePermissions': 'test'
333
+ }
334
+
335
+ res = requests.post(API_BASE_URL + API_CM_PATH, files=files, data=payload, headers=headers)
336
+ ```
337
+
338
+ Attach Content to Asset:
339
+
340
+ ```python
341
+ files = {'file': open('somefile.txt', 'rb')}
342
+ payload={
343
+ 'readPermissions': 'test',
344
+ 'readWritePermissions': 'test'
345
+ }
346
+
347
+ res = requests.post(API_BASE_URL + API_AM_PATH + '/1234/attachment', data=payload, files=files, headers=headers)
348
+ ```
349
+
350
+ </details>
351
+
352
+ <details>
353
+ <summary markdown="span">Typescript</summary>
354
+
355
+ Get all Contents:
356
+
357
+ ```typescript
358
+ const many = await api.contents.getMany();
359
+ const contents = many.docs;
360
+ ```
361
+
362
+ Download Content:
363
+
364
+ ```typescript
365
+ const content = await api.contents.getOne('1234');
366
+ const file = await api.contents.download(content.id);
367
+ ```
368
+
369
+ Download Content attached to an Asset:
370
+
371
+ ```typescript
372
+ const asset = await api.contents.getOne('1234');
373
+ const file = await api.contents.download(asset.attachments[0]);
374
+ ```
375
+
376
+ Upload new Content:
377
+
378
+ ```typescript
379
+ import FormData from 'form-data';
380
+
381
+ const form = new FormData();
382
+ form.append('file', fs.createReadStream('/foo/bar.jpg'));
383
+ form.append('readPermission', 'test');
384
+ form.append('readWritePermission', 'test');
385
+
386
+ await api.contents.upload(form);
387
+ ```
388
+
389
+ Attach Content to Asset:
390
+
391
+ ```typescript
392
+ import FormData from 'form-data';
393
+
394
+ const form = new FormData();
395
+ form.append('file', fs.createReadStream('/foo/bar.jpg'));
396
+ form.append('readPermission', 'test');
397
+ form.append('readWritePermission', 'test');
398
+
399
+ await api.assets.addAttachment('1234', form);
400
+ ```
401
+
402
+ </details>
403
+
404
+ ### 3.4. Timeseries
405
+
406
+ A TimeSeries object contains all the metadata of the timeseries but no values. The values
407
+ can be downloaded separately.
408
+
409
+ <details>
410
+ <summary markdown="span">Python</summary>
411
+
412
+ Get timeseries:
413
+
414
+ ```python
415
+ tsId = '1234'
416
+ res = requests.get(API_BASE_URL + API_TSM_PATH + '/' + tsId, headers=headers)
417
+ ts = res.json()
418
+
419
+ # download the first 1000 values
420
+ res = requests.get(API_BASE_URL + API_TSM_PATH + '/' + tsId + '/' + '0' + '?limit=1000', headers=headers)
421
+ values = res.json()
422
+ ```
423
+
424
+ Create new empty timeseries:
425
+
426
+ ```python
427
+ ts = {
428
+ 'name': 'newTS,
429
+ 'readPermissions': ['test'],
430
+ 'readWritePermissions': ['test']
431
+ }
432
+
433
+ res = requests.post(API_BASE_URL, data=json.dumps(ts), headers=headers)
434
+ ```
435
+
436
+ Add value to Timeseries:
437
+
438
+ ```python
439
+ data = { '1234': 5, '1235': 6}; // { *timestamp* : *value*}
440
+ # multiple values
441
+ data1 = { '1234': { val1: 1, val2: 2} };
442
+
443
+ requests.post(API_BASE_URL + API_TSM_PATH + '/1234', data=json.dumps(data), headers=headers)
444
+ ```
445
+
446
+ </details>
447
+
448
+ <details>
449
+ <summary markdown="span">Typescript</summary>
450
+
451
+ Get Timeseries:
452
+
453
+ ```typescript
454
+ const ts = await api.timeSeries.getOne('1234');
455
+
456
+ const from = 0; // timestamp
457
+ const to = Date.now(); // timestamp (optional)
458
+ const group = '12h'; // "10s", "1m", "5m", "15m", "30m", "1h", "3h", "6h", "12h", "1d", "7d" (optional)
459
+ const values = await api.timeSeries.getValuesOfPeriod(tsId, from, to, group);
460
+ ```
461
+
462
+ Create new empty timeseries:
463
+
464
+ ```typescript
465
+ const ts: TimeSeries = {
466
+ name: 'newTS',
467
+ readPermissions: ['test'],
468
+ readWritePermissions: ['test', 'admin'],
469
+ minDate: Date.now,
470
+ maxBucketTimeRange: 86400000,
471
+ };
472
+
473
+ await api.timeSeries.addOne(ts);
474
+ ```
475
+
476
+ Add value to Timeseries:
477
+
478
+ ```typescript
479
+ const value = { '1234': 5, '1235': 6 }; // { *timestamp* : *value*}
480
+ // multiple values
481
+ const value1 = { '1234': { val1: 1, val2: 2 } };
482
+
483
+ await api.timeSeries.addValue('1234', value);
484
+ ```
485
+
486
+ </details>
487
+
488
+ ## 4. FAQ
489
+
490
+ ### 4.1. How to log messages from Python in a FlowFunction
491
+
492
+ > this is just possible for _RPC_ style Python integration.
493
+
494
+ In Typescript, you can register a listener for messages and `stderr` and pipe them to your `logger`.
495
+
496
+ ```typescript
497
+ const script = this.runPyRpcScript(join(__dirname, 'my-awesome-script.py'));
498
+ script.addListener('stderr', (data) => this.logger.error('py: ' + data));
499
+ script.on('message', (data) => this.logger.debug('py: ' + data));
500
+ ```
501
+
502
+ Then you can simply use print in python for logging
503
+
504
+ ```python
505
+ print("log the logging log")
506
+ print("this is an error", file=sys.stderr)
507
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hahnpro/hpc-api",
3
- "version": "2024.4.0-0",
3
+ "version": "2025.2.0",
4
4
  "description": "Module for easy access to the HahnPRO Cloud API",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -8,24 +8,26 @@
8
8
  "url": "https://hahnpro.com"
9
9
  },
10
10
  "dependencies": {
11
+ "@swc/helpers": "0.5.11",
11
12
  "axios": "1.7.9",
12
- "eventsource": "2.0.2",
13
+ "eventsource": "3.0.2",
13
14
  "form-data": "4.0.1",
14
15
  "jose": "5.9.6",
15
16
  "jwt-decode": "4.0.0",
16
- "p-queue": "6.6.2",
17
+ "p-queue": "8.1.0",
17
18
  "ts-mixer": "6.0.4",
18
19
  "tslib": "2.8.1"
19
20
  },
20
21
  "devDependencies": {
21
- "@types/eventsource": "1.1.15",
22
22
  "axios-mock-adapter": "2.1.0"
23
23
  },
24
24
  "engines": {
25
- "node": ">=v20"
25
+ "node": ">=v22"
26
26
  },
27
27
  "main": "./src/index.js",
28
28
  "types": "./src/index.d.ts",
29
- "module": "./lib/hpc-api/src/index.js",
30
- "type": "module"
29
+ "type": "commonjs",
30
+ "scripts": {
31
+ "test": "vitest"
32
+ }
31
33
  }
package/src/index.js CHANGED
@@ -1,20 +1,27 @@
1
- export * from './lib/api';
2
- export * from './lib/asset.interface';
3
- export * from './lib/content.interface';
4
- export * from './lib/data.interface';
5
- export * from './lib/data.service';
6
- export * from './lib/endpoint.interface';
7
- export * from './lib/events.interface';
8
- export * from './lib/flow.interface';
9
- export * from './lib/flow-deployment.interface';
10
- export * from './lib/flow-function.interface';
11
- export * from './lib/http.service';
12
- export * from './lib/label.interface';
13
- export * from './lib/mock';
14
- export * from './lib/notification.interface';
15
- export * from './lib/resource.interface';
16
- export * from './lib/schema.interface';
17
- export * from './lib/secret.interface';
18
- export * from './lib/task.interface';
19
- export * from './lib/timeseries.interface';
20
- export * from './lib/vault.interface';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _export_star = require("@swc/helpers/_/_export_star");
6
+ _export_star._(require("./lib/api"), exports);
7
+ _export_star._(require("./lib/asset.interface"), exports);
8
+ _export_star._(require("./lib/content.interface"), exports);
9
+ _export_star._(require("./lib/data.interface"), exports);
10
+ _export_star._(require("./lib/data.service"), exports);
11
+ _export_star._(require("./lib/endpoint.interface"), exports);
12
+ _export_star._(require("./lib/events.interface"), exports);
13
+ _export_star._(require("./lib/flow.interface"), exports);
14
+ _export_star._(require("./lib/flow-deployment.interface"), exports);
15
+ _export_star._(require("./lib/flow-function.interface"), exports);
16
+ _export_star._(require("./lib/http.service"), exports);
17
+ _export_star._(require("./lib/label.interface"), exports);
18
+ _export_star._(require("./lib/mock"), exports);
19
+ _export_star._(require("./lib/notification.interface"), exports);
20
+ _export_star._(require("./lib/resource.interface"), exports);
21
+ _export_star._(require("./lib/schema.interface"), exports);
22
+ _export_star._(require("./lib/secret.interface"), exports);
23
+ _export_star._(require("./lib/task.interface"), exports);
24
+ _export_star._(require("./lib/timeseries.interface"), exports);
25
+ _export_star._(require("./lib/vault.interface"), exports);
26
+
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../lib/hpc-api/src/index.ts"],"sourcesContent":["export * from './lib/api';\nexport * from './lib/asset.interface';\nexport * from './lib/content.interface';\nexport * from './lib/data.interface';\nexport * from './lib/data.service';\nexport * from './lib/endpoint.interface';\nexport * from './lib/events.interface';\nexport * from './lib/flow.interface';\nexport * from './lib/flow-deployment.interface';\nexport * from './lib/flow-function.interface';\nexport * from './lib/http.service';\nexport * from './lib/label.interface';\nexport * from './lib/mock';\nexport * from './lib/notification.interface';\nexport * from './lib/resource.interface';\nexport * from './lib/schema.interface';\nexport * from './lib/secret.interface';\nexport * from './lib/task.interface';\nexport * from './lib/timeseries.interface';\nexport * from './lib/vault.interface';\n"],"names":[],"mappings":";;;;;uBAAc;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA;uBACA"}
package/src/lib/Queue.js CHANGED
@@ -1,13 +1,22 @@
1
- import PQueue from 'p-queue';
2
- export class Queue extends PQueue {
3
- constructor(options) {
4
- super(options);
5
- this.peak = 0;
6
- this.total = 0;
7
- this.on('add', () => {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "Queue", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Queue;
9
+ }
10
+ });
11
+ const _interop_require_default = require("@swc/helpers/_/_interop_require_default");
12
+ const _pqueue = /*#__PURE__*/ _interop_require_default._(require("p-queue"));
13
+ let Queue = class Queue extends _pqueue.default {
14
+ constructor(options){
15
+ super(options), this.peak = 0, this.total = 0;
16
+ this.on('add', ()=>{
8
17
  this.peak = Math.max(this.peak, this.size);
9
18
  });
10
- this.on('active', () => {
19
+ this.on('active', ()=>{
11
20
  this.total++;
12
21
  });
13
22
  }
@@ -16,7 +25,9 @@ export class Queue extends PQueue {
16
25
  peak: this.peak,
17
26
  pending: this.pending,
18
27
  size: this.size,
19
- total: this.total,
28
+ total: this.total
20
29
  };
21
30
  }
22
- }
31
+ };
32
+
33
+ //# sourceMappingURL=Queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../lib/hpc-api/src/lib/Queue.ts"],"sourcesContent":["import PQueue from 'p-queue';\n\nexport class Queue extends PQueue {\n private peak = 0;\n private total = 0;\n\n constructor(options: QueueOptions) {\n super(options);\n this.on('add', () => {\n this.peak = Math.max(this.peak, this.size);\n });\n this.on('active', () => {\n this.total++;\n });\n }\n\n getStats() {\n return {\n peak: this.peak,\n pending: this.pending,\n size: this.size,\n total: this.total,\n };\n }\n}\n\nexport interface QueueOptions {\n concurrency?: number;\n timeout?: number;\n throwOnTimeout?: boolean;\n}\n"],"names":["Queue","PQueue","constructor","options","peak","total","on","Math","max","size","getStats","pending"],"mappings":";;;;+BAEaA;;;eAAAA;;;;iEAFM;AAEZ,IAAA,AAAMA,QAAN,MAAMA,cAAcC,eAAM;IAI/BC,YAAYC,OAAqB,CAAE;QACjC,KAAK,CAACA,eAJAC,OAAO,QACPC,QAAQ;QAId,IAAI,CAACC,EAAE,CAAC,OAAO;YACb,IAAI,CAACF,IAAI,GAAGG,KAAKC,GAAG,CAAC,IAAI,CAACJ,IAAI,EAAE,IAAI,CAACK,IAAI;QAC3C;QACA,IAAI,CAACH,EAAE,CAAC,UAAU;YAChB,IAAI,CAACD,KAAK;QACZ;IACF;IAEAK,WAAW;QACT,OAAO;YACLN,MAAM,IAAI,CAACA,IAAI;YACfO,SAAS,IAAI,CAACA,OAAO;YACrBF,MAAM,IAAI,CAACA,IAAI;YACfJ,OAAO,IAAI,CAACA,KAAK;QACnB;IACF;AACF"}
@@ -1,6 +1,18 @@
1
- export class APIBase {
2
- constructor(httpClient, basePath) {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "APIBase", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return APIBase;
9
+ }
10
+ });
11
+ let APIBase = class APIBase {
12
+ constructor(httpClient, basePath){
3
13
  this.httpClient = httpClient;
4
14
  this.basePath = basePath;
5
15
  }
6
- }
16
+ };
17
+
18
+ //# sourceMappingURL=api-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../lib/hpc-api/src/lib/api-base.ts"],"sourcesContent":["import { HttpClient } from './http.service';\n\nexport class APIBase {\n constructor(\n protected readonly httpClient: HttpClient,\n protected readonly basePath: string,\n ) {}\n}\n"],"names":["APIBase","constructor","httpClient","basePath"],"mappings":";;;;+BAEaA;;;eAAAA;;;AAAN,IAAA,AAAMA,UAAN,MAAMA;IACXC,YACE,AAAmBC,UAAsB,EACzC,AAAmBC,QAAgB,CACnC;aAFmBD,aAAAA;aACAC,WAAAA;IAClB;AACL"}